aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/i386/i386.c7
-rw-r--r--gcc/config/i386/i386.md109
-rw-r--r--gcc/reg-stack.c21
4 files changed, 146 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9d62a10..5ba2bc6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2005-03-29 Uros Bizjak <uros@kss-loka.si>
+
+ * reg-stack.c (subst_stack_regs_pat): Handle <UNSPEC_FIST> case.
+ * config/i386/i386.c (output_fix_trunc): Add new round_mode
+ variable. Output "fldcw" depending on round_mode.
+ * config/i386/i386.md (UNSPEC_FIST): New.
+ (fistdi2, fistdi2_with_temp, fist<mode>2, fist<mode>2_with_temp):
+ New isns patterns to implement lrint and llrint built-ins as x87
+ intrinsic function.
+ (fistdi2, fist<mode>2 splitters): New splitters.
+ (lrint<mode>2): New expanders.
+
2005-03-28 Ian Lance Taylor <ian@airs.com>
* config/arc/arc.c (arc_output_function_epilogue): Pass prescan as
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e254017..1e9165f 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7287,6 +7287,7 @@ output_fix_trunc (rtx insn, rtx *operands, int fisttp)
{
int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
int dimode_p = GET_MODE (operands[0]) == DImode;
+ int round_mode = get_attr_i387_cw (insn);
/* Jump through a hoop or two for DImode, since the hardware has no
non-popping instruction. We used to do this a different way, but
@@ -7304,12 +7305,14 @@ output_fix_trunc (rtx insn, rtx *operands, int fisttp)
output_asm_insn ("fisttp%z0\t%0", operands);
else
{
- output_asm_insn ("fldcw\t%3", operands);
+ if (round_mode != I387_CW_ANY)
+ output_asm_insn ("fldcw\t%3", operands);
if (stack_top_dies || dimode_p)
output_asm_insn ("fistp%z0\t%0", operands);
else
output_asm_insn ("fist%z0\t%0", operands);
- output_asm_insn ("fldcw\t%2", operands);
+ if (round_mode != I387_CW_ANY)
+ output_asm_insn ("fldcw\t%2", operands);
}
return "";
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e168d11..9041cd0 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -119,7 +119,8 @@
(UNSPEC_FYL2X 66)
(UNSPEC_FYL2XP1 67)
(UNSPEC_FRNDINT 68)
- (UNSPEC_F2XM1 69)
+ (UNSPEC_FIST 69)
+ (UNSPEC_F2XM1 70)
; x87 Double output FP
(UNSPEC_SINCOS_COS 80)
@@ -16244,6 +16245,112 @@
DONE;
})
+(define_insn "fistdi2"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (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"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DI")])
+
+(define_insn "fistdi2_with_temp"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
+ 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"
+ "#"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DI")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:DI 2 "memory_operand" ""))
+ (clobber (match_scratch 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
+ (clobber (match_dup 3))])
+ (set (match_dup 0) (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:DI 2 "memory_operand" ""))
+ (clobber (match_scratch 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
+ (clobber (match_dup 3))])]
+ "")
+
+(define_insn "fist<mode>2"
+ [(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"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fist<mode>2_with_temp"
+ [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST))
+ (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m,m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "<MODE>")])
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "register_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST))
+ (set (match_dup 0) (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_scratch 2 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST))]
+ "")
+
+(define_expand "lrint<mode>2"
+ [(use (match_operand:X87MODEI 0 "nonimmediate_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ if (memory_operand (operands[0], VOIDmode))
+ emit_insn (gen_fist<mode>2 (operands[0], operands[1]));
+ else
+ {
+ operands[2] = assign_386_stack_local (<MODE>mode, 0);
+ emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
+ operands[2]));
+ }
+ DONE;
+})
+
(define_insn "frndintxf2_floor"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index e92e73c..6f58341 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -1672,6 +1672,27 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
case UNSPEC:
switch (XINT (pat_src, 1))
{
+ case UNSPEC_FIST:
+ /* These insns only operate on the top of the stack. */
+
+ src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+ emit_swap_insn (insn, regstack, *src1);
+
+ src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+
+ if (STACK_REG_P (*dest))
+ replace_reg (dest, FIRST_STACK_REG);
+
+ if (src1_note)
+ {
+ replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
+ regstack->top--;
+ CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
+ }
+
+ replace_reg (src1, FIRST_STACK_REG);
+ break;
+
case UNSPEC_SIN:
case UNSPEC_COS:
case UNSPEC_FRNDINT: