https://gcc.gnu.org/g:e1b871032e08928a0a3fc5218ecf4ca96376bff8
commit r14-12724-ge1b871032e08928a0a3fc5218ecf4ca96376bff8 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 19481c07db6a..dbff2a805f32 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; +}
