From: Michiel Derhaeg <[email protected]>

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]>
---
 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(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/pr127191-1.c
 create mode 100644 gcc/testsuite/gcc.target/arc/pr127191-2.c

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index d080143c45d..a406f793090 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -4840,7 +4840,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
@@ -5311,7 +5312,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)
@@ -5341,7 +5343,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
@@ -5389,7 +5392,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
@@ -5812,7 +5816,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 00000000000..b79ad2ae3fb
--- /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 00000000000..d5137af1450
--- /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;
+}
-- 
2.54.0

Reply via email to