https://gcc.gnu.org/g:eda5a15909c315f0a4a7e76ad083f5f16cf1aef9

commit r16-2028-geda5a15909c315f0a4a7e76ad083f5f16cf1aef9
Author: Raphael Moreira Zinsly <rzin...@ventanamicro.com>
Date:   Mon Jun 23 10:40:50 2025 -0300

    sh: Recognize >> 31 in treg_set_expr_not_const01
    
    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

Diff:
---
 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 7349c97a2b56..e67ec8a23202 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 c8cc19f4dc75..e78b6697a2b1 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 1bc34e0a3e39..09e4ff77c207 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 1e2f3bbcb56c..78befe437701 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);
 }

Reply via email to