A right shift of 31 will become 0 or 1, this can be checked for
treg_set_expr_not_const01 to avoid matching addc_t_r as this
can expand to a 3 insn sequence instead.
This improves tests 023 to 026 from gcc.target/sh/pr54236-2.c, e.g.:
test_023:
shll    r5
mov     #0,r1
mov     r4,r0
rts
addc    r1,r0

With this change:
test_023:
shll    r5
movt    r0
rts
add     r4,r0

We noticed this while evaluating a patch to improve how we handle
selecting between two constants based on the output of a LT/GE 0
test.

gcc/ChangeLog:
        * config/sh/predicates.md
        (treg_set_expr_not_const01): call sh_recog_treg_set_expr_not_01
        * config/sh/sh-protos.h
        (sh_recog_treg_set_expr_not_01): New function
        config/sh/sh.cc (sh_recog_treg_set_expr_not_01): Likewise

gcc/testsuite/ChangeLog:
        * gcc.target/sh/pr54236-2.c: Fix comments and expected output
---
 gcc/config/sh/predicates.md             |  4 +---
 gcc/config/sh/sh-protos.h               |  1 +
 gcc/config/sh/sh.cc                     | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/sh/pr54236-2.c | 14 +++++++-------
 4 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index 7349c97a2b5..e67ec8a2320 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -630,9 +630,7 @@
 ;; Same as treg_set_expr but disallow constants 0 and 1 which can be loaded
 ;; into the T bit.
 (define_predicate "treg_set_expr_not_const01"
-  (and (match_test "op != const0_rtx")
-       (match_test "op != const1_rtx")
-       (match_operand 0 "treg_set_expr")))
+  (match_test "sh_recog_treg_set_expr_not_01 (op, mode)"))
 
 ;; A predicate describing the T bit register in any form.
 (define_predicate "t_reg_operand"
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index c8cc19f4dc7..e78b6697a2b 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -261,6 +261,7 @@ extern rtx_insn* sh_peephole_emit_move_insn (rtx dst, rtx 
src);
 
 extern bool sh_in_recog_treg_set_expr (void);
 extern bool sh_recog_treg_set_expr (rtx op, machine_mode mode);
+extern bool sh_recog_treg_set_expr_not_01 (rtx op, machine_mode mode);
 
 /* Result value of sh_split_treg_set_expr.  Contains the first insn emitted
    and the optional trailing nott insn.  */
diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
index 1bc34e0a3e3..09e4ff77c20 100644
--- a/gcc/config/sh/sh.cc
+++ b/gcc/config/sh/sh.cc
@@ -12348,6 +12348,23 @@ sh_recog_treg_set_expr (rtx op, machine_mode mode)
   return result >= 0;
 }
 
+/* Return TRUE if OP is an expression for which there is a pattern to
+   set the T bit unless the expression is trivially loadable into
+   the T bit, FALSE otherwise.  */
+bool
+sh_recog_treg_set_expr_not_01 (rtx op, machine_mode mode)
+{
+  if (op == const0_rtx || op == const1_rtx)
+    return false;
+
+  /* A right shift of 31 will return 0 or 1.  */
+  if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT)
+      && INTVAL (XEXP (op, 1)) == 31)
+    return false;
+
+  return sh_recog_treg_set_expr (op, mode);
+}
+
 /* Returns true when recog of a 'treg_set_expr' is currently in progress.
    This can be used as a condition for insn/split patterns to allow certain
    T bit setting patters only to be matched as sub expressions of other
diff --git a/gcc/testsuite/gcc.target/sh/pr54236-2.c 
b/gcc/testsuite/gcc.target/sh/pr54236-2.c
index 1e2f3bbcb56..78befe43770 100644
--- a/gcc/testsuite/gcc.target/sh/pr54236-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr54236-2.c
@@ -4,10 +4,10 @@
 /* { dg-do compile }  */
 /* { dg-options "-O1" } */
 
-/* { dg-final { scan-assembler-times "addc" 36 } } */
+/* { dg-final { scan-assembler-times "addc" 32 } } */
 /* { dg-final { scan-assembler-times "shll" 14 } } */
-/* { dg-final { scan-assembler-times "add\tr" 12 } } */
-/* { dg-final { scan-assembler-not "movt" } } */
+/* { dg-final { scan-assembler-times "add\tr" 16 } } */
+/* { dg-final { scan-assembler-times "movt" 4 } } */
 
 /* { dg-final { scan-assembler-times "add\t#1" 1 } } */
 
@@ -184,28 +184,28 @@ test_022 (int a, int b, int c, int d)
 int
 test_023 (int a, int b, int c, int d)
 {
-  // 1x shll, 1x addc
+  // 1x shll, 1x add
   return a + ((b >> 31) & 1);
 }
 
 int
 test_024 (int a, int b, int c, int d)
 {
-  // 1x shll, 1x addc
+  // 1x shll, 1x add
   return ((b >> 31) & 1) + a;
 }
 
 int
 test_025 (int a, int b, int c, int d)
 {
-  // 1x shll, 1x addc
+  // 1x shll, 1x add
   return ((a >> 31) & 1) + a;
 }
 
 int
 test_026 (int a, int b, int c, int d)
 {
-  // 1x shll, 1x addc
+  // 1x shll, 1x add
   return a + ((a >> 31) & 1);
 }
 
-- 
2.47.0

Reply via email to