diff mbox series

committed: cris.md: Reinstate add/sub with extend

Message ID 202007052320.065NKCii029766@ignucius.se.axis.com
State New
Headers show
Series committed: cris.md: Reinstate add/sub with extend | expand

Commit Message

Hans-Peter Nilsson July 5, 2020, 11:20 p.m. UTC
When cleaning out the multitude of patterns with unknown
coverage, this one went the way of the bathwater.  It's use is
barely common enough to mark when diffing libgcc, and has a
minimal impact on performance-testsuites.  Anyway, reinstated
with a couple of test-cases.  It's suboptimal of gcc-core not to
make use of the SImode pattern when performing HImode; see the
FIXME (which is actually also reinstated).

This version uses match_operator, for continuity but will be
replaced with a version making use of iterators (like it does
for the mode).

gcc:
	* config/cris/cris.md ("*extopqihi", "*extop<mode>si<setnz>_swap")
	("*extop<mode>si<setnz>", "*addxqihi_swap"): Reinstate.

gcc/testsuite:
	* gcc.target/cris/pr93372-36.c, gcc.target/cris/pr93372-37.c,
	gcc.target/cris/pr93372-38.c: New tests.
---
 gcc/config/cris/cris.md                    | 83 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/cris/pr93372-36.c | 37 +++++++++++++
 gcc/testsuite/gcc.target/cris/pr93372-37.c | 26 ++++++++++
 gcc/testsuite/gcc.target/cris/pr93372-38.c | 30 +++++++++++
 4 files changed, 176 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/cris/pr93372-36.c
 create mode 100644 gcc/testsuite/gcc.target/cris/pr93372-37.c
 create mode 100644 gcc/testsuite/gcc.target/cris/pr93372-38.c
diff mbox series

Patch

diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 081041fa245..e700819d510 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -1108,6 +1108,89 @@  (define_insn "*sub<mode>3<setnz>"
   [(set_attr "slottable" "yes,yes,yes,yes,no,no")
    (set_attr "cc<ccnz>" "normal,normal,clobber,clobber,normal,normal")])
 
+;; Extend versions (zero/sign) of normal add/sub (no side-effects).
+
+;; QImode to HImode
+;; FIXME: GCC should widen.
+
+(define_insn "*extopqihi"
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
+	(match_operator:HI
+	 3 "cris_additive_operand_extend_operator"
+	 [(match_operand:HI 1 "register_operand" "0,0,0,r")
+	  (match_operator:HI
+	   4 "cris_extend_operator"
+	   [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
+   && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
+  "@
+   %x3%E4.%m4 %2,%0
+   %x3%E4.%m4 %2,%0
+   %x3%E4.%m4 %2,%0
+   %x3%E4.%m4 %2,%1,%0"
+  [(set_attr "slottable" "yes,yes,no,no")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*extop<mode>si<setnz>"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(match_operator:SI
+	 3 "cris_operand_extend_operator"
+	 [(match_operand:SI 1 "register_operand" "0,0,0,r")
+	  (match_operator:SI
+	   4 "cris_extend_operator"
+	   [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
+   && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
+   && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
+  "@
+   %x3%E4<m> %2,%0
+   %x3%E4<m> %2,%0
+   %x3%E4<m> %2,%0
+   %x3%E4<m> %2,%1,%0"
+  [(set_attr "slottable" "yes,yes,no,no")])
+
+;; We may have swapped operands for add or bound.
+;; For commutative operands, these are the canonical forms.
+
+;; QImode to HImode
+
+(define_insn "*addxqihi_swap"
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
+	(plus:HI
+	 (match_operator:HI
+	  3 "cris_extend_operator"
+	  [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
+	 (match_operand:HI 1 "register_operand" "0,0,0,r")))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "operands[1] != frame_pointer_rtx"
+  "@
+   add%e3.b %2,%0
+   add%e3.b %2,%0
+   add%e3.b %2,%0
+   add%e3.b %2,%1,%0"
+  [(set_attr "slottable" "yes,yes,no,no")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*extop<mode>si<setnz>_swap"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(match_operator:SI
+	 4 "cris_plus_or_bound_operator"
+	 [(match_operator:SI
+	   3 "cris_extend_operator"
+	   [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])
+	  (match_operand:SI 1 "register_operand" "0,0,0,r")]))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "(GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
+   && operands[1] != frame_pointer_rtx"
+  "@
+   %x4%E3<m> %2,%0
+   %x4%E3<m> %2,%0
+   %x4%E3<m> %2,%0
+   %x4%E3<m> %2,%1,%0"
+  [(set_attr "slottable" "yes,yes,no,no")])
+
 ;; This is the special case when we use what corresponds to the
 ;; instruction above in "casesi".  Do *not* change it to use the generic
 ;; pattern and "REG 15" as pc; I did that and it led to madness and
diff --git a/gcc/testsuite/gcc.target/cris/pr93372-36.c b/gcc/testsuite/gcc.target/cris/pr93372-36.c
new file mode 100644
index 00000000000..84fbdb7091d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/pr93372-36.c
@@ -0,0 +1,37 @@ 
+/* Check that we produce sign- and zero-extended additions and
+   subtractions, and that no (eliminable) test- or compare-instructions
+   are used. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not {\tcmp|\ttest|\tsub\.|\tadd\.|\tmovs} } } */
+/* { dg-final { scan-assembler "\tadds" } } */
+/* { dg-final { scan-assembler "\tsubs" } } */
+
+#ifndef t
+#define t signed char
+#define s _sc
+#endif
+
+#ifndef t2
+#define t2 int
+#endif
+
+#ifndef f
+#define f0(a, s) a ## s
+#define f(a, s) f0(a, s)
+#endif
+
+extern void g(int);
+
+t2 f(a, s) (t2 a, t *b, int *c)
+{
+  t2 d = a + *b;
+  *c = d == 0;
+  return d;
+}
+t2 f(b, s) (t2 a, t *b, int *c)
+{
+  t2 d = a - *b;
+  *c = d == 0;
+  return d;
+}
diff --git a/gcc/testsuite/gcc.target/cris/pr93372-37.c b/gcc/testsuite/gcc.target/cris/pr93372-37.c
new file mode 100644
index 00000000000..0c43d77fc72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/pr93372-37.c
@@ -0,0 +1,26 @@ 
+/* Check that we produce sign- and zero-extended additions and
+   subtractions, and that no (eliminable) test- or compare-instructions
+   are used. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not {\tcmp|\ttest|\tsub\.|\tadd\.|\tmovu|\tmovs} } } */
+/* { dg-final { scan-assembler-times "\tadds" 1 } } */
+/* { dg-final { scan-assembler-times "\tsubs" 1 } } */
+/* { dg-final { scan-assembler-times "\taddu" 2 } } */
+/* { dg-final { scan-assembler-times "\tsubu" 2 } } */
+
+#define t unsigned char
+#define s _uc
+#include "pr93372-36.c"
+
+#undef t
+#undef s
+#define t signed short int
+#define s _ss
+#include "pr93372-36.c"
+
+#undef t
+#undef s
+#define t unsigned short int
+#define s _us
+#include "pr93372-36.c"
diff --git a/gcc/testsuite/gcc.target/cris/pr93372-38.c b/gcc/testsuite/gcc.target/cris/pr93372-38.c
new file mode 100644
index 00000000000..c7cba3b4f15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/pr93372-38.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not {\tcmp|\tsub\.|\tadd\.|\tmovu|\tmovs} } } */
+/* { dg-final { scan-assembler-times "\ttest\.w" 4 } } */
+/* { dg-final { scan-assembler-times "\tadds" 1 } } */
+/* { dg-final { scan-assembler-times "\tsubs" 1 } } */
+/* { dg-final { scan-assembler-times "\taddu" 1 } } */
+/* { dg-final { scan-assembler-times "\tsubu" 1 } } */
+
+/* Check that we produce sign- and zero-extended additions and
+   subtractions, also for 8-bit to 16-bit results.  Note that we can't
+   eliminate compare insns, as the condition codes reflect the 32-bit
+   result.
+   This test-case is brittle, as with the presence of compare
+   instructions, there are several optimal instruction sequence, some of
+   which match the non-matcher patterns and do not contain the matching
+   patterns. */
+
+#define t unsigned char
+#define t2 unsigned short
+#define s _us
+#include "pr93372-36.c"
+
+#undef t
+#undef s
+#undef t2
+#define t signed char
+#define t2 signed short
+#define s _ss
+#include "pr93372-36.c"