Hello, Since r11-2903-g6b3034eaba83935d9f6dfb20d2efbdb34b5b00bf introduced a canonicalization from mult to shift on address reloads, a missing pattern in the AArch64 backend was exposed.
In particular, we were missing the ashift variant of *add_<optab><mode>_multp2 (this mult variant is redundant and was removed in r11-3033-g2f8ae301f6a125f50b0a758047fcddae7b68daa8). This patch adds that missing pattern (fixing PR96998), updates aarch64_is_extend_from_extract() to work for the shift pattern (instead of the redundant mult variant) and updates callers in the cost calculations to apply the costing for the shift variant instead. Testing: * Bootstrap and regtest on aarch64-none-linux-gnu, no regressions. * Checked new unit test passes on arm-none-linux-gnueabihf. * Checked new unit test isn't run on x86 (inline asm uses arm/aarch64-specific constraint). * Tested linux-next tree no longer encounters this ICE on arm64 with patched GCC (unfortunately still doesn't compile successfully due to a fix for PR96475 which introduces an ICE on arm64). OK for trunk? Thanks, Alex --- gcc/ChangeLog: PR target/96998 * config/aarch64/aarch64.c (aarch64_is_extend_from_extract): Update to work for shift pattern instead of mult. (aarch64_strip_extend): Cost extract+shift pattern instead of now-removed extract+mult pattern. (aarch64_rtx_arith_op_extract_p): Likewise. * config/aarch64/aarch64.md (*add_<optab><mode>_shftex): New. gcc/testsuite/ChangeLog: PR target/96998 * gcc.c-torture/compile/pr96998.c: New test.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index b6d74496cd0..55e0fc4e683 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -2815,27 +2815,24 @@ aarch64_is_noplt_call_p (rtx sym) represent an expression that matches an extend operation. The operands represent the parameters from - (extract:MODE (mult (reg) (MULT_IMM)) (EXTRACT_IMM) (const_int 0)). */ + (extract:MODE (ashift (reg) (SHIFT_IMM)) (EXTRACT_IMM) (const_int 0)). */ bool -aarch64_is_extend_from_extract (scalar_int_mode mode, rtx mult_imm, +aarch64_is_extend_from_extract (scalar_int_mode mode, rtx shift_imm, rtx extract_imm) { - HOST_WIDE_INT mult_val, extract_val; + HOST_WIDE_INT shift_val, extract_val; - if (! CONST_INT_P (mult_imm) || ! CONST_INT_P (extract_imm)) + if (! CONST_INT_P (shift_imm) || ! CONST_INT_P (extract_imm)) return false; - mult_val = INTVAL (mult_imm); + shift_val = INTVAL (shift_imm); extract_val = INTVAL (extract_imm); - if (extract_val > 8 - && extract_val < GET_MODE_BITSIZE (mode) - && exact_log2 (extract_val & ~7) > 0 - && (extract_val & 7) <= 4 - && mult_val == (1 << (extract_val & 7))) - return true; - - return false; + return extract_val > 8 + && extract_val < GET_MODE_BITSIZE (mode) + && exact_log2 (extract_val & ~7) > 0 + && shift_val <= 4 + && shift_val == (extract_val & 7); } /* Emit an insn that's a simple single-set. Both the operands must be @@ -11262,7 +11259,7 @@ aarch64_strip_extend (rtx x, bool strip_shift) /* Zero and sign extraction of a widened value. */ if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT) && XEXP (op, 2) == const0_rtx - && GET_CODE (XEXP (op, 0)) == MULT + && GET_CODE (XEXP (op, 0)) == ASHIFT && aarch64_is_extend_from_extract (mode, XEXP (XEXP (op, 0), 1), XEXP (op, 1))) return XEXP (XEXP (op, 0), 0); @@ -11617,7 +11614,7 @@ aarch64_rtx_arith_op_extract_p (rtx x, scalar_int_mode mode) rtx op1 = XEXP (x, 1); rtx op2 = XEXP (x, 2); - if (GET_CODE (op0) == MULT + if (GET_CODE (op0) == ASHIFT && CONST_INT_P (op1) && op2 == const0_rtx && CONST_INT_P (XEXP (op0, 1)) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index dbc6b1db176..4bb7b318b99 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -2471,6 +2471,19 @@ (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>" [(set_attr "type" "alu_ext")] ) +(define_insn "*add_<optab><mode>_shftex" + [(set (match_operand:GPI 0 "register_operand" "=rk") + (plus:GPI (ANY_EXTRACT:GPI + (ashift:GPI (match_operand:GPI 1 "register_operand" "r") + (match_operand 2 "aarch64_shift_imm_<mode>" "n")) + (match_operand 3 "const_int_operand" "n") + (const_int 0)) + (match_operand:GPI 4 "register_operand" "r")))] + "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])" + "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %2" + [(set_attr "type" "alu_ext")] +) + ;; zero_extend version of above (define_insn "*add_<optab><SHORT:mode>_si_uxtw" [(set (match_operand:DI 0 "register_operand" "=rk") diff --git a/gcc/testsuite/gcc.c-torture/compile/pr96998.c b/gcc/testsuite/gcc.c-torture/compile/pr96998.c new file mode 100644 index 00000000000..a75d5dcfe08 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr96998.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target arm*-*-* aarch64*-*-* } } */ + +int h(void); +struct c d; +struct c { + int e[1]; +}; + +void f(void) { + int g; + for (;; g = h()) { + int *i = &d.e[g]; + asm("" : "=Q"(*i)); + } +}