In straight-line strength reduction, a candidate expression of the form "(type1)x + (type2)x", where type1 and type2 are compatible, results in two interpretations of the candidate with different result types. Because the types are compatible, the first interpretation can appear to be a legal basis for the second, resulting in an invalid replacement. The obvious solution is to keep a statement from serving as its own basis.
Bootstrapped and tested on powerpc64-unknown-linux-gnu with no new regressions, committed as obvious. Thanks, Bill -- Bill Schmidt, Ph.D. IBM Advance Toolchain for PowerLinux IBM Linux Technology Center wschm...@linux.vnet.ibm.com wschm...@us.ibm.com gcc: 2012-10-22 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR tree-optimization/55008 * gimple-ssa-strength-reduction.c (find_basis_for_candidate): Don't allow a candidate to be a basis for itself under another interpretation. gcc/testsuite: 2012-10-22 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR tree-optimization/55008 * gcc.dg/tree-ssa/pr55008.c: New test. Index: gcc/testsuite/gcc.dg/tree-ssa/pr55008.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/pr55008.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/pr55008.c (revision 0) @@ -0,0 +1,17 @@ +/* This used to fail to compile; see PR55008. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -w" } */ + +typedef unsigned long long T; + +void f(void) +{ + int a, *p; + + T b = 6309343725; + + if(*p ? (b = 1) : 0) + if(b - (a = b /= 0) ? : (a + b)) + while(1); +} + Index: gcc/gimple-ssa-strength-reduction.c =================================================================== --- gcc/gimple-ssa-strength-reduction.c (revision 192691) +++ gcc/gimple-ssa-strength-reduction.c (working copy) @@ -366,6 +366,7 @@ find_basis_for_candidate (slsr_cand_t c) slsr_cand_t one_basis = chain->cand; if (one_basis->kind != c->kind + || one_basis->cand_stmt == c->cand_stmt || !operand_equal_p (one_basis->stride, c->stride, 0) || !types_compatible_p (one_basis->cand_type, c->cand_type) || !dominated_by_p (CDI_DOMINATORS,