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(); }

Reply via email to