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
