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 <pola...@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