The following testcase ICEd because we were trying to negate "-9223372036854775808", which results in UB, since it's LLONG_MAX + 1. Then we got a SIGFPE on -LLONG_MIN / -1 So fixed by doing the arithmetics on trees, and in case we got an overflow, we bail out.
The hunk probability = (double) REG_BR_PROB_BASE * compare_count / loop_count; in there should be probably handled in the same way. But I'll handle that separately. In the first hunk, I did s/int/HOST_WIDE_INT/, because HWI is what tree_low_cst returns. For why that could be a problem, see the Jakub's comment in the PR. Regtested/bootstrapped on x86_64-linux, ok for trunk? 2013-02-28 Marek Polacek <pola...@redhat.com> PR tree-optimization/56478 * predict.c (is_comparison_with_loop_invariant_p): Change the type of step to HOST_WIDE_INT. (predict_iv_comparison): Do the computation on trees, return in case of an overflow. * gcc.dg/torture/pr56478.c: New test. --- gcc/predict.c.mp 2013-02-28 17:26:47.950247877 +0100 +++ gcc/predict.c 2013-02-28 17:26:56.855275792 +0100 @@ -1034,7 +1034,7 @@ is_comparison_with_loop_invariant_p (gim tree op0, op1, bound, base; affine_iv iv0, iv1; enum tree_code code; - int step; + HOST_WIDE_INT step; code = gimple_cond_code (stmt); *loop_invariant = NULL; @@ -1224,11 +1224,29 @@ predict_iv_comparison (struct loop *loop && host_integerp (compare_base, 0)) { int probability; + tree step_var, loop_count_var; HOST_WIDE_INT compare_count; HOST_WIDE_INT loop_bound = tree_low_cst (loop_bound_var, 0); HOST_WIDE_INT compare_bound = tree_low_cst (compare_var, 0); HOST_WIDE_INT base = tree_low_cst (compare_base, 0); - HOST_WIDE_INT loop_count = (loop_bound - base) / compare_step; + + /* We want to do the arithmetics on trees (and punt in + case of an overflow). */ + step_var = build_int_cst (NULL_TREE, compare_step); + gcc_assert (TREE_CODE (step_var) == INTEGER_CST); + + /* Compute (loop_bound - base) / compare_step. */ + loop_count_var + = int_const_binop (TRUNC_DIV_EXPR, + int_const_binop (MINUS_EXPR, + loop_bound_var, + compare_base), + step_var); + + if (TREE_OVERFLOW_P (loop_count_var)) + return; + + HOST_WIDE_INT loop_count = tree_low_cst (loop_count_var, 0); if ((compare_step > 0) ^ (compare_code == LT_EXPR || compare_code == LE_EXPR)) --- gcc/testsuite/gcc.dg/torture/pr56478.c.mp 2013-02-28 17:32:26.430308968 +0100 +++ gcc/testsuite/gcc.dg/torture/pr56478.c 2013-02-28 18:15:41.641379179 +0100 @@ -0,0 +1,12 @@ +/* PR tree-optimization/56478 */ +/* { dg-do compile } */ + +int a; + +void +foo () +{ + int b; + for (b = 0;; b++) + a = 0 < -__LONG_LONG_MAX__ - 1 - b ? : 0; +} Marek