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;
+}

Reply via email to