From 6e858d450b5a9774494ce68c5084f7dc9a9d2138 Mon Sep 17 00:00:00 2001 From: Uros Bizjak <uros@kss-loka.si> Date: Tue, 29 Mar 2005 07:46:46 +0200 Subject: [PATCH] reg-stack.c (subst_stack_regs_pat): Handle <UNSPEC_FIST> case. * 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. From-SVN: r97151 --- gcc/ChangeLog | 12 +++++ gcc/config/i386/i386.c | 7 ++- gcc/config/i386/i386.md | 109 +++++++++++++++++++++++++++++++++++++++- gcc/reg-stack.c | 21 ++++++++ 4 files changed, 146 insertions(+), 3 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9d62a101b156..5ba2bc665a92 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 e25401738191..1e9165f4412a 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 e168d112933e..9041cd0b5347 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 e92e73cbf547..6f58341ba277 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: -- GitLab