]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AVR: target/116781 - Fix ICE due to (clobber (match_dup)) in tablejump.
authorGeorg-Johann Lay <avr@gjlay.de>
Sat, 16 Nov 2024 13:26:02 +0000 (14:26 +0100)
committerGeorg-Johann Lay <avr@gjlay.de>
Sat, 16 Nov 2024 18:56:13 +0000 (19:56 +0100)
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.

gcc/config/avr/avr-passes.cc
gcc/config/avr/avr.md

index 205b490950d745326a33c9ae1f743677a731c9a6..dff98368caa1708c3055ad58c4b98f3fdafdb960 100644 (file)
@@ -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);
     }
index 80ad7e97ac935c4cc81bd3af28da0880c22fff02..bf5115020ab75930538af9721663c055b0081744 100644 (file)
         (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"
   "#"
                    (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))])]
   ""
         (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"
    (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);
     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;
       }
   })
 
 ;; "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)
    (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(); }