From 044928d6127efd397fe450718e994768d7caa61e Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Sun, 29 Oct 2006 16:43:21 +0000 Subject: [PATCH] i386-protos.h (ix86_expand_trunc): Declare. 2006-10-29 Richard Guenther * 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 --- gcc/ChangeLog | 11 +++ gcc/config/i386/i386-protos.h | 2 + gcc/config/i386/i386.c | 94 +++++++++++++++++++ gcc/config/i386/i386.md | 57 +++++++---- gcc/testsuite/ChangeLog | 4 + .../gcc.target/i386/math-torture/trunc.c | 14 +++ 6 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/math-torture/trunc.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 431c7cd23b81..c4bd38882353 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2006-10-29 Richard Guenther + + * 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 * 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 6393f94a703b..e7154700577f 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 0a36e6026611..074ce92e668b 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 a274597b96c7..2da10a1c751e 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 6231f078fb27..067d97e9481d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-10-29 Richard Guenther + + * gcc.target/i386/math-torture/trunc.c: New testcase. + 2006-10-29 Richard Guenther * gcc.target/i386/math-torture/round.c: New testcase. 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 000000000000..a71e026c5180 --- /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); +} -- 2.47.2