Commit dc1d6150 by Torbjorn Granlund

(expand_divmod, case TRUNC_DIV_EXPR): Move some code

to avoid shifting by a too large count.

From-SVN: r11645
parent 6f334f44
...@@ -2855,10 +2855,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -2855,10 +2855,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
pre_shift = floor_log2 (d); pre_shift = floor_log2 (d);
if (rem_flag) if (rem_flag)
{ {
remainder = expand_binop (compute_mode, and_optab, op0, remainder =
GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1), expand_binop (compute_mode, and_optab, op0,
remainder, 1, GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
OPTAB_LIB_WIDEN); remainder, 1,
OPTAB_LIB_WIDEN);
if (remainder) if (remainder)
return gen_lowpart (mode, remainder); return gen_lowpart (mode, remainder);
} }
...@@ -2866,80 +2867,83 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -2866,80 +2867,83 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
build_int_2 (pre_shift, 0), build_int_2 (pre_shift, 0),
tquotient, 1); tquotient, 1);
} }
else if (d >= ((unsigned HOST_WIDE_INT) 1 << (size - 1)))
{
/* Most significant bit of divisor is set, emit a scc insn.
emit_store_flag needs to be passed a place for the
result. */
quotient = emit_store_flag (tquotient, GEU, op0, op1,
compute_mode, 1, 1);
if (quotient == 0)
goto fail1;
}
else if (size <= HOST_BITS_PER_WIDE_INT) else if (size <= HOST_BITS_PER_WIDE_INT)
{ {
/* Find a suitable multiplier and right shift count instead if (d >= ((unsigned HOST_WIDE_INT) 1 << (size - 1)))
of multiplying with D. */
mh = choose_multiplier (d, size, size,
&ml, &post_shift, &dummy);
/* If the suggested multiplier is more than SIZE bits, we
can do better for even divisors, using an initial right
shift. */
if (mh != 0 && (d & 1) == 0)
{
pre_shift = floor_log2 (d & -d);
mh = choose_multiplier (d >> pre_shift, size,
size - pre_shift,
&ml, &post_shift, &dummy);
if (mh)
abort ();
}
else
pre_shift = 0;
if (mh != 0)
{ {
rtx t1, t2, t3, t4; /* Most significant bit of divisor is set; emit an scc
insn. */
extra_cost = (shift_cost[post_shift - 1] quotient = emit_store_flag (tquotient, GEU, op0, op1,
+ shift_cost[1] + 2 * add_cost); compute_mode, 1, 1);
t1 = expand_mult_highpart (compute_mode, op0, ml, if (quotient == 0)
NULL_RTX, 1,
max_cost - extra_cost);
if (t1 == 0)
goto fail1; goto fail1;
t2 = force_operand (gen_rtx (MINUS, compute_mode,
op0, t1),
NULL_RTX);
t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
build_int_2 (1, 0), NULL_RTX, 1);
t4 = force_operand (gen_rtx (PLUS, compute_mode,
t1, t3),
NULL_RTX);
quotient = expand_shift (RSHIFT_EXPR, compute_mode, t4,
build_int_2 (post_shift - 1,
0),
tquotient, 1);
} }
else else
{ {
rtx t1, t2; /* Find a suitable multiplier and right shift count
instead of multiplying with D. */
t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0, mh = choose_multiplier (d, size, size,
build_int_2 (pre_shift, 0), &ml, &post_shift, &dummy);
NULL_RTX, 1);
extra_cost = (shift_cost[pre_shift] /* If the suggested multiplier is more than SIZE bits,
+ shift_cost[post_shift]); we can do better for even divisors, using an
t2 = expand_mult_highpart (compute_mode, t1, ml, initial right shift. */
NULL_RTX, 1, if (mh != 0 && (d & 1) == 0)
max_cost - extra_cost); {
if (t2 == 0) pre_shift = floor_log2 (d & -d);
goto fail1; mh = choose_multiplier (d >> pre_shift, size,
quotient = expand_shift (RSHIFT_EXPR, compute_mode, t2, size - pre_shift,
build_int_2 (post_shift, 0), &ml, &post_shift, &dummy);
tquotient, 1); if (mh)
abort ();
}
else
pre_shift = 0;
if (mh != 0)
{
rtx t1, t2, t3, t4;
extra_cost = (shift_cost[post_shift - 1]
+ shift_cost[1] + 2 * add_cost);
t1 = expand_mult_highpart (compute_mode, op0, ml,
NULL_RTX, 1,
max_cost - extra_cost);
if (t1 == 0)
goto fail1;
t2 = force_operand (gen_rtx (MINUS, compute_mode,
op0, t1),
NULL_RTX);
t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
build_int_2 (1, 0), NULL_RTX,1);
t4 = force_operand (gen_rtx (PLUS, compute_mode,
t1, t3),
NULL_RTX);
quotient =
expand_shift (RSHIFT_EXPR, compute_mode, t4,
build_int_2 (post_shift - 1, 0),
tquotient, 1);
}
else
{
rtx t1, t2;
t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
build_int_2 (pre_shift, 0),
NULL_RTX, 1);
extra_cost = (shift_cost[pre_shift]
+ shift_cost[post_shift]);
t2 = expand_mult_highpart (compute_mode, t1, ml,
NULL_RTX, 1,
max_cost - extra_cost);
if (t2 == 0)
goto fail1;
quotient =
expand_shift (RSHIFT_EXPR, compute_mode, t2,
build_int_2 (post_shift, 0),
tquotient, 1);
}
} }
} }
else /* Too wide mode to use tricky code */ else /* Too wide mode to use tricky code */
......
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