This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
better fp truncation sequence on i386
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com, patches at x86-64 dot org, timothy dot c dot prince at intel dot com
- Subject: better fp truncation sequence on i386
- From: Jan Hubicka <jh at suse dot cz>
- Date: Fri, 22 Jun 2001 19:05:33 +0200
Hi
Tim Prince has noticed, that current sequence emitted for float->int
converisons on i386 is several times slower than 2.95 ones on P3/P4.
The purpose is an partial memory stall, so I've redesigned the patterns
to use back original sequence.
Moreover I've split the control word value generation from pattern itself, so
redundant initialzations are usually eliminated.
There is an important drawback still. The FIX patterns now do use USE
and combine is not able to combine memory output to the pattern, as it loses
that uses. I will try to fix this at combine side.
Overall it should be still better to make unconditional pre-reload splitter
pass to add the USEs and use mode_switching pass to initialize the CW values.
Unconditional pre-reload splitting can be usefull on number of other passes
as well. Can be OK if I add one?
Bootstrapped on i686
Honza
Pá čen 22 18:47:46 CEST 2001 Jan Hubicka <jh@suse.cz>
* i386-protos.h (emit_i387_cw_initialization): Declare.
* i386.md (movsi_insv_1): Remove '*'.
(fix_trunc?f?i2): Revamp to use control word parameters.
(fix_trunc?i_1): Likewise; update splitters.
(fix splitter): Remove.
* i386.c (MAX_386_STACK_LOCALS): set to 3.
(emit_i387_cw_initialization): New function.
(output_fix_trunc): Do not initialize control word;
kill dead code; simplify.
*** i386.work/i386-protos.h Fri Jun 22 17:20:12 2001
--- i386/i386-protos.h Fri Jun 22 18:36:11 2001
*************** extern enum reg_class ix86_preferred_rel
*** 154,159 ****
--- 154,160 ----
extern int ix86_memory_move_cost PARAMS ((enum machine_mode, enum reg_class,
int));
extern void ix86_set_move_mem_attrs PARAMS ((rtx, rtx, rtx, rtx, rtx));
+ extern void emit_i387_cw_initialization PARAMS ((rtx, rtx));
#ifdef TREE_CODE
*** i386.work/i386.md Fri Jun 22 17:20:13 2001
--- i386/i386.md Fri Jun 22 18:17:36 2001
***************
*** 2313,2319 ****
(const_string "SI")
(const_string "QI")))])
! (define_insn "*movsi_insv_1"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
(const_int 8)
(const_int 8))
--- 2313,2319 ----
(const_string "SI")
(const_string "QI")))])
! (define_insn "movsi_insv_1"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
(const_int 8)
(const_int 8))
***************
*** 4692,4723 ****
(define_expand "fix_truncxfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:XF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:XF 5 ""))])]
"TARGET_80387 && !TARGET_64BIT"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (DImode, 1);")
(define_expand "fix_trunctfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:TF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))
! (clobber (match_scratch:TF 5 ""))])]
"TARGET_80387"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (DImode, 1);")
(define_expand "fix_truncdfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:DF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))
! (clobber (match_scratch:DF 5 ""))])]
"TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
"
{
--- 4692,4727 ----
(define_expand "fix_truncxfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:XF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))
(clobber (match_scratch:XF 5 ""))])]
"TARGET_80387 && !TARGET_64BIT"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (DImode, 0);")
(define_expand "fix_trunctfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:TF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))
! (clobber (match_scratch:XF 5 ""))])]
"TARGET_80387"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (DImode, 0);")
(define_expand "fix_truncdfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:DF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))
! (clobber (match_scratch:XF 5 ""))])]
"TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
"
{
***************
*** 4731,4748 ****
}
else
{
! operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (DImode, 1);
}
}")
(define_expand "fix_truncsfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:SF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))
! (clobber (match_scratch:SF 5 ""))])]
"TARGET_80387 || (TARGET_SSE && TARGET_64BIT)"
"
{
--- 4735,4754 ----
}
else
{
! operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (DImode, 0);
}
}")
(define_expand "fix_truncsfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (match_operand:SF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))
! (clobber (match_scratch:XF 5 ""))])]
"TARGET_80387 || (TARGET_SSE && TARGET_64BIT)"
"
{
***************
*** 4756,4773 ****
}
else
{
! operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (DImode, 1);
}
}")
(define_insn "*fix_truncdi_1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
(fix:DI (match_operand 1 "register_operand" "f,f")))
! (clobber (match_operand:SI 2 "memory_operand" "=o,o"))
! (clobber (match_operand:DI 3 "memory_operand" "=m,m"))
! (clobber (match_scratch:SI 4 "=&r,&r"))
! (clobber (match_scratch 5 "=&f,&f"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& (!TARGET_SSE2 || !TARGET_64BIT
|| !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
--- 4762,4781 ----
}
else
{
! operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (DImode, 0);
}
}")
(define_insn "*fix_truncdi_1"
[(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 5 "=&1f,&1f"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& (!TARGET_SSE2 || !TARGET_64BIT
|| !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
***************
*** 4777,4793 ****
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(fix:DI (match_operand 1 "register_operand" "")))
! (clobber (match_operand:SI 2 "memory_operand" ""))
! (clobber (match_operand:DI 3 "memory_operand" ""))
! (clobber (match_scratch:SI 4 ""))
(clobber (match_scratch 5 ""))]
! "reload_completed && !reg_overlap_mentioned_p (operands[4], operands[3])"
! [(parallel [(set (match_dup 3) (fix:DI (match_dup 1)))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])
! (set (match_dup 0) (match_dup 3))]
"")
;; When SSE available, it is always faster to use it!
--- 4785,4801 ----
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(fix:DI (match_operand 1 "register_operand" "")))
! (use (match_operand:HI 2 "memory_operand" ""))
! (use (match_operand:HI 3 "memory_operand" ""))
! (clobber (match_operand:DI 4 "memory_operand" ""))
(clobber (match_scratch 5 ""))]
! "reload_completed"
! [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
! (use (match_dup 2))
! (use (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])
! (set (match_dup 0) (match_dup 4))]
"")
;; When SSE available, it is always faster to use it!
***************
*** 4810,4838 ****
(define_expand "fix_truncxfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:XF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387 && !TARGET_64BIT"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (SImode, 1);")
(define_expand "fix_trunctfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:TF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (SImode, 1);")
(define_expand "fix_truncdfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:DF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387 || TARGET_SSE2"
"
{
--- 4818,4850 ----
(define_expand "fix_truncxfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:XF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387 && !TARGET_64BIT"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (SImode, 0);")
(define_expand "fix_trunctfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:TF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (SImode, 0);")
(define_expand "fix_truncdfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:DF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387 || TARGET_SSE2"
"
{
***************
*** 4846,4862 ****
}
else
{
! operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (SImode, 1);
}
}")
(define_expand "fix_truncsfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:SF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387 || TARGET_SSE"
"
{
--- 4858,4876 ----
}
else
{
! operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (SImode, 0);
}
}")
(define_expand "fix_truncsfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (match_operand:SF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387 || TARGET_SSE"
"
{
***************
*** 4870,4886 ****
}
else
{
! operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (SImode, 1);
}
}")
(define_insn "*fix_truncsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
(fix:SI (match_operand 1 "register_operand" "f,f")))
! (clobber (match_operand:SI 2 "memory_operand" "=o,o"))
! (clobber (match_operand:SI 3 "memory_operand" "=m,m"))
! (clobber (match_scratch:SI 4 "=&r,r"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& (!TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands);"
--- 4884,4902 ----
}
else
{
! operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (SImode, 0);
}
}")
(define_insn "*fix_truncsi_1"
[(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]))
&& (!TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands);"
***************
*** 4904,4918 ****
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(fix:SI (match_operand 1 "register_operand" "")))
! (clobber (match_operand:SI 2 "memory_operand" ""))
! (clobber (match_operand:SI 3 "memory_operand" ""))
! (clobber (match_scratch:SI 4 ""))]
"reload_completed"
! [(parallel [(set (match_dup 3) (fix:SI (match_dup 1)))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
(clobber (match_dup 4))])
! (set (match_dup 0) (match_dup 3))]
"")
;; Signed conversion to HImode.
--- 4920,4934 ----
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(fix:SI (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" ""))]
"reload_completed"
! [(parallel [(set (match_dup 4) (fix:SI (match_dup 1)))
! (use (match_dup 2))
! (use (match_dup 3))
(clobber (match_dup 4))])
! (set (match_dup 0) (match_dup 4))]
"")
;; Signed conversion to HImode.
***************
*** 4920,4968 ****
(define_expand "fix_truncxfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:XF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387 && !TARGET_64BIT"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (HImode, 1);")
(define_expand "fix_trunctfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:TF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (HImode, 1);")
(define_expand "fix_truncdfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:DF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387 && !TARGET_SSE2"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (HImode, 1);")
(define_expand "fix_truncsfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:SF 1 "register_operand" "")))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
! (clobber (match_scratch:SI 4 ""))])]
"TARGET_80387 && !TARGET_SSE"
! "operands[2] = assign_386_stack_local (SImode, 0);
! operands[3] = assign_386_stack_local (HImode, 1);")
(define_insn "*fix_trunchi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r")
(fix:HI (match_operand 1 "register_operand" "f,f")))
! (clobber (match_operand:SI 2 "memory_operand" "=o,o"))
! (clobber (match_operand:HI 3 "memory_operand" "=m,m"))
! (clobber (match_scratch:SI 4 "=&r,r"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands);"
--- 4936,4992 ----
(define_expand "fix_truncxfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:XF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387 && !TARGET_64BIT"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (HImode, 0);")
(define_expand "fix_trunctfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:TF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (HImode, 0);")
(define_expand "fix_truncdfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:DF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387 && !TARGET_SSE2"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (HImode, 0);")
(define_expand "fix_truncsfhi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(fix:HI (match_operand:SF 1 "register_operand" "")))
! (use (match_dup 2))
! (use (match_dup 3))
! (clobber (match_dup 4))])]
"TARGET_80387 && !TARGET_SSE"
! "operands[2] = assign_386_stack_local (HImode, 1);
! operands[3] = assign_386_stack_local (HImode, 2);
! emit_i387_cw_initialization (operands[2], operands[3]);
! operands[4] = assign_386_stack_local (HImode, 0);")
(define_insn "*fix_trunchi_1"
[(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]))
&& (TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands);"
***************
*** 4971,5003 ****
(define_split
[(set (match_operand:HI 0 "register_operand" "")
(fix:HI (match_operand 1 "register_operand" "")))
! (clobber (match_operand:SI 2 "memory_operand" ""))
! (clobber (match_operand:HI 3 "memory_operand" ""))
! (clobber (match_scratch:SI 4 ""))]
"reload_completed"
! [(parallel [(set (match_dup 3) (fix:HI (match_dup 1)))
! (clobber (match_dup 2))
! (clobber (match_dup 3))
(clobber (match_dup 4))])
! (set (match_dup 0) (match_dup 3))]
"")
-
- ;; %%% Kill these when reload knows how to do it.
- (define_split
- [(set (match_operand 0 "register_operand" "")
- (fix (match_operand 1 "register_operand" "")))]
- "reload_completed && FLOAT_MODE_P (GET_MODE (operands[1]))
- && FP_REG_P (operands[1])"
- [(const_int 0)]
- "
- {
- operands[2] = ix86_force_to_memory (GET_MODE (operands[0]), operands[0]);
- operands[2] = gen_rtx_FIX (GET_MODE (operands[2]), operands[1]);
- emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[1]));
- emit_move_insn (operands[0], operands[2]);
- ix86_free_from_memory (GET_MODE (operands[0]));
- DONE;
- }")
;; %% Not used yet.
(define_insn "x86_fnstcw_1"
--- 4995,5010 ----
(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))]
"")
;; %% Not used yet.
(define_insn "x86_fnstcw_1"
*** i386.work/i386.c Fri Jun 22 17:20:14 2001
--- i386/i386.c Fri Jun 22 18:22:04 2001
*************** int const svr4_dbx_register_map[FIRST_PS
*** 445,451 ****
struct rtx_def *ix86_compare_op0 = NULL_RTX;
struct rtx_def *ix86_compare_op1 = NULL_RTX;
! #define MAX_386_STACK_LOCALS 2
/* Size of the register save area. */
#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
--- 445,451 ----
struct rtx_def *ix86_compare_op0 = NULL_RTX;
struct rtx_def *ix86_compare_op1 = NULL_RTX;
! #define MAX_386_STACK_LOCALS 3
/* Size of the register save area. */
#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
*************** output_387_binary_op (insn, operands)
*** 4639,4644 ****
--- 4639,4663 ----
return buf;
}
+ /* Output code to initialize control word copies used by
+ trunc?f?i patterns. NORMAL is set to current control word, while ROUND_DOWN
+ is set to control word rounding downwards. */
+ void
+ emit_i387_cw_initialization (normal, round_down)
+ rtx normal, round_down;
+ {
+ rtx reg = gen_reg_rtx (HImode);
+
+ emit_insn (gen_x86_fnstcw_1 (normal));
+ emit_move_insn (reg, normal);
+ if (!TARGET_PARTIAL_REG_STALL && !optimize_size
+ && !TARGET_64BIT)
+ emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0xc)));
+ else
+ emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0xc00)));
+ emit_move_insn (round_down, reg);
+ }
+
/* Output code for INSN to convert a float to a signed int. OPERANDS
are the insn operands. The output may be [HSD]Imode and the input
operand may be [SDX]Fmode. */
*************** output_fix_trunc (insn, operands)
*** 4658,4701 ****
if (dimode_p && !stack_top_dies)
output_asm_insn ("fld\t%y1", operands);
! if (! STACK_TOP_P (operands[1]))
abort ();
- xops[0] = GEN_INT (12);
- xops[1] = adj_offsettable_operand (operands[2], 1);
- xops[1] = change_address (xops[1], QImode, NULL_RTX);
-
- xops[2] = operands[0];
if (GET_CODE (operands[0]) != MEM)
! xops[2] = operands[3];
!
! output_asm_insn ("fnstcw\t%2", operands);
! output_asm_insn ("mov{l}\t{%2, %4|%4, %2}", operands);
! output_asm_insn ("mov{b}\t{%0, %1|%1, %0}", xops);
! output_asm_insn ("fldcw\t%2", operands);
! output_asm_insn ("mov{l}\t{%4, %2|%2, %4}", operands);
if (stack_top_dies || dimode_p)
! output_asm_insn ("fistp%z2\t%2", xops);
else
! output_asm_insn ("fist%z2\t%2", xops);
!
output_asm_insn ("fldcw\t%2", operands);
-
- if (GET_CODE (operands[0]) != MEM)
- {
- if (dimode_p)
- {
- split_di (operands+0, 1, xops+0, xops+1);
- split_di (operands+3, 1, xops+2, xops+3);
- output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
- output_asm_insn ("mov{l}\t{%3, %1|%1, %3}", xops);
- }
- else if (GET_MODE (operands[0]) == SImode)
- output_asm_insn ("mov{l}\t{%3, %0|%0, %3}", operands);
- else
- output_asm_insn ("mov{w}\t{%3, %0|%0, %3}", operands);
- }
return "";
}
--- 4677,4694 ----
if (dimode_p && !stack_top_dies)
output_asm_insn ("fld\t%y1", operands);
! if (!STACK_TOP_P (operands[1]))
abort ();
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);
else
! output_asm_insn ("fist%z0\t%0", operands);
output_asm_insn ("fldcw\t%2", operands);
return "";
}