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

commit r16-9226-gc19754043d6eca2261d7a0dbf92a93c2c6a60153
Author: Oleg Endo <[email protected]>
Date:   Sat Jul 4 01:22:41 2026 +0900

    SH: Fix T bit set expressions of addc and subc insns.
    
    gcc/ChangeLog:
    
            PR target/67459
            PR target/122948
            * config/sh/sh.md (addc): Fix T bit set expression.
            (subc): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            PR target/67459
            PR target/122948
            * gcc.target/sh/pr122948.c: New test.

Diff:
---
 gcc/config/sh/sh.md                    | 11 ++++--
 gcc/testsuite/gcc.target/sh/pr122948.c | 67 ++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 07f8968b0f57..1b181b93b14f 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -1563,7 +1563,10 @@
                          (match_operand:SI 2 "arith_reg_operand" "r"))
                 (reg:SI T_REG)))
    (set (reg:SI T_REG)
-       (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
+       (gtu:SI (plus:DI (plus:DI (zero_extend:DI (match_dup 1))
+                                 (zero_extend:DI (match_dup 2)))
+                        (zero_extend:DI (reg:SI T_REG)))
+               (const_int 4294967295)))]
   "TARGET_SH1"
   "addc        %2,%0"
   [(set_attr "type" "arith")])
@@ -1955,9 +1958,9 @@
                            (match_operand:SI 2 "arith_reg_operand" "r"))
                  (reg:SI T_REG)))
    (set (reg:SI T_REG)
-       (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
-                         (reg:SI T_REG))
-               (match_dup 1)))]
+       (gtu:SI (plus:DI (zero_extend:DI (match_dup 2))
+                        (zero_extend:DI (reg:SI T_REG)))
+               (zero_extend:DI (match_dup 1))))]
   "TARGET_SH1"
   "subc        %2,%0"
   [(set_attr "type" "arith")])
diff --git a/gcc/testsuite/gcc.target/sh/pr122948.c 
b/gcc/testsuite/gcc.target/sh/pr122948.c
new file mode 100644
index 000000000000..91732b67d290
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr122948.c
@@ -0,0 +1,67 @@
+/* Verify that the T bit (carry/borrow) set expression of the subc insn is
+   correct.  */
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+extern void abort (void);
+
+__attribute__ ((noipa)) unsigned int
+foo (unsigned int a, unsigned int b)
+{
+  if (b - a - 1 <= b)
+    a = 0;
+  return a;
+}
+
+__attribute__ ((noipa)) unsigned int
+bar (unsigned int a, unsigned int b)
+{
+  return (b - a - 1) > b;
+}
+
+__attribute__ ((noipa)) unsigned int
+baz (unsigned int a, unsigned int b)
+{
+  return (a + b + 1) <= a;
+}
+
+int
+main (void)
+{
+  if (foo (0xffffffff, 0x4e92c833) != 0)
+    abort ();
+
+  if (bar (0xffffffff, 0x4e92c833) != 0)
+    abort ();
+
+  /* b - a - 1 wraps (borrow) whenever a + 1 > b (unsigned).  */
+  if (bar (5, 3) != 1)
+    abort ();
+
+  if (bar (0, 0) != 1)
+    abort ();
+
+  if (bar (0, 5) != 0)
+    abort ();
+
+  /* addc carry-out: (a + b + 1) <= a.  */
+  /* 0xffffffff + 0 + 1 wraps to 0.  */
+  if (baz (0xffffffff, 0) != 1)
+    abort ();
+
+  if (baz (0xffffffff, 0xffffffff) != 1)
+    abort ();
+
+  /* wraps to 0.  */
+  if (baz (0xfffffffe, 1) != 1)
+    abort ();
+
+  /* 1 <= 0 is false.  */
+  if (baz (0, 0) != 0)
+    abort ();
+
+  if (baz (1, 2) != 0)
+    abort ();
+
+  return 0;
+}

Reply via email to