Hi!
doloop_condition_get computes cmp in several places, and in one of them
wants to fail if the condition inside of it isn't NE against const0_rtx.
The problem with that is that nothing checked what cmp is yet,
/* Check for (set (pc) (if_then_else (condition)
(label_ref (label))
(pc))). */
if (GET_CODE (cmp) != SET
|| SET_DEST (cmp) != pc_rtx
|| GET_CODE (SET_SRC (cmp)) != IF_THEN_ELSE
|| GET_CODE (XEXP (SET_SRC (cmp), 1)) != LABEL_REF
|| XEXP (SET_SRC (cmp), 2) != pc_rtx)
return 0;
is checked only a couple of lines later.
To fix this, either we can use the following patch which guards the
early check with the necessary subset of the later check, or we could
for
if (GET_CODE (cmp) != SET || GET_CODE (SET_SRC (cmp)) != IF_THEN_ELSE)
return 0;
before cond = XEXP (SET_SRC (cmp), 0);,
or set some bool flag and only verify this requirement if the bool flag
is true after the later check.
Any preferences? The following has been successfully bootstrapped/regtested
on powerpc64le-linux.
2017-03-21 Jakub Jelinek <[email protected]>
PR rtl-optimization/80112
* loop-doloop.c (doloop_condition_get): Don't check condition
if cmp isn't SET with IF_THEN_ELSE src.
* gcc.dg/pr80112.c: New test.
--- gcc/loop-doloop.c.jj 2017-01-16 22:34:03.000000000 +0100
+++ gcc/loop-doloop.c 2017-03-21 11:57:58.000000000 +0100
@@ -153,10 +153,13 @@ doloop_condition_get (rtx_insn *doloop_p
}
else
inc = PATTERN (prev_insn);
- /* We expect the condition to be of the form (reg != 0) */
- cond = XEXP (SET_SRC (cmp), 0);
- if (GET_CODE (cond) != NE || XEXP (cond, 1) != const0_rtx)
- return 0;
+ if (GET_CODE (cmp) == SET && GET_CODE (SET_SRC (cmp)) == IF_THEN_ELSE)
+ {
+ /* We expect the condition to be of the form (reg != 0) */
+ cond = XEXP (SET_SRC (cmp), 0);
+ if (GET_CODE (cond) != NE || XEXP (cond, 1) != const0_rtx)
+ return 0;
+ }
}
else
{
--- gcc/testsuite/gcc.dg/pr80112.c.jj 2017-03-21 12:12:23.382509916 +0100
+++ gcc/testsuite/gcc.dg/pr80112.c 2017-03-21 12:11:18.000000000 +0100
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/80112 */
+/* { dg-do compile } */
+/* { dg-options "-Os -fmodulo-sched" } */
+
+void **a;
+
+void
+foo (int c)
+{
+ void *d[] = {&&e, &&f};
+ a = d;
+ switch (c)
+ {
+ f:
+ c = 9;
+ /* FALLTHRU */
+ case 9:
+ goto *a++;
+ e:;
+ }
+}
Jakub