arm_rtx_costs prices (lshiftrt:DI (mult:DI (extend) (extend)) 32) as a
DImode shift on top of the multiply, 24 against 12, although SMULL,
UMULL and SMMUL compute it in one instruction. The TRUNCATE case meant
to catch this is never reached: it tests ASHIFTRT, and rtx_cost does not
ask the port about a TRUNCATE between tieable modes. Price the shift as
the multiply, remove the TRUNCATE case, and give SMUL_HIGHPART the same
price. Both signs have to change together: pricing only the signed form
moved 63 unsigned divisions to SMMUL and grew the kernel by 32 bytes.
At -Os 621 of 1023 signed constant divisors now use SMMUL instead of
SMULL, at the same size. bcmrpi_defconfig -O2 .text is 96 bytes
smaller; no gcc.c-torture/compile file changes size at -O2 or -Os on
arm1176jzf-s or cortex-a9.
Bootstrapped on x86_64-pc-linux-gnu, regression tested on arm-none-eabi.
Assisted-by: Claude Opus 5 (Anthropic)
gcc/ChangeLog:
* config/arm/arm.cc (arm_rtx_costs_internal): Price a DImode
logical shift by 32 of a widening multiply as that multiply.
Add SMUL_HIGHPART. Remove the TRUNCATE case.
Signed-off-by: Dominic P <[email protected]>
---
gcc/config/arm/arm.cc | 39 ++++++++++++++++++---------------------
1 file changed, 18 insertions(+), 21 deletions(-)
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 33b64995442..c1d13f9d719 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -10758,6 +10758,18 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code,
enum rtx_code outer_code,
case ASHIFTRT:
if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
{
+ if (code == LSHIFTRT
+ && INTVAL (XEXP (x, 1)) == 32
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND
+ || GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND)
+ && (GET_CODE (XEXP (XEXP (x, 0), 1))
+ == GET_CODE (XEXP (XEXP (x, 0), 0))))
+ {
+ *cost = rtx_cost (XEXP (x, 0), mode, code, 0, speed_p);
+ return true;
+ }
+
*cost += (COSTS_N_INSNS (2)
+ rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
if (speed_p)
@@ -12173,27 +12185,12 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code,
enum rtx_code outer_code,
*cost += COSTS_N_INSNS (1);
return false;
- case TRUNCATE:
- if (GET_CODE (XEXP (x, 0)) == ASHIFTRT
- && CONST_INT_P (XEXP (XEXP (x, 0), 1))
- && INTVAL (XEXP (XEXP (x, 0), 1)) == 32
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
- && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND
- && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND)
- || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
- && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1))
- == ZERO_EXTEND))))
- {
- if (speed_p)
- *cost += extra_cost->mult[1].extend;
- *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), VOIDmode,
- ZERO_EXTEND, 0, speed_p)
- + rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1), VOIDmode,
- ZERO_EXTEND, 0, speed_p));
- return true;
- }
- *cost = LIBCALL_COST (1);
- return false;
+ case SMUL_HIGHPART:
+ if (speed_p)
+ *cost += extra_cost->mult[1].extend;
+ *cost += (rtx_cost (XEXP (x, 0), mode, code, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), mode, code, 1, speed_p));
+ return true;
case UNSPEC_VOLATILE:
case UNSPEC:
--
2.55.0