]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AVR: Tidy up subtract-and-zero_extend insns.
authorGeorg-Johann Lay <avr@gjlay.de>
Thu, 11 Jul 2024 11:08:19 +0000 (13:08 +0200)
committerGeorg-Johann Lay <avr@gjlay.de>
Thu, 11 Jul 2024 11:09:39 +0000 (13:09 +0200)
There are these insns that subtract and zero-extend where
the subtrahend is zero-extended to the mode of the minuend.
This patch uses one insn (and split) with mode iterators
instead of spelling out each variant individually.
This has the additional benefit that u32 - u24 is also supported,
which previously wasn't.

gcc/
* config/avr/avr-protos.h (avr_out_minus): New prototype.
* config/avr/avr.cc (avr_out_minus): New function.
* config/avr/avr.md (*sub<HISI:mode>3.zero_extend.<QIPSI:mode>)
(*sub<HISI:mode>3.zero_extend.<QIPSI:mode>_split): New insns.
(*subpsi3_zero_extend.qi_split): Remove isns_and_split.
(*subpsi3_zero_extend.hi_split): Remove insn_and_split.
(*subhi3_zero_extend1_split): Remove insn_and_split.
(*subsi3_zero_extend_split): Remove insn_and_split.
(*subsi3_zero_extend.hi_split): Remove insn_and_split.
(*subpsi3_zero_extend.qi): Remove insn.
(*subpsi3_zero_extend.hi): Remove insn.
(*subhi3_zero_extend1): Remove insn.
(*subsi3_zero_extend): Remove insn.
(*subsi3_zero_extend.hi): Remove insn.
gcc/testsuite/
* gcc.target/avr/torture/sub-zerox.c: New test.

gcc/config/avr/avr-protos.h
gcc/config/avr/avr.cc
gcc/config/avr/avr.md
gcc/testsuite/gcc.target/avr/torture/sub-zerox.c [new file with mode: 0644]

index dc23cfbf461c8c172946da5570a069fc044525a8..6e02161759cacadc480b078bd1e38869a5a029a7 100644 (file)
@@ -95,6 +95,7 @@ extern void avr_output_addr_vec (rtx_insn*, rtx);
 extern const char *avr_out_sbxx_branch (rtx_insn *insn, rtx operands[]);
 extern const char* avr_out_bitop (rtx, rtx*, int*);
 extern const char* avr_out_plus (rtx, rtx*, int* =NULL, bool =true);
+extern const char* avr_out_minus (rtx*);
 extern const char* avr_out_round (rtx_insn *, rtx*, int* =NULL);
 extern const char* avr_out_addto_sp (rtx*, int*);
 extern const char* avr_out_xload (rtx_insn *, rtx*, int*);
index d299fceb7824d68b6e53d1068233b885c24f8745..4a7cbd0e7bc69678ce85c4256944785f00681153 100644 (file)
@@ -8843,6 +8843,36 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
 }
 
 
+/* Output subtraction of integer registers XOP[0] and XOP[2] and return ""
+
+      XOP[0] = XOP[0] - XOP[2]
+
+   where the mode of XOP[0] is in { HI, PSI, SI }, and the mode of
+   XOP[2] is in { QI, HI, PSI }.  When the mode of XOP[0] is larger
+   than the mode of XOP[2], then the latter is zero-extended on the fly.
+   The number of instructions will be the mode size of XOP[0].  */
+
+const char *
+avr_out_minus (rtx *xop)
+{
+  int n_bytes0 = GET_MODE_SIZE (GET_MODE (xop[0]));
+  int n_bytes2 = GET_MODE_SIZE (GET_MODE (xop[2]));
+
+  output_asm_insn ("sub %0,%2", xop);
+
+  for (int i = 1; i < n_bytes0; ++i)
+    {
+      rtx op[2];
+      op[0] = all_regs_rtx[i + REGNO (xop[0])];
+      op[1] = (i < n_bytes2) ? all_regs_rtx[i + REGNO (xop[2])] : zero_reg_rtx;
+
+      output_asm_insn ("sbc %0,%1", op);
+    }
+
+  return "";
+}
+
+
 /* Output addition of register XOP[0] and compile time constant XOP[2].
    INSN is a single_set insn or an insn pattern.
    CODE == PLUS:  perform addition by using ADD instructions or
@@ -12717,7 +12747,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
          *total = COSTS_N_INSNS (2);
          return true;
        }
-      // *sub<mode>3_zero_extend1
+      // *sub<HISI:mode>3.zero_extend.<QIPSI:mode>
       if (REG_P (XEXP (x, 0))
          && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
        {
index 2783b8c986f19eb431b6dfe7170705acf9c014e0..8c3e55a91ee03743fa1f26618d0c3ff64575419d 100644 (file)
   "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
   [(set_attr "length" "3")])
 
-(define_insn_and_split "*subpsi3_zero_extend.qi_split"
-  [(set (match_operand:PSI 0 "register_operand"                           "=r")
-        (minus:PSI (match_operand:SI 1 "register_operand"                  "0")
-                   (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
-  ""
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0)
-                   (minus:PSI (match_dup 1)
-                              (zero_extend:PSI (match_dup 2))))
-              (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subpsi3_zero_extend.qi"
-  [(set (match_operand:PSI 0 "register_operand"                           "=r")
-        (minus:PSI (match_operand:SI 1 "register_operand"                  "0")
-                   (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))
-   (clobber (reg:CC REG_CC))]
-  "reload_completed"
-  "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
-  [(set_attr "length" "3")])
-
-(define_insn_and_split "*subpsi3_zero_extend.hi_split"
-  [(set (match_operand:PSI 0 "register_operand"                           "=r")
-        (minus:PSI (match_operand:PSI 1 "register_operand"                 "0")
-                   (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
-  ""
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0)
-                   (minus:PSI (match_dup 1)
-                              (zero_extend:PSI (match_dup 2))))
-              (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subpsi3_zero_extend.hi"
-  [(set (match_operand:PSI 0 "register_operand"                           "=r")
-        (minus:PSI (match_operand:PSI 1 "register_operand"                 "0")
-                   (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))
-   (clobber (reg:CC REG_CC))]
-  "reload_completed"
-  "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
-  [(set_attr "length" "3")])
 
 (define_insn_and_split "*subpsi3_sign_extend.hi_split"
   [(set (match_operand:PSI 0 "register_operand"                           "=r")
   }
   [(set_attr "adjust_len" "plus")])
 
-(define_insn_and_split "*subhi3_zero_extend1_split"
-  [(set (match_operand:HI 0 "register_operand"                          "=r")
-        (minus:HI (match_operand:HI 1 "register_operand"                 "0")
-                  (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
-  ""
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0)
-                   (minus:HI (match_dup 1)
-                             (zero_extend:HI (match_dup 2))))
-             (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subhi3_zero_extend1"
-  [(set (match_operand:HI 0 "register_operand"                          "=r")
-        (minus:HI (match_operand:HI 1 "register_operand"                 "0")
-                  (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))
-  (clobber (reg:CC REG_CC))]
-  "reload_completed"
-  "sub %A0,%2\;sbc %B0,__zero_reg__"
-  [(set_attr "length" "2")])
 
 (define_insn_and_split "*subhi3.sign_extend2_split"
   [(set (match_operand:HI 0 "register_operand"                          "=r")
   }
   [(set_attr "adjust_len" "plus")])
 
-(define_insn_and_split "*subsi3_zero_extend_split"
-  [(set (match_operand:SI 0 "register_operand"                          "=r")
-        (minus:SI (match_operand:SI 1 "register_operand"                 "0")
-                  (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))]
-  ""
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0)
-                   (minus:SI (match_dup 1)
-                             (zero_extend:SI (match_dup 2))))
-              (clobber (reg:CC REG_CC))])])
 
-(define_insn "*subsi3_zero_extend"
-  [(set (match_operand:SI 0 "register_operand"                          "=r")
-        (minus:SI (match_operand:SI 1 "register_operand"                 "0")
-                  (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))
-   (clobber (reg:CC REG_CC))]
-  "reload_completed"
-  "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
-  [(set_attr "length" "4")
-   ])
-
-(define_insn_and_split "*subsi3_zero_extend.hi_split"
-  [(set (match_operand:SI 0 "register_operand"                          "=r")
-        (minus:SI (match_operand:SI 1 "register_operand"                 "0")
-                  (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
-  ""
+;; "*subhi3.zero_extend.qi_split"
+;; "*subpsi3.zero_extend.qi_split"  "*subpsi3.zero_extend.hi_split"
+;; "*subsi3.zero_extend.qi_split"   "*subsi3.zero_extend.hi_split"
+;; "*subsi3.zero_extend.psi_split"
+(define_insn_and_split "*sub<HISI:mode>3.zero_extend.<QIPSI:mode>_split"
+  [(set (match_operand:HISI 0 "register_operand"             "=r")
+        (minus:HISI (match_operand:HISI 1 "register_operand"  "0")
+                    (zero_extend:HISI (match_operand:QIPSI 2 "register_operand" "r"))))]
+  "GET_MODE_SIZE (<HISI:MODE>mode) > GET_MODE_SIZE (<QIPSI:MODE>mode)"
   "#"
   "&& reload_completed"
   [(parallel [(set (match_dup 0)
-                   (minus:SI (match_dup 1)
-                             (zero_extend:SI (match_dup 2))))
+                   (minus:HISI (match_dup 1)
+                               (zero_extend:HISI (match_dup 2))))
               (clobber (reg:CC REG_CC))])])
 
-(define_insn "*subsi3_zero_extend.hi"
-  [(set (match_operand:SI 0 "register_operand"                          "=r")
-        (minus:SI (match_operand:SI 1 "register_operand"                 "0")
-                  (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))
+;; "*subhi3.zero_extend.qi"
+;; "*subpsi3.zero_extend.qi"  "*subpsi3.zero_extend.hi"
+;; "*subsi3.zero_extend.qi"   "*subsi3.zero_extend.hi"
+;; "*subsi3.zero_extend.psi"
+(define_insn "*sub<HISI:mode>3.zero_extend.<QIPSI:mode>"
+  [(set (match_operand:HISI 0 "register_operand"             "=r")
+        (minus:HISI (match_operand:HISI 1 "register_operand"  "0")
+                    (zero_extend:HISI (match_operand:QIPSI 2 "register_operand" "r"))))
    (clobber (reg:CC REG_CC))]
-  "reload_completed"
-  "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
-  [(set_attr "length" "4")])
+  "reload_completed
+   && GET_MODE_SIZE (<HISI:MODE>mode) > GET_MODE_SIZE (<QIPSI:MODE>mode)"
+  {
+    return avr_out_minus (operands);
+  }
+  [(set_attr "length" "<HISI:SIZE>")])
+
 
 ;******************************************************************************
 ; mul
diff --git a/gcc/testsuite/gcc.target/avr/torture/sub-zerox.c b/gcc/testsuite/gcc.target/avr/torture/sub-zerox.c
new file mode 100644 (file)
index 0000000..435fc70
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+typedef __UINT8_TYPE__ u8;
+typedef __UINT16_TYPE__ u16;
+typedef __uint24 u24;
+typedef __UINT32_TYPE__ u32;
+
+u32 sub_32_8  (u32 a, u8 b)  { return a - b; }
+u32 sub_32_16 (u32 a, u16 b) { return a - b; }
+u32 sub_32_24 (u32 a, u24 b) { return a - b; }
+
+u24 sub_24_8  (u24 a, u8 b)  { return a - b; }
+u24 sub_24_16 (u24 a, u16 b) { return a - b; }
+
+u16 sub_16_8  (u16 a, u8 b)  { return a - b; }