diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 891 |
1 files changed, 469 insertions, 422 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index d9a4ce599ed..a8d1c2bd6da 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -113,6 +113,11 @@ (UNSPEC_MOVSLDUP 75) (UNSPEC_LDQQU 76) (UNSPEC_MOVDDUP 77) + ; APPLE LOCAL begin 4121692 + (UNSPEC_LDQ 101) + (UNSPEC_MOVQ 102) + (UNSPEC_STOQ 103) + ; APPLE LOCAL end 4121692 ; x87 Floating point (UNSPEC_FPATAN 65) @@ -187,6 +192,7 @@ ;; A basic instruction type. Refinements due to arguments to be ;; provided in other attributes. +; APPLE LOCAL begin mainline 2005-03-16 4054919 (define_attr "type" "other,multi, alu,alu1,negnot,imov,imovx,lea, @@ -194,11 +200,12 @@ 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" (const_string "other")) +; APPLE LOCAL end mainline 2005-03-16 4054919 ;; Main data type used by the insn (define_attr "mode" @@ -207,7 +214,8 @@ ;; 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") +; APPLE LOCAL mainline 2005-03-16 4054919 + (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") @@ -441,6 +449,24 @@ (define_asm_attributes [(set_attr "length" "128") (set_attr "type" "multi")]) +; APPLE LOCAL begin mainline 2005-03-16 4054919 + +;; 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]) + +; APPLE LOCAL end mainline 2005-03-16 4054919 ;; Scheduling descriptions @@ -1443,9 +1469,10 @@ ;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial ;; register stall machines with, where we use QImode instructions, since ;; partial register stall can be caused there. Then we use movzx. +;; APPLE LOCAL begin mainline 4104248 (define_insn "*movqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m") - (match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,qm,qn"))] + (match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,m ,qn"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" { switch (get_attr_type (insn)) @@ -1462,7 +1489,9 @@ } } [(set (attr "type") - (cond [(ne (symbol_ref "optimize_size") (const_int 0)) + (cond [(eq_attr "alternative" "5") + (const_string "imovx") + (ne (symbol_ref "optimize_size") (const_int 0)) (const_string "imov") (and (eq_attr "alternative" "3") (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") @@ -1470,7 +1499,7 @@ (eq (symbol_ref "TARGET_QIMODE_MATH") (const_int 0)))) (const_string "imov") - (eq_attr "alternative" "3,5") + (eq_attr "alternative" "3") (const_string "imovx") (and (ne (symbol_ref "TARGET_MOVX") (const_int 0)) @@ -1500,6 +1529,7 @@ (const_string "SI") ] (const_string "QI")))]) +;; APPLE LOCAL end mainline 4104248 (define_expand "reload_outqi" [(parallel [(match_operand:QI 0 "" "=m") @@ -3770,6 +3800,22 @@ [(set_attr "type" "fmov,multi") (set_attr "mode" "SF")]) +(define_insn "*truncdfsf2_i387_1" + [(set (match_operand:SF 0 "memory_operand" "=m") + (float_truncate:SF + (match_operand:DF 1 "register_operand" "f")))] + "TARGET_80387 + && !(TARGET_SSE2 && TARGET_SSE_MATH) + && !TARGET_MIX_SSE_I387" +{ + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return "fstp%z0\t%y0"; + else + return "fst%z0\t%y0"; +} + [(set_attr "type" "fmov") + (set_attr "mode" "SF")]) + (define_split [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF @@ -3995,8 +4041,7 @@ [(set (match_dup 0) (float_truncate:DF (match_dup 1)))] "") -;; %%% Break up all these bad boys. - +; APPLE LOCAL begin mainline 2005-03-16 4054919 ;; Signed conversion to DImode. (define_expand "fix_truncxfdi2" @@ -4004,361 +4049,234 @@ (fix:DI (match_operand:XF 1 "register_operand" ""))) (clobber (reg:CC FLAGS_REG))])] "TARGET_80387" - "") - -(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) + if (TARGET_FISTTP) { - 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); + emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1])); DONE; } }) -(define_expand "fix_truncsfdi2" +(define_expand "fix_trunc<mode>di2" [(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)" + (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_64BIT && TARGET_SSE) + 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_truncsfdi_sse (out, operands[1])); + emit_insn (gen_fix_trunc<mode>di_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_truncdi_i387" - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") - (fix:DI (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)" - "#" - "&& 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_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") - (set_attr "i387_cw" "trunc") - (set_attr "mode" "DI")]) - -(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:DF 5 "=&1f,&1f"))] - "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) - && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)" - "#" - [(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" ""))) - (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 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,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" ""))) + (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) + if (TARGET_FISTTP) { - 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); + emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1])); DONE; } }) -(define_expand "fix_truncsfsi2" +(define_expand "fix_trunc<mode>si2" [(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" + (fix:SI (match_operand:SSEMODEF 1 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode))" { - if (TARGET_SSE) + 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_truncsfsi_sse (out, operands[1])); + emit_insn (gen_fix_trunc<mode>si_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)] +;; 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))" { - 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")]) + if (TARGET_FISTTP) + { + emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1])); + DONE; + } +}) -(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")]) +;; 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_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" "fistp") - (set_attr "i387_cw" "trunc") - (set_attr "mode" "SI")]) +(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")]) -;; 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" + "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")]) -;; 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" + "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 form of the instruction. +;; Avoid vector decoded forms 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" "")))] + (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:SI (match_dup 2)))] - "") - -(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))]) - (set (match_dup 0) (match_dup 4))] + (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))] "") -(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))])] +(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)))] "") -;; 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_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 (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_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_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_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" +(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_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]))" +;; 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 && !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)] @@ -4367,71 +4285,131 @@ 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])); + emit_insn (gen_fix_trunc<mode>_i387 (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])); + 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" "HI")]) + (set_attr "mode" "<MODE>")]) -(define_insn "fix_trunchi_nomemory" - [(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r") - (fix:HI (match_operand 1 "register_operand" "f,f"))) +(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_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:HI 4 "memory_operand" "=m,m"))] - "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) - && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" + (clobber (match_operand:DI 4 "memory_operand" "=m,m")) + (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" "HI")]) + (set_attr "mode" "DI")]) -(define_insn "fix_trunchi_memory" - [(set (match_operand:HI 0 "memory_operand" "=m") - (fix:HI (match_operand 1 "register_operand" "f"))) +(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 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))])] + "") + +(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" "HI")]) + (set_attr "mode" "<MODE>")]) + +(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:HI 0 "memory_operand" "") - (fix:HI (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:HI 4 "memory_operand" ""))] + (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))] "reload_completed" - [(parallel [(set (match_dup 0) (fix:HI (match_dup 1))) + [(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1))) (use (match_dup 2)) - (use (match_dup 3))])] + (use (match_dup 3))]) + (set (match_dup 0) (match_dup 4))] "") (define_split - [(set (match_operand:HI 0 "register_operand" "") - (fix:HI (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:HI 4 "memory_operand" ""))] + (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))] "reload_completed" - [(parallel [(set (match_dup 4) (fix:HI (match_dup 1))) + [(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1))) (use (match_dup 2)) - (use (match_dup 3)) - (clobber (match_dup 4))]) - (set (match_dup 0) (match_dup 4))] + (use (match_dup 3))])] "") +; APPLE LOCAL end mainline 2005-03-16 4054919 (define_insn "x86_fnstcw_1" [(set (match_operand:HI 0 "memory_operand" "=m") @@ -9749,6 +9727,7 @@ operands[1] = tmp; }) +; APPLE LOCAL begin radar 4117515 (define_split [(set (match_operand 0 "memory_operand" "") (match_operator 1 "absneg_operator" [(match_dup 0)])) @@ -9762,19 +9741,37 @@ int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode); rtx tmp; - operands[0] = adjust_address (operands[0], QImode, size - 1); - if (GET_CODE (operands[1]) == ABS) + if (size == 4) { - tmp = gen_int_mode (0x7f, QImode); - tmp = gen_rtx_AND (QImode, operands[0], tmp); + operands[0] = adjust_address (operands[0], SImode, 0); + if (GET_CODE (operands[1]) == ABS) + { + tmp = gen_int_mode (0x7fffffff, SImode); + tmp = gen_rtx_AND (SImode, operands[0], tmp); + } + else + { + tmp = gen_int_mode (0x80000000, SImode); + tmp = gen_rtx_XOR (SImode, operands[0], tmp); + } } else { - tmp = gen_int_mode (0x80, QImode); - tmp = gen_rtx_XOR (QImode, operands[0], tmp); + operands[0] = adjust_address (operands[0], QImode, size - 1); + if (GET_CODE (operands[1]) == ABS) + { + tmp = gen_int_mode (0x7f, QImode); + tmp = gen_rtx_AND (QImode, operands[0], tmp); + } + else + { + tmp = gen_int_mode (0x80, QImode); + tmp = gen_rtx_XOR (QImode, operands[0], tmp); + } } operands[1] = tmp; }) +; APPLE LOCAL end radar 4117515 ;; Conditionalize these after reload. If they match before reload, we ;; lose the clobber and ability to use integer instructions. @@ -16297,7 +16294,33 @@ DONE; }) -(define_insn "frndintxf2_floor" +;; Rounding mode control word calculation could clobber FLAGS_REG. +(define_insn_and_split "frndintxf2_floor" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_FLOOR)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations + && !(reload_completed || reload_in_progress)" + "#" + "&& 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); + + emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1], + operands[2], operands[3])); + DONE; +} + [(set_attr "type" "frndint") + (set_attr "i387_cw" "floor") + (set_attr "mode" "XF")]) + +(define_insn "frndintxf2_floor_i387" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_FRNDINT_FLOOR)) @@ -16310,6 +16333,16 @@ (set_attr "i387_cw" "floor") (set_attr "mode" "XF")]) +(define_expand "floorxf2" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + emit_insn (gen_frndintxf2_floor (operands[0], operands[1])); + DONE; +}) + (define_expand "floordf2" [(use (match_operand:DF 0 "register_operand" "")) (use (match_operand:DF 1 "register_operand" ""))] @@ -16319,13 +16352,9 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extenddfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_floor (op0, op1)); emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); DONE; @@ -16340,34 +16369,41 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extendsfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_floor (op0, op1)); emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); DONE; }) -(define_expand "floorxf2" - [(use (match_operand:XF 0 "register_operand" "")) - (use (match_operand:XF 1 "register_operand" ""))] +;; Rounding mode control word calculation could clobber FLAGS_REG. +(define_insn_and_split "frndintxf2_ceil" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_CEIL)) + (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + && flag_unsafe_math_optimizations + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] { - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - ix86_optimize_mode_switching = 1; - emit_insn (gen_frndintxf2_floor (operands[0], operands[1], op2, op3)); + operands[2] = assign_386_stack_local (HImode, 1); + operands[3] = assign_386_stack_local (HImode, 2); + + emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1], + operands[2], operands[3])); DONE; -}) +} + [(set_attr "type" "frndint") + (set_attr "i387_cw" "ceil") + (set_attr "mode" "XF")]) -(define_insn "frndintxf2_ceil" +(define_insn "frndintxf2_ceil_i387" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_FRNDINT_CEIL)) @@ -16380,6 +16416,16 @@ (set_attr "i387_cw" "ceil") (set_attr "mode" "XF")]) +(define_expand "ceilxf2" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + emit_insn (gen_frndintxf2_ceil (operands[0], operands[1])); + DONE; +}) + (define_expand "ceildf2" [(use (match_operand:DF 0 "register_operand" "")) (use (match_operand:DF 1 "register_operand" ""))] @@ -16389,13 +16435,9 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extenddfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_ceil (op0, op1)); emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); DONE; @@ -16410,34 +16452,41 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extendsfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_ceil (op0, op1)); emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); DONE; }) -(define_expand "ceilxf2" - [(use (match_operand:XF 0 "register_operand" "")) - (use (match_operand:XF 1 "register_operand" ""))] +;; Rounding mode control word calculation could clobber FLAGS_REG. +(define_insn_and_split "frndintxf2_trunc" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_TRUNC)) + (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + && flag_unsafe_math_optimizations + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] { - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - ix86_optimize_mode_switching = 1; - emit_insn (gen_frndintxf2_ceil (operands[0], operands[1], op2, op3)); + operands[2] = assign_386_stack_local (HImode, 1); + operands[3] = assign_386_stack_local (HImode, 2); + + emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1], + operands[2], operands[3])); DONE; -}) +} + [(set_attr "type" "frndint") + (set_attr "i387_cw" "trunc") + (set_attr "mode" "XF")]) -(define_insn "frndintxf2_trunc" +(define_insn "frndintxf2_trunc_i387" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_FRNDINT_TRUNC)) @@ -16450,6 +16499,16 @@ (set_attr "i387_cw" "trunc") (set_attr "mode" "XF")]) +(define_expand "btruncxf2" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + emit_insn (gen_frndintxf2_trunc (operands[0], operands[1])); + DONE; +}) + (define_expand "btruncdf2" [(use (match_operand:DF 0 "register_operand" "")) (use (match_operand:DF 1 "register_operand" ""))] @@ -16459,13 +16518,9 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extenddfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_trunc (op0, op1)); emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); DONE; @@ -16480,34 +16535,41 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extendsfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_trunc (op0, op1)); emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); DONE; }) -(define_expand "btruncxf2" - [(use (match_operand:XF 0 "register_operand" "")) - (use (match_operand:XF 1 "register_operand" ""))] +;; Rounding mode control word calculation could clobber FLAGS_REG. +(define_insn_and_split "frndintxf2_mask_pm" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_MASK_PM)) + (clobber (reg:CC FLAGS_REG))] "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + && flag_unsafe_math_optimizations + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] { - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - ix86_optimize_mode_switching = 1; - emit_insn (gen_frndintxf2_trunc (operands[0], operands[1], op2, op3)); + operands[2] = assign_386_stack_local (HImode, 1); + operands[3] = assign_386_stack_local (HImode, 2); + + emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1], + operands[2], operands[3])); DONE; -}) +} + [(set_attr "type" "frndint") + (set_attr "i387_cw" "mask_pm") + (set_attr "mode" "XF")]) -(define_insn "frndintxf2_mask_pm" +(define_insn "frndintxf2_mask_pm_i387" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_FRNDINT_MASK_PM)) @@ -16520,6 +16582,17 @@ (set_attr "i387_cw" "mask_pm") (set_attr "mode" "XF")]) +(define_expand "nearbyintxf2" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1])); + + DONE; +}) + (define_expand "nearbyintdf2" [(use (match_operand:DF 0 "register_operand" "")) (use (match_operand:DF 1 "register_operand" ""))] @@ -16529,13 +16602,9 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extenddfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_mask_pm (op0, op1)); emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); DONE; @@ -16550,34 +16619,14 @@ { rtx op0 = gen_reg_rtx (XFmode); rtx op1 = gen_reg_rtx (XFmode); - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; emit_insn (gen_extendsfxf2 (op1, operands[1])); - emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3)); + emit_insn (gen_frndintxf2_mask_pm (op0, op1)); emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); DONE; }) -(define_expand "nearbyintxf2" - [(use (match_operand:XF 0 "register_operand" "")) - (use (match_operand:XF 1 "register_operand" ""))] - "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" -{ - rtx op2 = assign_386_stack_local (HImode, 1); - rtx op3 = assign_386_stack_local (HImode, 2); - - ix86_optimize_mode_switching = 1; - - emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1], - op2, op3)); - DONE; -}) - ;; Block operation instructions @@ -18537,18 +18586,16 @@ ;; Attempt to always use XOR for zeroing registers. (define_peephole2 [(set (match_operand 0 "register_operand" "") - (const_int 0))] - "(GET_MODE (operands[0]) == QImode - || GET_MODE (operands[0]) == HImode - || GET_MODE (operands[0]) == SImode - || (GET_MODE (operands[0]) == DImode && TARGET_64BIT)) + (match_operand 1 "const0_operand" ""))] + "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD && (! TARGET_USE_MOV0 || optimize_size) && GENERAL_REG_P (operands[0]) && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (const_int 0)) (clobber (reg:CC FLAGS_REG))])] - "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode, - operands[0]);") +{ + operands[0] = gen_lowpart (word_mode, operands[0]); +}) (define_peephole2 [(set (strict_low_part (match_operand 0 "register_operand" "")) |