aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2006-10-28 11:30:41 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2006-10-28 11:30:41 +0000
commit4d81bf84358f0f905b606a5cb27777e614d213e1 (patch)
tree984f65a3da9766999d6ccf8748f98e89fbad2338 /gcc
parent6f16dafb641b6c935c94f87c8ceaac9458dadc72 (diff)
downloadgcc-4d81bf84358f0f905b606a5cb27777e614d213e1.zip
gcc-4d81bf84358f0f905b606a5cb27777e614d213e1.tar.gz
gcc-4d81bf84358f0f905b606a5cb27777e614d213e1.tar.bz2
re PR target/28806 (lround is not expanded inline to SSE conversion sequence)
2006-10-28 Richard Guenther <rguenther@suse.de> PR target/28806 * builtins.c (expand_builtin_int_roundingfn_2): Expand BUILT_IN_LROUND and BUILT_IN_LLROUND from here. (expand_builtin): Adjust likewise. * genopinit.c (optabs[]): Add lround optab. * optabs.c (init_optabs): Initialize lround_optab. * optabs.h (enum convert_optab_index): Add COI_lround. (lround_optab): Define. * config/i386/i386-protos.h (ix86_expand_lround): Declare. * config/i386/i386.c (ix86_sse_copysign_to_positive): New static function. (ix86_expand_lround): New function. * config/i386/i386.md (lround<mode>di2, lround<mode>si2): New expanders. * doc/md.texi (lroundMN2): Document. * gcc.target/i386/math-torture/lround.c: New testcase. From-SVN: r118105
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/builtins.c5
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c52
-rw-r--r--gcc/config/i386/i386.md20
-rw-r--r--gcc/doc/md.texi6
-rw-r--r--gcc/genopinit.c1
-rw-r--r--gcc/optabs.c3
-rw-r--r--gcc/optabs.h2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/math-torture/lround.c26
11 files changed, 140 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a0bdc81..e64b3f4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2006-10-28 Richard Guenther <rguenther@suse.de>
+
+ PR target/28806
+ * builtins.c (expand_builtin_int_roundingfn_2): Expand
+ BUILT_IN_LROUND and BUILT_IN_LLROUND from here.
+ (expand_builtin): Adjust likewise.
+ * genopinit.c (optabs[]): Add lround optab.
+ * optabs.c (init_optabs): Initialize lround_optab.
+ * optabs.h (enum convert_optab_index): Add COI_lround.
+ (lround_optab): Define.
+ * config/i386/i386-protos.h (ix86_expand_lround): Declare.
+ * config/i386/i386.c (ix86_sse_copysign_to_positive): New
+ static function.
+ (ix86_expand_lround): New function.
+ * config/i386/i386.md (lround<mode>di2, lround<mode>si2):
+ New expanders.
+ * doc/md.texi (lroundMN2): Document.
+
2006-10-28 Uros Bizjak <uros@kss-loka.si>
PR target/29377
diff --git a/gcc/builtins.c b/gcc/builtins.c
index fec89cc..ecd9461 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2341,6 +2341,9 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LLRINT):
builtin_optab = lrint_optab; break;
+ CASE_FLT_FN (BUILT_IN_LROUND):
+ CASE_FLT_FN (BUILT_IN_LLROUND):
+ builtin_optab = lround_optab; break;
default:
gcc_unreachable ();
}
@@ -5770,6 +5773,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LLRINT):
+ CASE_FLT_FN (BUILT_IN_LROUND):
+ CASE_FLT_FN (BUILT_IN_LLROUND):
target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
if (target)
return target;
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 6b9ed89..13e8064 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -157,6 +157,8 @@ extern void ix86_emit_i387_log1p (rtx, rtx);
extern enum rtx_code ix86_reverse_condition (enum rtx_code, enum machine_mode);
+extern void ix86_expand_lround (rtx, rtx);
+
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 14974ff..a535b45 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -19223,5 +19223,57 @@ asm_preferred_eh_data_format (int code, int global)
return DW_EH_PE_udata4;
return DW_EH_PE_absptr;
}
+
+/* Expand copysign from SIGN to the positive value ABS_VALUE
+ storing in RESULT. */
+static void
+ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign)
+{
+ enum machine_mode mode = GET_MODE (sign);
+ rtx sgn = gen_reg_rtx (mode);
+ rtx mask = ix86_build_signbit_mask (mode, VECTOR_MODE_P (mode), false);
+ if (!VECTOR_MODE_P (mode))
+ {
+ /* We need to generate a scalar mode mask in this case. */
+ rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
+ tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
+ mask = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, mask, tmp));
+ }
+ emit_insn (gen_rtx_SET (VOIDmode, sgn,
+ gen_rtx_AND (mode, mask, sign)));
+ emit_insn (gen_rtx_SET (VOIDmode, result,
+ gen_rtx_IOR (mode, abs_value, sgn)));
+}
+
+/* Expand SSE sequence for computing lround from OP1 storing
+ into OP0. */
+void
+ix86_expand_lround (rtx op0, rtx op1)
+{
+ /* C code for the stuff we're doing below:
+ tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
+ return (long)tmp;
+ */
+ enum machine_mode mode = GET_MODE (op1);
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE pred_half, half_minus_pred_half;
+ rtx adj;
+
+ /* load nextafter (0.5, 0.0) */
+ fmt = REAL_MODE_FORMAT (mode);
+ real_2expN (&half_minus_pred_half, -(fmt->p) - 1);
+ REAL_ARITHMETIC (pred_half, MINUS_EXPR, dconsthalf, half_minus_pred_half);
+
+ /* adj = copysign (0.5, op1) */
+ adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
+ ix86_sse_copysign_to_positive (adj, adj, force_reg (mode, op1));
+
+ /* adj = op1 + adj */
+ expand_simple_binop (mode, PLUS, adj, op1, adj, 0, OPTAB_DIRECT);
+
+ /* op0 = (imode)adj */
+ expand_fix (op0, adj, 0);
+}
#include "gt-i386.h"
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 4e2f9dd..d7c2733 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -17347,6 +17347,26 @@
"SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
"")
+(define_expand "lround<mode>di2"
+ [(match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:SSEMODEF 1 "register_operand" "")]
+ "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH && TARGET_64BIT
+ && !flag_trapping_math && !flag_rounding_math"
+{
+ ix86_expand_lround (operand0, operand1);
+ DONE;
+})
+
+(define_expand "lround<mode>si2"
+ [(match_operand:SI 0 "nonimmediate_operand" "")
+ (match_operand:SSEMODEF 1 "register_operand" "")]
+ "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
+ && !flag_trapping_math && !flag_rounding_math"
+{
+ ix86_expand_lround (operand0, operand1);
+ DONE;
+})
+
;; Rounding mode control word calculation could clobber FLAGS_REG.
(define_insn_and_split "frndintxf2_floor"
[(set (match_operand:XF 0 "register_operand" "=f")
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index a41391c..7b55db7 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -3708,6 +3708,12 @@ Convert operand 1 (valid for floating point mode @var{m}) to fixed
point mode @var{n} as a signed number according to the current
rounding mode and store in operand 0 (which has mode @var{n}).
+@cindex @code{lround@var{m}@var{n}2}
+@item @samp{lround@var{m}2}
+Convert operand 1 (valid for floating point mode @var{m}) to fixed
+point mode @var{n} as a signed number rounding to nearest and away
+from zero and store in operand 0 (which has mode @var{n}).
+
@cindex @code{copysign@var{m}3} instruction pattern
@item @samp{copysign@var{m}3}
Store a value with the magnitude of operand 1 and the sign of operand
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 1575735..fcd2a68 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -128,6 +128,7 @@ static const char * const optabs[] =
"nearbyint_optab->handlers[$A].insn_code = CODE_FOR_$(nearbyint$a2$)",
"rint_optab->handlers[$A].insn_code = CODE_FOR_$(rint$a2$)",
"lrint_optab->handlers[$B][$A].insn_code = CODE_FOR_$(lrint$F$a$I$b2$)",
+ "lround_optab->handlers[$B][$A].insn_code = CODE_FOR_$(lround$F$a$I$b2$)",
"sincos_optab->handlers[$A].insn_code = CODE_FOR_$(sincos$a3$)",
"sin_optab->handlers[$A].insn_code = CODE_FOR_$(sin$a2$)",
"asin_optab->handlers[$A].insn_code = CODE_FOR_$(asin$a2$)",
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 11cacae..ea6b7f3 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5365,6 +5365,7 @@ init_optabs (void)
sfloat_optab = init_convert_optab (FLOAT);
ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);
lrint_optab = init_convert_optab (UNKNOWN);
+ lround_optab = init_convert_optab (UNKNOWN);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
@@ -5486,6 +5487,8 @@ init_optabs (void)
MODE_INT, MODE_DECIMAL_FLOAT);
init_interclass_conv_libfuncs (lrint_optab, "lrint",
MODE_INT, MODE_FLOAT);
+ init_interclass_conv_libfuncs (lround_optab, "lround",
+ MODE_INT, MODE_FLOAT);
/* sext_optab is also used for FLOAT_EXTEND. */
init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 4670b5b7..0afc2ec 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -406,6 +406,7 @@ enum convert_optab_index
COI_ufloat,
COI_lrint,
+ COI_lround,
COI_MAX
};
@@ -422,6 +423,7 @@ extern GTY(()) convert_optab convert_optab_table[COI_MAX];
#define sfloat_optab (convert_optab_table[COI_sfloat])
#define ufloat_optab (convert_optab_table[COI_ufloat])
#define lrint_optab (convert_optab_table[COI_lrint])
+#define lround_optab (convert_optab_table[COI_lround])
/* These arrays record the insn_code of insns that may be needed to
perform input and output reloads of special objects. They provide a
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 50ff789..8f5a435 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-10-28 Richard Guenther <rguenther@suse.de>
+
+ PR target/28806
+ * gcc.target/i386/math-torture/lround.c: New testcase.
+
2006-10-27 Kaz Kojima <kkojima@gcc.gnu.org>
* gcc.dg/builtins-43.c: Add -fno-finite-math-only.
diff --git a/gcc/testsuite/gcc.target/i386/math-torture/lround.c b/gcc/testsuite/gcc.target/i386/math-torture/lround.c
new file mode 100644
index 0000000..756356d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/math-torture/lround.c
@@ -0,0 +1,26 @@
+/* { dg-do assemble } */
+
+long testlf (float x)
+{
+ return __builtin_lroundf (x);
+}
+long testl (double x)
+{
+ return __builtin_lround (x);
+}
+long testll (long double x)
+{
+ return __builtin_lroundl (x);
+}
+long long testllf (float x)
+{
+ return __builtin_llroundf (x);
+}
+long long testll_ (double x)
+{
+ return __builtin_llround (x);
+}
+long long testlll (long double x)
+{
+ return __builtin_llroundl (x);
+}