This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix phiopt ICE in Factor conversion in COND_EXPR (PR tree-optimization/66949)
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Jeff Law <law at redhat dot com>
- Cc: Kugan <kugan dot vivekanandarajah at linaro dot org>
- Date: Tue, 8 Dec 2015 17:21:33 +0100
- Subject: [PATCH] Fix phiopt ICE in Factor conversion in COND_EXPR (PR tree-optimization/66949)
- Authentication-results: sourceware.org; auth=none
The following is a conservative fix for this PR. This is an ICE transpiring
in the new "Factor conversion in COND_EXPR" optimization added in r225722.
Before this optimization kicks in, we have
<bb 2>:
...
p1_32 = (short unsigned int) _20;
<bb 3>:
...
iftmp.0_18 = (short unsigned int) _20;
<bb 4>:
...
# iftmp.0_19 = PHI <iftmp.0_18(3), p1_32(2)>
after factor_out_conditional_conversion does its work, we end up with those two
def stmts removed and instead of the PHI we'll have
# _35 = PHI <_20(3), _20(2)>
iftmp.0_19 = (short unsigned int) _35;
That itself looks like a fine optimization, but after factor_out_conditional_conversion
there's
320 phis = phi_nodes (bb2);
321 phi = single_non_singleton_phi_for_edges (phis, e1, e2);
322 gcc_assert (phi);
and phis look like
b.2_38 = PHI <b.2_9(3), b.2_9(2)>
_35 = PHI <_20(3), _20(2)>
so single_non_singleton_phi_for_edges returns NULL and the subsequent assert triggers.
With this patch we won't ICE (and PRE should clean this up anyway), but I don't know,
maybe I should try harder to optimize even this problematical case (not sure how hard
it would be...)?
pr66949-2.c only ICEd on powerpc64le and I have verified that this patch fixes it too.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
2015-12-08 Marek Polacek <polacek@redhat.com>
PR tree-optimization/66949
* tree-ssa-phiopt.c (factor_out_conditional_conversion): Return false if
NEW_ARG0 and NEW_ARG1 are equal.
* gcc.dg/torture/pr66949-1.c: New test.
* gcc.dg/torture/pr66949-2.c: New test.
diff --git gcc/testsuite/gcc.dg/torture/pr66949-1.c gcc/testsuite/gcc.dg/torture/pr66949-1.c
index e69de29..1b765bc 100644
--- gcc/testsuite/gcc.dg/torture/pr66949-1.c
+++ gcc/testsuite/gcc.dg/torture/pr66949-1.c
@@ -0,0 +1,28 @@
+/* PR tree-optimization/66949 */
+/* { dg-do compile } */
+
+int a, *b = &a, c;
+
+unsigned short
+fn1 (unsigned short p1, unsigned int p2)
+{
+ return p2 > 1 || p1 >> p2 ? p1 : p1 << p2;
+}
+
+void
+fn2 ()
+{
+ int *d = &a;
+ for (a = 0; a < -1; a = 1)
+ ;
+ if (a < 0)
+ c = 0;
+ *b = fn1 (*d || c, *d);
+}
+
+int
+main ()
+{
+ fn2 ();
+ return 0;
+}
diff --git gcc/testsuite/gcc.dg/torture/pr66949-2.c gcc/testsuite/gcc.dg/torture/pr66949-2.c
index e69de29..e6250a3 100644
--- gcc/testsuite/gcc.dg/torture/pr66949-2.c
+++ gcc/testsuite/gcc.dg/torture/pr66949-2.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/66949 */
+/* { dg-do compile } */
+
+char a;
+int b, c, d;
+extern int fn2 (void);
+
+short
+fn1 (short p1, short p2)
+{
+ return p2 == 0 ? p1 : p1 / p2;
+}
+
+int
+main (void)
+{
+ char e = 1;
+ int f = 7;
+ c = a >> f;
+ b = fn1 (c, 0 < d <= e && fn2 ());
+
+ return 0;
+}
diff --git gcc/tree-ssa-phiopt.c gcc/tree-ssa-phiopt.c
index 344cd2f..caac5d5 100644
--- gcc/tree-ssa-phiopt.c
+++ gcc/tree-ssa-phiopt.c
@@ -477,6 +477,11 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
return false;
}
+ /* If we were to continue, we'd create a PHI with same arguments for edges
+ E0 and E1. That could get us in trouble later, so punt. */
+ if (operand_equal_for_phi_arg_p (new_arg0, new_arg1))
+ return false;
+
/* If arg0/arg1 have > 1 use, then this transformation actually increases
the number of expressions evaluated at runtime. */
if (!has_single_use (arg0)
Marek