diff mbox series

[avr,applied] Tidy up subtract + zero_extend insns

Message ID 8081850b-ee2b-4837-9ebd-6cd7b3116810@gjlay.de
State New
Headers show
Series [avr,applied] Tidy up subtract + zero_extend insns | expand

Commit Message

Georg-Johann Lay July 11, 2024, 11:06 a.m. UTC
There are currently five insns and five splits that handle
subtraction where the subtrahend is zero-extended to the mode
of the minuend.

This patch represents them as one insn (and one split) using
mode iterators.

Applied as obvious.

Johann

--

AVR: Tidy up subtract-and-zero_extend insns.

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.
diff mbox series

Patch

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index dc23cfbf461..6e02161759c 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -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*);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index d299fceb782..4a7cbd0e7bc 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -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)
 	{
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 2783b8c986f..8c3e55a91ee 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -2030,47 +2030,6 @@  (define_insn "*subpsi3"
   "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")
@@ -2154,26 +2113,6 @@  (define_insn "*sub<mode>3"
   }
   [(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")
@@ -2231,48 +2170,39 @@  (define_insn "*sub<mode>3"
   }
   [(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
index 00000000000..435fc7065f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/sub-zerox.c
@@ -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; }