aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2006-10-29 16:43:21 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2006-10-29 16:43:21 +0000
commit044928d6127efd397fe450718e994768d7caa61e (patch)
tree8b6533a6eefd2ae32471956c89d21ee089fbaa2d
parent0f45f0f588d8af6ed4047e0ce4351749b6c0328b (diff)
downloadgcc-044928d6127efd397fe450718e994768d7caa61e.zip
gcc-044928d6127efd397fe450718e994768d7caa61e.tar.gz
gcc-044928d6127efd397fe450718e994768d7caa61e.tar.bz2
i386-protos.h (ix86_expand_trunc): Declare.
2006-10-29 Richard Guenther <rguenther@suse.de> * config/i386/i386-protos.h (ix86_expand_trunc): Declare. (ix86_expand_truncdf_32): Likewise. * config/i386/i386.c (ix86_expand_trunc): New function expanding trunc inline for SSE math and -fno-trapping-math and if not optimizing for size. (ix86_expand_truncdf_32): Same for DFmode on 32bit archs. * config/i386/i386.md (btruncsf2, btruncdf2): Adjust expanders for expanding btrunc inline for SSE math. * gcc.target/i386/math-torture/trunc.c: New testcase. From-SVN: r118148
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c94
-rw-r--r--gcc/config/i386/i386.md57
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/math-torture/trunc.c14
6 files changed, 166 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 431c7cd..c4bd388 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2006-10-29 Richard Guenther <rguenther@suse.de>
+
+ * config/i386/i386-protos.h (ix86_expand_trunc): Declare.
+ (ix86_expand_truncdf_32): Likewise.
+ * config/i386/i386.c (ix86_expand_trunc): New function expanding
+ trunc inline for SSE math and -fno-trapping-math and if not
+ optimizing for size.
+ (ix86_expand_truncdf_32): Same for DFmode on 32bit archs.
+ * config/i386/i386.md (btruncsf2, btruncdf2): Adjust expanders
+ for expanding btrunc inline for SSE math.
+
2006-10-29 Joseph Myers <joseph@codesourcery.com>
* config.gcc (i[34567]86-*-linux*): Handle --enable-targets=all.
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 6393f94..e715470 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -164,6 +164,8 @@ extern void ix86_expand_floorceil (rtx, rtx, bool);
extern void ix86_expand_floorceildf_32 (rtx, rtx, bool);
extern void ix86_expand_round (rtx, rtx);
extern void ix86_expand_rounddf_32 (rtx, rtx);
+extern void ix86_expand_trunc (rtx, rtx);
+extern void ix86_expand_truncdf_32 (rtx, rtx);
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0a36e60..074ce92 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -19639,6 +19639,100 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
emit_move_insn (operand0, res);
}
+/* Expand SSE sequence for computing trunc from OPERAND1 storing
+ into OPERAND0. */
+void
+ix86_expand_trunc (rtx operand0, rtx operand1)
+{
+ /* C code for SSE variant we expand below.
+ double xa = fabs (x), x2;
+ if (!isless (xa, TWO52))
+ return x;
+ return (double)(long)x;
+ */
+ enum machine_mode mode = GET_MODE (operand0);
+ rtx xa, xi, TWO52, label, res;
+
+ TWO52 = ix86_gen_TWO52 (mode);
+
+ /* Temporary for holding the result, initialized to the input
+ operand to ease control flow. */
+ res = gen_reg_rtx (mode);
+ emit_move_insn (res, operand1);
+
+ /* xa = abs (operand1) */
+ xa = ix86_expand_sse_fabs (res, NULL);
+
+ /* if (!isless (xa, TWO52)) goto label; */
+ label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
+
+ /* x = (double)(long)x */
+ xi = gen_reg_rtx (mode == DFmode ? DImode : SImode);
+ expand_fix (xi, res, 0);
+ expand_float (res, xi, 0);
+
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+
+ emit_move_insn (operand0, res);
+}
+
+/* Expand SSE sequence for computing trunc from OPERAND1 storing
+ into OPERAND0. */
+void
+ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
+{
+ enum machine_mode mode = GET_MODE (operand0);
+ rtx xa, mask, TWO52, label, one, res, smask;
+
+ /* C code for SSE variant we expand below.
+ double xa = fabs (x), x2;
+ if (!isless (xa, TWO52))
+ return x;
+ xa2 = xa + TWO52 - TWO52;
+ Compensate:
+ if (xa2 > xa)
+ xa2 -= 1.0;
+ x2 = copysign (xa2, x);
+ return x2;
+ */
+
+ TWO52 = ix86_gen_TWO52 (mode);
+
+ /* Temporary for holding the result, initialized to the input
+ operand to ease control flow. */
+ res = gen_reg_rtx (mode);
+ emit_move_insn (res, operand1);
+
+ /* xa = abs (operand1) */
+ xa = ix86_expand_sse_fabs (res, &smask);
+
+ /* if (!isless (xa, TWO52)) goto label; */
+ label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
+
+ /* res = xa + TWO52 - TWO52; */
+ expand_simple_binop (mode, PLUS, xa, TWO52, res, 0, OPTAB_DIRECT);
+ expand_simple_binop (mode, MINUS, res, TWO52, res, 0, OPTAB_DIRECT);
+
+ /* generate 1.0 */
+ one = force_reg (mode, const_double_from_real_value (dconst1, mode));
+
+ /* Compensate: res = xa2 - (res > xa ? 1 : 0) */
+ mask = ix86_expand_sse_compare_mask (UNGT, res, xa, false);
+ emit_insn (gen_rtx_SET (VOIDmode, mask,
+ gen_rtx_AND (mode, mask, one)));
+ expand_simple_binop (mode, MINUS,
+ res, mask, res, 0, OPTAB_DIRECT);
+
+ /* res = copysign (res, operand1) */
+ ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), smask);
+
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+
+ emit_move_insn (operand0, res);
+}
+
/* Expand SSE sequence for computing round from OPERAND1 storing
into OPERAND0. */
void
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index a274597..2da10a1 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18032,34 +18032,59 @@
(define_expand "btruncdf2"
[(use (match_operand:DF 0 "register_operand" ""))
(use (match_operand:DF 1 "register_operand" ""))]
- "TARGET_USE_FANCY_MATH_387
- && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
+ "(TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations)
+ || (SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH
+ && !flag_trapping_math
+ && !optimize_size)"
{
- rtx op0 = gen_reg_rtx (XFmode);
- rtx op1 = gen_reg_rtx (XFmode);
+ if (SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH
+ && !flag_trapping_math
+ && !optimize_size)
+ {
+ if (TARGET_64BIT)
+ ix86_expand_trunc (operand0, operand1);
+ else
+ ix86_expand_truncdf_32 (operand0, operand1);
+ }
+ else
+ {
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- emit_insn (gen_extenddfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_trunc (op0, op1));
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_trunc (op0, op1));
- emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ }
DONE;
})
(define_expand "btruncsf2"
[(use (match_operand:SF 0 "register_operand" ""))
(use (match_operand:SF 1 "register_operand" ""))]
- "TARGET_USE_FANCY_MATH_387
- && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
+ "(TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations)
+ || (SSE_FLOAT_MODE_P (SFmode) && TARGET_SSE_MATH
+ && !flag_trapping_math
+ && !optimize_size)"
{
- rtx op0 = gen_reg_rtx (XFmode);
- rtx op1 = gen_reg_rtx (XFmode);
+ if (SSE_FLOAT_MODE_P (SFmode) && TARGET_SSE_MATH
+ && !flag_trapping_math
+ && !optimize_size)
+ ix86_expand_trunc (operand0, operand1);
+ else
+ {
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- emit_insn (gen_extendsfxf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_trunc (op0, op1));
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_trunc (op0, op1));
- emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ }
DONE;
})
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6231f07..067d97e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2006-10-29 Richard Guenther <rguenther@suse.de>
+ * gcc.target/i386/math-torture/trunc.c: New testcase.
+
+2006-10-29 Richard Guenther <rguenther@suse.de>
+
* gcc.target/i386/math-torture/round.c: New testcase.
2006-10-29 Richard Guenther <rguenther@suse.de>
diff --git a/gcc/testsuite/gcc.target/i386/math-torture/trunc.c b/gcc/testsuite/gcc.target/i386/math-torture/trunc.c
new file mode 100644
index 0000000..a71e026
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/math-torture/trunc.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+
+float testlf (float x)
+{
+ return __builtin_truncf (x);
+}
+double testl (double x)
+{
+ return __builtin_trunc (x);
+}
+long double testll (long double x)
+{
+ return __builtin_truncl (x);
+}