aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-03-15 09:12:03 +0100
committerJakub Jelinek <jakub@redhat.com>2022-03-15 09:12:03 +0100
commita2645cd8fb33b36d737b310e26f4c47401305c7b (patch)
treef4f9ff1a7fd8a4b5e73f804393b4b6e5f435a148
parent373a2dc2be0089ae59b61202a6023458aaaf63d8 (diff)
downloadgcc-a2645cd8fb33b36d737b310e26f4c47401305c7b.zip
gcc-a2645cd8fb33b36d737b310e26f4c47401305c7b.tar.gz
gcc-a2645cd8fb33b36d737b310e26f4c47401305c7b.tar.bz2
ifcvt: Punt if not onlyjump_p for find_if_case_{1,2} [PR104814]
find_if_case_{1,2} implicitly assumes conditional jumps and rewrites them, so if they have extra side-effects or are say asm goto, things don't work well, either the side-effects are lost or we could ICE. In particular, the testcase below on s390x has there a doloop instruction that decrements a register in addition to testing it for non-zero and conditionally jumping based on that. The following patch fixes that by punting for !onlyjump_p case, i.e. if there are side-effects in the jump instruction or it isn't a plain PC setter. Also, it assumes BB_END (test_bb) will be always non-NULL, because basic blocks with 2 non-abnormal successor edges should always have some instruction at the end that determines which edge to take. 2022-03-15 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/104814 * ifcvt.cc (find_if_case_1, find_if_case_2): Punt if test_bb doesn't end with onlyjump_p. Assume BB_END (test_bb) is always non-NULL. * gcc.c-torture/execute/pr104814.c: New test.
-rw-r--r--gcc/ifcvt.cc14
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr104814.c30
2 files changed, 40 insertions, 4 deletions
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 6305621..22960a6 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -5251,14 +5251,17 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
if ((BB_END (then_bb)
&& JUMP_P (BB_END (then_bb))
&& CROSSING_JUMP_P (BB_END (then_bb)))
- || (BB_END (test_bb)
- && JUMP_P (BB_END (test_bb))
+ || (JUMP_P (BB_END (test_bb))
&& CROSSING_JUMP_P (BB_END (test_bb)))
|| (BB_END (else_bb)
&& JUMP_P (BB_END (else_bb))
&& CROSSING_JUMP_P (BB_END (else_bb))))
return FALSE;
+ /* Verify test_bb ends in a conditional jump with no other side-effects. */
+ if (!onlyjump_p (BB_END (test_bb)))
+ return FALSE;
+
/* THEN has one successor. */
if (!single_succ_p (then_bb))
return FALSE;
@@ -5372,14 +5375,17 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
if ((BB_END (then_bb)
&& JUMP_P (BB_END (then_bb))
&& CROSSING_JUMP_P (BB_END (then_bb)))
- || (BB_END (test_bb)
- && JUMP_P (BB_END (test_bb))
+ || (JUMP_P (BB_END (test_bb))
&& CROSSING_JUMP_P (BB_END (test_bb)))
|| (BB_END (else_bb)
&& JUMP_P (BB_END (else_bb))
&& CROSSING_JUMP_P (BB_END (else_bb))))
return FALSE;
+ /* Verify test_bb ends in a conditional jump with no other side-effects. */
+ if (!onlyjump_p (BB_END (test_bb)))
+ return FALSE;
+
/* ELSE has one successor. */
if (!single_succ_p (else_bb))
return FALSE;
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr104814.c b/gcc/testsuite/gcc.c-torture/execute/pr104814.c
new file mode 100644
index 0000000..7d4f8ab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr104814.c
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/104814 */
+
+short a = 0;
+static long b = 0;
+int c = 7;
+char d = 0;
+short *e = &a;
+long f = 0;
+
+unsigned long
+foo (unsigned long h, long j)
+{
+ return j == 0 ? h : h / j;
+}
+
+int
+main ()
+{
+ long k = f;
+ for (; c; --c)
+ {
+ for (int i = 0; i < 7; ++i)
+ ;
+ long m = foo (f, --b);
+ d = ((char) m | *e) <= 43165;
+ }
+ if (b != -7)
+ __builtin_abort ();
+ return 0;
+}