------- Comment #5 from rguenth at gcc dot gnu dot org 2010-01-08 14:07 ------- I believe we can only either allow truncations or widenings in following SSA edges. Otherwise we miss that in
int l_2; for (l_2 = -1; l_2 != 0; l_2 = (unsigned char)(l_2 - 1)) g_3 |= l_2; the evolution is irregular in that the initial value is integer -1. That is what happens - we compute the evolution of the result of (unsigned char)(l_2 -1) as { 255, +, 255 }_1 but we may not use this evolution to derive that of the value assigned to l_2, (int) { 255, +, 255 }_1 because we cannot represent this. The correct evolution is -1, 254, 253 ..., 0 which isn't representable. Thus I think we need to either kill the conversion code completely or at least severely restrict it with sth like Index: gcc/tree-scalar-evolution.c =================================================================== --- gcc/tree-scalar-evolution.c (revision 155732) +++ gcc/tree-scalar-evolution.c (working copy) @@ -1161,9 +1161,19 @@ follow_ssa_edge_expr (struct loop *loop, { CASE_CONVERT: /* This assignment is under the form "a_1 = (cast) rhs. */ - res = follow_ssa_edge_expr (loop, at_stmt, TREE_OPERAND (expr, 0), - halting_phi, evolution_of_loop, limit); - *evolution_of_loop = chrec_convert (type, *evolution_of_loop, at_stmt); + rhs0 = TREE_OPERAND (expr, 0); + if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (rhs0)) + || TREE_CODE (*evolution_of_loop) != POLYNOMIAL_CHREC) + { + res = follow_ssa_edge_expr (loop, at_stmt, TREE_OPERAND (expr, 0), + halting_phi, evolution_of_loop, limit); + *evolution_of_loop = chrec_convert (type, *evolution_of_loop, at_stmt); + } + else + { + *evolution_of_loop = chrec_dont_know; + res = t_false; + } break; case INTEGER_CST: @@ -1219,14 +1229,25 @@ follow_ssa_edge_in_rhs (struct loop *loo enum tree_code code = gimple_assign_rhs_code (stmt); tree type = gimple_expr_type (stmt), rhs1, rhs2; t_bool res; + tree name; switch (code) { CASE_CONVERT: /* This assignment is under the form "a_1 = (cast) rhs. */ - res = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt), - halting_phi, evolution_of_loop, limit); - *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt); + name = gimple_assign_rhs1 (stmt); + if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (name)) + || TREE_CODE (*evolution_of_loop) != POLYNOMIAL_CHREC) + { + res = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt), + halting_phi, evolution_of_loop, limit); + *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt); + } + else + { + *evolution_of_loop = chrec_dont_know; + res = t_false; + } break; case POINTER_PLUS_EXPR: @@ -1759,7 +1780,11 @@ interpret_rhs_expr (struct loop *loop, g CASE_CONVERT: chrec1 = analyze_scalar_evolution (loop, rhs1); - res = chrec_convert (type, chrec1, at_stmt); + if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (rhs1)) + || TREE_CODE (chrec1) != POLYNOMIAL_CHREC) + res = chrec_convert (type, chrec1, at_stmt); + else + res = chrec_dont_know; break; default: Sebastian - any better idea? This will at least regress FAIL: gcc.dg/tree-ssa/scev-cast.c scan-tree-dump-times optimized "= \(unsigned char\)" 1 FAIL: gcc.dg/tree-ssa/scev-cast.c scan-tree-dump-times optimized "= \(char\)" 1 because we cannot distinguish the really critical cases from ok ones. The patch in comment #4 just makes the issue latent again. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42512