Commit ecd4f20a by Marek Polacek Committed by Marek Polacek

re PR tree-optimization/56478 (ICE: Floating point exception in tree_estimate_probability)

PR tree-optimization/56478
* predict.c (is_comparison_with_loop_invariant_p): Change the 
type of loop_step to tree.
(predict_loops): Adjust.
(predict_iv_comparison): Perform the computations on double_ints.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>

From-SVN: r196547
parent 64366d35
2013-03-08 Marek Polacek <polacek@redhat.com>
Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/56478
* predict.c (is_comparison_with_loop_invariant_p): Change the
type of loop_step to tree.
(predict_loops): Adjust.
(predict_iv_comparison): Perform the computations on double_ints.
2013-03-08 Richard Biener <rguenther@suse.de> 2013-03-08 Richard Biener <rguenther@suse.de>
PR tree-optimization/56570 PR tree-optimization/56570
......
...@@ -1028,13 +1028,13 @@ static bool ...@@ -1028,13 +1028,13 @@ static bool
is_comparison_with_loop_invariant_p (gimple stmt, struct loop *loop, is_comparison_with_loop_invariant_p (gimple stmt, struct loop *loop,
tree *loop_invariant, tree *loop_invariant,
enum tree_code *compare_code, enum tree_code *compare_code,
int *loop_step, tree *loop_step,
tree *loop_iv_base) tree *loop_iv_base)
{ {
tree op0, op1, bound, base; tree op0, op1, bound, base;
affine_iv iv0, iv1; affine_iv iv0, iv1;
enum tree_code code; enum tree_code code;
int step; tree step;
code = gimple_cond_code (stmt); code = gimple_cond_code (stmt);
*loop_invariant = NULL; *loop_invariant = NULL;
...@@ -1077,7 +1077,7 @@ is_comparison_with_loop_invariant_p (gimple stmt, struct loop *loop, ...@@ -1077,7 +1077,7 @@ is_comparison_with_loop_invariant_p (gimple stmt, struct loop *loop,
bound = iv0.base; bound = iv0.base;
base = iv1.base; base = iv1.base;
if (host_integerp (iv1.step, 0)) if (host_integerp (iv1.step, 0))
step = tree_low_cst (iv1.step, 0); step = iv1.step;
else else
return false; return false;
} }
...@@ -1086,7 +1086,7 @@ is_comparison_with_loop_invariant_p (gimple stmt, struct loop *loop, ...@@ -1086,7 +1086,7 @@ is_comparison_with_loop_invariant_p (gimple stmt, struct loop *loop,
bound = iv1.base; bound = iv1.base;
base = iv0.base; base = iv0.base;
if (host_integerp (iv0.step, 0)) if (host_integerp (iv0.step, 0))
step = tree_low_cst (iv0.step, 0); step = iv0.step;
else else
return false; return false;
} }
...@@ -1178,7 +1178,7 @@ predict_iv_comparison (struct loop *loop, basic_block bb, ...@@ -1178,7 +1178,7 @@ predict_iv_comparison (struct loop *loop, basic_block bb,
gimple stmt; gimple stmt;
tree compare_var, compare_base; tree compare_var, compare_base;
enum tree_code compare_code; enum tree_code compare_code;
int compare_step; tree compare_step_var;
edge then_edge; edge then_edge;
edge_iterator ei; edge_iterator ei;
...@@ -1192,7 +1192,7 @@ predict_iv_comparison (struct loop *loop, basic_block bb, ...@@ -1192,7 +1192,7 @@ predict_iv_comparison (struct loop *loop, basic_block bb,
return; return;
if (!is_comparison_with_loop_invariant_p (stmt, loop, &compare_var, if (!is_comparison_with_loop_invariant_p (stmt, loop, &compare_var,
&compare_code, &compare_code,
&compare_step, &compare_step_var,
&compare_base)) &compare_base))
return; return;
...@@ -1224,34 +1224,78 @@ predict_iv_comparison (struct loop *loop, basic_block bb, ...@@ -1224,34 +1224,78 @@ predict_iv_comparison (struct loop *loop, basic_block bb,
&& host_integerp (compare_base, 0)) && host_integerp (compare_base, 0))
{ {
int probability; int probability;
HOST_WIDE_INT compare_count; bool of, overflow = false;
HOST_WIDE_INT loop_bound = tree_low_cst (loop_bound_var, 0); double_int mod, compare_count, tem, loop_count;
HOST_WIDE_INT compare_bound = tree_low_cst (compare_var, 0);
HOST_WIDE_INT base = tree_low_cst (compare_base, 0); double_int loop_bound = tree_to_double_int (loop_bound_var);
HOST_WIDE_INT loop_count = (loop_bound - base) / compare_step; double_int compare_bound = tree_to_double_int (compare_var);
double_int base = tree_to_double_int (compare_base);
if ((compare_step > 0) double_int compare_step = tree_to_double_int (compare_step_var);
/* (loop_bound - base) / compare_step */
tem = loop_bound.sub_with_overflow (base, &of);
overflow |= of;
loop_count = tem.divmod_with_overflow (compare_step,
0, TRUNC_DIV_EXPR,
&mod, &of);
overflow |= of;
if ((!compare_step.is_negative ())
^ (compare_code == LT_EXPR || compare_code == LE_EXPR)) ^ (compare_code == LT_EXPR || compare_code == LE_EXPR))
compare_count = (loop_bound - compare_bound) / compare_step; {
/* (loop_bound - compare_bound) / compare_step */
tem = loop_bound.sub_with_overflow (compare_bound, &of);
overflow |= of;
compare_count = tem.divmod_with_overflow (compare_step,
0, TRUNC_DIV_EXPR,
&mod, &of);
overflow |= of;
}
else else
compare_count = (compare_bound - base) / compare_step; {
/* (compare_bound - base) / compare_step */
tem = compare_bound.sub_with_overflow (base, &of);
overflow |= of;
compare_count = tem.divmod_with_overflow (compare_step,
0, TRUNC_DIV_EXPR,
&mod, &of);
overflow |= of;
}
if (compare_code == LE_EXPR || compare_code == GE_EXPR) if (compare_code == LE_EXPR || compare_code == GE_EXPR)
compare_count ++; ++compare_count;
if (loop_bound_code == LE_EXPR || loop_bound_code == GE_EXPR) if (loop_bound_code == LE_EXPR || loop_bound_code == GE_EXPR)
loop_count ++; ++loop_count;
if (compare_count < 0) if (compare_count.is_negative ())
compare_count = 0; compare_count = double_int_zero;
if (loop_count < 0) if (loop_count.is_negative ())
loop_count = 0; loop_count = double_int_zero;
if (loop_count.is_zero ())
if (loop_count == 0)
probability = 0; probability = 0;
else if (compare_count > loop_count) else if (compare_count.scmp (loop_count) == 1)
probability = REG_BR_PROB_BASE; probability = REG_BR_PROB_BASE;
else else
probability = (double) REG_BR_PROB_BASE * compare_count / loop_count; {
predict_edge (then_edge, PRED_LOOP_IV_COMPARE, probability); /* If loop_count is too big, such that REG_BR_PROB_BASE * loop_count
could overflow, shift both loop_count and compare_count right
a bit so that it doesn't overflow. Note both counts are known not
to be negative at this point. */
int clz_bits = clz_hwi (loop_count.high);
gcc_assert (REG_BR_PROB_BASE < 32768);
if (clz_bits < 16)
{
loop_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
compare_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
}
tem = compare_count.mul_with_sign (double_int::from_shwi
(REG_BR_PROB_BASE), true, &of);
gcc_assert (!of);
tem = tem.divmod (loop_count, true, TRUNC_DIV_EXPR, &mod);
probability = tem.to_uhwi ();
}
if (!overflow)
predict_edge (then_edge, PRED_LOOP_IV_COMPARE, probability);
return; return;
} }
...@@ -1402,7 +1446,7 @@ predict_loops (void) ...@@ -1402,7 +1446,7 @@ predict_loops (void)
edge ex; edge ex;
struct nb_iter_bound *nb_iter; struct nb_iter_bound *nb_iter;
enum tree_code loop_bound_code = ERROR_MARK; enum tree_code loop_bound_code = ERROR_MARK;
int loop_bound_step = 0; tree loop_bound_step = NULL;
tree loop_bound_var = NULL; tree loop_bound_var = NULL;
tree loop_iv_base = NULL; tree loop_iv_base = NULL;
gimple stmt = NULL; gimple stmt = NULL;
...@@ -1549,7 +1593,7 @@ predict_loops (void) ...@@ -1549,7 +1593,7 @@ predict_loops (void)
if (loop_bound_var) if (loop_bound_var)
predict_iv_comparison (loop, bb, loop_bound_var, loop_iv_base, predict_iv_comparison (loop, bb, loop_bound_var, loop_iv_base,
loop_bound_code, loop_bound_code,
loop_bound_step); tree_low_cst (loop_bound_step, 0));
} }
/* Free basic blocks from get_loop_body. */ /* Free basic blocks from get_loop_body. */
......
2013-03-08 Marek Polacek <polacek@redhat.com>
PR tree-optimization/56478
* gcc.dg/torture/pr56478.c: New test.
2013-03-08 Kai Tietz <ktietz@redhat.com> 2013-03-08 Kai Tietz <ktietz@redhat.com>
* gcc.c-torture/execute/builtins/builtins.exp: Add for mingw * gcc.c-torture/execute/builtins/builtins.exp: Add for mingw
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment