]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
SH: pin input args to hard-regs via predicates for sfuncs
authorKaz Kojima <kkojima@rr.iij4u.or.jp>
Tue, 24 Sep 2024 09:26:42 +0000 (18:26 +0900)
committerOleg Endo <olegendo@gcc.gnu.org>
Wed, 25 Sep 2024 01:20:31 +0000 (10:20 +0900)
Some sfuncs uses hard reg as input and clobber its raw reg pattern. It
seems that LRA doesn't process this clobber pattern.  Rewrite these
patterns so as to work with LRA.

gcc/ChangeLog:
* config/sh/predicates.md (hard_reg_r4, hard_reg_r5,
hard_reg_r6): New predicates.
* config/sh/sh.md (udivsi3_i4, udivsi3_i4_single,
udivsi3_i1): Rewrite with match_operand and match_dup.
(block_lump_real, block_lump_real_i4): Ditto.
(udivsi3): Adjust for it.
* config/sh/sh-mem.cc (expand_block_move): Ditto.

gcc/config/sh/predicates.md
gcc/config/sh/sh-mem.cc
gcc/config/sh/sh.md

index 3732cec9608b086dddf35fcb50a5f12ff5a219f2..b10af71c280e4338253a384f40c4b4d2d929f826 100644 (file)
 
   return false;
 })
+
+;; Predicats for the arguments of sfunc R4, R5 and R6.
+(define_predicate "hard_reg_r4"
+  (match_code "reg")
+{
+  return REGNO (op) == R4_REG;
+})
+
+(define_predicate "hard_reg_r5"
+  (match_code "reg")
+{
+  return REGNO (op) == R5_REG;
+})
+
+(define_predicate "hard_reg_r6"
+  (match_code "reg")
+{
+  return REGNO (op) == R6_REG;
+})
index e22419912d6ff421bed3c69bd92c8eec0655d44d..751c826e84fb445b7aec2ae10c3f860e7fecddb6 100644 (file)
@@ -134,7 +134,7 @@ expand_block_move (rtx *operands)
 
          int dwords = bytes >> 3;
          emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
-         emit_insn (gen_block_lump_real_i4 (func_addr_rtx, lab));
+         emit_insn (gen_block_lump_real_i4 (func_addr_rtx, lab, r4, r5, r6));
          return true;
        }
       else
@@ -178,7 +178,7 @@ expand_block_move (rtx *operands)
       final_switch = 16 - ((bytes / 4) % 16);
       while_loop = ((bytes / 4) / 16 - 1) * 16;
       emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
-      emit_insn (gen_block_lump_real (func_addr_rtx, lab));
+      emit_insn (gen_block_lump_real (func_addr_rtx, lab, r4, r5, r6));
       return true;
     }
 
index c69eda36885f5a32d27281acb74afa76c0d38777..451ae0b7689138df18cc4b61c1b2061b8cbb1df6 100644 (file)
 ;; there is nothing to prevent reload from using r0 to reload the address.
 ;; This reload would clobber the value in r0 we are trying to store.
 ;; If we let reload allocate r0, then this problem can never happen.
+;;
+;; In addition to that, we also must pin the input regs to hard-regs via the
+;; predicates.  When these insns are instantiated it also emits the
+;; accompanying mov insns to load the hard-regs.  However, subsequent RTL
+;; passes might move things around and reassign the operands to pseudo regs
+;; which might get allocated to different (wrong) hard-regs eventually.  To
+;; avoid that, only allow matching these insns if the operands are the
+;; expected hard-regs.
 (define_insn "udivsi3_i1"
   [(set (match_operand:SI 0 "register_operand" "=z,z")
-       (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
+       (udiv:SI (match_operand:SI 3 "hard_reg_r4" "=r,r")
+                (match_operand:SI 4 "hard_reg_r5" "=r,r")))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
    (clobber (reg:SI R1_REG))
-   (clobber (reg:SI R4_REG))
+   (clobber (match_dup 3))
+   (use (reg:SI R4_REG))
+   (use (reg:SI R5_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
    (use (match_operand 2 "" "Z,Ccl"))]
   "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
 
 (define_insn "udivsi3_i4"
   [(set (match_operand:SI 0 "register_operand" "=y,y")
-       (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
+       (udiv:SI (match_operand:SI 3 "hard_reg_r4" "=r,r")
+                (match_operand:SI 4 "hard_reg_r5" "=r,r")))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
    (clobber (reg:DF DR0_REG))
    (clobber (reg:DF DR4_REG))
    (clobber (reg:SI R0_REG))
    (clobber (reg:SI R1_REG))
-   (clobber (reg:SI R4_REG))
-   (clobber (reg:SI R5_REG))
+   (clobber (match_dup 3))
+   (clobber (match_dup 4))
    (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI R4_REG))
+   (use (reg:SI R5_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
    (use (match_operand 2 "" "Z,Ccl"))
    (use (reg:SI FPSCR_MODES_REG))]
 
 (define_insn "udivsi3_i4_single"
   [(set (match_operand:SI 0 "register_operand" "=y,y")
-       (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
+       (udiv:SI (match_operand:SI 3 "hard_reg_r4" "=r,r")
+                (match_operand:SI 4 "hard_reg_r5" "=r,r")))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
    (clobber (reg:DF DR0_REG))
    (clobber (reg:DF DR4_REG))
    (clobber (reg:SI R0_REG))
    (clobber (reg:SI R1_REG))
-   (clobber (reg:SI R4_REG))
-   (clobber (reg:SI R5_REG))
+   (clobber (match_dup 3))
+   (clobber (match_dup 4))
+   (use (reg:SI R4_REG))
+   (use (reg:SI R5_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
    (use (match_operand 2 "" "Z,Ccl"))]
   "TARGET_FPU_ANY && TARGET_FPU_SINGLE"
 {
   rtx last;
   rtx func_ptr = gen_reg_rtx (Pmode);
+  rtx r4 = gen_rtx_REG (SImode, R4_REG);
+  rtx r5 = gen_rtx_REG (SImode, R5_REG);
 
   /* Emit the move of the address to a pseudo outside of the libcall.  */
   if (TARGET_DIVIDE_CALL_TABLE)
     {
       rtx lab = function_symbol (func_ptr, "__udivsi3_i4", SFUNC_STATIC).lab;
       if (TARGET_FPU_SINGLE)
-       last = gen_udivsi3_i4_single (operands[0], func_ptr, lab);
+       last = gen_udivsi3_i4_single (operands[0], func_ptr, lab, r4, r5);
       else
-       last = gen_udivsi3_i4 (operands[0], func_ptr, lab);
+       last = gen_udivsi3_i4 (operands[0], func_ptr, lab, r4, r5);
     }
   else if (TARGET_SH2A)
     {
   else
     {
       rtx lab = function_symbol (func_ptr, "__udivsi3", SFUNC_STATIC).lab;
-      last = gen_udivsi3_i1 (operands[0], func_ptr, lab);
+      last = gen_udivsi3_i1 (operands[0], func_ptr, lab, r4, r5);
     }
-  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
-  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
+  emit_move_insn (r4, operands[1]);
+  emit_move_insn (r5, operands[2]);
   emit_insn (last);
   DONE;
 })
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "block_lump_real"
-  [(parallel [(set (mem:BLK (reg:SI R4_REG))
-                  (mem:BLK (reg:SI R5_REG)))
-             (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
-             (use (match_operand 1 "" "Z,Ccl"))
-             (use (reg:SI R6_REG))
-             (clobber (reg:SI PR_REG))
-             (clobber (reg:SI T_REG))
-             (clobber (reg:SI R4_REG))
-             (clobber (reg:SI R5_REG))
-             (clobber (reg:SI R6_REG))
-             (clobber (reg:SI R0_REG))])]
+  [(set (mem:BLK (match_operand:SI 2 "hard_reg_r4" "=r,r"))
+       (mem:BLK (match_operand:SI 3 "hard_reg_r5" "=r,r")))
+   (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+   (use (match_operand 1 "" "Z,Ccl"))
+   (use (match_operand:SI 4 "hard_reg_r6" "=r,r"))
+   (use (reg:SI R4_REG))
+   (use (reg:SI R5_REG))
+   (use (reg:SI R6_REG))
+   (clobber (match_dup 2))
+   (clobber (match_dup 3))
+   (clobber (match_dup 4))
+   (clobber (reg:SI PR_REG))
+   (clobber (reg:SI T_REG))
+   (clobber (reg:SI R0_REG))]
   "TARGET_SH1 && ! TARGET_HARD_SH4"
   "@
        jsr     @%0%#
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "block_lump_real_i4"
-  [(parallel [(set (mem:BLK (reg:SI R4_REG))
-                  (mem:BLK (reg:SI R5_REG)))
-             (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
-             (use (match_operand 1 "" "Z,Ccl"))
-             (use (reg:SI R6_REG))
-             (clobber (reg:SI PR_REG))
-             (clobber (reg:SI T_REG))
-             (clobber (reg:SI R4_REG))
-             (clobber (reg:SI R5_REG))
-             (clobber (reg:SI R6_REG))
-             (clobber (reg:SI R0_REG))
-             (clobber (reg:SI R1_REG))
-             (clobber (reg:SI R2_REG))
-             (clobber (reg:SI R3_REG))])]
+  [(set (mem:BLK (match_operand:SI 2 "hard_reg_r4" "=r,r"))
+       (mem:BLK (match_operand:SI 3 "hard_reg_r5" "=r,r")))
+   (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+   (use (match_operand 1 "" "Z,Ccl"))
+   (use (match_operand:SI 4 "hard_reg_r6" "=r,r"))
+   (use (reg:SI R4_REG))
+   (use (reg:SI R5_REG))
+   (use (reg:SI R6_REG))
+   (clobber (match_dup 2))
+   (clobber (match_dup 3))
+   (clobber (match_dup 4))
+   (clobber (reg:SI PR_REG))
+   (clobber (reg:SI T_REG))
+   (clobber (reg:SI R0_REG))
+   (clobber (reg:SI R1_REG))
+   (clobber (reg:SI R2_REG))
+   (clobber (reg:SI R3_REG))]
   "TARGET_HARD_SH4"
   "@
        jsr     @%0%#