aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-07-15 18:59:06 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2001-07-15 16:59:06 +0000
commit22fb740dcc3541a5b9430c79976c6327c7c470a0 (patch)
treedd53511e79ae0e7f9c00238719bce809718f79c4
parent135d50f10fe27b77c879038d7adff5724ece1988 (diff)
downloadgcc-22fb740dcc3541a5b9430c79976c6327c7c470a0.zip
gcc-22fb740dcc3541a5b9430c79976c6327c7c470a0.tar.gz
gcc-22fb740dcc3541a5b9430c79976c6327c7c470a0.tar.bz2
toplev.c (rest_of_compilation): Fix register_life_up_to_date handling...
* toplev.c (rest_of_compilation): Fix register_life_up_to_date handling; move unconditional splitting before mode switching. * i386.md (type): Add fistp type. (i387, length_attr, scheduling definitions): Handle this type. (fix_trunc?f?i2): Revamp to use mode switching. (fix_trunct?f?i_nonmemory, fix_trunc?f?i_memory): New patterns. * i386.h (fp_cw_mode): New enum (OPTIMIZE_MODE_SWITCHING, NUM_MODES_FOR_MODE_SWITCHING, MODE_NEEDED, MODE_PRIORITY_TO_MODE, ENUM_MODE_SET): New macros. From-SVN: r44027
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/i386/i386.h63
-rw-r--r--gcc/config/i386/i386.md366
-rw-r--r--gcc/toplev.c14
4 files changed, 297 insertions, 159 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0246e85a..b39e15e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+Sun Jul 15 14:07:36 CEST 2001 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Fix register_life_up_to_date
+ handling; move unconditional splitting before mode switching.
+
+ * i386.md (type): Add fistp type.
+ (i387, length_attr, scheduling definitions): Handle this type.
+ (fix_trunc?f?i2): Revamp to use mode switching.
+ (fix_trunct?f?i_nonmemory, fix_trunc?f?i_memory): New patterns.
+ * i386.h (fp_cw_mode): New enum
+ (OPTIMIZE_MODE_SWITCHING, NUM_MODES_FOR_MODE_SWITCHING, MODE_NEEDED,
+ MODE_PRIORITY_TO_MODE, ENUM_MODE_SET): New macros.
+
Sun Jul 15 12:53:51 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Makefile.in (integrate.o): Add debug.h.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 5869602..408ea2b 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -3118,6 +3118,69 @@ extern enum reg_class const regclass_map[]; /* smalled class containing REGNO */
extern struct rtx_def *ix86_compare_op0; /* operand 0 for comparisons */
extern struct rtx_def *ix86_compare_op1; /* operand 1 for comparisons */
+/* To properly truncate FP values into integers, we need to set i387 control
+ word. We can't emit proper mode switching code before reload, as spills
+ generated by reload may truncate values incorrectly, but we still can avoid
+ redundant computation of new control word by the mode switching pass.
+ The fldcw instructions are still emitted redundantly, but this is probably
+ not going to be noticeable problem, as most CPUs do have fast path for
+ the sequence.
+
+ The machinery is to emit simple truncation instructions and split them
+ before reload to instructions having USEs of two memory locations that
+ are filled by this code to old and new control word.
+
+ Post-reload pass may be later used to eliminate the redundant fildcw if
+ needed. */
+
+enum fp_cw_mode {FP_CW_STORED, FP_CW_UNINITIALIZED, FP_CW_ANY};
+
+/* Define this macro if the port needs extra instructions inserted
+ for mode switching in an optimizing compilation. */
+
+#define OPTIMIZE_MODE_SWITCHING(ENTITY) 1
+
+/* If you define `OPTIMIZE_MODE_SWITCHING', you have to define this as
+ initializer for an array of integers. Each initializer element N
+ refers to an entity that needs mode switching, and specifies the
+ number of different modes that might need to be set for this
+ entity. The position of the initializer in the initializer -
+ starting counting at zero - determines the integer that is used to
+ refer to the mode-switched entity in question. */
+
+#define NUM_MODES_FOR_MODE_SWITCHING { FP_CW_ANY }
+
+/* ENTITY is an integer specifying a mode-switched entity. If
+ `OPTIMIZE_MODE_SWITCHING' is defined, you must define this macro to
+ return an integer value not larger than the corresponding element
+ in `NUM_MODES_FOR_MODE_SWITCHING', to denote the mode that ENTITY
+ must be switched into prior to the execution of INSN. */
+
+#define MODE_NEEDED(ENTITY, I) \
+ (GET_CODE (I) == CALL_INSN \
+ || (GET_CODE (I) == INSN && (asm_noperands (PATTERN (I)) >= 0 \
+ || GET_CODE (PATTERN (I)) == ASM_INPUT))\
+ ? FP_CW_UNINITIALIZED \
+ : recog_memoized (I) < 0 || get_attr_type (I) != TYPE_FISTP \
+ ? FP_CW_ANY \
+ : FP_CW_STORED)
+
+/* This macro specifies the order in which modes for ENTITY are
+ processed. 0 is the highest priority. */
+
+#define MODE_PRIORITY_TO_MODE(ENTITY, N) N
+
+/* Generate one or more insns to set ENTITY to MODE. HARD_REG_LIVE
+ is the set of hard registers live at the point where the insn(s)
+ are to be inserted. */
+
+#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
+ (MODE == FP_CW_STORED \
+ ? emit_i387_cw_initialization (assign_386_stack_local (HImode, 1), \
+ assign_386_stack_local (HImode, 2)), 0\
+ : 0)
+
+
/*
Local variables:
version-control: t
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index baff6bc..56158b9 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -105,7 +105,7 @@
;; A basic instruction type. Refinements due to arguments to be
;; provided in other attributes.
(define_attr "type"
- "other,multi,alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,imul,idiv,ibr,setcc,push,pop,call,callv,icmov,fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,str,cld,sse,mmx"
+ "other,multi,alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,imul,idiv,ibr,setcc,push,pop,call,callv,icmov,fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,str,cld,sse,mmx,fistp"
(const_string "other"))
;; Main data type used by the insn
@@ -114,7 +114,7 @@
;; Set for i387 operations.
(define_attr "i387" ""
- (if_then_else (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch")
+ (if_then_else (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp")
(const_int 1)
(const_int 0)))
@@ -198,8 +198,10 @@
(const_int 1)))
;; The (bounding maximum) length of an instruction in bytes.
+;; ??? fistp is in fact fldcw/fistp/fldcw sequence. Later we may want
+;; to split it and compute proper length as for other insns.
(define_attr "length" ""
- (cond [(eq_attr "type" "other,multi")
+ (cond [(eq_attr "type" "other,multi,fistp")
(const_int 16)
]
(plus (plus (attr "modrm")
@@ -220,6 +222,8 @@
(const_string "unknown")
(eq_attr "type" "lea,fcmov,fpspc,cld")
(const_string "none")
+ (eq_attr "type" "fistp")
+ (const_string "both")
(eq_attr "type" "push")
(if_then_else (match_operand 1 "memory_operand" "")
(const_string "both")
@@ -503,9 +507,9 @@
; integer instructions, because of the inpaired fxch instruction.
(define_function_unit "pent_np" 1 0
(and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp"))
+ (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp,fistp"))
2 2
- [(eq_attr "type" "!fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp")])
+ [(eq_attr "type" "!fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp,fistp")])
(define_function_unit "fpu" 1 0
(and (eq_attr "cpu" "pentium")
@@ -516,7 +520,7 @@
; ??? Trivial fp operations such as fabs or fchs takes only one cycle.
(define_function_unit "fpu" 1 0
(and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fop,fop1"))
+ (eq_attr "type" "fop,fop1,fistp"))
3 1)
; Multiplication takes 3 cycles and is only half pipelined.
@@ -614,7 +618,7 @@
(define_function_unit "ppro_p0" 1 0
(and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fop,fop1,fsgn"))
+ (eq_attr "type" "fop,fop1,fsgn,fistp"))
3 1)
(define_function_unit "ppro_p0" 1 0
@@ -667,7 +671,7 @@
(define_function_unit "fpu" 1 0
(and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fop,fop1,fsgn,fmov,fcmp,fcmov"))
+ (eq_attr "type" "fop,fop1,fsgn,fmov,fcmp,fcmov,fistp"))
1 1)
(define_function_unit "fpu" 1 0
@@ -770,7 +774,7 @@
(define_function_unit "k6_fpu" 1 1
(and (eq_attr "cpu" "k6")
- (eq_attr "type" "fop,fop1,fmov,fcmp"))
+ (eq_attr "type" "fop,fop1,fmov,fcmp,fistp"))
2 2)
(define_function_unit "k6_fpu" 1 1
@@ -882,7 +886,7 @@
42 42)
(define_attr "athlon_fpunits" "none,store,mul,add,muladd,any"
- (cond [(eq_attr "type" "fop,fop1,fcmp")
+ (cond [(eq_attr "type" "fop,fop1,fcmp,fistp")
(const_string "add")
(eq_attr "type" "fmul,fdiv,fpspc,fsgn,fcmov")
(const_string "mul")
@@ -917,7 +921,7 @@
(define_function_unit "athlon_fp" 3 0
(and (eq_attr "cpu" "athlon")
- (eq_attr "type" "fop,fop1,fmul"))
+ (eq_attr "type" "fop,fop1,fmul,fistp"))
4 1)
;; XFmode loads are slow.
@@ -4620,38 +4624,20 @@
;; Signed conversion to DImode.
(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 ""))])]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (match_operand:XF 1 "register_operand" "")))]
"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 ""))])]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (match_operand:TF 1 "register_operand" "")))]
"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 ""))])]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (match_operand:DF 1 "register_operand" "")))]
"TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
{
if (TARGET_SSE2 && TARGET_64BIT)
@@ -4662,25 +4648,14 @@
emit_move_insn (operands[0], out);
DONE;
}
- 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 ""))])]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (match_operand:SF 1 "register_operand" "")))]
"TARGET_80387 || (TARGET_SSE && TARGET_64BIT)"
{
- if (TARGET_SSE2 && TARGET_64BIT)
+ if (TARGET_SSE && TARGET_64BIT)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
emit_insn (gen_fix_truncsfdi_sse (out, operands[1]));
@@ -4688,27 +4663,58 @@
emit_move_insn (operands[0], out);
DONE;
}
- 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"
+;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
+;; of the machinery.
+(define_insn_and_split "*fix_truncdi_1"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (fix:DI (match_operand 1 "register_operand" "f,f")))]
+ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !reload_completed && !reload_in_progress
+ && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
+ "#"
+ ""
+ [(const_int 0)]
+{
+ 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]));
+ 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]));
+ }
+ DONE;
+}
+ [(set_attr "type" "fistp")])
+
+(define_insn "fix_truncdi_nomemory"
[(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"))]
+ (clobber (match_scratch:DF 5 "=&1f,&1f"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && (!TARGET_SSE2 || !TARGET_64BIT
- || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
- "* return output_fix_trunc (insn, operands);"
- [(set_attr "type" "multi")])
+ && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
+ "#"
+ [(set_attr "type" "fistp")])
+
+(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)"
+ "* operands[5] = operands[4]; return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fistp")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -4721,11 +4727,24 @@
[(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))]
"")
+(define_split
+ [(set (match_operand:DI 0 "memory_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 0) (fix:DI (match_dup 1)))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (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")
@@ -4744,35 +4763,20 @@
;; Signed conversion to SImode.
(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))])]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (match_operand:XF 1 "register_operand" "")))]
"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))])]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (match_operand:TF 1 "register_operand" "")))]
"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))])]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (match_operand:DF 1 "register_operand" "")))]
"TARGET_80387 || TARGET_SSE2"
{
if (TARGET_SSE2)
@@ -4783,24 +4787,14 @@
emit_move_insn (operands[0], out);
DONE;
}
- 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))])]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (match_operand:SF 1 "register_operand" "")))]
"TARGET_80387 || TARGET_SSE"
{
- if (TARGET_SSE2)
+ if (TARGET_SSE)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
emit_insn (gen_fix_truncsfsi_sse (out, operands[1]));
@@ -4808,25 +4802,56 @@
emit_move_insn (operands[0], out);
DONE;
}
- 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"
+;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
+;; of the machinery.
+(define_insn_and_split "*fix_truncsi_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
+ (fix:SI (match_operand 1 "register_operand" "f,f")))]
+ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !reload_completed && !reload_in_progress
+ && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "#"
+ ""
+ [(const_int 0)]
+{
+ 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")])
+
+(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]))
- && (!TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
+ && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "#"
+ [(set_attr "type" "fistp")])
+
+(define_insn "fix_truncsi_memory"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (fix:SI (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" "multi")])
+ [(set_attr "type" "fistp")])
;; When SSE available, it is always faster to use it!
(define_insn "fix_truncsfsi_sse"
@@ -4852,71 +4877,108 @@
"reload_completed"
[(parallel [(set (match_dup 4) (fix:SI (match_dup 1)))
(use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 4))])
+ (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" "")))
+ (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 0) (fix:SI (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" "")))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 4))])]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ (fix:HI (match_operand:XF 1 "register_operand" "")))]
"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))])]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ (fix:HI (match_operand:TF 1 "register_operand" "")))]
"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))])]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ (fix:HI (match_operand:DF 1 "register_operand" "")))]
"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))])]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ (fix:HI (match_operand:SF 1 "register_operand" "")))]
"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"
+;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
+;; of the machinery.
+(define_insn_and_split "*fix_trunchi_1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r")
+ (fix:HI (match_operand 1 "register_operand" "f,f")))]
+ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !reload_completed && !reload_in_progress
+ && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "#"
+ ""
+ [(const_int 0)]
+{
+ 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")])
+
+(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]))
- && (TARGET_SSE2 || !SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
+ && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "#"
+ [(set_attr "type" "fistp")])
+
+(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" "multi")])
+ [(set_attr "type" "fistp")])
+
+(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" "")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index b3154dc..746ea90 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3327,7 +3327,6 @@ rest_of_compilation (decl)
life_analysis (insns, rtl_dump_file, PROP_FINAL);
timevar_pop (TV_FLOW);
- register_life_up_to_date = 1;
no_new_pseudos = 1;
if (warn_uninitialized || extra_warnings)
@@ -3415,15 +3414,18 @@ rest_of_compilation (decl)
ggc_collect ();
}
+ /* Do unconditional splitting before register allocation to allow machine
+ description to add extra information not needed previously. */
+ split_all_insns (1);
+
/* Any of the several passes since flow1 will have munged register
lifetime data a bit. */
- if (optimize > 0)
- register_life_up_to_date = 0;
+ register_life_up_to_date = 0;
#ifdef OPTIMIZE_MODE_SWITCHING
timevar_push (TV_GCSE);
- no_new_pseudos = 1;
+ no_new_pseudos = 0;
if (optimize_mode_switching (NULL))
{
/* We did work, and so had to regenerate global life information.
@@ -3431,15 +3433,13 @@ rest_of_compilation (decl)
information below. */
register_life_up_to_date = 1;
}
- no_new_pseudos = 0;
+ no_new_pseudos = 1;
timevar_pop (TV_GCSE);
#endif
timevar_push (TV_SCHED);
- split_all_insns (1);
-
#ifdef INSN_SCHEDULING
/* Print function header into sched dump now