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