From: Jan Hubicka Date: Sun, 15 Jul 2001 16:59:06 +0000 (+0200) Subject: toplev.c (rest_of_compilation): Fix register_life_up_to_date handling... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=22fb740dcc3541a5b9430c79976c6327c7c470a0;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0246e85aa20..b39e15e67be 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +Sun Jul 15 14:07:36 CEST 2001 Jan Hubicka + + * 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 * Makefile.in (integrate.o): Add debug.h. diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 5869602ef51..408ea2bac12 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -3117,6 +3117,69 @@ extern const char * const qi_high_reg_name[]; /* names for 8 bit regs (high) */ 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: diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index baff6bc7745..56158b9b22e 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 b3154dcdaec..746ea908afa 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