aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2006-10-25 13:01:14 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2006-10-25 13:01:14 +0000
commitbb7f04236c6c8c1f248f27eb86d9eb486a93c64b (patch)
treea42a7cd31e5e9d2deb0e1ba2a6a9064a8aeaef12
parentef984648a15c2c9b8b5127c1ac2e10f3f9793cec (diff)
downloadgcc-bb7f04236c6c8c1f248f27eb86d9eb486a93c64b.zip
gcc-bb7f04236c6c8c1f248f27eb86d9eb486a93c64b.tar.gz
gcc-bb7f04236c6c8c1f248f27eb86d9eb486a93c64b.tar.bz2
optabs.h (enum optab_index): Remove OTI_lrint.
2006-10-25 Richard Guenther <rguenther@suse.de> * optabs.h (enum optab_index): Remove OTI_lrint. (enum convert_optab_index): Add COI_lrint. (lrint_optab): Adjust. (expand_sfix_optab): Declare. * optabs.c (expand_sfix_optab): New function. (init_optabs): Init lrint_optab as conversion optab. * genopinit.c (lrint_optab): Change to a conversion optab. * builtins.c (expand_builtin_int_roundingfn_2): Adjust to expansion via conversion optab. * config/i386/i386.md (*fistdi2_1): Remove flag_unsafe_math_optimizations guard. (fistdi2, fistdi2_with_temp, *fist<mode>2_1, fist<mode>2, fist<mode>2_with_temp): Likewise. (lrint<mode>2): Split into... (lrintxf<mode>2): ... x87 part (lrint<mode>di2, lrint<mode>si2): ... and SSE parts. * config/i386/sse.md (sse_cvtss2si_2, sse_cvtss2_siq_2, sse2_cvtsd2si_2, sse2_cvtsd2siq_2): New insns for UNSPEC_FIX_NOTRUNC matching non-vector float modes. * doc/md.texi (lrintMN2): Document. From-SVN: r118029
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/builtins.c58
-rw-r--r--gcc/config/i386/i386.md38
-rw-r--r--gcc/config/i386/sse.md40
-rw-r--r--gcc/doc/md.texi6
-rw-r--r--gcc/genopinit.c2
-rw-r--r--gcc/optabs.c44
-rw-r--r--gcc/optabs.h8
8 files changed, 167 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a4ffc2d..3db23d4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2006-10-25 Richard Guenther <rguenther@suse.de>
+
+ PR target/28803
+ * optabs.h (enum optab_index): Remove OTI_lrint.
+ (enum convert_optab_index): Add COI_lrint.
+ (lrint_optab): Adjust.
+ (expand_sfix_optab): Declare.
+ * optabs.c (expand_sfix_optab): New function.
+ (init_optabs): Init lrint_optab as conversion optab.
+ * genopinit.c (lrint_optab): Change to a conversion optab.
+ * builtins.c (expand_builtin_int_roundingfn_2): Adjust to
+ expansion via conversion optab.
+ * config/i386/i386.md (*fistdi2_1): Remove
+ flag_unsafe_math_optimizations guard.
+ (fistdi2, fistdi2_with_temp, *fist<mode>2_1, fist<mode>2,
+ fist<mode>2_with_temp): Likewise.
+ (lrint<mode>2): Split into...
+ (lrintxf<mode>2): ... x87 part
+ (lrint<mode>di2, lrint<mode>si2): ... and SSE parts.
+ * config/i386/sse.md (sse_cvtss2si_2, sse_cvtss2_siq_2,
+ sse2_cvtsd2si_2, sse2_cvtsd2siq_2): New insns for
+ UNSPEC_FIX_NOTRUNC matching non-vector float modes.
+ * doc/md.texi (lrintMN2): Document.
+
2006-10-25 Uros Bizjak <uros@kss-loka.si>
PR target/28909
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 6955cda..1dcda03 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2320,7 +2320,7 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
static rtx
expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
{
- optab builtin_optab;
+ convert_optab builtin_optab;
rtx op0, insns;
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
@@ -2348,45 +2348,37 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
/* Make a suitable register to place result in. */
mode = TYPE_MODE (TREE_TYPE (exp));
- /* Before working hard, check whether the instruction is available. */
- if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- target = gen_reg_rtx (mode);
-
- /* Wrap the computation of the argument in a SAVE_EXPR, as we may
- need to expand the argument again. This way, we will not perform
- side-effects more the once. */
- narg = builtin_save_expr (arg);
- if (narg != arg)
- {
- arg = narg;
- arglist = build_tree_list (NULL_TREE, arg);
- exp = build_function_call_expr (fndecl, arglist);
- }
-
- op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+ target = gen_reg_rtx (mode);
- start_sequence ();
+ /* Wrap the computation of the argument in a SAVE_EXPR, as we may
+ need to expand the argument again. This way, we will not perform
+ side-effects more the once. */
+ narg = builtin_save_expr (arg);
+ if (narg != arg)
+ {
+ arg = narg;
+ arglist = build_tree_list (NULL_TREE, arg);
+ exp = build_function_call_expr (fndecl, arglist);
+ }
- /* Compute into TARGET.
- Set TARGET to wherever the result comes back. */
- target = expand_unop (mode, builtin_optab, op0, target, 0);
+ op0 = expand_expr (arg, subtarget, VOIDmode, 0);
- if (target != 0)
- {
- /* Output the entire sequence. */
- insns = get_insns ();
- end_sequence ();
- emit_insn (insns);
- return target;
- }
+ start_sequence ();
- /* If we were unable to expand via the builtin, stop the sequence
- (without outputting the insns) and call to the library function
- with the stabilized argument list. */
+ if (expand_sfix_optab (target, op0, builtin_optab))
+ {
+ /* Output the entire sequence. */
+ insns = get_insns ();
end_sequence ();
+ emit_insn (insns);
+ return target;
}
+ /* If we were unable to expand via the builtin, stop the sequence
+ (without outputting the insns) and call to the library function
+ with the stabilized argument list. */
+ end_sequence ();
+
target = expand_call (exp, target, target == const0_rtx);
return target;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aadf2ff..5e69167 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -17205,7 +17205,6 @@
(unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
UNSPEC_FIST))]
"TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations
&& !(reload_completed || reload_in_progress)"
"#"
"&& 1"
@@ -17229,8 +17228,7 @@
(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FIST))
(clobber (match_scratch:XF 2 "=&1f"))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
+ "TARGET_USE_FANCY_MATH_387"
"* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fpspc")
(set_attr "mode" "DI")])
@@ -17241,8 +17239,7 @@
UNSPEC_FIST))
(clobber (match_operand:DI 2 "memory_operand" "=m,m"))
(clobber (match_scratch:XF 3 "=&1f,&1f"))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
+ "TARGET_USE_FANCY_MATH_387"
"#"
[(set_attr "type" "fpspc")
(set_attr "mode" "DI")])
@@ -17275,7 +17272,6 @@
(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FIST))]
"TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations
&& !(reload_completed || reload_in_progress)"
"#"
"&& 1"
@@ -17293,8 +17289,7 @@
[(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FIST))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
+ "TARGET_USE_FANCY_MATH_387"
"* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fpspc")
(set_attr "mode" "<MODE>")])
@@ -17304,8 +17299,7 @@
(unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FIST))
(clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
+ "TARGET_USE_FANCY_MATH_387"
"#"
[(set_attr "type" "fpspc")
(set_attr "mode" "<MODE>")])
@@ -17331,13 +17325,25 @@
UNSPEC_FIST))]
"")
-(define_expand "lrint<mode>2"
+(define_expand "lrintxf<mode>2"
[(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
- (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
- UNSPEC_FIST))]
- "TARGET_USE_FANCY_MATH_387
- && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
+ (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))]
+ "TARGET_USE_FANCY_MATH_387"
+ "")
+
+(define_expand "lrint<mode>di2"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (unspec:DI [(match_operand:SSEMODEF 1 "register_operand" "")]
+ UNSPEC_FIX_NOTRUNC))]
+ "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH && TARGET_64BIT"
+ "")
+
+(define_expand "lrint<mode>si2"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (unspec:SI [(match_operand:SSEMODEF 1 "register_operand" "")]
+ UNSPEC_FIX_NOTRUNC))]
+ "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
"")
;; Rounding mode control word calculation could clobber FLAGS_REG.
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 1424149..8f5786a 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -974,6 +974,16 @@
(set_attr "athlon_decode" "double,vector")
(set_attr "mode" "SI")])
+(define_insn "sse_cvtss2si_2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec:SI [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE"
+ "cvtss2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "SI")])
+
(define_insn "sse_cvtss2siq"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(unspec:DI
@@ -987,6 +997,16 @@
(set_attr "athlon_decode" "double,vector")
(set_attr "mode" "DI")])
+(define_insn "sse_cvtss2siq_2"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (unspec:DI [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE && TARGET_64BIT"
+ "cvtss2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "DI")])
+
(define_insn "sse_cvttss2si"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI
@@ -1932,6 +1952,16 @@
(set_attr "athlon_decode" "double,vector")
(set_attr "mode" "SI")])
+(define_insn "sse2_cvtsd2si_2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec:SI [(match_operand:DF 1 "nonimmediate_operand" "x,m")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE2"
+ "cvtsd2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "SI")])
+
(define_insn "sse2_cvtsd2siq"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(unspec:DI
@@ -1945,6 +1975,16 @@
(set_attr "athlon_decode" "double,vector")
(set_attr "mode" "DI")])
+(define_insn "sse2_cvtsd2siq_2"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (unspec:DI [(match_operand:DF 1 "nonimmediate_operand" "x,m")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvtsd2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "DI")])
+
(define_insn "sse2_cvttsd2si"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index a05f9d0..a41391c 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -3702,6 +3702,12 @@ corresponds to the C data type @code{double} and the @code{rintf}
built-in function uses the mode which corresponds to the C data
type @code{float}.
+@cindex @code{lrint@var{m}@var{n}2}
+@item @samp{lrint@var{m}@var{n}2}
+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{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 4f7bd46..1575735 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -127,7 +127,7 @@ static const char * const optabs[] =
"btrunc_optab->handlers[$A].insn_code = CODE_FOR_$(btrunc$a2$)",
"nearbyint_optab->handlers[$A].insn_code = CODE_FOR_$(nearbyint$a2$)",
"rint_optab->handlers[$A].insn_code = CODE_FOR_$(rint$a2$)",
- "lrint_optab->handlers[$A].insn_code = CODE_FOR_$(lrint$a2$)",
+ "lrint_optab->handlers[$B][$A].insn_code = CODE_FOR_$(lrint$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 12fd34e..11cacae 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4861,6 +4861,46 @@ expand_fix (rtx to, rtx from, int unsignedp)
convert_move (to, target, 0);
}
}
+
+/* Generate code to convert FROM to fixed point and store in TO. FROM
+ must be floating point, TO must be signed. Use the conversion optab
+ TAB to do the conversion. */
+
+bool
+expand_sfix_optab (rtx to, rtx from, convert_optab tab)
+{
+ enum insn_code icode;
+ rtx target = to;
+ enum machine_mode fmode, imode;
+
+ /* We first try to find a pair of modes, one real and one integer, at
+ least as wide as FROM and TO, respectively, in which we can open-code
+ this conversion. If the integer mode is wider than the mode of TO,
+ we can do the conversion either signed or unsigned. */
+
+ for (fmode = GET_MODE (from); fmode != VOIDmode;
+ fmode = GET_MODE_WIDER_MODE (fmode))
+ for (imode = GET_MODE (to); imode != VOIDmode;
+ imode = GET_MODE_WIDER_MODE (imode))
+ {
+ icode = tab->handlers[imode][fmode].insn_code;
+ if (icode != CODE_FOR_nothing)
+ {
+ if (fmode != GET_MODE (from))
+ from = convert_to_mode (fmode, from, 0);
+
+ if (imode != GET_MODE (to))
+ target = gen_reg_rtx (imode);
+
+ emit_unop_insn (icode, target, from, UNKNOWN);
+ if (target != to)
+ convert_move (to, target, 0);
+ return true;
+ }
+ }
+
+ return false;
+}
/* Report whether we have an instruction to perform the operation
specified by CODE on operands of mode MODE. */
@@ -5266,7 +5306,6 @@ init_optabs (void)
btrunc_optab = init_optab (UNKNOWN);
nearbyint_optab = init_optab (UNKNOWN);
rint_optab = init_optab (UNKNOWN);
- lrint_optab = init_optab (UNKNOWN);
sincos_optab = init_optab (UNKNOWN);
sin_optab = init_optab (UNKNOWN);
asin_optab = init_optab (UNKNOWN);
@@ -5325,6 +5364,7 @@ init_optabs (void)
ufixtrunc_optab = init_convert_optab (UNKNOWN);
sfloat_optab = init_convert_optab (FLOAT);
ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);
+ lrint_optab = init_convert_optab (UNKNOWN);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
@@ -5444,6 +5484,8 @@ init_optabs (void)
MODE_DECIMAL_FLOAT, MODE_INT);
init_interclass_conv_libfuncs (ufloat_optab, "floatuns",
MODE_INT, MODE_DECIMAL_FLOAT);
+ init_interclass_conv_libfuncs (lrint_optab, "lrint",
+ 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 69dcbe1..4670b5b7 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -196,7 +196,6 @@ enum optab_index
OTI_round,
OTI_nearbyint,
OTI_rint,
- OTI_lrint,
/* Tangent */
OTI_tan,
/* Inverse tangent */
@@ -345,7 +344,6 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define round_optab (optab_table[OTI_round])
#define nearbyint_optab (optab_table[OTI_nearbyint])
#define rint_optab (optab_table[OTI_rint])
-#define lrint_optab (optab_table[OTI_lrint])
#define tan_optab (optab_table[OTI_tan])
#define atan_optab (optab_table[OTI_atan])
#define copysign_optab (optab_table[OTI_copysign])
@@ -407,6 +405,8 @@ enum convert_optab_index
COI_sfloat,
COI_ufloat,
+ COI_lrint,
+
COI_MAX
};
@@ -421,6 +421,7 @@ extern GTY(()) convert_optab convert_optab_table[COI_MAX];
#define ufixtrunc_optab (convert_optab_table[COI_ufixtrunc])
#define sfloat_optab (convert_optab_table[COI_sfloat])
#define ufloat_optab (convert_optab_table[COI_ufloat])
+#define lrint_optab (convert_optab_table[COI_lrint])
/* These arrays record the insn_code of insns that may be needed to
perform input and output reloads of special objects. They provide a
@@ -597,6 +598,9 @@ extern void expand_float (rtx, rtx, int);
/* Generate code for a FIX_EXPR. */
extern void expand_fix (rtx, rtx, int);
+/* Generate code for float to integral conversion. */
+extern bool expand_sfix_optab (rtx, rtx, convert_optab);
+
/* Return tree if target supports vector operations for COND_EXPR. */
bool expand_vec_cond_expr_p (tree, enum machine_mode);