https://gcc.gnu.org/g:76dad9582058739e3e5f6d4db10c3c2e4de27a32
commit r17-4384-g76dad9582058739e3e5f6d4db10c3c2e4de27a32 Author: Michiel Derhaeg <[email protected]> Date: Thu Sep 17 11:45:25 2026 +0300 arc: Add missing CC clobbers [PR127191] This is a similar issue as PR120375. doloop_end, loop_end, dbnz, flag, and kflag all write the condition codes without declaring it. Since r16-3301-g724d88900b7a moved aarch64-cc-fusion into late-combine, GCC exploits that and keeps condition codes live across these insns, producing wrong code. If a loop fails to resolve to a hardware loop, doloop_end and loop_end fall back to instructions that clobber CC. This needs to be declared on the pattern itself or it will not be taken into account. This fixes gcc.c-torture/execute/pr68185.c for ARC60x and ARC700. dbnz is wrong in the same way as (do)loop_end but I didn't succeed in creating a reproducer for it. flag and kflag write STATUS32, which holds the condition codes. Since the cc-fusion move they can cause unintended clobbers too. PR target/127191 gcc/ChangeLog: * config/arc/arc.md (doloop_end): Clobber CC. (loop_end): Likewise. (dbnz): Likewise. (flag): Likewise. (kflag): Likewise. gcc/testsuite/ChangeLog: * gcc.target/arc/pr127191-1.c: New test. * gcc.target/arc/pr127191-2.c: New test. Signed-off-by: Michiel Derhaeg <[email protected]> Diff: --- gcc/config/arc/arc.md | 15 ++++++---- gcc/testsuite/gcc.target/arc/pr127191-1.c | 30 +++++++++++++++++++ gcc/testsuite/gcc.target/arc/pr127191-2.c | 50 +++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index e0f132118997..fb905cfef058 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -4672,7 +4672,8 @@ archs4x, archs4xd" (define_insn "flag" [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")] - VUNSPEC_ARC_FLAG)] + VUNSPEC_ARC_FLAG) + (clobber (reg:CC CC_REG))] "" "@ flag%?\\t%0 @@ -5136,7 +5137,8 @@ archs4x, archs4xd" (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) (unspec:SI [(const_int 0)] UNSPEC_ARC_LP) - (clobber (match_dup 2))])] + (clobber (match_dup 2)) + (clobber (reg:CC CC_REG))])] "" { if (GET_MODE (operands[0]) != SImode) @@ -5166,7 +5168,8 @@ archs4x, archs4xd" (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) (unspec:SI [(const_int 0)] UNSPEC_ARC_LP) - (clobber (match_scratch:SI 2 "=X,&r"))] + (clobber (match_scratch:SI 2 "=X,&r")) + (clobber (reg:CC CC_REG))] "" "@ ; ZOL_END, begins @%l1 @@ -5213,7 +5216,8 @@ archs4x, archs4xd" (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) - (clobber (match_scratch:SI 2 "=X,r"))] + (clobber (match_scratch:SI 2 "=X,r")) + (clobber (reg:CC CC_REG))] "TARGET_DBNZ" "@ dbnz%*\\t%0,%l1 @@ -5625,7 +5629,8 @@ archs4x, archs4xd" (define_insn "kflag" [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")] - VUNSPEC_ARC_KFLAG)] + VUNSPEC_ARC_KFLAG) + (clobber (reg:CC CC_REG))] "TARGET_V2" "@ kflag%?\\t%0 diff --git a/gcc/testsuite/gcc.target/arc/pr127191-1.c b/gcc/testsuite/gcc.target/arc/pr127191-1.c new file mode 100644 index 000000000000..b79ad2ae3fbe --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/pr127191-1.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +/* Verifies that the potential CC clobber is taken into account when expanding + doloop_end but this fails to resolve into a hardware loop. */ + +int d = 1, e, f, o, w = 1, q, t; + +int +main (void) +{ + int g = 0; + + for (; d; d--) + { + while (o) + while (e) + ; + + g = t ? g : w; + f = g; + if (g) + q = 1; + } + + if (q != 1) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/arc/pr127191-2.c b/gcc/testsuite/gcc.target/arc/pr127191-2.c new file mode 100644 index 000000000000..d5137af14508 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/pr127191-2.c @@ -0,0 +1,50 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int q, sink; + +int __attribute__ ((noipa)) +flag_clobbers_cc (int a, int b, int *p) +{ + int s = a | b; + + *p = s; + __builtin_arc_flag (0); + if (s == 0) + q = 1; + + return s; +} + +#if defined (__ARCEM__) || defined (__ARCHS__) +int r; + +int __attribute__ ((noipa)) +kflag_clobbers_cc (int a, int b, int *p) +{ + int s = a | b; + + *p = s; + __builtin_arc_kflag (0); + if (s == 0) + r = 1; + + return s; +} +#endif + +int +main (void) +{ + flag_clobbers_cc (0, 0, &sink); + if (q != 1) + __builtin_abort (); + +#if defined (__ARCEM__) || defined (__ARCHS__) + kflag_clobbers_cc (0, 0, &sink); + if (r != 1) + __builtin_abort (); +#endif + + return 0; +}
