Commit 69f61901 by Richard Kenner

(expand_divmod, case ROUND_DIV_EXPR): Implement.

From-SVN: r8442
parent 923f781d
...@@ -2608,13 +2608,13 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -2608,13 +2608,13 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
Second comes a switch statement with code specific for each rounding mode. Second comes a switch statement with code specific for each rounding mode.
For some special operands this code emits all RTL for the desired For some special operands this code emits all RTL for the desired
operation, for other cases, it generates a quotient and stores it in operation, for other cases, it generates only a quotient and stores it in
QUOTIENT. The case for trunc division/remainder might leave quotient = 0, QUOTIENT. The case for trunc division/remainder might leave quotient = 0,
to indicate that it has not done anything. to indicate that it has not done anything.
Last comes code that finishes the operation. If QUOTIENT is set an Last comes code that finishes the operation. If QUOTIENT is set and
REM_FLAG, the remainder is computed as OP0 - QUOTIENT * OP1. If QUOTIENT REM_FLAG is set, the remainder is computed as OP0 - QUOTIENT * OP1. If
is not set, it is computed using trunc rounding. QUOTIENT is not set, it is computed using trunc rounding.
We try to generate special code for division and remainder when OP1 is a We try to generate special code for division and remainder when OP1 is a
constant. If |OP1| = 2**n we can use shifts and some other fast constant. If |OP1| = 2**n we can use shifts and some other fast
...@@ -3408,10 +3408,70 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -3408,10 +3408,70 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
case ROUND_DIV_EXPR: case ROUND_DIV_EXPR:
case ROUND_MOD_EXPR: case ROUND_MOD_EXPR:
/* The code that used to be here was wrong, and nothing really if (unsignedp)
depends on it. */ {
abort (); rtx tem;
break; rtx label;
label = gen_label_rtx ();
quotient = gen_reg_rtx (compute_mode);
remainder = gen_reg_rtx (compute_mode);
if (expand_twoval_binop (udivmod_optab, op0, op1, quotient, remainder, 1) == 0)
{
rtx tem;
quotient = expand_binop (compute_mode, udiv_optab, op0, op1,
quotient, 1, OPTAB_LIB_WIDEN);
tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 1);
remainder = expand_binop (compute_mode, sub_optab, op0, tem,
remainder, 1, OPTAB_LIB_WIDEN);
}
tem = plus_constant (op1, -1);
tem = expand_shift (RSHIFT_EXPR, compute_mode, tem,
build_int_2 (1, 0), NULL_RTX, 1);
emit_cmp_insn (remainder, tem, LEU, NULL_RTX, compute_mode, 0, 0);
emit_jump_insn (gen_bleu (label));
expand_inc (quotient, const1_rtx);
expand_dec (remainder, op1);
emit_label (label);
}
else
{
rtx abs_rem, abs_op1, tem, mask;
rtx label;
label = gen_label_rtx ();
quotient = gen_reg_rtx (compute_mode);
remainder = gen_reg_rtx (compute_mode);
if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient, remainder, 0) == 0)
{
rtx tem;
quotient = expand_binop (compute_mode, sdiv_optab, op0, op1,
quotient, 0, OPTAB_LIB_WIDEN);
tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 0);
remainder = expand_binop (compute_mode, sub_optab, op0, tem,
remainder, 0, OPTAB_LIB_WIDEN);
}
abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0, 0);
abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0, 0);
tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
build_int_2 (1, 0), NULL_RTX, 1);
emit_cmp_insn (tem, abs_op1, LTU, NULL_RTX, compute_mode, 0, 0);
emit_jump_insn (gen_bltu (label));
tem = expand_binop (compute_mode, xor_optab, op0, op1,
NULL_RTX, 0, OPTAB_WIDEN);
mask = expand_shift (RSHIFT_EXPR, compute_mode, tem,
build_int_2 (size - 1, 0), NULL_RTX, 0);
tem = expand_binop (compute_mode, xor_optab, mask, const1_rtx,
NULL_RTX, 0, OPTAB_WIDEN);
tem = expand_binop (compute_mode, sub_optab, tem, mask,
NULL_RTX, 0, OPTAB_WIDEN);
expand_inc (quotient, tem);
tem = expand_binop (compute_mode, xor_optab, mask, op1,
NULL_RTX, 0, OPTAB_WIDEN);
tem = expand_binop (compute_mode, sub_optab, tem, mask,
NULL_RTX, 0, OPTAB_WIDEN);
expand_dec (remainder, tem);
emit_label (label);
}
return gen_lowpart (mode, rem_flag ? remainder : quotient);
} }
if (quotient == 0) if (quotient == 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