summaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c81
1 files changed, 32 insertions, 49 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index a847ec6f9d9..d8669e39327 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -1306,76 +1306,59 @@ predict_iv_comparison (struct loop *loop, basic_block bb,
&& tree_fits_shwi_p (compare_base))
{
int probability;
- bool of, overflow = false;
- double_int mod, compare_count, tem, loop_count;
-
- double_int loop_bound = tree_to_double_int (loop_bound_var);
- double_int compare_bound = tree_to_double_int (compare_var);
- double_int base = tree_to_double_int (compare_base);
- double_int compare_step = tree_to_double_int (compare_step_var);
+ bool overflow, overall_overflow = false;
+ widest_int compare_count, tem;
/* (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 ())
+ tem = wi::sub (wi::to_widest (loop_bound_var),
+ wi::to_widest (compare_base), SIGNED, &overflow);
+ overall_overflow |= overflow;
+ widest_int loop_count = wi::div_trunc (tem,
+ wi::to_widest (compare_step_var),
+ SIGNED, &overflow);
+ overall_overflow |= overflow;
+
+ if (!wi::neg_p (wi::to_widest (compare_step_var))
^ (compare_code == LT_EXPR || compare_code == LE_EXPR))
{
/* (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;
+ tem = wi::sub (wi::to_widest (loop_bound_var),
+ wi::to_widest (compare_var), SIGNED, &overflow);
+ overall_overflow |= overflow;
+ compare_count = wi::div_trunc (tem, wi::to_widest (compare_step_var),
+ SIGNED, &overflow);
+ overall_overflow |= overflow;
}
else
{
/* (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;
+ tem = wi::sub (wi::to_widest (compare_var),
+ wi::to_widest (compare_base), SIGNED, &overflow);
+ overall_overflow |= overflow;
+ compare_count = wi::div_trunc (tem, wi::to_widest (compare_step_var),
+ SIGNED, &overflow);
+ overall_overflow |= overflow;
}
if (compare_code == LE_EXPR || compare_code == GE_EXPR)
++compare_count;
if (loop_bound_code == LE_EXPR || loop_bound_code == GE_EXPR)
++loop_count;
- if (compare_count.is_negative ())
- compare_count = double_int_zero;
- if (loop_count.is_negative ())
- loop_count = double_int_zero;
- if (loop_count.is_zero ())
+ if (wi::neg_p (compare_count))
+ compare_count = 0;
+ if (wi::neg_p (loop_count))
+ loop_count = 0;
+ if (loop_count == 0)
probability = 0;
- else if (compare_count.scmp (loop_count) == 1)
+ else if (wi::cmps (compare_count, loop_count) == 1)
probability = REG_BR_PROB_BASE;
else
{
- /* 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);
+ tem = compare_count * REG_BR_PROB_BASE;
+ tem = wi::udiv_trunc (tem, loop_count);
probability = tem.to_uhwi ();
}
- if (!overflow)
+ if (!overall_overflow)
predict_edge (then_edge, PRED_LOOP_IV_COMPARE, probability);
return;