re PR target/18668 (use prescott's fisttp)

PR target/18668
	* config/i386/i386.h (x86_fisttp): New.
	(TARGET_FISTTP): New macro.
	* config/i386/i386.c (x86_fisttp): Set for NOCONA.
	(output_fix_trunc): Add fisttp parameter.  Generate fisttp x87
	instruction when fisttp flag is set.
	* config/i386/i386-protos.h (output_fix_trunc): Change declaration.

	* config/i386/i386.md (type attribute): Add fisttp.
	(unit attribute): Set to i387 for fisttp type.
	(X87MODEF, X87MODEI, SSEMODEF, SSEMODEI24): New mode macros.
	(fix_truncxfdi2, fix_truncxfsi2): Generate fisttp patterns for
	TARGET_FISTTP.
	(fix_truncdfdi2, fix_truncsfdi2, fix_truncdfsi2, fix_truncsfsi2):
	Generate fisttp patterns for TARGET_FISTTP. Implement using mode
	macros.
	(fix_truncxfhi2, fix_truncdfhi2, fix_truncsfhi2): Generate fisttp
	patterns for TARGET_FISTTP.  Enable patterns for
	(TARGET_FISTTP && !TARGET_SSE_MATH). Implement using mode macros.
	(fix_trunc<mode>_i387_fisttp_1, fix_trunc<mode>_i387_fisttp,
	fix_trunc<mode>_i387_fisttp_with_temp): New instruction patterns to
	implement fisttp x87 insn.
	(fix_trunc*_i387_fisttp splitters): New patterns.
	(*fix_truncdi_i387, *fix_truncsi_i387, *fix_trunchi_i387):
	Rename to *fix_trunc<mode>_i387_1.  Implement using mode macros.
	Disable patterns for TARGET_FISTTP.  Add comment about FLAGS_REG
	clobber.
	(fix_truncdi_memory, fix_truncdi_nomemory, fix_trunchi_nomemory):
	Rename to fix_trunc<mode>_i387 and fix_trunc<mode>_i387_with_temp.
	Implement using mode macros. Disable patterns for TARGET_FISTTP.
	(fix_truncsi_memory, fix_truncsi_nomemory, fix_trunchi_memory,
	fix_trunchi_nomemory): Rename to fix_trunc<mode>_i387 and
	fix_trunc<mode>_i387_with_temp. Implement using mode macros.
	Disable patterns for TARGET_FISTTP.
	(fix_trunc*_i387 splitters): Implement usign mode macros.
	(fix_truncdfdi_sse, fix_truncsfdi_sse, fix_truncdfsi_sse,
	fix_truncsfsi_sse): Disable for (TARGET_FISTTP && !TARGET_SSE_MATH).
	(fix_trunx*_sse peephole2s): Implement using mode macros.

From-SVN: r96477
This commit is contained in:
Uros Bizjak 2005-03-15 15:44:09 +01:00 committed by Uros Bizjak
parent 9b12dc4f93
commit 9199f050fa
5 changed files with 346 additions and 355 deletions

View File

@ -1,3 +1,44 @@
2005-03-15 Uros Bizjak <uros@kss-loka.si>
PR target/18668
* config/i386/i386.h (x86_fisttp): New.
(TARGET_FISTTP): New macro.
* config/i386/i386.c (x86_fisttp): Set for NOCONA.
(output_fix_trunc): Add fisttp parameter. Generate fisttp x87
instruction when fisttp flag is set.
* config/i386/i386-protos.h (output_fix_trunc): Change declaration.
* config/i386/i386.md (type attribute): Add fisttp.
(unit attribute): Set to i387 for fisttp type.
(X87MODEF, X87MODEI, SSEMODEF, SSEMODEI24): New mode macros.
(fix_truncxfdi2, fix_truncxfsi2): Generate fisttp patterns for
TARGET_FISTTP.
(fix_truncdfdi2, fix_truncsfdi2, fix_truncdfsi2, fix_truncsfsi2):
Generate fisttp patterns for TARGET_FISTTP. Implement using mode
macros.
(fix_truncxfhi2, fix_truncdfhi2, fix_truncsfhi2): Generate fisttp
patterns for TARGET_FISTTP. Enable patterns for
(TARGET_FISTTP && !TARGET_SSE_MATH). Implement using mode macros.
(fix_trunc<mode>_i387_fisttp_1, fix_trunc<mode>_i387_fisttp,
fix_trunc<mode>_i387_fisttp_with_temp): New instruction patterns to
implement fisttp x87 insn.
(fix_trunc*_i387_fisttp splitters): New patterns.
(*fix_truncdi_i387, *fix_truncsi_i387, *fix_trunchi_i387):
Rename to *fix_trunc<mode>_i387_1. Implement using mode macros.
Disable patterns for TARGET_FISTTP. Add comment about FLAGS_REG
clobber.
(fix_truncdi_memory, fix_truncdi_nomemory, fix_trunchi_nomemory):
Rename to fix_trunc<mode>_i387 and fix_trunc<mode>_i387_with_temp.
Implement using mode macros. Disable patterns for TARGET_FISTTP.
(fix_truncsi_memory, fix_truncsi_nomemory, fix_trunchi_memory,
fix_trunchi_nomemory): Rename to fix_trunc<mode>_i387 and
fix_trunc<mode>_i387_with_temp. Implement using mode macros.
Disable patterns for TARGET_FISTTP.
(fix_trunc*_i387 splitters): Implement usign mode macros.
(fix_truncdfdi_sse, fix_truncsfdi_sse, fix_truncdfsi_sse,
fix_truncsfsi_sse): Disable for (TARGET_FISTTP && !TARGET_SSE_MATH).
(fix_trunx*_sse peephole2s): Implement using mode macros.
2005-03-15 J"orn Rennecke <joern.rennecke@st.com>
PR rtl-optimization/20291

View File

@ -117,7 +117,7 @@ extern void split_ti (rtx[], int, rtx[], rtx[]);
extern const char *output_set_got (rtx);
extern const char *output_387_binary_op (rtx, rtx*);
extern const char *output_387_reg_move (rtx, rtx*);
extern const char *output_fix_trunc (rtx, rtx*);
extern const char *output_fix_trunc (rtx, rtx*, int);
extern const char *output_fp_compare (rtx, rtx*, int, int);
extern void i386_output_dwarf_dtprel (FILE*, int, rtx);

View File

@ -525,6 +525,7 @@ const int x86_double_with_add = ~m_386;
const int x86_use_bit_test = m_386;
const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON_K8 | m_K6;
const int x86_cmove = m_PPRO | m_ATHLON_K8 | m_PENT4 | m_NOCONA;
const int x86_fisttp = m_NOCONA;
const int x86_3dnow_a = m_ATHLON_K8;
const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON_K8 | m_PENT4 | m_NOCONA;
/* Branch hints were put in P4 based on simulation result. But
@ -7282,7 +7283,7 @@ emit_i387_cw_initialization (rtx current_mode, rtx new_mode, int mode)
operand may be [SDX]Fmode. */
const char *
output_fix_trunc (rtx insn, rtx *operands)
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;
@ -7290,7 +7291,7 @@ output_fix_trunc (rtx insn, rtx *operands)
/* 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
that was somewhat fragile and broke with post-reload splitters. */
if (dimode_p && !stack_top_dies)
if ((dimode_p || fisttp) && !stack_top_dies)
output_asm_insn ("fld\t%y1", operands);
if (!STACK_TOP_P (operands[1]))
@ -7299,12 +7300,17 @@ output_fix_trunc (rtx insn, rtx *operands)
if (GET_CODE (operands[0]) != MEM)
abort ();
output_asm_insn ("fldcw\t%3", operands);
if (stack_top_dies || dimode_p)
output_asm_insn ("fistp%z0\t%0", operands);
if (fisttp)
output_asm_insn ("fisttp%z0\t%0", operands);
else
output_asm_insn ("fist%z0\t%0", operands);
output_asm_insn ("fldcw\t%2", operands);
{
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);
}
return "";
}

View File

@ -229,7 +229,7 @@ extern int target_flags;
#define TUNEMASK (1 << ix86_tune)
extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
extern const int x86_use_bit_test, x86_cmove, x86_deep_branch;
extern const int x86_use_bit_test, x86_cmove, x86_fisttp, x86_deep_branch;
extern const int x86_branch_hints, x86_unroll_strlen;
extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx;
extern const int x86_use_loop, x86_use_himode_fiop, x86_use_simode_fiop;
@ -258,6 +258,7 @@ extern int x86_prefetch_sse;
/* For sane SSE instruction set generation we need fcomi instruction. It is
safe to enable all CMOVE instructions. */
#define TARGET_CMOVE ((x86_cmove & (1 << ix86_arch)) || TARGET_SSE)
#define TARGET_FISTTP (x86_fisttp & (1 << ix86_arch))
#define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & TUNEMASK)
#define TARGET_BRANCH_PREDICTION_HINTS (x86_branch_hints & TUNEMASK)
#define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & TUNEMASK)

View File

@ -194,7 +194,7 @@
icmp,test,ibr,setcc,icmov,
push,pop,call,callv,leave,
str,cld,
fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,frndint,
fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
sselog,sselog1,sseiadd,sseishft,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,
mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
@ -207,7 +207,7 @@
;; The CPU unit operations uses.
(define_attr "unit" "integer,i387,sse,mmx,unknown"
(cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,frndint")
(cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
(const_string "i387")
(eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv")
@ -442,8 +442,21 @@
[(set_attr "length" "128")
(set_attr "type" "multi")])
;; All x87 floating point modes
(define_mode_macro X87MODEF [SF DF XF])
;; All integer modes handled by x87 fisttp operator.
(define_mode_macro X87MODEI [HI SI DI])
;; All integer modes handled by integer x87 operators.
(define_mode_macro X87MODEI12 [HI SI])
;; All SSE floating point modes
(define_mode_macro SSEMODEF [SF DF])
;; All integer modes handled by SSE cvtts?2si* operators.
(define_mode_macro SSEMODEI24 [SI DI])
;; Scheduling descriptions
@ -3998,8 +4011,6 @@
[(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
"")
;; %%% Break up all these bad boys.
;; Signed conversion to DImode.
(define_expand "fix_truncxfdi2"
@ -4007,49 +4018,234 @@
(fix:DI (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387"
{
if (TARGET_FISTTP)
{
emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
})
(define_expand "fix_trunc<mode>di2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))"
{
if (TARGET_FISTTP
&& !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
{
emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
emit_insn (gen_fix_trunc<mode>di_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
;; Signed conversion to SImode.
(define_expand "fix_truncxfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387"
{
if (TARGET_FISTTP)
{
emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
})
(define_expand "fix_trunc<mode>si2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode))"
{
if (TARGET_FISTTP
&& !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
{
emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
if (SSE_FLOAT_MODE_P (<MODE>mode))
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
emit_insn (gen_fix_trunc<mode>si_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
;; Signed conversion to HImode.
(define_expand "fix_trunc<mode>hi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:X87MODEF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387
&& !(SSE_FLOAT_MODE_P (<MODE>mode) && (!TARGET_FISTTP || TARGET_SSE_MATH))"
{
if (TARGET_FISTTP)
{
emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
})
;; When SSE is available, it is always faster to use it!
(define_insn "fix_truncsfdi_sse"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
"TARGET_64BIT && TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvttss2si{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "SF")
(set_attr "athlon_decode" "double,vector")])
(define_insn "fix_truncdfdi_sse"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
"TARGET_64BIT && TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvttsd2si{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
(define_insn "fix_truncsfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
"TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvttss2si\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
(define_insn "fix_truncdfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
"TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvttsd2si\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
;; Avoid vector decoded forms of the instruction.
(define_peephole2
[(match_scratch:DF 2 "Y")
(set (match_operand:SSEMODEI24 0 "register_operand" "")
(fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
"TARGET_K8 && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
"")
(define_expand "fix_truncdfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || (TARGET_64BIT && TARGET_SSE2)"
{
if (TARGET_64BIT && TARGET_SSE2)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
emit_insn (gen_fix_truncdfdi_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
(define_peephole2
[(match_scratch:SF 2 "x")
(set (match_operand:SSEMODEI24 0 "register_operand" "")
(fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
"TARGET_K8 && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
"")
(define_expand "fix_truncsfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || (TARGET_64BIT && TARGET_SSE)"
(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
[(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
"TARGET_80387 && TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || <MODE>mode != DImode))
&& TARGET_SSE_MATH)
&& !(reload_completed || reload_in_progress)"
"#"
"&& 1"
[(const_int 0)]
{
if (TARGET_64BIT && TARGET_SSE)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
emit_insn (gen_fix_truncsfdi_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
if (memory_operand (operands[0], VOIDmode))
emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
else
{
operands[2] = assign_386_stack_local (<MODE>mode, 0);
emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
operands[1],
operands[2]));
}
DONE;
}
[(set_attr "type" "fisttp")
(set_attr "mode" "<MODE>")])
(define_insn "fix_trunc<mode>_i387_fisttp"
[(set (match_operand:X87MODEI 0 "memory_operand" "=m")
(fix:X87MODEI (match_operand 1 "register_operand" "f")))
(clobber (match_scratch:XF 2 "=&1f"))]
"TARGET_80387 && TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || <MODE>mode != DImode))
&& TARGET_SSE_MATH)"
"* return output_fix_trunc (insn, operands, 1);"
[(set_attr "type" "fisttp")
(set_attr "mode" "<MODE>")])
(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
[(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
(clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
(clobber (match_scratch:XF 3 "=&1f,&1f"))]
"TARGET_80387 && TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || <MODE>mode != DImode))
&& TARGET_SSE_MATH)"
"#"
[(set_attr "type" "fisttp")
(set_attr "mode" "<MODE>")])
(define_split
[(set (match_operand:X87MODEI 0 "register_operand" "")
(fix:X87MODEI (match_operand 1 "register_operand" "")))
(clobber (match_operand:X87MODEI 2 "memory_operand" ""))
(clobber (match_scratch 3 ""))]
"reload_completed"
[(parallel [(set (match_dup 2) (fix:X87MODEI (match_dup 1)))
(clobber (match_dup 3))])
(set (match_dup 0) (match_dup 2))]
"")
(define_split
[(set (match_operand:X87MODEI 0 "memory_operand" "")
(fix:X87MODEI (match_operand 1 "register_operand" "")))
(clobber (match_operand:X87MODEI 2 "memory_operand" ""))
(clobber (match_scratch 3 ""))]
"reload_completed"
[(parallel [(set (match_dup 0) (fix:X87MODEI (match_dup 1)))
(clobber (match_dup 3))])]
"")
;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
;; of the machinery.
(define_insn_and_split "*fix_truncdi_i387"
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
(fix:DI (match_operand 1 "register_operand" "f,f")))
;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
;; function in i386.c.
(define_insn_and_split "*fix_trunc<mode>_i387_1"
[(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !reload_completed && !reload_in_progress
&& (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
"TARGET_80387 && !TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || <MODE>mode != DImode))
&& !(reload_completed || reload_in_progress)"
"#"
"&& 1"
[(const_int 0)]
@ -4058,48 +4254,50 @@
operands[2] = assign_386_stack_local (HImode, 1);
operands[3] = assign_386_stack_local (HImode, 2);
if (memory_operand (operands[0], VOIDmode))
emit_insn (gen_fix_truncdi_memory (operands[0], operands[1],
operands[2], operands[3]));
emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
operands[2], operands[3]));
else
{
operands[4] = assign_386_stack_local (DImode, 0);
emit_insn (gen_fix_truncdi_nomemory (operands[0], operands[1],
operands[2], operands[3],
operands[4]));
operands[4] = assign_386_stack_local (<MODE>mode, 0);
emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
operands[2], operands[3],
operands[4]));
}
DONE;
}
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "<MODE>")])
(define_insn "fix_truncdi_i387"
[(set (match_operand:DI 0 "memory_operand" "=m")
(fix:DI (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))
(clobber (match_scratch:XF 4 "=&1f"))]
"TARGET_80387 && !TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
(define_insn "fix_truncdi_nomemory"
(define_insn "fix_truncdi_i387_with_temp"
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
(fix:DI (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:DI 4 "memory_operand" "=m,m"))
(clobber (match_scratch:DF 5 "=&1f,&1f"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
(clobber (match_scratch:XF 5 "=&1f,&1f"))]
"TARGET_80387 && !TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"#"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
(define_insn "fix_truncdi_memory"
[(set (match_operand:DI 0 "memory_operand" "=m")
(fix:DI (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))
(clobber (match_scratch:DF 4 "=&1f"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(fix:DI (match_operand 1 "register_operand" "")))
@ -4129,313 +4327,58 @@
(clobber (match_dup 5))])]
"")
;; When SSE available, it is always faster to use it!
(define_insn "fix_truncsfdi_sse"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
"TARGET_64BIT && TARGET_SSE"
"cvttss2si{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "SF")
(set_attr "athlon_decode" "double,vector")])
;; Avoid vector decoded form of the instruction.
(define_peephole2
[(match_scratch:SF 2 "x")
(set (match_operand:DI 0 "register_operand" "")
(fix:DI (match_operand:SF 1 "memory_operand" "")))]
"TARGET_K8 && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:DI (match_dup 2)))]
"")
(define_insn "fix_truncdfdi_sse"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
"TARGET_64BIT && TARGET_SSE2"
"cvttsd2si{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt,sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
;; Avoid vector decoded form of the instruction.
(define_peephole2
[(match_scratch:DF 2 "Y")
(set (match_operand:DI 0 "register_operand" "")
(fix:DI (match_operand:DF 1 "memory_operand" "")))]
"TARGET_K8 && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:DI (match_dup 2)))]
"")
;; Signed conversion to SImode.
(define_expand "fix_truncxfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387"
"")
(define_expand "fix_truncdfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || TARGET_SSE2"
{
if (TARGET_SSE2)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
emit_insn (gen_fix_truncdfsi_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
(define_expand "fix_truncsfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || TARGET_SSE"
{
if (TARGET_SSE)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
emit_insn (gen_fix_truncsfsi_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
;; of the machinery.
(define_insn_and_split "*fix_truncsi_i387"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
(fix:SI (match_operand 1 "register_operand" "f,f")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !reload_completed && !reload_in_progress
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
"&& 1"
[(const_int 0)]
{
ix86_optimize_mode_switching = 1;
operands[2] = assign_386_stack_local (HImode, 1);
operands[3] = assign_386_stack_local (HImode, 2);
if (memory_operand (operands[0], VOIDmode))
emit_insn (gen_fix_truncsi_memory (operands[0], operands[1],
operands[2], operands[3]));
else
{
operands[4] = assign_386_stack_local (SImode, 0);
emit_insn (gen_fix_truncsi_nomemory (operands[0], operands[1],
operands[2], operands[3],
operands[4]));
}
DONE;
}
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "SI")])
(define_insn "fix_truncsi_nomemory"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
(fix:SI (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:SI 4 "memory_operand" "=m,m"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "SI")])
(define_insn "fix_truncsi_memory"
[(set (match_operand:SI 0 "memory_operand" "=m")
(fix:SI (match_operand 1 "register_operand" "f")))
(define_insn "fix_trunc<mode>_i387"
[(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
(fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
"TARGET_80387 && !TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"* return output_fix_trunc (insn, operands);"
"* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "SI")])
(set_attr "mode" "<MODE>")])
;; When SSE available, it is always faster to use it!
(define_insn "fix_truncsfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
"TARGET_SSE"
"cvttss2si\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
;; Avoid vector decoded form of the instruction.
(define_peephole2
[(match_scratch:SF 2 "x")
(set (match_operand:SI 0 "register_operand" "")
(fix:SI (match_operand:SF 1 "memory_operand" "")))]
"TARGET_K8 && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SI (match_dup 2)))]
"")
(define_insn "fix_truncdfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
"TARGET_SSE2"
"cvttsd2si\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
;; Avoid vector decoded form of the instruction.
(define_peephole2
[(match_scratch:DF 2 "Y")
(set (match_operand:SI 0 "register_operand" "")
(fix:SI (match_operand:DF 1 "memory_operand" "")))]
"TARGET_K8 && !optimize_size"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SI (match_dup 2)))]
"")
(define_insn "fix_trunc<mode>_i387_with_temp"
[(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
(fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
"TARGET_80387 && !TARGET_FISTTP
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "<MODE>")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(fix:SI (match_operand 1 "register_operand" "")))
[(set (match_operand:X87MODEI12 0 "register_operand" "")
(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
(use (match_operand:HI 2 "memory_operand" ""))
(use (match_operand:HI 3 "memory_operand" ""))
(clobber (match_operand:SI 4 "memory_operand" ""))]
(clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
"reload_completed"
[(parallel [(set (match_dup 4) (fix:SI (match_dup 1)))
[(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1)))
(use (match_dup 2))
(use (match_dup 3))])
(set (match_dup 0) (match_dup 4))]
"")
(define_split
[(set (match_operand:SI 0 "memory_operand" "")
(fix:SI (match_operand 1 "register_operand" "")))
[(set (match_operand:X87MODEI12 0 "memory_operand" "")
(fix:X87MODEI12 (match_operand 1 "register_operand" "")))
(use (match_operand:HI 2 "memory_operand" ""))
(use (match_operand:HI 3 "memory_operand" ""))
(clobber (match_operand:SI 4 "memory_operand" ""))]
(clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
"reload_completed"
[(parallel [(set (match_dup 0) (fix:SI (match_dup 1)))
[(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1)))
(use (match_dup 2))
(use (match_dup 3))])]
"")
;; Signed conversion to HImode.
(define_expand "fix_truncxfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387"
"")
(define_expand "fix_truncdfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 && !TARGET_SSE2"
"")
(define_expand "fix_truncsfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 && !TARGET_SSE"
"")
;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
;; of the machinery.
(define_insn_and_split "*fix_trunchi_i387"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r")
(fix:HI (match_operand 1 "register_operand" "f,f")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !reload_completed && !reload_in_progress
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
"&& 1"
[(const_int 0)]
{
ix86_optimize_mode_switching = 1;
operands[2] = assign_386_stack_local (HImode, 1);
operands[3] = assign_386_stack_local (HImode, 2);
if (memory_operand (operands[0], VOIDmode))
emit_insn (gen_fix_trunchi_memory (operands[0], operands[1],
operands[2], operands[3]));
else
{
operands[4] = assign_386_stack_local (HImode, 0);
emit_insn (gen_fix_trunchi_nomemory (operands[0], operands[1],
operands[2], operands[3],
operands[4]));
}
DONE;
}
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "HI")])
(define_insn "fix_trunchi_nomemory"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r")
(fix:HI (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:HI 4 "memory_operand" "=m,m"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "HI")])
(define_insn "fix_trunchi_memory"
[(set (match_operand:HI 0 "memory_operand" "=m")
(fix:HI (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fistp")
(set_attr "i387_cw" "trunc")
(set_attr "mode" "HI")])
(define_split
[(set (match_operand:HI 0 "memory_operand" "")
(fix:HI (match_operand 1 "register_operand" "")))
(use (match_operand:HI 2 "memory_operand" ""))
(use (match_operand:HI 3 "memory_operand" ""))
(clobber (match_operand:HI 4 "memory_operand" ""))]
"reload_completed"
[(parallel [(set (match_dup 0) (fix:HI (match_dup 1)))
(use (match_dup 2))
(use (match_dup 3))])]
"")
(define_split
[(set (match_operand:HI 0 "register_operand" "")
(fix:HI (match_operand 1 "register_operand" "")))
(use (match_operand:HI 2 "memory_operand" ""))
(use (match_operand:HI 3 "memory_operand" ""))
(clobber (match_operand:HI 4 "memory_operand" ""))]
"reload_completed"
[(parallel [(set (match_dup 4) (fix:HI (match_dup 1)))
(use (match_dup 2))
(use (match_dup 3))
(clobber (match_dup 4))])
(set (match_dup 0) (match_dup 4))]
"")
(define_insn "x86_fnstcw_1"
[(set (match_operand:HI 0 "memory_operand" "=m")
(unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]