From: uros Date: Tue, 29 Mar 2005 05:46:46 +0000 (+0000) Subject: * reg-stack.c (subst_stack_regs_pat): Handle case. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=3cd431f42e00e947ba4451ba4f4521fbd7a6246a * reg-stack.c (subst_stack_regs_pat): Handle 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, fist2, fist2_with_temp): New isns patterns to implement lrint and llrint built-ins as x87 intrinsic function. (fistdi2, fist2 splitters): New splitters. (lrint2): New expanders. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97151 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9d62a101b15..5ba2bc665a9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2005-03-29 Uros Bizjak + + * reg-stack.c (subst_stack_regs_pat): Handle 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, fist2, fist2_with_temp): + New isns patterns to implement lrint and llrint built-ins as x87 + intrinsic function. + (fistdi2, fist2 splitters): New splitters. + (lrint2): New expanders. + 2005-03-28 Ian Lance Taylor * 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 e2540173819..1e9165f4412 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 e168d112933..9041cd0b534 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 "fist2" + [(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" "")]) + +(define_insn "fist2_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" "")]) + +(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 "lrint2" + [(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_fist2 (operands[0], operands[1])); + else + { + operands[2] = assign_386_stack_local (mode, 0); + emit_insn (gen_fist2_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 e92e73cbf54..6f58341ba27 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: