A STRICT_ALIGNMENT target that provides movmisalign<m> is saying only that it
can perform the access, not that doing so is worth it: alpha's expands to the
ldq_u/insxh/mskxl sequence, arm's to a single unaligned ldr or str.
TARGET_SLOW_UNALIGNED_ACCESS cannot express the difference, because it is
documented to return true whenever STRICT_ALIGNMENT is true and its two dozen
callers read it as "act as if STRICT_ALIGNMENT".  Add a hook for just that
question.  Its default is false on every STRICT_ALIGNMENT target, and it has
no callers yet, so this patch changes no generated code on any target.

Assisted-by: Claude Opus 5 (Anthropic)
Signed-off-by: Dominic P <[email protected]>

gcc/ChangeLog:

        * target.def (misaligned_access_cheap_p): New hook.
        * doc/tm.texi.in (TARGET_MISALIGNED_ACCESS_CHEAP_P): Document it.
        * doc/tm.texi: Regenerate.
        * targhooks.h (default_misaligned_access_cheap_p): Declare.
        * targhooks.cc (default_misaligned_access_cheap_p): New function.
---
 gcc/doc/tm.texi    | 19 +++++++++++++++++++
 gcc/doc/tm.texi.in |  2 ++
 gcc/target.def     | 21 +++++++++++++++++++++
 gcc/targhooks.cc   |  9 +++++++++
 gcc/targhooks.h    |  1 +
 5 files changed, 52 insertions(+)

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index ca68bdc3e61..d3847e739b5 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7184,6 +7184,25 @@ The hook must return true whenever 
@code{STRICT_ALIGNMENT} is true.
 The default implementation returns @code{STRICT_ALIGNMENT}.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_MISALIGNED_ACCESS_CHEAP_P (machine_mode 
@var{mode}, unsigned int @var{align})
+This hook returns true if a single memory access of @var{mode} at
+@var{align} bits of alignment costs no more than the sequence of naturally
+aligned accesses that would otherwise be needed to cover it, so that a
+@code{STRICT_ALIGNMENT} target may still be given the wider access.  It is
+invoked only for unaligned accesses, i.e.@: when
+@code{@var{align} < GET_MODE_ALIGNMENT (@var{mode})}.
+
+Unlike @code{TARGET_SLOW_UNALIGNED_ACCESS}, which must return true whenever
+@code{STRICT_ALIGNMENT} is true, this hook lets a target that implements
+@code{movmisalign@var{m}} with a single instruction say so.  A target whose
+@code{movmisalign@var{m}} is a multi-instruction sequence must leave it
+false.
+
+The default implementation returns true if @code{movmisalign@var{m}} exists
+for @var{mode} and @code{TARGET_SLOW_UNALIGNED_ACCESS} is false, which is
+never the case on a @code{STRICT_ALIGNMENT} target.
+@end deftypefn
+
 @defmac MOVE_RATIO (@var{speed})
 The threshold of number of scalar memory-to-memory move insns, @emph{below}
 which a sequence of insns should be generated instead of a
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 532e95ef216..039a520ad5b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4660,6 +4660,8 @@ other fields in the same word of the structure, but to 
different bytes.
 
 @hook TARGET_SLOW_UNALIGNED_ACCESS
 
+@hook TARGET_MISALIGNED_ACCESS_CHEAP_P
+
 @defmac MOVE_RATIO (@var{speed})
 The threshold of number of scalar memory-to-memory move insns, @emph{below}
 which a sequence of insns should be generated instead of a
diff --git a/gcc/target.def b/gcc/target.def
index 66c20a9c9d2..1e12e0e98b1 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4008,6 +4008,27 @@ The default implementation returns 
@code{STRICT_ALIGNMENT}.",
  bool, (machine_mode mode, unsigned int align),
  default_slow_unaligned_access)
 
+DEFHOOK
+(misaligned_access_cheap_p,
+ "This hook returns true if a single memory access of @var{mode} at\n\
+@var{align} bits of alignment costs no more than the sequence of naturally\n\
+aligned accesses that would otherwise be needed to cover it, so that a\n\
+@code{STRICT_ALIGNMENT} target may still be given the wider access.  It is\n\
+invoked only for unaligned accesses, i.e.@: when\n\
+@code{@var{align} < GET_MODE_ALIGNMENT (@var{mode})}.\n\
+\n\
+Unlike @code{TARGET_SLOW_UNALIGNED_ACCESS}, which must return true whenever\n\
+@code{STRICT_ALIGNMENT} is true, this hook lets a target that implements\n\
+@code{movmisalign@var{m}} with a single instruction say so.  A target whose\n\
+@code{movmisalign@var{m}} is a multi-instruction sequence must leave it\n\
+false.\n\
+\n\
+The default implementation returns true if @code{movmisalign@var{m}} exists\n\
+for @var{mode} and @code{TARGET_SLOW_UNALIGNED_ACCESS} is false, which is\n\
+never the case on a @code{STRICT_ALIGNMENT} target.",
+ bool, (machine_mode mode, unsigned int align),
+ default_misaligned_access_cheap_p)
+
 DEFHOOK
 (optab_supported_p,
  "Return true if the optimizers should use optab @var{op} with\n\
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index 388f696c8aa..0f5562fba59 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -2156,6 +2156,15 @@ default_slow_unaligned_access (machine_mode, unsigned 
int)
   return STRICT_ALIGNMENT;
 }
 
+/* The default implementation of TARGET_MISALIGNED_ACCESS_CHEAP_P.  */
+
+bool
+default_misaligned_access_cheap_p (machine_mode mode, unsigned int align)
+{
+  return (optab_handler (movmisalign_optab, mode) != CODE_FOR_nothing
+         && !targetm.slow_unaligned_access (mode, align));
+}
+
 /* The default implementation of TARGET_ESTIMATED_POLY_VALUE.  */
 
 HOST_WIDE_INT
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 86de6ef8a69..d9bda73c34a 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -244,6 +244,7 @@ extern int default_callee_save_cost (spill_cost_type, 
unsigned int,
 extern int default_frame_allocation_cost (frame_cost_type,
                                          const HARD_REG_SET &);
 extern bool default_slow_unaligned_access (machine_mode, unsigned int);
+extern bool default_misaligned_access_cheap_p (machine_mode, unsigned int);
 extern HOST_WIDE_INT default_estimated_poly_value (poly_int64,
                                                   poly_value_estimate_kind);
 
-- 
2.55.0

Reply via email to