diff options
author | Richard Guenther <rguenther@suse.de> | 2006-10-29 16:43:21 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2006-10-29 16:43:21 +0000 |
commit | 044928d6127efd397fe450718e994768d7caa61e (patch) | |
tree | 8b6533a6eefd2ae32471956c89d21ee089fbaa2d | |
parent | 0f45f0f588d8af6ed4047e0ce4351749b6c0328b (diff) | |
download | gcc-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/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 94 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 57 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/math-torture/trunc.c | 14 |
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); +} |