diff options
Diffstat (limited to 'gcc/predict.c')
-rw-r--r-- | gcc/predict.c | 81 |
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; |