aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2018-10-02 17:12:30 +0200
committerUros Bizjak <uros@gcc.gnu.org>2018-10-02 17:12:30 +0200
commit34c77d0b2fb7325c1b318b2de755b588cb7179ce (patch)
tree289b5c49a7e8c982b92ff1a39fa760d583c53807
parent4913fc07e0b3f1d574dc20f83ec819a26ab4346e (diff)
downloadgcc-34c77d0b2fb7325c1b318b2de755b588cb7179ce.zip
gcc-34c77d0b2fb7325c1b318b2de755b588cb7179ce.tar.gz
gcc-34c77d0b2fb7325c1b318b2de755b588cb7179ce.tar.bz2
i386.c (ix86_emit_i387_round): Extend op1 to XFmode before emitting fxam.
* config/i386/i386.c (ix86_emit_i387_round): Extend op1 to XFmode before emitting fxam. Perform calculations in XFmode. From-SVN: r264794
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/i386/i386.c86
2 files changed, 38 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0b67fa6..fce5984 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2018-10-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_emit_i387_round): Extend op1 to XFmode
+ before emitting fxam. Perform calculations in XFmode.
+
2018-10-02 Marc Glisse <marc.glisse@inria.fr>
* match.pd (((X /[ex] A) +- B) * A): New transformation.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 55bf18b..d35ad91 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -43951,24 +43951,27 @@ void ix86_emit_i387_round (rtx op0, rtx op1)
{
machine_mode inmode = GET_MODE (op1);
machine_mode outmode = GET_MODE (op0);
- rtx e1, e2, res, tmp, tmp1, half;
+ rtx e1 = gen_reg_rtx (XFmode);
+ rtx e2 = gen_reg_rtx (XFmode);
rtx scratch = gen_reg_rtx (HImode);
rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
+ rtx half = const_double_from_real_value (dconsthalf, XFmode);
+ rtx res = gen_reg_rtx (outmode);
rtx_code_label *jump_label = gen_label_rtx ();
- rtx insn;
- rtx (*gen_abs) (rtx, rtx);
- rtx (*gen_neg) (rtx, rtx);
+ rtx (*floor_insn) (rtx, rtx);
+ rtx (*neg_insn) (rtx, rtx);
+ rtx insn, tmp;
switch (inmode)
{
case E_SFmode:
- gen_abs = gen_abssf2;
- break;
case E_DFmode:
- gen_abs = gen_absdf2;
+ tmp = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_FLOAT_EXTEND (XFmode, op1)));
+ op1 = tmp;
break;
case E_XFmode:
- gen_abs = gen_absxf2;
break;
default:
gcc_unreachable ();
@@ -43977,84 +43980,61 @@ void ix86_emit_i387_round (rtx op0, rtx op1)
switch (outmode)
{
case E_SFmode:
- gen_neg = gen_negsf2;
+ floor_insn = gen_frndintxf2_floor;
+ neg_insn = gen_negsf2;
break;
case E_DFmode:
- gen_neg = gen_negdf2;
+ floor_insn = gen_frndintxf2_floor;
+ neg_insn = gen_negdf2;
break;
case E_XFmode:
- gen_neg = gen_negxf2;
+ floor_insn = gen_frndintxf2_floor;
+ neg_insn = gen_negxf2;
break;
case E_HImode:
- gen_neg = gen_neghi2;
+ floor_insn = gen_lfloorxfhi2;
+ neg_insn = gen_neghi2;
break;
case E_SImode:
- gen_neg = gen_negsi2;
+ floor_insn = gen_lfloorxfsi2;
+ neg_insn = gen_negsi2;
break;
case E_DImode:
- gen_neg = gen_negdi2;
+ floor_insn = gen_lfloorxfdi2;
+ neg_insn = 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 (scratch,
- gen_rtx_UNSPEC (HImode, gen_rtvec (1, op1),
- UNSPEC_FXAM)));
+ emit_insn (gen_fxamxf2_i387 (scratch, op1));
+
/* e1 = fabs(op1) */
- emit_insn (gen_abs (e1, op1));
+ emit_insn (gen_absxf2 (e1, op1));
/* e2 = e1 + 0.5 */
- half = force_reg (inmode, half);
- emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (inmode, e1, half)));
+ half = force_reg (XFmode, half);
+ emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (XFmode, e1, half)));
/* res = floor(e2) */
- if (inmode != XFmode)
- {
- tmp1 = gen_reg_rtx (XFmode);
-
- emit_insn (gen_rtx_SET (tmp1, gen_rtx_FLOAT_EXTEND (XFmode, e2)));
- }
- else
- tmp1 = e2;
-
switch (outmode)
{
case E_SFmode:
case E_DFmode:
{
- rtx tmp0 = gen_reg_rtx (XFmode);
-
- emit_insn (gen_frndintxf2_floor (tmp0, tmp1));
+ tmp = gen_reg_rtx (XFmode);
+ emit_insn (floor_insn (tmp, e2));
emit_insn (gen_rtx_SET (res,
- gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp0),
+ gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp),
UNSPEC_TRUNC_NOOP)));
}
break;
- case E_XFmode:
- emit_insn (gen_frndintxf2_floor (res, tmp1));
- break;
- case E_HImode:
- emit_insn (gen_lfloorxfhi2 (res, tmp1));
- break;
- case E_SImode:
- emit_insn (gen_lfloorxfsi2 (res, tmp1));
- break;
- case E_DImode:
- emit_insn (gen_lfloorxfdi2 (res, tmp1));
- break;
default:
- gcc_unreachable ();
+ emit_insn (floor_insn (res, e2));
}
/* flags = signbit(a) */
@@ -44069,7 +44049,7 @@ void ix86_emit_i387_round (rtx op0, rtx op1)
predict_jump (REG_BR_PROB_BASE * 50 / 100);
JUMP_LABEL (insn) = jump_label;
- emit_insn (gen_neg (res, res));
+ emit_insn (neg_insn (res, res));
emit_label (jump_label);
LABEL_NUSES (jump_label) = 1;