i386.c (ix86_emit_i387_round): New function.
* config/i386/i386.c (ix86_emit_i387_round): New function. * config/i386/i386-protos.h (ix86_emit_i387_round): Declare. * config/i386/i386.md (round<mode>2): Use X87MODEF mode iterator. Use ix86_emit_i387_round to expand round function for i387 math. (lround<X87MODEF:mode><SWI248x:mode>2): Use X87MODEF mode iterator. Use ix86_emit_i387_round to expand {l,ll}round function for i387 math. From-SVN: r177605
This commit is contained in:
parent
c6412d8676
commit
2813f1b15f
4 changed files with 188 additions and 17 deletions
|
@ -1,8 +1,16 @@
|
|||
2011-08-09 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/i386/i386.c (ix86_emit_i387_round): New function.
|
||||
* config/i386/i386-protos.h (ix86_emit_i387_round): Declare.
|
||||
* config/i386/i386.md (round<mode>2): Use X87MODEF mode iterator.
|
||||
Use ix86_emit_i387_round to expand round function for i387 math.
|
||||
(lround<X87MODEF:mode><SWI248x:mode>2): Use X87MODEF mode iterator.
|
||||
Use ix86_emit_i387_round to expand {l,ll}round function for i387 math.
|
||||
|
||||
2011-08-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||
|
||||
* config/sync.c: Move to ../libgcc.
|
||||
* Makefile.in (libgcc.mvars): Remove LIBGCC_SYNC,
|
||||
LIBGCC_SYNC_CFLAGS.
|
||||
* Makefile.in (libgcc.mvars): Remove LIBGCC_SYNC, LIBGCC_SYNC_CFLAGS.
|
||||
* config/mips/t-libgcc-mips16 (LIBGCC_SYNC, LIBGCC_SYNC_CFLAGS):
|
||||
Remove.
|
||||
|
||||
|
|
|
@ -163,6 +163,7 @@ extern void x86_emit_floatuns (rtx [2]);
|
|||
extern void ix86_emit_fp_unordered_jump (rtx);
|
||||
|
||||
extern void ix86_emit_i387_log1p (rtx, rtx);
|
||||
extern void ix86_emit_i387_round (rtx, rtx);
|
||||
extern void ix86_emit_swdivsf (rtx, rtx, rtx, enum machine_mode);
|
||||
extern void ix86_emit_swsqrtsf (rtx, rtx, enum machine_mode, bool);
|
||||
|
||||
|
|
|
@ -28260,7 +28260,7 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
|
|||
sri->icode = (in_p
|
||||
? CODE_FOR_reload_noff_load
|
||||
: CODE_FOR_reload_noff_store);
|
||||
/* Add the cost of move to a temporary. */
|
||||
/* Add the cost of moving address to a temporary. */
|
||||
sri->extra_cost = 1;
|
||||
|
||||
return NO_REGS;
|
||||
|
@ -31731,6 +31731,139 @@ void ix86_emit_i387_log1p (rtx op0, rtx op1)
|
|||
emit_label (label2);
|
||||
}
|
||||
|
||||
/* Emit code for round calculation. */
|
||||
void ix86_emit_i387_round (rtx op0, rtx op1)
|
||||
{
|
||||
enum machine_mode inmode = GET_MODE (op1);
|
||||
enum machine_mode outmode = GET_MODE (op0);
|
||||
rtx e1, e2, res, tmp, tmp1, half;
|
||||
rtx scratch = gen_reg_rtx (HImode);
|
||||
rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
|
||||
rtx jump_label = gen_label_rtx ();
|
||||
rtx insn;
|
||||
rtx (*gen_abs) (rtx, rtx);
|
||||
rtx (*gen_neg) (rtx, rtx);
|
||||
|
||||
switch (inmode)
|
||||
{
|
||||
case SFmode:
|
||||
gen_abs = gen_abssf2;
|
||||
break;
|
||||
case DFmode:
|
||||
gen_abs = gen_absdf2;
|
||||
break;
|
||||
case XFmode:
|
||||
gen_abs = gen_absxf2;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
switch (outmode)
|
||||
{
|
||||
case SFmode:
|
||||
gen_neg = gen_negsf2;
|
||||
break;
|
||||
case DFmode:
|
||||
gen_neg = gen_negdf2;
|
||||
break;
|
||||
case XFmode:
|
||||
gen_neg = gen_negxf2;
|
||||
break;
|
||||
case HImode:
|
||||
gen_neg = gen_neghi2;
|
||||
break;
|
||||
case SImode:
|
||||
gen_neg = gen_negsi2;
|
||||
break;
|
||||
case DImode:
|
||||
gen_neg = gen_negdi2;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
e1 = gen_reg_rtx (inmode);
|
||||
e2 = gen_reg_rtx (inmode);
|
||||
res = gen_reg_rtx (outmode);
|
||||
|
||||
half = CONST_DOUBLE_FROM_REAL_VALUE (dconsthalf, inmode);
|
||||
|
||||
/* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
|
||||
|
||||
/* scratch = fxam(op1) */
|
||||
emit_insn (gen_rtx_SET (VOIDmode, scratch,
|
||||
gen_rtx_UNSPEC (HImode, gen_rtvec (1, op1),
|
||||
UNSPEC_FXAM)));
|
||||
/* e1 = fabs(op1) */
|
||||
emit_insn (gen_abs (e1, op1));
|
||||
|
||||
/* e2 = e1 + 0.5 */
|
||||
half = force_reg (inmode, half);
|
||||
emit_insn (gen_rtx_SET (VOIDmode, e2,
|
||||
gen_rtx_PLUS (inmode, e1, half)));
|
||||
|
||||
/* res = floor(e2) */
|
||||
if (inmode != XFmode)
|
||||
{
|
||||
tmp1 = gen_reg_rtx (XFmode);
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, tmp1,
|
||||
gen_rtx_FLOAT_EXTEND (XFmode, e2)));
|
||||
}
|
||||
else
|
||||
tmp1 = e2;
|
||||
|
||||
switch (outmode)
|
||||
{
|
||||
case SFmode:
|
||||
case DFmode:
|
||||
{
|
||||
rtx tmp0 = gen_reg_rtx (XFmode);
|
||||
|
||||
emit_insn (gen_frndintxf2_floor (tmp0, tmp1));
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, res,
|
||||
gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp0),
|
||||
UNSPEC_TRUNC_NOOP)));
|
||||
}
|
||||
break;
|
||||
case XFmode:
|
||||
emit_insn (gen_frndintxf2_floor (res, tmp1));
|
||||
break;
|
||||
case HImode:
|
||||
emit_insn (gen_lfloorxfhi2 (res, tmp1));
|
||||
break;
|
||||
case SImode:
|
||||
emit_insn (gen_lfloorxfsi2 (res, tmp1));
|
||||
break;
|
||||
case DImode:
|
||||
emit_insn (gen_lfloorxfdi2 (res, tmp1));
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* flags = signbit(a) */
|
||||
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x02)));
|
||||
|
||||
/* if (flags) then res = -res */
|
||||
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
|
||||
gen_rtx_EQ (VOIDmode, flags, const0_rtx),
|
||||
gen_rtx_LABEL_REF (VOIDmode, jump_label),
|
||||
pc_rtx);
|
||||
insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
|
||||
predict_jump (REG_BR_PROB_BASE * 50 / 100);
|
||||
JUMP_LABEL (insn) = jump_label;
|
||||
|
||||
emit_insn (gen_neg (res, res));
|
||||
|
||||
emit_label (jump_label);
|
||||
LABEL_NUSES (jump_label) = 1;
|
||||
|
||||
emit_move_insn (op0, res);
|
||||
}
|
||||
|
||||
/* Output code to perform a Newton-Rhapson approximation of a single precision
|
||||
floating point divide [http://en.wikipedia.org/wiki/N-th_root_algorithm]. */
|
||||
|
||||
|
|
|
@ -14396,17 +14396,31 @@
|
|||
})
|
||||
|
||||
(define_expand "round<mode>2"
|
||||
[(match_operand:MODEF 0 "register_operand" "")
|
||||
(match_operand:MODEF 1 "nonimmediate_operand" "")]
|
||||
"SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
|
||||
&& !flag_trapping_math && !flag_rounding_math"
|
||||
[(match_operand:X87MODEF 0 "register_operand" "")
|
||||
(match_operand:X87MODEF 1 "nonimmediate_operand" "")]
|
||||
"(TARGET_USE_FANCY_MATH_387
|
||||
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|
||||
|| TARGET_MIX_SSE_I387)
|
||||
&& flag_unsafe_math_optimizations)
|
||||
|| (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
|
||||
&& !flag_trapping_math && !flag_rounding_math)"
|
||||
{
|
||||
if (optimize_insn_for_size_p ())
|
||||
FAIL;
|
||||
if (TARGET_64BIT || (<MODE>mode != DFmode))
|
||||
ix86_expand_round (operand0, operand1);
|
||||
|
||||
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
|
||||
&& !flag_trapping_math && !flag_rounding_math)
|
||||
{
|
||||
if (TARGET_64BIT || (<MODE>mode != DFmode))
|
||||
ix86_expand_round (operands[0], operands[1]);
|
||||
else
|
||||
ix86_expand_rounddf_32 (operands[0], operands[1]);
|
||||
}
|
||||
else
|
||||
ix86_expand_rounddf_32 (operand0, operand1);
|
||||
{
|
||||
operands[1] = force_reg (<MODE>mode, operands[1]);
|
||||
ix86_emit_i387_round (operands[0], operands[1]);
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
@ -14542,16 +14556,31 @@
|
|||
"SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
|
||||
&& ((<SWI48x:MODE>mode != DImode) || TARGET_64BIT)")
|
||||
|
||||
(define_expand "lround<MODEF:mode><SWI48x:mode>2"
|
||||
[(match_operand:SWI48x 0 "nonimmediate_operand" "")
|
||||
(match_operand:MODEF 1 "register_operand" "")]
|
||||
"SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
|
||||
&& ((<SWI48x:MODE>mode != DImode) || TARGET_64BIT)
|
||||
&& !flag_trapping_math && !flag_rounding_math"
|
||||
(define_expand "lround<X87MODEF:mode><SWI248x:mode>2"
|
||||
[(match_operand:SWI248x 0 "nonimmediate_operand" "")
|
||||
(match_operand:X87MODEF 1 "register_operand" "")]
|
||||
"(TARGET_USE_FANCY_MATH_387
|
||||
&& (!(SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH)
|
||||
|| TARGET_MIX_SSE_I387)
|
||||
&& flag_unsafe_math_optimizations)
|
||||
|| (SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH
|
||||
&& <SWI248x:MODE>mode != HImode
|
||||
&& ((<SWI248x:MODE>mode != DImode) || TARGET_64BIT)
|
||||
&& !flag_trapping_math && !flag_rounding_math)"
|
||||
{
|
||||
if (optimize_insn_for_size_p ())
|
||||
FAIL;
|
||||
ix86_expand_lround (operand0, operand1);
|
||||
|
||||
if (SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH
|
||||
&& <SWI248x:MODE>mode != HImode
|
||||
&& ((<SWI248x:MODE>mode != DImode) || TARGET_64BIT)
|
||||
&& !flag_trapping_math && !flag_rounding_math)
|
||||
ix86_expand_lround (operand0, operand1);
|
||||
else
|
||||
{
|
||||
operands[0] = force_reg (<SWI248x:MODE>mode, operands[0]);
|
||||
ix86_emit_i387_round (operands[0], operands[1]);
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue