https://gcc.gnu.org/g:083892ba18452383a1f240072d2a96dd72321a4f
commit r15-5353-g083892ba18452383a1f240072d2a96dd72321a4f Author: Georg-Johann Lay <a...@gjlay.de> Date: Sat Nov 16 14:26:02 2024 +0100 AVR: target/116781 - Fix ICE due to (clobber (match_dup)) in tablejump. This patch avoids (clobber (match_dup)) in insn patterns for tablejump. The machine description now uses a scratch_operand instead which is possible since the clobbered entity is known in advance: 3-byte PC : REG_Z 2-byte PC + JMP : REG_Z 2-byte PC + RJMP : None, hence scratch:HI is used. The avr-casesi pass and optimization has to be adjusted to the new patterns. PR target/116781 gcc/ * config/avr/avr.md (*tablejump_split, *tablejump): Add operand 2 as a "scratch_operand" instead of a match_dup. (casesi): Adjust expander operands accordingly. Use a scratch:HI when the jump address is not clobbered. This is the case for a 2-byte PC + has no JMP instruction. In all the other cases, the affected operand is REG_Z (reg:HI 30). (casesi_<mode>_sequence): Adjust matcher to new anatomy. * config/avr/avr-passes.cc (avr_is_casesi_sequence) (avr_is_casesi_sequence, avr_optimize_casesi) (avr_casei_sequence_check_operands): Adjust to new anatomy. Diff: --- gcc/config/avr/avr-passes.cc | 23 ++++++++++++----------- gcc/config/avr/avr.md | 36 +++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc index 205b490950d7..dff98368caa1 100644 --- a/gcc/config/avr/avr-passes.cc +++ b/gcc/config/avr/avr-passes.cc @@ -769,8 +769,8 @@ avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[5]) // Assert on the anatomy of xinsn's operands we are going to work with. - gcc_assert (recog_data.n_operands == 11); - gcc_assert (recog_data.n_dups == 4); + gcc_assert (recog_data.n_operands == 12); + gcc_assert (recog_data.n_dups == 3); if (dump_file) { @@ -789,7 +789,7 @@ avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[5]) operands of INSNS as extracted by insn_extract from pattern casesi_<mode>_sequence: - $0: SImode reg switch value as result of $9. + $0: SImode reg switch value as result of $10. $1: Negative of smallest index in switch. $2: Number of entries in switch. $3: Label to table. @@ -798,9 +798,10 @@ avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[5]) $6: 3-byte PC: subreg:HI ($5) + label_ref ($3) 2-byte PC: subreg:HI ($5) $7: HI reg index into table (Z or pseudo) - $8: R24 or const0_rtx (to be clobbered) - $9: Extension to SImode of an 8-bit or 16-bit integer register $10. - $10: QImode or HImode register input of $9. + $8: Z or scratch:HI (to be clobbered) + $9: R24 or const0_rtx (to be clobbered) + $10: Extension to SImode of an 8-bit or 16-bit integer register $11. + $11: QImode or HImode register input of $10. Try to optimize this sequence, i.e. use the original HImode / QImode switch value instead of SImode. */ @@ -809,11 +810,11 @@ static void avr_optimize_casesi (rtx_insn *insns[5], rtx *xop) { // Original mode of the switch value; this is QImode or HImode. - machine_mode mode = GET_MODE (xop[10]); + machine_mode mode = GET_MODE (xop[11]); // How the original switch value was extended to SImode; this is // SIGN_EXTEND or ZERO_EXTEND. - rtx_code code = GET_CODE (xop[9]); + rtx_code code = GET_CODE (xop[10]); // Lower index, upper index (plus one) and range of case calues. HOST_WIDE_INT low_idx = -INTVAL (xop[1]); @@ -857,7 +858,7 @@ avr_optimize_casesi (rtx_insn *insns[5], rtx *xop) start_sequence(); - rtx reg = copy_to_mode_reg (mode, xop[10]); + rtx reg = copy_to_mode_reg (mode, xop[11]); rtx (*gen_add)(rtx,rtx,rtx) = QImode == mode ? gen_addqi3 : gen_addhi3; rtx (*gen_cbranch)(rtx,rtx,rtx,rtx) @@ -967,7 +968,7 @@ avr_casei_sequence_check_operands (rtx *xop) if (AVR_HAVE_EIJMP_EICALL // The last clobber op of the tablejump. - && xop[8] == all_regs_rtx[REG_24]) + && xop[9] == all_regs_rtx[REG_24]) { // $6 is: (subreg:SI ($5) 0) sub_5 = xop[6]; @@ -980,7 +981,7 @@ avr_casei_sequence_check_operands (rtx *xop) && LABEL_REF == GET_CODE (XEXP (xop[6], 1)) && rtx_equal_p (xop[3], XEXP (XEXP (xop[6], 1), 0)) // The last clobber op of the tablejump. - && xop[8] == const0_rtx) + && xop[9] == const0_rtx) { sub_5 = XEXP (xop[6], 0); } diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 80ad7e97ac93..bf5115020ab7 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -7684,7 +7684,7 @@ (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")] UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 1 "" ""))) - (clobber (match_dup 0)) + (clobber (match_operand:HI 2 "scratch_operand" "=X,X,0")) (clobber (const_int 0))] "!AVR_HAVE_EIJMP_EICALL" "#" @@ -7693,7 +7693,7 @@ (unspec:HI [(match_dup 0)] UNSPEC_INDEX_JMP)) (use (label_ref (match_dup 1))) - (clobber (match_dup 0)) + (clobber (match_dup 2)) (clobber (const_int 0)) (clobber (reg:CC REG_CC))])] "" @@ -7704,7 +7704,7 @@ (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")] UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 1 "" ""))) - (clobber (match_dup 0)) + (clobber (match_operand:HI 2 "scratch_operand" "=X,X,0")) (clobber (const_int 0)) (clobber (reg:CC REG_CC))] "!AVR_HAVE_EIJMP_EICALL && reload_completed" @@ -7790,8 +7790,8 @@ (parallel [(set (pc) (unspec:HI [(match_dup 7)] UNSPEC_INDEX_JMP)) (use (label_ref (match_dup 3))) - (clobber (match_dup 7)) - (clobber (match_dup 8))])] + (clobber (match_dup 8)) + (clobber (match_dup 9))])] "" { operands[1] = simplify_unary_operation (NEG, SImode, operands[1], SImode); @@ -7801,14 +7801,24 @@ if (AVR_HAVE_EIJMP_EICALL) { operands[7] = gen_rtx_REG (HImode, REG_Z); - operands[8] = all_regs_rtx[24]; + operands[8] = gen_rtx_REG (HImode, REG_Z); + operands[9] = all_regs_rtx[24]; } else { operands[6] = gen_rtx_PLUS (HImode, operands[6], gen_rtx_LABEL_REF (VOIDmode, operands[3])); - operands[7] = gen_reg_rtx (HImode); - operands[8] = const0_rtx; + if (AVR_HAVE_JMP_CALL) + { + operands[7] = gen_rtx_REG (HImode, REG_Z); + operands[8] = gen_rtx_REG (HImode, REG_Z); + } + else + { + operands[7] = gen_reg_rtx (HImode); + operands[8] = gen_rtx_SCRATCH (HImode); + } + operands[9] = const0_rtx; } }) @@ -7821,11 +7831,11 @@ ;; "casesi_hi_sequence" (define_insn "casesi_<mode>_sequence" [(set (match_operand:SI 0 "register_operand") - (match_operator:SI 9 "extend_operator" - [(match_operand:QIHI 10 "register_operand")])) + (match_operator:SI 10 "extend_operator" + [(match_operand:QIHI 11 "register_operand")])) ;; What follows is a matcher for code from casesi. - ;; We keep the same operand numbering (except for $9 and $10 + ;; We keep the same operand numbering (except for $10 and $11 ;; which don't appear in casesi). (parallel [(set (match_operand:SI 5 "register_operand") (plus:SI (match_dup 0) @@ -7845,8 +7855,8 @@ (parallel [(set (pc) (unspec:HI [(match_dup 7)] UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 3))) - (clobber (match_dup 7)) - (clobber (match_operand:QI 8))])] + (clobber (match_operand:HI 8)) + (clobber (match_operand:QI 9))])] "optimize && avr_casei_sequence_check_operands (operands)" { gcc_unreachable(); }