diff options
author | kan <kan@FreeBSD.org> | 2007-05-19 02:12:21 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2007-05-19 02:12:21 +0000 |
commit | cadd557b2c028e9d17846ceb76b7abe3b967db5d (patch) | |
tree | b4d827b7febdefd02ed5f510413d9d8c8f76ab39 /contrib/gcc/config/i386/i386.md | |
parent | cbd790c8d27189110c36da6503196f44d88a5860 (diff) | |
download | FreeBSD-src-cadd557b2c028e9d17846ceb76b7abe3b967db5d.zip FreeBSD-src-cadd557b2c028e9d17846ceb76b7abe3b967db5d.tar.gz |
FreeBSD uses unchanged versions of this files.
Diffstat (limited to 'contrib/gcc/config/i386/i386.md')
-rw-r--r-- | contrib/gcc/config/i386/i386.md | 16165 |
1 files changed, 7048 insertions, 9117 deletions
diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md index 0fbe00b..d24b32a 100644 --- a/contrib/gcc/config/i386/i386.md +++ b/contrib/gcc/config/i386/i386.md @@ -1,6 +1,6 @@ ;; GCC machine description for IA-32 and x86-64. ;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002, 2003, 2004 +;; 2001, 2002, 2003, 2004, 2005, 2006 ;; Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; x86_64 support added by Jan Hubicka @@ -19,8 +19,8 @@ ;; ;; You should have received a copy of the GNU General Public License ;; along with GCC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. */ +;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. */ ;; ;; The original PO technology requires these to be ordered by speed, ;; so that assigner will pick the fastest. @@ -66,76 +66,114 @@ (UNSPEC_STACK_ALLOC 11) (UNSPEC_SET_GOT 12) (UNSPEC_SSE_PROLOGUE_SAVE 13) + (UNSPEC_REG_SAVE 14) + (UNSPEC_DEF_CFA 15) ; TLS support - (UNSPEC_TP 15) - (UNSPEC_TLS_GD 16) - (UNSPEC_TLS_LD_BASE 17) + (UNSPEC_TP 16) + (UNSPEC_TLS_GD 17) + (UNSPEC_TLS_LD_BASE 18) + (UNSPEC_TLSDESC 19) ; Other random patterns (UNSPEC_SCAS 20) - (UNSPEC_SIN 21) - (UNSPEC_COS 22) - (UNSPEC_FNSTSW 24) - (UNSPEC_SAHF 25) - (UNSPEC_FSTCW 26) - (UNSPEC_ADD_CARRY 27) - (UNSPEC_FLDCW 28) + (UNSPEC_FNSTSW 21) + (UNSPEC_SAHF 22) + (UNSPEC_FSTCW 23) + (UNSPEC_ADD_CARRY 24) + (UNSPEC_FLDCW 25) + (UNSPEC_REP 26) + (UNSPEC_EH_RETURN 27) + (UNSPEC_LD_MPIC 28) ; load_macho_picbase ; For SSE/MMX support: - (UNSPEC_FIX 30) - (UNSPEC_MASKMOV 32) - (UNSPEC_MOVMSK 33) - (UNSPEC_MOVNT 34) - (UNSPEC_MOVA 38) - (UNSPEC_MOVU 39) - (UNSPEC_SHUFFLE 41) - (UNSPEC_RCP 42) - (UNSPEC_RSQRT 43) - (UNSPEC_SFENCE 44) - (UNSPEC_NOP 45) ; prevents combiner cleverness - (UNSPEC_PAVGUSB 49) - (UNSPEC_PFRCP 50) - (UNSPEC_PFRCPIT1 51) - (UNSPEC_PFRCPIT2 52) - (UNSPEC_PFRSQRT 53) - (UNSPEC_PFRSQIT1 54) - (UNSPEC_PSHUFLW 55) - (UNSPEC_PSHUFHW 56) - (UNSPEC_MFENCE 59) - (UNSPEC_LFENCE 60) - (UNSPEC_PSADBW 61) - (UNSPEC_ADDSUB 71) - (UNSPEC_HADD 72) - (UNSPEC_HSUB 73) - (UNSPEC_MOVSHDUP 74) - (UNSPEC_MOVSLDUP 75) - (UNSPEC_LDQQU 76) - (UNSPEC_MOVDDUP 77) + (UNSPEC_FIX_NOTRUNC 30) + (UNSPEC_MASKMOV 31) + (UNSPEC_MOVMSK 32) + (UNSPEC_MOVNT 33) + (UNSPEC_MOVU 34) + (UNSPEC_RCP 35) + (UNSPEC_RSQRT 36) + (UNSPEC_SFENCE 37) + (UNSPEC_NOP 38) ; prevents combiner cleverness + (UNSPEC_PFRCP 39) + (UNSPEC_PFRCPIT1 40) + (UNSPEC_PFRCPIT2 41) + (UNSPEC_PFRSQRT 42) + (UNSPEC_PFRSQIT1 43) + (UNSPEC_MFENCE 44) + (UNSPEC_LFENCE 45) + (UNSPEC_PSADBW 46) + (UNSPEC_LDQQU 47) + + ; Generic math support + (UNSPEC_COPYSIGN 50) + (UNSPEC_IEEE_MIN 51) ; not commutative + (UNSPEC_IEEE_MAX 52) ; not commutative ; x87 Floating point - (UNSPEC_FPATAN 65) - (UNSPEC_FYL2X 66) - (UNSPEC_FSCALE 67) - (UNSPEC_FRNDINT 68) - (UNSPEC_F2XM1 69) - - ; REP instruction - (UNSPEC_REP 75) + (UNSPEC_SIN 60) + (UNSPEC_COS 61) + (UNSPEC_FPATAN 62) + (UNSPEC_FYL2X 63) + (UNSPEC_FYL2XP1 64) + (UNSPEC_FRNDINT 65) + (UNSPEC_FIST 66) + (UNSPEC_F2XM1 67) + + ; x87 Rounding + (UNSPEC_FRNDINT_FLOOR 70) + (UNSPEC_FRNDINT_CEIL 71) + (UNSPEC_FRNDINT_TRUNC 72) + (UNSPEC_FRNDINT_MASK_PM 73) + (UNSPEC_FIST_FLOOR 74) + (UNSPEC_FIST_CEIL 75) + + ; x87 Double output FP + (UNSPEC_SINCOS_COS 80) + (UNSPEC_SINCOS_SIN 81) + (UNSPEC_TAN_ONE 82) + (UNSPEC_TAN_TAN 83) + (UNSPEC_XTRACT_FRACT 84) + (UNSPEC_XTRACT_EXP 85) + (UNSPEC_FSCALE_FRACT 86) + (UNSPEC_FSCALE_EXP 87) + (UNSPEC_FPREM_F 88) + (UNSPEC_FPREM_U 89) + (UNSPEC_FPREM1_F 90) + (UNSPEC_FPREM1_U 91) + + ; SSP patterns + (UNSPEC_SP_SET 100) + (UNSPEC_SP_TEST 101) + (UNSPEC_SP_TLS_SET 102) + (UNSPEC_SP_TLS_TEST 103) ]) (define_constants [(UNSPECV_BLOCKAGE 0) - (UNSPECV_STACK_PROBE 10) - (UNSPECV_EH_RETURN 13) - (UNSPECV_EMMS 31) - (UNSPECV_LDMXCSR 37) - (UNSPECV_STMXCSR 40) - (UNSPECV_FEMMS 46) - (UNSPECV_CLFLUSH 57) - (UNSPECV_ALIGN 68) - (UNSPECV_MONITOR 69) - (UNSPECV_MWAIT 70) + (UNSPECV_STACK_PROBE 1) + (UNSPECV_EMMS 2) + (UNSPECV_LDMXCSR 3) + (UNSPECV_STMXCSR 4) + (UNSPECV_FEMMS 5) + (UNSPECV_CLFLUSH 6) + (UNSPECV_ALIGN 7) + (UNSPECV_MONITOR 8) + (UNSPECV_MWAIT 9) + (UNSPECV_CMPXCHG_1 10) + (UNSPECV_CMPXCHG_2 11) + (UNSPECV_XCHG 12) + (UNSPECV_LOCK 13) + ]) + +;; Registers by name. +(define_constants + [(BP_REG 6) + (SP_REG 7) + (FLAGS_REG 17) + (FPSR_REG 18) + (DIRFLAG_REG 19) ]) ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls @@ -149,7 +187,7 @@ ;; Processor type. This attribute must exactly match the processor_type ;; enumeration in i386.h. -(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8" +(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona,generic32,generic64" (const (symbol_ref "ix86_tune"))) ;; A basic instruction type. Refinements due to arguments to be @@ -161,22 +199,22 @@ icmp,test,ibr,setcc,icmov, push,pop,call,callv,leave, str,cld, - fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp, - sselog,sseiadd,sseishft,sseimul, + 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")) ;; Main data type used by the insn (define_attr "mode" - "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF" + "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF,V1DF" (const_string "unknown")) ;; 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") + (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint") (const_string "i387") - (eq_attr "type" "sselog,sseiadd,sseishft,sseimul, + (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul, sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv") (const_string "sse") (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft") @@ -210,7 +248,7 @@ (const_int 1) ] (symbol_ref "/* Update immediate_length and other attributes! */ - abort(),1"))) + gcc_unreachable (),1"))) ;; The (bounding maximum) length of an instruction address. (define_attr "length_address" "" @@ -246,7 +284,7 @@ (const_int 1) (const_int 0))) -;; Set when 0f opcode prefix is used. +;; Set when REX opcode prefix is used. (define_attr "prefix_rex" "" (cond [(and (eq_attr "mode" "DI") (eq_attr "type" "!push,pop,call,callv,leave,ibr")) @@ -278,8 +316,12 @@ (not (match_operand 0 "memory_operand" ""))) (const_int 0) (and (eq_attr "type" "imov") - (and (match_operand 0 "register_operand" "") - (match_operand 1 "immediate_operand" ""))) + (ior (and (match_operand 0 "register_operand" "") + (match_operand 1 "immediate_operand" "")) + (ior (and (match_operand 0 "ax_reg_operand" "") + (match_operand 1 "memory_displacement_only_operand" "")) + (and (match_operand 0 "memory_displacement_only_operand" "") + (match_operand 1 "ax_reg_operand" ""))))) (const_int 0) (and (eq_attr "type" "call") (match_operand 0 "constant_call_address_operand" "")) @@ -291,10 +333,11 @@ (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. +;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences. +;; Later we may want to split them and compute proper length as for +;; other insns. (define_attr "length" "" - (cond [(eq_attr "type" "other,multi,fistp") + (cond [(eq_attr "type" "other,multi,fistp,frndint") (const_int 16) (eq_attr "type" "fcmp") (const_int 4) @@ -322,6 +365,8 @@ (const_string "none") (eq_attr "type" "fistp,leave") (const_string "both") + (eq_attr "type" "frndint") + (const_string "load") (eq_attr "type" "push") (if_then_else (match_operand 1 "memory_operand" "") (const_string "both") @@ -351,7 +396,7 @@ (if_then_else (match_operand 1 "constant_call_address_operand" "") (const_string "none") (const_string "load")) - (and (eq_attr "type" "alu1,negnot,ishift1") + (and (eq_attr "type" "alu1,negnot,ishift1,sselog1") (match_operand 1 "memory_operand" "")) (const_string "both") (and (match_operand 0 "memory_operand" "") @@ -365,7 +410,7 @@ "!alu1,negnot,ishift1, imov,imovx,icmp,test, fmov,fcmp,fsgn, - sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt, + sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1, mmx,mmxmov,mmxcmp,mmxcvt") (match_operand 2 "memory_operand" "")) (const_string "load") @@ -396,15 +441,45 @@ (define_attr "fp_int_src" "false,true" (const_string "false")) +;; Defines rounding mode of an FP operation. + +(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any" + (const_string "any")) + ;; Describe a user's asm statement. (define_asm_attributes [(set_attr "length" "128") (set_attr "type" "multi")]) + +;; All x87 floating point modes +(define_mode_macro X87MODEF [SF DF XF]) + +;; All integer modes handled by x87 fisttp operator. +(define_mode_macro X87MODEI [HI SI DI]) + +;; All integer modes handled by integer x87 operators. +(define_mode_macro X87MODEI12 [HI SI]) + +;; All SSE floating point modes +(define_mode_macro SSEMODEF [SF DF]) + +;; All integer modes handled by SSE cvtts?2si* operators. +(define_mode_macro SSEMODEI24 [SI DI]) + +;; Scheduling descriptions + (include "pentium.md") (include "ppro.md") (include "k6.md") (include "athlon.md") + + +;; Operand and operator predicates and constraints + +(include "predicates.md") +(include "constraints.md") + ;; Compare instructions. @@ -412,8 +487,21 @@ ;; actually generating RTL. The bCOND or sCOND (emitted immediately ;; after the cmp) will actually emit the cmpM. +(define_expand "cmpti" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "x86_64_general_operand" "")))] + "TARGET_64BIT" +{ + if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) + operands[0] = force_reg (TImode, operands[0]); + ix86_compare_op0 = operands[0]; + ix86_compare_op1 = operands[1]; + DONE; +}) + (define_expand "cmpdi" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") (match_operand:DI 1 "x86_64_general_operand" "")))] "" @@ -426,7 +514,7 @@ }) (define_expand "cmpsi" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:SI 0 "cmpsi_operand" "") (match_operand:SI 1 "general_operand" "")))] "" @@ -439,7 +527,7 @@ }) (define_expand "cmphi" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" "")))] "" @@ -452,7 +540,7 @@ }) (define_expand "cmpqi" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:QI 0 "nonimmediate_operand" "") (match_operand:QI 1 "general_operand" "")))] "TARGET_QIMODE_MATH" @@ -465,7 +553,7 @@ }) (define_insn "cmpdi_ccno_1_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr") (match_operand:DI 1 "const0_operand" "n,n")))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" @@ -477,7 +565,7 @@ (set_attr "mode" "DI")]) (define_insn "*cmpdi_minus_1_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r") (match_operand:DI 1 "x86_64_general_operand" "re,mr")) (const_int 0)))] @@ -487,14 +575,14 @@ (set_attr "mode" "DI")]) (define_expand "cmpdi_1_rex64" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") (match_operand:DI 1 "general_operand" "")))] "TARGET_64BIT" "") (define_insn "cmpdi_1_insn_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:DI 0 "nonimmediate_operand" "mr,r") (match_operand:DI 1 "x86_64_general_operand" "re,mr")))] "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)" @@ -504,7 +592,7 @@ (define_insn "*cmpsi_ccno_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr") (match_operand:SI 1 "const0_operand" "n,n")))] "ix86_match_ccmode (insn, CCNOmode)" @@ -516,7 +604,7 @@ (set_attr "mode" "SI")]) (define_insn "*cmpsi_minus_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r") (match_operand:SI 1 "general_operand" "ri,mr")) (const_int 0)))] @@ -526,14 +614,14 @@ (set_attr "mode" "SI")]) (define_expand "cmpsi_1" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r") (match_operand:SI 1 "general_operand" "ri,mr")))] "" "") (define_insn "*cmpsi_1_insn" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:SI 0 "nonimmediate_operand" "rm,r") (match_operand:SI 1 "general_operand" "ri,mr")))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) @@ -543,7 +631,7 @@ (set_attr "mode" "SI")]) (define_insn "*cmphi_ccno_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr") (match_operand:HI 1 "const0_operand" "n,n")))] "ix86_match_ccmode (insn, CCNOmode)" @@ -555,7 +643,7 @@ (set_attr "mode" "HI")]) (define_insn "*cmphi_minus_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r") (match_operand:HI 1 "general_operand" "ri,mr")) (const_int 0)))] @@ -565,7 +653,7 @@ (set_attr "mode" "HI")]) (define_insn "*cmphi_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:HI 0 "nonimmediate_operand" "rm,r") (match_operand:HI 1 "general_operand" "ri,mr")))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) @@ -575,7 +663,7 @@ (set_attr "mode" "HI")]) (define_insn "*cmpqi_ccno_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq") (match_operand:QI 1 "const0_operand" "n,n")))] "ix86_match_ccmode (insn, CCNOmode)" @@ -587,7 +675,7 @@ (set_attr "mode" "QI")]) (define_insn "*cmpqi_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:QI 0 "nonimmediate_operand" "qm,q") (match_operand:QI 1 "general_operand" "qi,mq")))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) @@ -597,7 +685,7 @@ (set_attr "mode" "QI")]) (define_insn "*cmpqi_minus_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q") (match_operand:QI 1 "general_operand" "qi,mq")) (const_int 0)))] @@ -607,7 +695,7 @@ (set_attr "mode" "QI")]) (define_insn "*cmpqi_ext_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:QI 0 "general_operand" "Qm") (subreg:QI @@ -621,7 +709,7 @@ (set_attr "mode" "QI")]) (define_insn "*cmpqi_ext_1_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:QI 0 "register_operand" "Q") (subreg:QI @@ -635,7 +723,7 @@ (set_attr "mode" "QI")]) (define_insn "*cmpqi_ext_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (subreg:QI (zero_extract:SI @@ -650,7 +738,7 @@ (set_attr "mode" "QI")]) (define_expand "cmpqi_ext_3" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (subreg:QI (zero_extract:SI @@ -662,7 +750,7 @@ "") (define_insn "cmpqi_ext_3_insn" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (subreg:QI (zero_extract:SI @@ -676,7 +764,7 @@ (set_attr "mode" "QI")]) (define_insn "cmpqi_ext_3_insn_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (subreg:QI (zero_extract:SI @@ -690,7 +778,7 @@ (set_attr "mode" "QI")]) (define_insn "*cmpqi_ext_4" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (subreg:QI (zero_extract:SI @@ -713,9 +801,9 @@ ;; the old patterns did, but with many more of them. (define_expand "cmpxf" - [(set (reg:CC 17) - (compare:CC (match_operand:XF 0 "cmp_fp_expander_operand" "") - (match_operand:XF 1 "cmp_fp_expander_operand" "")))] + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:XF 0 "nonmemory_operand" "") + (match_operand:XF 1 "nonmemory_operand" "")))] "TARGET_80387" { ix86_compare_op0 = operands[0]; @@ -724,10 +812,10 @@ }) (define_expand "cmpdf" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "") (match_operand:DF 1 "cmp_fp_expander_operand" "")))] - "TARGET_80387 || TARGET_SSE2" + "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" { ix86_compare_op0 = operands[0]; ix86_compare_op1 = operands[1]; @@ -735,10 +823,10 @@ }) (define_expand "cmpsf" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "") (match_operand:SF 1 "cmp_fp_expander_operand" "")))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" { ix86_compare_op0 = operands[0]; ix86_compare_op1 = operands[1]; @@ -751,34 +839,22 @@ ;; CCFPmode compare with exceptions ;; CCFPUmode compare with no exceptions -;; %%% It is an unfortunate fact that ftst has no non-popping variant, -;; and that fp moves clobber the condition codes, and that there is -;; currently no way to describe this fact to reg-stack. So there are -;; no splitters yet for this. - -;; %%% YIKES! This scheme does not retain a strong connection between -;; the real compare and the ultimate cc0 user, so CC_REVERSE does not -;; work! Only allow tos/mem with tos in op 0. -;; -;; Hmm, of course, this is what the actual _hardware_ does. Perhaps -;; things aren't as bad as they sound... +;; We may not use "#" to split and emit these, since the REG_DEAD notes +;; used to manage the reg stack popping would not be preserved. (define_insn "*cmpfp_0" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI - [(compare:CCFP (match_operand 1 "register_operand" "f") - (match_operand 2 "const0_operand" "X"))] - UNSPEC_FNSTSW))] + [(compare:CCFP + (match_operand 1 "register_operand" "f") + (match_operand 2 "const0_operand" "X"))] + UNSPEC_FNSTSW))] "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" -{ - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "ftst\;fnstsw\t%0\;fstp\t%y0"; - else - return "ftst\;fnstsw\t%0"; -} + "* return output_fp_compare (insn, operands, 0, 0);" [(set_attr "type" "multi") + (set_attr "unit" "i387") (set (attr "mode") (cond [(match_operand:SF 1 "" "") (const_string "SF") @@ -787,20 +863,7 @@ ] (const_string "XF")))]) -;; We may not use "#" to split and emit these, since the REG_DEAD notes -;; used to manage the reg stack popping would not be preserved. - -(define_insn "*cmpfp_2_sf" - [(set (reg:CCFP 18) - (compare:CCFP - (match_operand:SF 0 "register_operand" "f") - (match_operand:SF 1 "nonimmediate_operand" "fm")))] - "TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" - [(set_attr "type" "fcmp") - (set_attr "mode" "SF")]) - -(define_insn "*cmpfp_2_sf_1" +(define_insn "*cmpfp_sf" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI [(compare:CCFP @@ -808,21 +871,12 @@ (match_operand:SF 2 "nonimmediate_operand" "fm"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 2, 0);" - [(set_attr "type" "fcmp") - (set_attr "mode" "SF")]) - -(define_insn "*cmpfp_2_df" - [(set (reg:CCFP 18) - (compare:CCFP - (match_operand:DF 0 "register_operand" "f") - (match_operand:DF 1 "nonimmediate_operand" "fm")))] - "TARGET_80387" "* return output_fp_compare (insn, operands, 0, 0);" - [(set_attr "type" "fcmp") - (set_attr "mode" "DF")]) + [(set_attr "type" "multi") + (set_attr "unit" "i387") + (set_attr "mode" "SF")]) -(define_insn "*cmpfp_2_df_1" +(define_insn "*cmpfp_df" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI [(compare:CCFP @@ -830,21 +884,12 @@ (match_operand:DF 2 "nonimmediate_operand" "fm"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 2, 0);" + "* return output_fp_compare (insn, operands, 0, 0);" [(set_attr "type" "multi") + (set_attr "unit" "i387") (set_attr "mode" "DF")]) -(define_insn "*cmpfp_2_xf" - [(set (reg:CCFP 18) - (compare:CCFP - (match_operand:XF 0 "register_operand" "f") - (match_operand:XF 1 "register_operand" "f")))] - "TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" - [(set_attr "type" "fcmp") - (set_attr "mode" "XF")]) - -(define_insn "*cmpfp_2_xf_1" +(define_insn "*cmpfp_xf" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI [(compare:CCFP @@ -852,29 +897,12 @@ (match_operand:XF 2 "register_operand" "f"))] UNSPEC_FNSTSW))] "TARGET_80387" - "* return output_fp_compare (insn, operands, 2, 0);" + "* return output_fp_compare (insn, operands, 0, 0);" [(set_attr "type" "multi") + (set_attr "unit" "i387") (set_attr "mode" "XF")]) -(define_insn "*cmpfp_2u" - [(set (reg:CCFPU 18) - (compare:CCFPU - (match_operand 0 "register_operand" "f") - (match_operand 1 "register_operand" "f")))] - "TARGET_80387 - && FLOAT_MODE_P (GET_MODE (operands[0])) - && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 0, 1);" - [(set_attr "type" "fcmp") - (set (attr "mode") - (cond [(match_operand:SF 1 "" "") - (const_string "SF") - (match_operand:DF 1 "" "") - (const_string "DF") - ] - (const_string "XF")))]) - -(define_insn "*cmpfp_2u_1" +(define_insn "*cmpfp_u" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI [(compare:CCFPU @@ -884,8 +912,9 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" - "* return output_fp_compare (insn, operands, 2, 1);" + "* return output_fp_compare (insn, operands, 0, 1);" [(set_attr "type" "multi") + (set_attr "unit" "i387") (set (attr "mode") (cond [(match_operand:SF 1 "" "") (const_string "SF") @@ -894,95 +923,56 @@ ] (const_string "XF")))]) -;; Patterns to match the SImode-in-memory ficom instructions. -;; -;; %%% Play games with accepting gp registers, as otherwise we have to -;; force them to memory during rtl generation, which is no good. We -;; can get rid of this once we teach reload to do memory input reloads -;; via pushes. - -(define_insn "*ficom_1" - [(set (reg:CCFP 18) - (compare:CCFP - (match_operand 0 "register_operand" "f,f") - (float (match_operand:SI 1 "nonimmediate_operand" "m,?r"))))] - "0 && TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[0])) - && GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == GET_MODE (operands[0])" - "#") - -;; Split the not-really-implemented gp register case into a -;; push-op-pop sequence. -;; -;; %%% This is most efficient, but am I gonna get in trouble -;; for separating cc0_setter and cc0_user? - -(define_split - [(set (reg:CCFP 18) - (compare:CCFP - (match_operand:SF 0 "register_operand" "") - (float (match_operand:SI 1 "register_operand" ""))))] - "0 && TARGET_80387 && reload_completed" - [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 1)) - (set (reg:CCFP 18) (compare:CCFP (match_dup 0) (match_dup 2))) - (parallel [(set (match_dup 1) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])] - "operands[2] = gen_rtx_MEM (Pmode, stack_pointer_rtx); - operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);") +(define_insn "*cmpfp_<mode>" + [(set (match_operand:HI 0 "register_operand" "=a") + (unspec:HI + [(compare:CCFP + (match_operand 1 "register_operand" "f") + (match_operator 3 "float_operator" + [(match_operand:X87MODEI12 2 "memory_operand" "m")]))] + UNSPEC_FNSTSW))] + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP + && FLOAT_MODE_P (GET_MODE (operands[1])) + && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" + "* return output_fp_compare (insn, operands, 0, 0);" + [(set_attr "type" "multi") + (set_attr "unit" "i387") + (set_attr "fp_int_src" "true") + (set_attr "mode" "<MODE>")]) ;; FP compares, step 2 ;; Move the fpsw to ax. -(define_insn "*x86_fnstsw_1" +(define_insn "x86_fnstsw_1" [(set (match_operand:HI 0 "register_operand" "=a") - (unspec:HI [(reg 18)] UNSPEC_FNSTSW))] + (unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))] "TARGET_80387" "fnstsw\t%0" [(set_attr "length" "2") (set_attr "mode" "SI") - (set_attr "unit" "i387") - (set_attr "ppro_uops" "few")]) + (set_attr "unit" "i387")]) ;; FP compares, step 3 ;; Get ax into flags, general case. (define_insn "x86_sahf_1" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))] "!TARGET_64BIT" "sahf" [(set_attr "length" "1") (set_attr "athlon_decode" "vector") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "one")]) + (set_attr "mode" "SI")]) ;; Pentium Pro can do steps 1 through 3 in one go. -(define_insn "*cmpfp_i" - [(set (reg:CCFP 17) - (compare:CCFP (match_operand 0 "register_operand" "f") - (match_operand 1 "register_operand" "f")))] - "TARGET_80387 && TARGET_CMOVE - && !SSE_FLOAT_MODE_P (GET_MODE (operands[0])) - && FLOAT_MODE_P (GET_MODE (operands[0])) - && GET_MODE (operands[0]) == GET_MODE (operands[0])" - "* return output_fp_compare (insn, operands, 1, 0);" - [(set_attr "type" "fcmp") - (set (attr "mode") - (cond [(match_operand:SF 1 "" "") - (const_string "SF") - (match_operand:DF 1 "" "") - (const_string "DF") - ] - (const_string "XF"))) - (set_attr "athlon_decode" "vector")]) - -(define_insn "*cmpfp_i_sse" - [(set (reg:CCFP 17) - (compare:CCFP (match_operand 0 "register_operand" "f#x,x#f") - (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))] - "TARGET_80387 +(define_insn "*cmpfp_i_mixed" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP (match_operand 0 "register_operand" "f,x") + (match_operand 1 "nonimmediate_operand" "f,xm")))] + "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) - && GET_MODE (operands[0]) == GET_MODE (operands[0])" + && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 0);" [(set_attr "type" "fcmp,ssecomi") (set (attr "mode") @@ -991,12 +981,13 @@ (const_string "DF"))) (set_attr "athlon_decode" "vector")]) -(define_insn "*cmpfp_i_sse_only" - [(set (reg:CCFP 17) +(define_insn "*cmpfp_i_sse" + [(set (reg:CCFP FLAGS_REG) (compare:CCFP (match_operand 0 "register_operand" "x") (match_operand 1 "nonimmediate_operand" "xm")))] - "SSE_FLOAT_MODE_P (GET_MODE (operands[0])) - && GET_MODE (operands[0]) == GET_MODE (operands[0])" + "TARGET_SSE_MATH + && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) + && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 0);" [(set_attr "type" "ssecomi") (set (attr "mode") @@ -1005,15 +996,15 @@ (const_string "DF"))) (set_attr "athlon_decode" "vector")]) -(define_insn "*cmpfp_iu" - [(set (reg:CCFPU 17) - (compare:CCFPU (match_operand 0 "register_operand" "f") - (match_operand 1 "register_operand" "f")))] +(define_insn "*cmpfp_i_i387" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP (match_operand 0 "register_operand" "f") + (match_operand 1 "register_operand" "f")))] "TARGET_80387 && TARGET_CMOVE - && !SSE_FLOAT_MODE_P (GET_MODE (operands[0])) + && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0]))) && FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" - "* return output_fp_compare (insn, operands, 1, 1);" + "* return output_fp_compare (insn, operands, 1, 0);" [(set_attr "type" "fcmp") (set (attr "mode") (cond [(match_operand:SF 1 "" "") @@ -1024,11 +1015,11 @@ (const_string "XF"))) (set_attr "athlon_decode" "vector")]) -(define_insn "*cmpfp_iu_sse" - [(set (reg:CCFPU 17) - (compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f") - (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))] - "TARGET_80387 +(define_insn "*cmpfp_iu_mixed" + [(set (reg:CCFPU FLAGS_REG) + (compare:CCFPU (match_operand 0 "register_operand" "f,x") + (match_operand 1 "nonimmediate_operand" "f,xm")))] + "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 1);" @@ -1039,11 +1030,12 @@ (const_string "DF"))) (set_attr "athlon_decode" "vector")]) -(define_insn "*cmpfp_iu_sse_only" - [(set (reg:CCFPU 17) +(define_insn "*cmpfp_iu_sse" + [(set (reg:CCFPU FLAGS_REG) (compare:CCFPU (match_operand 0 "register_operand" "x") (match_operand 1 "nonimmediate_operand" "xm")))] - "SSE_FLOAT_MODE_P (GET_MODE (operands[0])) + "TARGET_SSE_MATH + && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 1);" [(set_attr "type" "ssecomi") @@ -1052,6 +1044,25 @@ (const_string "SF") (const_string "DF"))) (set_attr "athlon_decode" "vector")]) + +(define_insn "*cmpfp_iu_387" + [(set (reg:CCFPU FLAGS_REG) + (compare:CCFPU (match_operand 0 "register_operand" "f") + (match_operand 1 "register_operand" "f")))] + "TARGET_80387 && TARGET_CMOVE + && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0]))) + && FLOAT_MODE_P (GET_MODE (operands[0])) + && GET_MODE (operands[0]) == GET_MODE (operands[1])" + "* return output_fp_compare (insn, operands, 1, 1);" + [(set_attr "type" "fcmp") + (set (attr "mode") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF"))) + (set_attr "athlon_decode" "vector")]) ;; Move instructions. @@ -1100,9 +1111,9 @@ (define_insn "*popsi1_epilogue" [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m") - (mem:SI (reg:SI 7))) - (set (reg:SI 7) - (plus:SI (reg:SI 7) (const_int 4))) + (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int 4))) (clobber (mem:BLK (scratch)))] "!TARGET_64BIT" "pop{l}\t%0" @@ -1111,9 +1122,9 @@ (define_insn "popsi1" [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m") - (mem:SI (reg:SI 7))) - (set (reg:SI 7) - (plus:SI (reg:SI 7) (const_int 4)))] + (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int 4)))] "!TARGET_64BIT" "pop{l}\t%0" [(set_attr "type" "pop") @@ -1122,7 +1133,7 @@ (define_insn "*movsi_xor" [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "const0_operand" "i")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && (!TARGET_USE_MOV0 || optimize_size)" "xor{l}\t{%0, %0|%0, %0}" [(set_attr "type" "alu1") @@ -1132,7 +1143,7 @@ (define_insn "*movsi_or" [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "immediate_operand" "i")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && operands[1] == constm1_rtx && (TARGET_PENTIUM || optimize_size)" @@ -1145,56 +1156,36 @@ (set_attr "length_immediate" "1")]) (define_insn "*movsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!rm,!*y,!*Y,!rm,!*Y") - (match_operand:SI 1 "general_operand" "rinm,rin,*y,*y,rm,*Y,*Y,rm"))] - "(TARGET_INTER_UNIT_MOVES || optimize_size) - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + [(set (match_operand:SI 0 "nonimmediate_operand" + "=r ,m ,*y,*y,?rm,?*y,*x,*x,?r,m ,?*Y,*x") + (match_operand:SI 1 "general_operand" + "rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y,*x,r ,m "))] + "!(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) { - case TYPE_SSEMOV: + case TYPE_SSELOG1: if (get_attr_mode (insn) == MODE_TI) - return "movdqa\t{%1, %0|%0, %1}"; - return "movd\t{%1, %0|%0, %1}"; + return "pxor\t%0, %0"; + return "xorps\t%0, %0"; - case TYPE_MMXMOV: - if (get_attr_mode (insn) == MODE_DI) - return "movq\t{%1, %0|%0, %1}"; - return "movd\t{%1, %0|%0, %1}"; - - case TYPE_LEA: - return "lea{l}\t{%1, %0|%0, %1}"; - - default: - if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1])) - abort(); - return "mov{l}\t{%1, %0|%0, %1}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "2,3,4") - (const_string "mmxmov") - (eq_attr "alternative" "5,6,7") - (const_string "ssemov") - (and (ne (symbol_ref "flag_pic") (const_int 0)) - (match_operand:SI 1 "symbolic_operand" "")) - (const_string "lea") - ] - (const_string "imov"))) - (set_attr "mode" "SI,SI,DI,SI,SI,TI,SI,SI")]) - -(define_insn "*movsi_1_nointernunit" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!m,!*y,!*Y,!m,!*Y") - (match_operand:SI 1 "general_operand" "rinm,rin,*y,*y,m,*Y,*Y,m"))] - "(!TARGET_INTER_UNIT_MOVES && !optimize_size) - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (get_attr_type (insn)) - { case TYPE_SSEMOV: - if (get_attr_mode (insn) == MODE_TI) - return "movdqa\t{%1, %0|%0, %1}"; - return "movd\t{%1, %0|%0, %1}"; + switch (get_attr_mode (insn)) + { + case MODE_TI: + return "movdqa\t{%1, %0|%0, %1}"; + case MODE_V4SF: + return "movaps\t{%1, %0|%0, %1}"; + case MODE_SI: + return "movd\t{%1, %0|%0, %1}"; + case MODE_SF: + return "movss\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } + + case TYPE_MMXADD: + return "pxor\t%0, %0"; case TYPE_MMXMOV: if (get_attr_mode (insn) == MODE_DI) @@ -1205,22 +1196,36 @@ return "lea{l}\t{%1, %0|%0, %1}"; default: - if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1])) - abort(); + gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); return "mov{l}\t{%1, %0|%0, %1}"; } } [(set (attr "type") - (cond [(eq_attr "alternative" "2,3,4") + (cond [(eq_attr "alternative" "2") + (const_string "mmxadd") + (eq_attr "alternative" "3,4,5") (const_string "mmxmov") - (eq_attr "alternative" "5,6,7") + (eq_attr "alternative" "6") + (const_string "sselog1") + (eq_attr "alternative" "7,8,9,10,11") (const_string "ssemov") - (and (ne (symbol_ref "flag_pic") (const_int 0)) - (match_operand:SI 1 "symbolic_operand" "")) + (match_operand:DI 1 "pic_32bit_operand" "") (const_string "lea") ] (const_string "imov"))) - (set_attr "mode" "SI,SI,DI,SI,SI,TI,SI,SI")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "2,3") + (const_string "DI") + (eq_attr "alternative" "6,7") + (if_then_else + (eq (symbol_ref "TARGET_SSE2") (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (and (eq_attr "alternative" "8,9,10,11") + (eq (symbol_ref "TARGET_SSE2") (const_int 0))) + (const_string "SF") + ] + (const_string "SI")))]) ;; Stores and loads of ax to arbitrary constant address. ;; We fake an second form of instruction to force reload to load address @@ -1263,8 +1268,7 @@ [(set_attr "type" "imov") (set_attr "mode" "SI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) (define_expand "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "") @@ -1273,14 +1277,12 @@ "ix86_expand_move (HImode, operands); DONE;") (define_insn "*pushhi2" - [(set (match_operand:HI 0 "push_operand" "=<,<") - (match_operand:HI 1 "general_no_elim_operand" "n,r*m"))] + [(set (match_operand:HI 0 "push_operand" "=X") + (match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))] "!TARGET_64BIT" - "@ - push{w}\t{|WORD PTR }%1 - push{w}\t%1" + "push{l}\t%k1" [(set_attr "type" "push") - (set_attr "mode" "HI")]) + (set_attr "mode" "SI")]) ;; For 64BIT abi we always round up to 8 bytes. (define_insn "*pushhi2_rex64" @@ -1289,7 +1291,7 @@ "TARGET_64BIT" "push{q}\t%q1" [(set_attr "type" "push") - (set_attr "mode" "QI")]) + (set_attr "mode" "DI")]) (define_insn "*movhi_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m") @@ -1310,7 +1312,9 @@ } } [(set (attr "type") - (cond [(and (eq_attr "alternative" "0") + (cond [(ne (symbol_ref "optimize_size") (const_int 0)) + (const_string "imov") + (and (eq_attr "alternative" "0") (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") (const_int 0)) (eq (symbol_ref "TARGET_HIMODE_MATH") @@ -1381,8 +1385,7 @@ [(set_attr "type" "imov") (set_attr "mode" "SI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) (define_insn "*swaphi_2" [(set (match_operand:HI 0 "register_operand" "+r") @@ -1394,8 +1397,7 @@ [(set_attr "type" "imov") (set_attr "mode" "HI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) (define_expand "movstricthi" [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "")) @@ -1419,7 +1421,7 @@ (define_insn "*movstricthi_xor" [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r")) (match_operand:HI 1 "const0_operand" "i")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && ((!TARGET_USE_MOV0 && !TARGET_PARTIAL_REG_STALL) || optimize_size)" "xor{w}\t{%0, %0|%0, %0}" @@ -1434,18 +1436,16 @@ "ix86_expand_move (QImode, operands); DONE;") ;; emit_push_insn when it calls move_by_pieces requires an insn to -;; "push a byte". But actually we use pushw, which has the effect -;; of rounding the amount pushed up to a halfword. +;; "push a byte". But actually we use pushl, which has the effect +;; of rounding the amount pushed up to a word. (define_insn "*pushqi2" - [(set (match_operand:QI 0 "push_operand" "=X,X") - (match_operand:QI 1 "nonmemory_no_elim_operand" "n,r"))] + [(set (match_operand:QI 0 "push_operand" "=X") + (match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))] "!TARGET_64BIT" - "@ - push{w}\t{|word ptr }%1 - push{w}\t%w1" + "push{l}\t%k1" [(set_attr "type" "push") - (set_attr "mode" "HI")]) + (set_attr "mode" "SI")]) ;; For 64BIT abi we always round up to 8 bytes. (define_insn "*pushqi2_rex64" @@ -1454,7 +1454,7 @@ "TARGET_64BIT" "push{q}\t%q1" [(set_attr "type" "push") - (set_attr "mode" "QI")]) + (set_attr "mode" "DI")]) ;; Situation is quite tricky about when to choose full sized (SImode) move ;; over QImode moves. For Q_REG -> Q_REG move we use full size only for @@ -1474,8 +1474,7 @@ switch (get_attr_type (insn)) { case TYPE_IMOVX: - if (!ANY_QI_REG_P (operands[1]) && GET_CODE (operands[1]) != MEM) - abort (); + gcc_assert (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM); return "movz{bl|x}\t{%1, %k0|%k0, %1}"; default: if (get_attr_mode (insn) == MODE_SI) @@ -1485,7 +1484,12 @@ } } [(set (attr "type") - (cond [(and (eq_attr "alternative" "3") + (cond [(and (eq_attr "alternative" "5") + (not (match_operand:QI 1 "aligned_operand" ""))) + (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") (const_int 0)) (eq (symbol_ref "TARGET_QIMODE_MATH") @@ -1507,13 +1511,17 @@ (eq_attr "type" "imovx") (const_string "SI") (and (eq_attr "type" "imov") - (and (eq_attr "alternative" "0,1,2") - (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY") - (const_int 0)))) + (and (eq_attr "alternative" "0,1") + (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (and (eq (symbol_ref "optimize_size") + (const_int 0)) + (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") + (const_int 0)))))) (const_string "SI") ;; Avoid partial register stalls when not using QImode arithmetic (and (eq_attr "type" "imov") - (and (eq_attr "alternative" "0,1,2") + (and (eq_attr "alternative" "0,1") (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL") (const_int 0)) (eq (symbol_ref "TARGET_QIMODE_MATH") @@ -1531,8 +1539,7 @@ rtx op0, op1, op2; op0 = operands[0]; op1 = operands[1]; op2 = operands[2]; - if (reg_overlap_mentioned_p (op2, op0)) - abort (); + gcc_assert (!reg_overlap_mentioned_p (op2, op0)); if (! q_regs_operand (op1, QImode)) { emit_insn (gen_movqi (op2, op1)); @@ -1552,8 +1559,7 @@ [(set_attr "type" "imov") (set_attr "mode" "SI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) (define_insn "*swapqi_2" [(set (match_operand:QI 0 "register_operand" "+q") @@ -1565,8 +1571,7 @@ [(set_attr "type" "imov") (set_attr "mode" "QI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) (define_expand "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "")) @@ -1590,7 +1595,7 @@ (define_insn "*movstrictqi_xor" [(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q")) (match_operand:QI 1 "const0_operand" "i")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && (!TARGET_USE_MOV0 || optimize_size)" "xor{b}\t{%0, %0|%0, %0}" [(set_attr "type" "alu1") @@ -1702,6 +1707,16 @@ (set_attr "memory" "load") (set_attr "mode" "QI")]) +(define_insn "*movdi_extzv_1" + [(set (match_operand:DI 0 "register_operand" "=R") + (zero_extract:DI (match_operand 1 "ext_register_operand" "Q") + (const_int 8) + (const_int 8)))] + "TARGET_64BIT" + "movz{bl|x}\t{%h1, %k0|%k0, %h1}" + [(set_attr "type" "imovx") + (set_attr "mode" "DI")]) + (define_insn "*movsi_extzv_1" [(set (match_operand:SI 0 "register_operand" "=R") (zero_extract:SI (match_operand 1 "ext_register_operand" "Q") @@ -1808,7 +1823,7 @@ "!TARGET_64BIT" "#") -(define_insn "pushdi2_rex64" +(define_insn "*pushdi2_rex64" [(set (match_operand:DI 0 "push_operand" "=<,!<") (match_operand:DI 1 "general_no_elim_operand" "re*m,n"))] "TARGET_64BIT" @@ -1834,6 +1849,7 @@ ;; We need to define this as both peepholer and splitter for case ;; peephole2 pass is not run. +;; "&& 1" is needed to keep it from matching the previous pattern. (define_peephole2 [(set (match_operand:DI 0 "push_operand" "") (match_operand:DI 1 "immediate_operand" ""))] @@ -1851,7 +1867,7 @@ [(set (match_operand:DI 0 "push_operand" "") (match_operand:DI 1 "immediate_operand" ""))] "TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? flow2_completed : reload_completed) + ? flow2_completed : reload_completed) && !symbolic_operand (operands[1], DImode) && !x86_64_immediate_operand (operands[1], DImode)" [(set (match_dup 0) (match_dup 1)) @@ -1873,9 +1889,9 @@ (define_insn "*popdi1_epilogue_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m") - (mem:DI (reg:DI 7))) - (set (reg:DI 7) - (plus:DI (reg:DI 7) (const_int 8))) + (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) + (plus:DI (reg:DI SP_REG) (const_int 8))) (clobber (mem:BLK (scratch)))] "TARGET_64BIT" "pop{q}\t%0" @@ -1884,9 +1900,9 @@ (define_insn "popdi1" [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m") - (mem:DI (reg:DI 7))) - (set (reg:DI 7) - (plus:DI (reg:DI 7) (const_int 8)))] + (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) + (plus:DI (reg:DI SP_REG) (const_int 8)))] "TARGET_64BIT" "pop{q}\t%0" [(set_attr "type" "pop") @@ -1895,7 +1911,7 @@ (define_insn "*movdi_xor_rex64" [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "const0_operand" "i")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (!TARGET_USE_MOV0 || optimize_size) && reload_completed" "xor{l}\t{%k0, %k0|%k0, %k0}" @@ -1906,7 +1922,7 @@ (define_insn "*movdi_or_rex64" [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "const_int_operand" "i")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_PENTIUM || optimize_size) && reload_completed && operands[1] == constm1_rtx" @@ -1919,20 +1935,27 @@ (set_attr "length_immediate" "1")]) (define_insn "*movdi_2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!m*y,!*y,!m,!*Y,!*Y") - (match_operand:DI 1 "general_operand" "riFo,riF,*y,m,*Y,*Y,m"))] - "!TARGET_64BIT - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + [(set (match_operand:DI 0 "nonimmediate_operand" + "=r ,o ,*y,m*y,*y,*Y,m ,*Y,*Y,*x,m ,*x,*x") + (match_operand:DI 1 "general_operand" + "riFo,riF,C ,*y ,m ,C ,*Y,*Y,m ,C ,*x,*x,m "))] + "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "@ # # + pxor\t%0, %0 movq\t{%1, %0|%0, %1} movq\t{%1, %0|%0, %1} + pxor\t%0, %0 movq\t{%1, %0|%0, %1} movdqa\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1}" - [(set_attr "type" "*,*,mmx,mmx,ssemov,ssemov,ssemov") - (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI")]) + movq\t{%1, %0|%0, %1} + xorps\t%0, %0 + movlps\t{%1, %0|%0, %1} + movaps\t{%1, %0|%0, %1} + movlps\t{%1, %0|%0, %1}" + [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov") + (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")]) (define_split [(set (match_operand:DI 0 "push_operand" "") @@ -1953,14 +1976,19 @@ "ix86_split_long_move (operands); DONE;") (define_insn "*movdi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!*y,!rm,!*y,!*Y,!rm,!*Y") - (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,*y,rm,*Y,*Y,rm"))] - "TARGET_64BIT - && (TARGET_INTER_UNIT_MOVES || optimize_size) - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + [(set (match_operand:DI 0 "nonimmediate_operand" + "=r,r ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y") + (match_operand:DI 1 "general_operand" + "Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))] + "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) { + case TYPE_SSECVT: + if (which_alternative == 13) + return "movq2dq\t{%1, %0|%0, %1}"; + else + return "movdq2q\t{%1, %0|%0, %1}"; case TYPE_SSEMOV: if (get_attr_mode (insn) == MODE_TI) return "movdqa\t{%1, %0|%0, %1}"; @@ -1971,59 +1999,15 @@ if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) return "movd\t{%1, %0|%0, %1}"; return "movq\t{%1, %0|%0, %1}"; + case TYPE_SSELOG1: + case TYPE_MMXADD: + return "pxor\t%0, %0"; case TYPE_MULTI: return "#"; case TYPE_LEA: return "lea{q}\t{%a1, %0|%0, %a1}"; default: - if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1])) - abort (); - if (get_attr_mode (insn) == MODE_SI) - return "mov{l}\t{%k1, %k0|%k0, %k1}"; - else if (which_alternative == 2) - return "movabs{q}\t{%1, %0|%0, %1}"; - else - return "mov{q}\t{%1, %0|%0, %1}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "5,6,7") - (const_string "mmxmov") - (eq_attr "alternative" "8,9,10") - (const_string "ssemov") - (eq_attr "alternative" "4") - (const_string "multi") - (and (ne (symbol_ref "flag_pic") (const_int 0)) - (match_operand:DI 1 "symbolic_operand" "")) - (const_string "lea") - ] - (const_string "imov"))) - (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*") - (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*") - (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI,DI")]) - -(define_insn "*movdi_1_rex64_nointerunit" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!*y,!m,!*y,!*Y,!m,!*Y") - (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,*y,m,*Y,*Y,m"))] - "TARGET_64BIT - && (!TARGET_INTER_UNIT_MOVES && !optimize_size) - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (get_attr_type (insn)) - { - case TYPE_SSEMOV: - if (get_attr_mode (insn) == MODE_TI) - return "movdqa\t{%1, %0|%0, %1}"; - /* FALLTHRU */ - case TYPE_MMXMOV: - return "movq\t{%1, %0|%0, %1}"; - case TYPE_MULTI: - return "#"; - case TYPE_LEA: - return "lea{q}\t{%a1, %0|%0, %a1}"; - default: - if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1])) - abort (); + gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); if (get_attr_mode (insn) == MODE_SI) return "mov{l}\t{%k1, %k0|%k0, %k1}"; else if (which_alternative == 2) @@ -2033,20 +2017,25 @@ } } [(set (attr "type") - (cond [(eq_attr "alternative" "5,6,7") + (cond [(eq_attr "alternative" "5") + (const_string "mmxadd") + (eq_attr "alternative" "6,7,8") (const_string "mmxmov") - (eq_attr "alternative" "8,9,10") + (eq_attr "alternative" "9") + (const_string "sselog1") + (eq_attr "alternative" "10,11,12") (const_string "ssemov") + (eq_attr "alternative" "13,14") + (const_string "ssecvt") (eq_attr "alternative" "4") (const_string "multi") - (and (ne (symbol_ref "flag_pic") (const_int 0)) - (match_operand:DI 1 "symbolic_operand" "")) + (match_operand:DI 1 "pic_32bit_operand" "") (const_string "lea") ] (const_string "imov"))) - (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*") - (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*") - (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI,DI")]) + (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*") + (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*") + (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")]) ;; Stores and loads of ax to arbitrary constant address. ;; We fake an second form of instruction to force reload to load address @@ -2094,6 +2083,7 @@ ;; We need to define this as both peepholer and splitter for case ;; peephole2 pass is not run. +;; "&& 1" is needed to keep it from matching the previous pattern. (define_peephole2 [(set (match_operand:DI 0 "memory_operand" "") (match_operand:DI 1 "immediate_operand" ""))] @@ -2107,7 +2097,7 @@ [(set (match_operand:DI 0 "memory_operand" "") (match_operand:DI 1 "immediate_operand" ""))] "TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? flow2_completed : reload_completed) + ? flow2_completed : reload_completed) && !symbolic_operand (operands[1], DImode) && !x86_64_immediate_operand (operands[1], DImode)" [(set (match_dup 2) (match_dup 3)) @@ -2124,8 +2114,105 @@ [(set_attr "type" "imov") (set_attr "mode" "DI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) + +(define_expand "movti" + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "nonimmediate_operand" ""))] + "TARGET_SSE || TARGET_64BIT" +{ + if (TARGET_64BIT) + ix86_expand_move (TImode, operands); + else + ix86_expand_vector_move (TImode, operands); + DONE; +}) + +(define_insn "*movti_internal" + [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m") + (match_operand:TI 1 "vector_move_operand" "C,xm,x"))] + "TARGET_SSE && !TARGET_64BIT + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } +} + [(set_attr "type" "sselog1,ssemov,ssemov") + (set (attr "mode") + (cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0)) + (ne (symbol_ref "optimize_size") (const_int 0))) + (const_string "V4SF") + (and (eq_attr "alternative" "2") + (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0))) + (const_string "V4SF")] + (const_string "TI")))]) + +(define_insn "*movti_rex64" + [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm") + (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))] + "TARGET_64BIT + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (which_alternative) + { + case 0: + case 1: + return "#"; + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 3: + case 4: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } +} + [(set_attr "type" "*,*,sselog1,ssemov,ssemov") + (set (attr "mode") + (cond [(eq_attr "alternative" "2,3") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "4") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "DI")))]) + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "general_operand" ""))] + "reload_completed && !SSE_REG_P (operands[0]) + && !SSE_REG_P (operands[1])" + [(const_int 0)] + "ix86_split_long_move (operands); DONE;") (define_expand "movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "") @@ -2135,38 +2222,28 @@ (define_insn "*pushsf" [(set (match_operand:SF 0 "push_operand" "=<,<,<") - (match_operand:SF 1 "general_no_elim_operand" "f#rx,rFm#fx,x#rf"))] + (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))] "!TARGET_64BIT" { - switch (which_alternative) - { - case 1: - return "push{l}\t%1"; - - default: - /* This insn should be already split before reg-stack. */ - abort (); - } + /* Anything else should be already split before reg-stack. */ + gcc_assert (which_alternative == 1); + return "push{l}\t%1"; } [(set_attr "type" "multi,push,multi") + (set_attr "unit" "i387,*,*") (set_attr "mode" "SF,SI,SF")]) (define_insn "*pushsf_rex64" [(set (match_operand:SF 0 "push_operand" "=X,X,X") - (match_operand:SF 1 "nonmemory_no_elim_operand" "f#rx,rF#fx,x#rf"))] + (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))] "TARGET_64BIT" { - switch (which_alternative) - { - case 1: - return "push{q}\t%q1"; - - default: - /* This insn should be already split before reg-stack. */ - abort (); - } + /* Anything else should be already split before reg-stack. */ + gcc_assert (which_alternative == 1); + return "push{q}\t%q1"; } [(set_attr "type" "multi,push,multi") + (set_attr "unit" "i387,*,*") (set_attr "mode" "SF,DI,SF")]) (define_split @@ -2185,21 +2262,22 @@ [(set (match_operand:SF 0 "push_operand" "") (match_operand:SF 1 "any_fp_register_operand" ""))] "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4))) - (set (mem:SF (reg:SI 7)) (match_dup 1))]) + [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) + (set (mem:SF (reg:SI SP_REG)) (match_dup 1))]) (define_split [(set (match_operand:SF 0 "push_operand" "") (match_operand:SF 1 "any_fp_register_operand" ""))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8))) - (set (mem:SF (reg:DI 7)) (match_dup 1))]) + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) + (set (mem:SF (reg:DI SP_REG)) (match_dup 1))]) (define_insn "*movsf_1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!rm,!*y") - (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,rm,*y,*y"))] - "(TARGET_INTER_UNIT_MOVES || optimize_size) - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + [(set (match_operand:SF 0 "nonimmediate_operand" + "=f,m ,f,r ,m ,x,x,x ,m ,!*y,!rm,!*y") + (match_operand:SF 1 "general_operand" + "fm,f,G ,rmF,Fr,C ,x ,xm,x,rm ,*y ,*y"))] + "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2208,13 +2286,7 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) @@ -2250,10 +2322,10 @@ return "movq\t{%1, %0|%0, %1}"; default: - abort(); + gcc_unreachable (); } } - [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov") + [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov") (set (attr "mode") (cond [(eq_attr "alternative" "3,4,9,10") (const_string "SI") @@ -2281,106 +2353,7 @@ (if_then_else (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") (const_int 0)) - (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") - (const_int 0))) - (const_string "V4SF") - (const_string "SF")) - (eq_attr "alternative" "11") - (const_string "DI")] - (const_string "SF")))]) - -(define_insn "*movsf_1_nointerunit" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!m,!*y") - (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,m,*y,*y"))] - "(!TARGET_INTER_UNIT_MOVES && !optimize_size) - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && (reload_in_progress || reload_completed - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || GET_CODE (operands[1]) != CONST_DOUBLE - || memory_operand (operands[0], SFmode))" -{ - switch (which_alternative) - { - case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - { - if (REGNO (operands[0]) == FIRST_STACK_REG - && TARGET_USE_FFREEP) - return "ffreep\t%y0"; - return "fstp\t%y0"; - } - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; - - case 1: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; - - case 2: - return standard_80387_constant_opcode (operands[1]); - - case 3: - case 4: - return "mov{l}\t{%1, %0|%0, %1}"; - case 5: - if (get_attr_mode (insn) == MODE_TI) - return "pxor\t%0, %0"; - else - return "xorps\t%0, %0"; - case 6: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movss\t{%1, %0|%0, %1}"; - case 7: - case 8: - return "movss\t{%1, %0|%0, %1}"; - - case 9: - case 10: - return "movd\t{%1, %0|%0, %1}"; - - case 11: - return "movq\t{%1, %0|%0, %1}"; - - default: - abort(); - } -} - [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov") - (set (attr "mode") - (cond [(eq_attr "alternative" "3,4,9,10") - (const_string "SI") - (eq_attr "alternative" "5") - (if_then_else - (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") - (const_int 0)) - (ne (symbol_ref "TARGET_SSE2") - (const_int 0))) - (eq (symbol_ref "optimize_size") - (const_int 0))) - (const_string "TI") - (const_string "V4SF")) - /* For architectures resolving dependencies on - whole SSE registers use APS move to break dependency - chains, otherwise use short move to avoid extra work. - - Do the same for architectures resolving dependencies on - the parts. While in DF mode it is better to always handle - just register parts, the SF mode is different due to lack - of instructions to load just part of the register. It is - better to maintain the whole registers in single format - to avoid problems on using packed logical operations. */ - (eq_attr "alternative" "6") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (const_int 0)) - (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (ne (symbol_ref "TARGET_SSE_SPLIT_REGS") (const_int 0))) (const_string "V4SF") (const_string "SF")) @@ -2389,11 +2362,11 @@ (const_string "SF")))]) (define_insn "*swapsf" - [(set (match_operand:SF 0 "register_operand" "+f") - (match_operand:SF 1 "register_operand" "+f")) + [(set (match_operand:SF 0 "fp_register_operand" "+f") + (match_operand:SF 1 "fp_register_operand" "+f")) (set (match_dup 1) (match_dup 0))] - "reload_completed || !TARGET_SSE" + "reload_completed || TARGET_80387" { if (STACK_TOP_P (operands[0])) return "fxch\t%1"; @@ -2416,24 +2389,26 @@ (define_insn "*pushdf_nointeger" [(set (match_operand:DF 0 "push_operand" "=<,<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))] + (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))] "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES" { /* This insn should be already split before reg-stack. */ - abort (); + gcc_unreachable (); } [(set_attr "type" "multi") + (set_attr "unit" "i387,*,*,*") (set_attr "mode" "DF,SI,SI,DF")]) (define_insn "*pushdf_integer" [(set (match_operand:DF 0 "push_operand" "=<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))] + (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))] "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES" { /* This insn should be already split before reg-stack. */ - abort (); + gcc_unreachable (); } [(set_attr "type" "multi") + (set_attr "unit" "i387,*,*") (set_attr "mode" "DF,SI,DF")]) ;; %%% Kill this when call knows how to work this out. @@ -2441,16 +2416,16 @@ [(set (match_operand:DF 0 "push_operand" "") (match_operand:DF 1 "any_fp_register_operand" ""))] "!TARGET_64BIT && reload_completed" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (set (mem:DF (reg:SI 7)) (match_dup 1))] + [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) + (set (mem:DF (reg:SI SP_REG)) (match_dup 1))] "") (define_split [(set (match_operand:DF 0 "push_operand" "") (match_operand:DF 1 "any_fp_register_operand" ""))] "TARGET_64BIT && reload_completed" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8))) - (set (mem:DF (reg:DI 7)) (match_dup 1))] + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) + (set (mem:DF (reg:DI SP_REG)) (match_dup 1))] "") (define_split @@ -2465,8 +2440,10 @@ ;; when optimizing for size. (define_insn "*movdf_nointeger" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m,f#Y,*r,o,Y#f,Y#f,Y#f,m") - (match_operand:DF 1 "general_operand" "fm#Y,f#Y,G,*roF,F*r,C,Y#f,YHm#f,Y#f"))] + [(set (match_operand:DF 0 "nonimmediate_operand" + "=f,m,f,*r ,o ,Y*x,Y*x,Y*x ,m ") + (match_operand:DF 1 "general_operand" + "fm,f,G,*roF,F*r,C ,Y*x,mY*x,Y*x"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT) && (reload_in_progress || reload_completed @@ -2477,18 +2454,7 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - { - if (REGNO (operands[0]) == FIRST_STACK_REG - && TARGET_USE_FFREEP) - return "ffreep\t%y0"; - return "fstp\t%y0"; - } - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) @@ -2512,36 +2478,49 @@ case MODE_TI: return "pxor\t%0, %0"; default: - abort (); + gcc_unreachable (); } case 6: + case 7: + case 8: switch (get_attr_mode (insn)) { case MODE_V4SF: return "movaps\t{%1, %0|%0, %1}"; case MODE_V2DF: return "movapd\t{%1, %0|%0, %1}"; + case MODE_TI: + return "movdqa\t{%1, %0|%0, %1}"; + case MODE_DI: + return "movq\t{%1, %0|%0, %1}"; case MODE_DF: return "movsd\t{%1, %0|%0, %1}"; + case MODE_V1DF: + return "movlpd\t{%1, %0|%0, %1}"; + case MODE_V2SF: + return "movlps\t{%1, %0|%0, %1}"; default: - abort (); + gcc_unreachable (); } - case 7: - if (get_attr_mode (insn) == MODE_V2DF) - return "movlpd\t{%1, %0|%0, %1}"; - else - return "movsd\t{%1, %0|%0, %1}"; - case 8: - return "movsd\t{%1, %0|%0, %1}"; default: - abort(); + gcc_unreachable (); } } - [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov") + [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov") (set (attr "mode") - (cond [(eq_attr "alternative" "3,4") + (cond [(eq_attr "alternative" "0,1,2") + (const_string "DF") + (eq_attr "alternative" "3,4") (const_string "SI") + + /* For SSE1, we have many fewer alternatives. */ + (eq (symbol_ref "TARGET_SSE2") (const_int 0)) + (cond [(eq_attr "alternative" "5,6") + (const_string "V4SF") + ] + (const_string "V2SF")) + /* xorps is one byte shorter. */ (eq_attr "alternative" "5") (cond [(ne (symbol_ref "optimize_size") @@ -2549,8 +2528,10 @@ (const_string "V4SF") (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") (const_int 0)) - (const_string "TI")] + (const_string "TI") + ] (const_string "V2DF")) + /* For architectures resolving dependencies on whole SSE registers use APD move to break dependency chains, otherwise use short move to avoid extra work. @@ -2558,27 +2539,31 @@ movaps encodes one byte shorter. */ (eq_attr "alternative" "6") (cond - [(ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (const_int 0)) - (const_string "V2DF")] + [(ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (const_string "V2DF") + ] (const_string "DF")) /* For architectures resolving dependencies on register parts we may avoid extra work to zero out upper part of register. */ (eq_attr "alternative" "7") (if_then_else - (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (ne (symbol_ref "TARGET_SSE_SPLIT_REGS") (const_int 0)) - (const_string "V2DF") - (const_string "DF"))] - (const_string "DF")))]) + (const_string "V1DF") + (const_string "DF")) + ] + (const_string "DF")))]) (define_insn "*movdf_integer" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Yr,m,f#Yr,r#Yf,o,Y#rf,Y#rf,Y#rf,m") - (match_operand:DF 1 "general_operand" "fm#Yr,f#Yr,G,roF#Yf,Fr#Yf,C,Y#rf,Ym#rf,Y#rf"))] + [(set (match_operand:DF 0 "nonimmediate_operand" + "=f,m,f,r ,o ,Y*x,Y*x,Y*x,m ") + (match_operand:DF 1 "general_operand" + "fm,f,G,roF,Fr,C ,Y*x,m ,Y*x"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT) && (reload_in_progress || reload_completed @@ -2589,18 +2574,7 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - { - if (REGNO (operands[0]) == FIRST_STACK_REG - && TARGET_USE_FFREEP) - return "ffreep\t%y0"; - return "fstp\t%y0"; - } - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) @@ -2625,36 +2599,49 @@ case MODE_TI: return "pxor\t%0, %0"; default: - abort (); + gcc_unreachable (); } case 6: + case 7: + case 8: switch (get_attr_mode (insn)) { case MODE_V4SF: return "movaps\t{%1, %0|%0, %1}"; case MODE_V2DF: return "movapd\t{%1, %0|%0, %1}"; + case MODE_TI: + return "movdqa\t{%1, %0|%0, %1}"; + case MODE_DI: + return "movq\t{%1, %0|%0, %1}"; case MODE_DF: return "movsd\t{%1, %0|%0, %1}"; + case MODE_V1DF: + return "movlpd\t{%1, %0|%0, %1}"; + case MODE_V2SF: + return "movlps\t{%1, %0|%0, %1}"; default: - abort (); + gcc_unreachable (); } - case 7: - if (get_attr_mode (insn) == MODE_V2DF) - return "movlpd\t{%1, %0|%0, %1}"; - else - return "movsd\t{%1, %0|%0, %1}"; - case 8: - return "movsd\t{%1, %0|%0, %1}"; default: - abort(); + gcc_unreachable(); } } - [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov") + [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov") (set (attr "mode") - (cond [(eq_attr "alternative" "3,4") + (cond [(eq_attr "alternative" "0,1,2") + (const_string "DF") + (eq_attr "alternative" "3,4") (const_string "SI") + + /* For SSE1, we have many fewer alternatives. */ + (eq (symbol_ref "TARGET_SSE2") (const_int 0)) + (cond [(eq_attr "alternative" "5,6") + (const_string "V4SF") + ] + (const_string "V2SF")) + /* xorps is one byte shorter. */ (eq_attr "alternative" "5") (cond [(ne (symbol_ref "optimize_size") @@ -2662,32 +2649,36 @@ (const_string "V4SF") (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") (const_int 0)) - (const_string "TI")] + (const_string "TI") + ] (const_string "V2DF")) + /* For architectures resolving dependencies on whole SSE registers use APD move to break dependency - chains, otherwise use short move to avoid extra work. + chains, otherwise use short move to avoid extra work. movaps encodes one byte shorter. */ (eq_attr "alternative" "6") (cond - [(ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") - (const_int 0)) - (const_string "V2DF")] + [(ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (const_string "V2DF") + ] (const_string "DF")) /* For architectures resolving dependencies on register parts we may avoid extra work to zero out upper part of register. */ (eq_attr "alternative" "7") (if_then_else - (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (ne (symbol_ref "TARGET_SSE_SPLIT_REGS") (const_int 0)) - (const_string "V2DF") - (const_string "DF"))] - (const_string "DF")))]) + (const_string "V1DF") + (const_string "DF")) + ] + (const_string "DF")))]) (define_split [(set (match_operand:DF 0 "nonimmediate_operand" "") @@ -2704,11 +2695,11 @@ "ix86_split_long_move (operands); DONE;") (define_insn "*swapdf" - [(set (match_operand:DF 0 "register_operand" "+f") - (match_operand:DF 1 "register_operand" "+f")) + [(set (match_operand:DF 0 "fp_register_operand" "+f") + (match_operand:DF 1 "fp_register_operand" "+f")) (set (match_dup 1) (match_dup 0))] - "reload_completed || !TARGET_SSE2" + "reload_completed || TARGET_80387" { if (STACK_TOP_P (operands[0])) return "fxch\t%1"; @@ -2737,20 +2728,22 @@ "optimize_size" { /* This insn should be already split before reg-stack. */ - abort (); + gcc_unreachable (); } [(set_attr "type" "multi") + (set_attr "unit" "i387,*,*") (set_attr "mode" "XF,SI,SI")]) (define_insn "*pushxf_integer" [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))] + (match_operand:XF 1 "general_no_elim_operand" "f,ro"))] "!optimize_size" { /* This insn should be already split before reg-stack. */ - abort (); + gcc_unreachable (); } [(set_attr "type" "multi") + (set_attr "unit" "i387,*") (set_attr "mode" "XF,SI")]) (define_split @@ -2767,16 +2760,16 @@ [(set (match_operand:XF 0 "push_operand" "") (match_operand:XF 1 "any_fp_register_operand" ""))] "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2))) - (set (mem:XF (reg:SI 7)) (match_dup 1))] + [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2))) + (set (mem:XF (reg:SI SP_REG)) (match_dup 1))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split [(set (match_operand:XF 0 "push_operand" "") (match_operand:XF 1 "any_fp_register_operand" ""))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2))) - (set (mem:XF (reg:DI 7)) (match_dup 1))] + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2))) + (set (mem:XF (reg:DI SP_REG)) (match_dup 1))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") ;; Do not use integer registers when optimizing for size @@ -2792,18 +2785,7 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - { - if (REGNO (operands[0]) == FIRST_STACK_REG - && TARGET_USE_FFREEP) - return "ffreep\t%y0"; - return "fstp\t%y0"; - } - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: /* There is no non-popping store to memory for XFmode. So if @@ -2818,15 +2800,16 @@ case 3: case 4: return "#"; + default: + gcc_unreachable (); } - abort(); } [(set_attr "type" "fmov,fmov,fmov,multi,multi") (set_attr "mode" "XF,XF,XF,SI,SI")]) (define_insn "*movxf_integer" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o") - (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))] + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o") + (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))] "!optimize_size && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (reload_in_progress || reload_completed @@ -2836,18 +2819,7 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - { - if (REGNO (operands[0]) == FIRST_STACK_REG - && TARGET_USE_FFREEP) - return "ffreep\t%y0"; - return "fstp\t%y0"; - } - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: /* There is no non-popping store to memory for XFmode. So if @@ -2862,8 +2834,10 @@ case 3: case 4: return "#"; + + default: + gcc_unreachable (); } - abort(); } [(set_attr "type" "fmov,fmov,fmov,multi,multi") (set_attr "mode" "XF,XF,XF,SI,SI")]) @@ -2920,7 +2894,7 @@ (match_operand:XF 1 "register_operand" "+f")) (set (match_dup 1) (match_dup 0))] - "" + "TARGET_80387" { if (STACK_TOP_P (operands[0])) return "fxch\t%1"; @@ -2929,6 +2903,67 @@ } [(set_attr "type" "fxch") (set_attr "mode" "XF")]) + +(define_expand "movtf" + [(set (match_operand:TF 0 "nonimmediate_operand" "") + (match_operand:TF 1 "nonimmediate_operand" ""))] + "TARGET_64BIT" +{ + ix86_expand_move (TFmode, operands); + DONE; +}) + +(define_insn "*movtf_internal" + [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm") + (match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))] + "TARGET_64BIT + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (which_alternative) + { + case 0: + case 1: + return "#"; + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 3: + case 4: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } +} + [(set_attr "type" "*,*,sselog1,ssemov,ssemov") + (set (attr "mode") + (cond [(eq_attr "alternative" "2,3") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "4") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "DI")))]) + +(define_split + [(set (match_operand:TF 0 "nonimmediate_operand" "") + (match_operand:TF 1 "general_operand" ""))] + "reload_completed && !SSE_REG_P (operands[0]) + && !SSE_REG_P (operands[1])" + [(const_int 0)] + "ix86_split_long_move (operands); DONE;") ;; Zero extension instructions @@ -2948,7 +2983,7 @@ (define_insn "zero_extendhisi2_and" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size" "#" [(set_attr "type" "alu1") @@ -2957,10 +2992,10 @@ (define_split [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:HI 1 "register_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size" [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_insn "*zero_extendhisi2_movzwl" @@ -2975,14 +3010,14 @@ [(parallel [(set (match_operand:HI 0 "register_operand" "") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") (define_insn "*zero_extendqihi2_and" [(set (match_operand:HI 0 "register_operand" "=r,?&q") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size" "#" [(set_attr "type" "alu1") @@ -2991,25 +3026,26 @@ (define_insn "*zero_extendqihi2_movzbw_and" [(set (match_operand:HI 0 "register_operand" "=r,r") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size" "#" [(set_attr "type" "imovx,alu1") (set_attr "mode" "HI")]) -(define_insn "*zero_extendqihi2_movzbw" +; zero extend to SImode here to avoid partial register stalls +(define_insn "*zero_extendqihi2_movzbl" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed" - "movz{bw|x}\t{%1, %0|%0, %1}" + "movz{bl|x}\t{%1, %k0|%k0, %k1}" [(set_attr "type" "imovx") - (set_attr "mode" "HI")]) + (set_attr "mode" "SI")]) ;; For the movzbw case strip only the clobber (define_split [(set (match_operand:HI 0 "register_operand" "") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))" @@ -3021,7 +3057,7 @@ (define_split [(set (match_operand:HI 0 "register_operand" "") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && ANY_QI_REG_P (operands[0]) && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size) @@ -3034,25 +3070,25 @@ (define_split [(set (match_operand:HI 0 "register_operand" "") (zero_extend:HI (match_operand:QI 1 "register_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])" [(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_expand "zero_extendqisi2" [(parallel [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") (define_insn "*zero_extendqisi2_and" [(set (match_operand:SI 0 "register_operand" "=r,?&q") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size" "#" [(set_attr "type" "alu1") @@ -3061,7 +3097,7 @@ (define_insn "*zero_extendqisi2_movzbw_and" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_ZERO_EXTEND_WITH_AND || optimize_size" "#" [(set_attr "type" "imovx,alu1") @@ -3079,7 +3115,7 @@ (define_split [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))" @@ -3091,7 +3127,7 @@ (define_split [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && ANY_QI_REG_P (operands[0]) && (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM) @@ -3105,11 +3141,11 @@ (define_split [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "register_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])" [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") ;; %%% Kill me once multi-word ops are sane. @@ -3125,24 +3161,10 @@ ") (define_insn "zero_extendsidi2_32" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,!?y,!?Y") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,m,m"))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && !TARGET_INTER_UNIT_MOVES" - "@ - # - # - # - movd\t{%1, %0|%0, %1} - movd\t{%1, %0|%0, %1}" - [(set_attr "mode" "SI,SI,SI,DI,TI") - (set_attr "type" "multi,multi,multi,mmxmov,ssemov")]) - -(define_insn "*zero_extendsidi2_32_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,!?y,!?Y") + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y") (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm"))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_INTER_UNIT_MOVES" + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT" "@ # # @@ -3153,21 +3175,9 @@ (set_attr "type" "multi,multi,multi,mmxmov,ssemov")]) (define_insn "zero_extendsidi2_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!?y,!?Y") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,m,m")))] - "TARGET_64BIT && !TARGET_INTER_UNIT_MOVES" - "@ - mov\t{%k1, %k0|%k0, %k1} - # - movd\t{%1, %0|%0, %1} - movd\t{%1, %0|%0, %1}" - [(set_attr "type" "imovx,imov,mmxmov,ssemov") - (set_attr "mode" "SI,DI,DI,TI")]) - -(define_insn "*zero_extendsidi2_rex64_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!?y,!*?") + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y") (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))] - "TARGET_64BIT && TARGET_INTER_UNIT_MOVES" + "TARGET_64BIT" "@ mov\t{%k1, %k0|%k0, %k1} # @@ -3186,7 +3196,7 @@ (define_split [(set (match_operand:DI 0 "register_operand" "") (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])" [(set (match_dup 4) (const_int 0))] @@ -3195,7 +3205,7 @@ (define_split [(set (match_operand:DI 0 "nonimmediate_operand" "") (zero_extend:DI (match_operand:SI 1 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && reload_completed && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])" [(set (match_dup 3) (match_dup 1)) @@ -3203,31 +3213,27 @@ "split_di (&operands[0], 1, &operands[3], &operands[4]);") (define_insn "zero_extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))] "TARGET_64BIT" - "@ - movz{wl|x}\t{%1, %k0|%k0, %1} - movz{wq|x}\t{%1, %0|%0, %1}" + "movz{wl|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") - (set_attr "mode" "SI,DI")]) + (set_attr "mode" "DI")]) (define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "Q,m")))] + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))] "TARGET_64BIT" - "@ - movz{bl|x}\t{%1, %k0|%k0, %1} - movz{bq|x}\t{%1, %0|%0, %1}" + "movz{bl|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") - (set_attr "mode" "SI,DI")]) + (set_attr "mode" "DI")]) ;; Sign extension instructions (define_expand "extendsidi2" [(parallel [(set (match_operand:DI 0 "register_operand" "") (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (match_scratch:SI 2 ""))])] "" { @@ -3241,7 +3247,7 @@ (define_insn "*extendsidi2_1" [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o") (sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r"))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (match_scratch:SI 2 "=X,X,X,&r"))] "!TARGET_64BIT" "#") @@ -3278,14 +3284,14 @@ (define_split [(set (match_operand:DI 0 "memory_operand" "") (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (match_operand:SI 2 "register_operand" ""))] "(reload_completed && dead_or_set_p (insn, operands[1]) && !reg_mentioned_p (operands[1], operands[0]))" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (set (match_dup 4) (match_dup 1))] "split_di (&operands[0], 1, &operands[3], &operands[4]);") @@ -3293,7 +3299,7 @@ (define_split [(set (match_operand:DI 0 "memory_operand" "") (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (match_operand:SI 2 "register_operand" ""))] "reload_completed" [(const_int 0)] @@ -3323,7 +3329,7 @@ (define_split [(set (match_operand:DI 0 "register_operand" "") (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (match_scratch:SI 2 ""))] "reload_completed" [(const_int 0)] @@ -3460,15 +3466,15 @@ [(set (match_operand:DF 0 "push_operand" "") (float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))] "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (set (mem:DF (reg:SI 7)) (float_extend:DF (match_dup 1)))]) + [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) + (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))]) (define_split [(set (match_operand:DF 0 "push_operand" "") (float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8))) - (set (mem:DF (reg:DI 7)) (float_extend:DF (match_dup 1)))]) + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) + (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))]) (define_insn "*dummy_extendsfxf2" [(set (match_operand:XF 0 "push_operand" "=<") @@ -3480,89 +3486,117 @@ [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2))) - (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))] + [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2))) + (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2))) - (set (mem:DF (reg:DI 7)) (float_extend:XF (match_dup 1)))] + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2))) + (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2))) - (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))] + [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2))) + (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2))) - (set (mem:XF (reg:DI 7)) (float_extend:XF (match_dup 1)))] + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2))) + (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))] "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_expand "extendsfdf2" [(set (match_operand:DF 0 "nonimmediate_operand" "") (float_extend:DF (match_operand:SF 1 "general_operand" "")))] - "TARGET_80387 || TARGET_SSE2" + "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" { /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + { + if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387) + && standard_80387_constant_p (operands[1]) > 0) + { + operands[1] = simplify_const_unary_operation + (FLOAT_EXTEND, DFmode, operands[1], SFmode); + emit_move_insn_1 (operands[0], operands[1]); + DONE; + } + operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + } if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) -(define_insn "*extendsfdf2_1" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,mf#Y,Y#f") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f")))] - "(TARGET_80387 || TARGET_SSE2) +(define_insn "*extendsfdf2_mixed" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y") + (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))] + "TARGET_SSE2 && TARGET_MIX_SSE_I387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) return "fstp%z0\t%y0"; - else return "fst%z0\t%y0"; + case 2: return "cvtss2sd\t{%1, %0|%0, %1}"; default: - abort (); + gcc_unreachable (); } } [(set_attr "type" "fmov,fmov,ssecvt") (set_attr "mode" "SF,XF,DF")]) -(define_insn "*extendsfdf2_1_sse_only" - [(set (match_operand:DF 0 "register_operand" "=Y") +(define_insn "*extendsfdf2_sse" + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y") (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))] - "!TARGET_80387 && TARGET_SSE2 + "TARGET_SSE2 && TARGET_SSE_MATH && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "cvtss2sd\t{%1, %0|%0, %1}" [(set_attr "type" "ssecvt") (set_attr "mode" "DF")]) +(define_insn "*extendsfdf2_i387" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m") + (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))] + "TARGET_80387 + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (which_alternative) + { + case 0: + return output_387_reg_move (insn, operands); + + case 1: + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return "fstp%z0\t%y0"; + else + return "fst%z0\t%y0"; + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "fmov") + (set_attr "mode" "SF,XF")]) + (define_expand "extendsfxf2" [(set (match_operand:XF 0 "nonimmediate_operand" "") (float_extend:XF (match_operand:SF 1 "general_operand" "")))] @@ -3571,12 +3605,21 @@ /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + { + if (standard_80387_constant_p (operands[1]) > 0) + { + operands[1] = simplify_const_unary_operation + (FLOAT_EXTEND, XFmode, operands[1], SFmode); + emit_move_insn_1 (operands[0], operands[1]); + DONE; + } + operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + } if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) -(define_insn "*extendsfxf2_1" +(define_insn "*extendsfxf2_i387" [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m") (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))] "TARGET_80387 @@ -3585,24 +3628,18 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: /* There is no non-popping store to memory for XFmode. So if we need one, follow the store with a load. */ - if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0\n\tfld%z0\t%y0"; - else + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) return "fstp%z0\t%y0"; + else + return "fstp%z0\t%y0\n\tfld%z0\t%y0"; default: - abort (); + gcc_unreachable (); } } [(set_attr "type" "fmov") @@ -3616,12 +3653,21 @@ /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (DFmode, operands[1])); + { + if (standard_80387_constant_p (operands[1]) > 0) + { + operands[1] = simplify_const_unary_operation + (FLOAT_EXTEND, XFmode, operands[1], DFmode); + emit_move_insn_1 (operands[0], operands[1]); + DONE; + } + operands[1] = validize_mem (force_const_mem (DFmode, operands[1])); + } if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (DFmode, operands[1]); }) -(define_insn "*extenddfxf2_1" +(define_insn "*extenddfxf2_i387" [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m") (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))] "TARGET_80387 @@ -3630,13 +3676,7 @@ switch (which_alternative) { case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; + return output_387_reg_move (insn, operands); case 1: /* There is no non-popping store to memory for XFmode. So if @@ -3647,7 +3687,7 @@ return "fstp%z0\t%y0"; default: - abort (); + gcc_unreachable (); } } [(set_attr "type" "fmov") @@ -3659,49 +3699,40 @@ ;; insn. So we pretend we can output to a reg in order to get better ;; register preferencing, but we really use a stack slot. -(define_expand "truncdfsf2" - [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") - (float_truncate:SF - (match_operand:DF 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387 || TARGET_SSE2" - " - if (TARGET_80387) - operands[2] = assign_386_stack_local (SFmode, 0); - else - { - emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1])); - DONE; - } -") +;; Conversion from DFmode to SFmode. -(define_insn "*truncdfsf2_1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf") +(define_expand "truncdfsf2" + [(set (match_operand:SF 0 "nonimmediate_operand" "") (float_truncate:SF - (match_operand:DF 1 "register_operand" "f,f,f,f"))) - (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))] - "TARGET_80387 && !TARGET_SSE2" + (match_operand:DF 1 "nonimmediate_operand" "")))] + "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" { - switch (which_alternative) + if (MEM_P (operands[0]) && MEM_P (operands[1])) + operands[1] = force_reg (DFmode, operands[1]); + + if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387) + ; + else if (flag_unsafe_math_optimizations) + ; + else { - case 0: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; - default: - abort (); + rtx temp = assign_386_stack_local (SFmode, SLOT_TEMP); + emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp)); + DONE; } -} - [(set_attr "type" "fmov,multi,multi,multi") - (set_attr "mode" "SF,SF,SF,SF")]) +}) -(define_insn "*truncdfsf2_1_sse" - [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m#fxr,?f#xr,?r#fx,?x#fr,Y#fr") - (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f"))) - (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))] - "TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" +(define_expand "truncdfsf2_with_temp" + [(parallel [(set (match_operand:SF 0 "" "") + (float_truncate:SF (match_operand:DF 1 "" ""))) + (clobber (match_operand:SF 2 "" ""))])] + "") + +(define_insn "*truncdfsf_fast_mixed" + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f,Y") + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))] + "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations" { switch (which_alternative) { @@ -3710,21 +3741,43 @@ return "fstp%z0\t%y0"; else return "fst%z0\t%y0"; - case 4: - return "#"; + case 1: + return output_387_reg_move (insn, operands); + case 2: + return "cvtsd2ss\t{%1, %0|%0, %1}"; default: - abort (); + gcc_unreachable (); } } - [(set_attr "type" "fmov,multi,multi,multi,ssecvt") - (set_attr "mode" "SF,SF,SF,SF,DF")]) + [(set_attr "type" "fmov,fmov,ssecvt") + (set_attr "mode" "SF")]) + +;; Yes, this one doesn't depend on flag_unsafe_math_optimizations, +;; because nothing we do here is unsafe. +(define_insn "*truncdfsf_fast_sse" + [(set (match_operand:SF 0 "nonimmediate_operand" "=Y") + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand" "Ym")))] + "TARGET_SSE2 && TARGET_SSE_MATH" + "cvtsd2ss\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "SF")]) + +(define_insn "*truncdfsf_fast_i387" + [(set (match_operand:SF 0 "nonimmediate_operand" "=fm") + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand" "f")))] + "TARGET_80387 && flag_unsafe_math_optimizations" + "* return output_387_reg_move (insn, operands);" + [(set_attr "type" "fmov") + (set_attr "mode" "SF")]) -(define_insn "*truncdfsf2_1_sse_nooverlap" - [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m,?f#rx,?r#fx,?x#rf,&Y") +(define_insn "*truncdfsf_mixed" + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r,Y") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f"))) - (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))] - "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" + (match_operand:DF 1 "nonimmediate_operand" "f ,f ,Ym"))) + (clobber (match_operand:SF 2 "memory_operand" "=X,m ,X"))] + "TARGET_MIX_SSE_I387" { switch (which_alternative) { @@ -3733,68 +3786,49 @@ return "fstp%z0\t%y0"; else return "fst%z0\t%y0"; - case 4: - return "#"; - default: - abort (); - } -} - [(set_attr "type" "fmov,multi,multi,multi,ssecvt") - (set_attr "mode" "SF,SF,SF,SF,DF")]) - -(define_insn "*truncdfsf2_2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=Y,Y,!m") - (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "Y,mY,f#Y")))] - "TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: case 1: - return "cvtsd2ss\t{%1, %0|%0, %1}"; + return "#"; case 2: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; + return "cvtsd2ss\t{%1, %0|%0, %1}"; default: - abort (); + gcc_unreachable (); } } - [(set_attr "type" "ssecvt,ssecvt,fmov") - (set_attr "athlon_decode" "vector,double,*") - (set_attr "mode" "SF,SF,SF")]) + [(set_attr "type" "fmov,multi,ssecvt") + (set_attr "unit" "*,i387,*") + (set_attr "mode" "SF")]) -(define_insn "*truncdfsf2_2_nooverlap" - [(set (match_operand:SF 0 "nonimmediate_operand" "=&Y,!m") +(define_insn "*truncdfsf_i387" + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "mY,f")))] - "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + (match_operand:DF 1 "nonimmediate_operand" "f,f"))) + (clobber (match_operand:SF 2 "memory_operand" "=X,m"))] + "TARGET_80387" { switch (which_alternative) { case 0: - return "#"; - case 1: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) return "fstp%z0\t%y0"; else return "fst%z0\t%y0"; + case 1: + return "#"; default: - abort (); + gcc_unreachable (); } } - [(set_attr "type" "ssecvt,fmov") - (set_attr "mode" "DF,SF")]) + [(set_attr "type" "fmov,multi") + (set_attr "unit" "*,i387") + (set_attr "mode" "SF")]) -(define_insn "*truncdfsf2_3" +(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" + (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"; @@ -3804,94 +3838,19 @@ [(set_attr "type" "fmov") (set_attr "mode" "SF")]) -(define_insn "truncdfsf2_sse_only" - [(set (match_operand:SF 0 "register_operand" "=Y,Y") - (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "Y,mY")))] - "!TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" - "cvtsd2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "athlon_decode" "vector,double") - (set_attr "mode" "SF")]) - -(define_insn "*truncdfsf2_sse_only_nooverlap" - [(set (match_operand:SF 0 "register_operand" "=&Y") - (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "mY")))] - "!TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" - "#" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) - -(define_split - [(set (match_operand:SF 0 "memory_operand" "") - (float_truncate:SF - (match_operand:DF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387" - [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] - "") - -; Avoid possible reformatting penalty on the destination by first -; zeroing it out (define_split [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" ""))) + (match_operand:DF 1 "fp_register_operand" ""))) (clobber (match_operand 2 "" ""))] - "TARGET_80387 && reload_completed - && SSE_REG_P (operands[0]) - && !STACK_REG_P (operands[1])" - [(const_int 0)] -{ - rtx src, dest; - if (!TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS) - emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1])); - else - { - dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - src = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); - /* simplify_gen_subreg refuses to widen memory references. */ - if (GET_CODE (src) == SUBREG) - alter_subreg (&src); - if (reg_overlap_mentioned_p (operands[0], operands[1])) - abort (); - emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); - emit_insn (gen_cvtsd2ss (dest, dest, src)); - } - DONE; -}) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "")))] - "TARGET_80387 && reload_completed - && SSE_REG_P (operands[0]) && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" - [(const_int 0)] + "reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (match_dup 2))] { - rtx src, dest; - dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - src = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); - /* simplify_gen_subreg refuses to widen memory references. */ - if (GET_CODE (src) == SUBREG) - alter_subreg (&src); - if (reg_overlap_mentioned_p (operands[0], operands[1])) - abort (); - emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); - emit_insn (gen_cvtsd2ss (dest, dest, src)); - DONE; + operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1])); }) -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float_truncate:SF - (match_operand:DF 1 "fp_register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) (float_truncate:SF (match_dup 1))) - (set (match_dup 0) (match_dup 2))] - "") +;; Conversion from XFmode to SFmode. (define_expand "truncxfsf2" [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") @@ -3899,30 +3858,64 @@ (match_operand:XF 1 "register_operand" ""))) (clobber (match_dup 2))])] "TARGET_80387" - "operands[2] = assign_386_stack_local (SFmode, 0);") +{ + if (flag_unsafe_math_optimizations) + { + rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode); + emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1])); + if (reg != operands[0]) + emit_move_insn (operands[0], reg); + DONE; + } + else + operands[2] = assign_386_stack_local (SFmode, SLOT_TEMP); +}) -(define_insn "*truncxfsf2_1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf") +(define_insn "*truncxfsf2_mixed" + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x") (float_truncate:SF (match_operand:XF 1 "register_operand" "f,f,f,f"))) (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))] - "TARGET_80387" + "TARGET_MIX_SSE_I387" { - switch (which_alternative) - { - case 0: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; - default: - abort(); - } + gcc_assert (!which_alternative); + 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,multi,multi,multi") + (set_attr "unit" "*,i387,i387,i387") + (set_attr "mode" "SF")]) + +(define_insn "truncxfsf2_i387_noop" + [(set (match_operand:SF 0 "register_operand" "=f") + (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))] + "TARGET_80387 && flag_unsafe_math_optimizations" +{ + return output_387_reg_move (insn, operands); +} + [(set_attr "type" "fmov") (set_attr "mode" "SF")]) -(define_insn "*truncxfsf2_2" +(define_insn "*truncxfsf2_i387" + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r") + (float_truncate:SF + (match_operand:XF 1 "register_operand" "f,f,f"))) + (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))] + "TARGET_80387" +{ + gcc_assert (!which_alternative); + 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,multi,multi") + (set_attr "unit" "*,i387,i387") + (set_attr "mode" "SF")]) + +(define_insn "*truncxfsf2_i387_1" [(set (match_operand:SF 0 "memory_operand" "=m") (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))] @@ -3937,55 +3930,90 @@ (set_attr "mode" "SF")]) (define_split - [(set (match_operand:SF 0 "memory_operand" "") + [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF (match_operand:XF 1 "register_operand" ""))) (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387" - [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] + "TARGET_80387 && reload_completed" + [(set (match_dup 2) (float_truncate:SF (match_dup 1))) + (set (match_dup 0) (match_dup 2))] "") (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(set (match_operand:SF 0 "memory_operand" "") (float_truncate:SF (match_operand:XF 1 "register_operand" ""))) (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) (float_truncate:SF (match_dup 1))) - (set (match_dup 0) (match_dup 2))] + "TARGET_80387" + [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] "") +;; Conversion from XFmode to DFmode. + (define_expand "truncxfdf2" [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") (float_truncate:DF (match_operand:XF 1 "register_operand" ""))) (clobber (match_dup 2))])] "TARGET_80387" - "operands[2] = assign_386_stack_local (DFmode, 0);") +{ + if (flag_unsafe_math_optimizations) + { + rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode); + emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1])); + if (reg != operands[0]) + emit_move_insn (operands[0], reg); + DONE; + } + else + operands[2] = assign_386_stack_local (DFmode, SLOT_TEMP); +}) -(define_insn "*truncxfdf2_1" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf") +(define_insn "*truncxfdf2_mixed" + [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y") (float_truncate:DF (match_operand:XF 1 "register_operand" "f,f,f,f"))) (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))] - "TARGET_80387" + "TARGET_SSE2 && TARGET_MIX_SSE_I387" { - switch (which_alternative) - { - case 0: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; - default: - abort(); - } - abort (); + gcc_assert (!which_alternative); + 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,multi,multi,multi") + (set_attr "unit" "*,i387,i387,i387") (set_attr "mode" "DF")]) -(define_insn "*truncxfdf2_2" +(define_insn "truncxfdf2_i387_noop" + [(set (match_operand:DF 0 "register_operand" "=f") + (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))] + "TARGET_80387 && flag_unsafe_math_optimizations" +{ + return output_387_reg_move (insn, operands); +} + [(set_attr "type" "fmov") + (set_attr "mode" "DF")]) + +(define_insn "*truncxfdf2_i387" + [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r") + (float_truncate:DF + (match_operand:XF 1 "register_operand" "f,f,f"))) + (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))] + "TARGET_80387" +{ + gcc_assert (!which_alternative); + 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,multi,multi") + (set_attr "unit" "*,i387,i387") + (set_attr "mode" "DF")]) + +(define_insn "*truncxfdf2_i387_1" [(set (match_operand:DF 0 "memory_operand" "=m") (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))] @@ -4000,463 +4028,411 @@ (set_attr "mode" "DF")]) (define_split - [(set (match_operand:DF 0 "memory_operand" "") + [(set (match_operand:DF 0 "register_operand" "") (float_truncate:DF (match_operand:XF 1 "register_operand" ""))) (clobber (match_operand:DF 2 "memory_operand" ""))] - "TARGET_80387" - [(set (match_dup 0) (float_truncate:DF (match_dup 1)))] + "TARGET_80387 && reload_completed" + [(set (match_dup 2) (float_truncate:DF (match_dup 1))) + (set (match_dup 0) (match_dup 2))] "") (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(set (match_operand:DF 0 "memory_operand" "") (float_truncate:DF (match_operand:XF 1 "register_operand" ""))) (clobber (match_operand:DF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) (float_truncate:DF (match_dup 1))) - (set (match_dup 0) (match_dup 2))] + "TARGET_80387" + [(set (match_dup 0) (float_truncate:DF (match_dup 1)))] "") - -;; %%% Break up all these bad boys. - ;; Signed conversion to DImode. (define_expand "fix_truncxfdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (match_operand:XF 1 "register_operand" "")))] + [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") + (fix:DI (match_operand:XF 1 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] "TARGET_80387" - "") - -(define_expand "fix_truncdfdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (match_operand:DF 1 "register_operand" "")))] - "TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)" { - 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" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (match_operand:SF 1 "register_operand" "")))] - "TARGET_80387 || (TARGET_SSE && TARGET_64BIT)" +(define_expand "fix_trunc<mode>di2" + [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") + (fix:DI (match_operand:SSEMODEF 1 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))" { - if (TARGET_SSE && TARGET_64BIT) + 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_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)" - "#" - "&& 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 "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 "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)" - "* operands[5] = operands[4]; return output_fix_trunc (insn, operands);" - [(set_attr "type" "fistp") - (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" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (match_operand:XF 1 "register_operand" "")))] + [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") + (fix:SI (match_operand:XF 1 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] "TARGET_80387" - "") - -(define_expand "fix_truncdfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (match_operand:DF 1 "register_operand" "")))] - "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" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (match_operand:SF 1 "register_operand" "")))] - "TARGET_80387 || TARGET_SSE" +(define_expand "fix_trunc<mode>si2" + [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") + (fix:SI (match_operand:SSEMODEF 1 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_80387 || SSE_FLOAT_MODE_P (<MODE>mode)" { - if (TARGET_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_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]))" - "#" - "&& 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 "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 "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 "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" "")))] - "TARGET_K8 && !optimize_size" + (set (match_operand:SSEMODEI24 0 "register_operand" "") + (fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))] + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size" [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (fix:SI (match_dup 2)))] + (set (match_dup 0) (fix:SSEMODEI24 (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))] - "") - -(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 || TARGET_GENERIC64) && !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" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (fix:HI (match_operand:XF 1 "register_operand" "")))] - "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_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, SLOT_TEMP); + 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_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_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" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (fix:HI (match_operand:DF 1 "register_operand" "")))] - "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" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (fix:HI (match_operand:SF 1 "register_operand" "")))] - "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_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]))" +;; 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)] { - ix86_optimize_mode_switching = 1; - operands[2] = assign_386_stack_local (HImode, 1); - operands[3] = assign_386_stack_local (HImode, 2); + ix86_optimize_mode_switching[I387_TRUNC] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC); 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, SLOT_TEMP); + 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 "mode" "HI")]) + (set_attr "i387_cw" "trunc") + (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 "mode" "HI")]) + (set_attr "i387_cw" "trunc") + (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 "mode" "HI")]) + (set_attr "i387_cw" "trunc") + (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))])] "") -;; %% Not used yet. (define_insn "x86_fnstcw_1" [(set (match_operand:HI 0 "memory_operand" "=m") - (unspec:HI [(reg:HI 18)] UNSPEC_FSTCW))] + (unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))] "TARGET_80387" "fnstcw\t%0" [(set_attr "length" "2") (set_attr "mode" "HI") - (set_attr "unit" "i387") - (set_attr "ppro_uops" "few")]) + (set_attr "unit" "i387")]) (define_insn "x86_fldcw_1" - [(set (reg:HI 18) + [(set (reg:HI FPSR_REG) (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))] "TARGET_80387" "fldcw\t%0" [(set_attr "length" "2") (set_attr "mode" "HI") (set_attr "unit" "i387") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) ;; Conversion between fixed point and floating point. @@ -4466,9 +4442,9 @@ (define_expand "floathisf2" [(set (match_operand:SF 0 "register_operand" "") (float:SF (match_operand:HI 1 "nonimmediate_operand" "")))] - "TARGET_SSE || TARGET_80387" + "TARGET_80387 || TARGET_SSE_MATH" { - if (TARGET_SSE && TARGET_SSE_MATH) + if (TARGET_SSE_MATH) { emit_insn (gen_floatsisf2 (operands[0], convert_to_mode (SImode, operands[1], 0))); @@ -4476,27 +4452,28 @@ } }) -(define_insn "*floathisf2_1" +(define_insn "*floathisf2_i387" [(set (match_operand:SF 0 "register_operand" "=f,f") - (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] - "TARGET_80387 && (!TARGET_SSE || !TARGET_SSE_MATH)" + (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))] + "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "SF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) (define_expand "floatsisf2" [(set (match_operand:SF 0 "register_operand" "") (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_SSE || TARGET_80387" + "TARGET_80387 || TARGET_SSE_MATH" "") -(define_insn "*floatsisf2_i387" - [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f") +(define_insn "*floatsisf2_mixed" + [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x") (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))] - "TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)" + "TARGET_MIX_SSE_I387" "@ fild%z1\t%1 # @@ -4504,56 +4481,42 @@ cvtsi2ss\t{%1, %0|%0, %1}" [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "SF") + (set_attr "unit" "*,i387,*,*") (set_attr "athlon_decode" "*,*,vector,double") (set_attr "fp_int_src" "true")]) (define_insn "*floatsisf2_sse" [(set (match_operand:SF 0 "register_operand" "=x,x") (float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))] - "TARGET_SSE" + "TARGET_SSE_MATH" "cvtsi2ss\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "mode" "SF") (set_attr "athlon_decode" "vector,double") (set_attr "fp_int_src" "true")]) -; Avoid possible reformatting penalty on the destination by first -; zeroing it out -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_80387 && reload_completed && TARGET_SSE_PARTIAL_REGS - && SSE_REG_P (operands[0])" - [(const_int 0)] -{ - rtx dest; - dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); - emit_insn (gen_cvtsi2ss (dest, dest, operands[1])); - DONE; -}) - -(define_expand "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] - "(TARGET_64BIT && TARGET_SSE) || TARGET_80387" - "") - -(define_insn "*floatdisf2_i387_only" - [(set (match_operand:SF 0 "register_operand" "=f,?f") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r")))] - "TARGET_80387 && (!TARGET_SSE || !TARGET_64BIT || TARGET_MIX_SSE_I387)" +(define_insn "*floatsisf2_i387" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))] + "TARGET_80387" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "SF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) -(define_insn "*floatdisf2_i387" - [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f") +(define_expand "floatdisf2" + [(set (match_operand:SF 0 "register_operand" "") + (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] + "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)" + "") + +(define_insn "*floatdisf2_mixed" + [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x") (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))] - "TARGET_64BIT && TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)" + "TARGET_64BIT && TARGET_MIX_SSE_I387" "@ fild%z1\t%1 # @@ -4561,41 +4524,38 @@ cvtsi2ss{q}\t{%1, %0|%0, %1}" [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "SF") + (set_attr "unit" "*,i387,*,*") (set_attr "athlon_decode" "*,*,vector,double") (set_attr "fp_int_src" "true")]) (define_insn "*floatdisf2_sse" [(set (match_operand:SF 0 "register_operand" "=x,x") (float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))] - "TARGET_64BIT && TARGET_SSE" + "TARGET_64BIT && TARGET_SSE_MATH" "cvtsi2ss{q}\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "mode" "SF") (set_attr "athlon_decode" "vector,double") (set_attr "fp_int_src" "true")]) -; Avoid possible reformatting penalty on the destination by first -; zeroing it out -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] - "TARGET_80387 && reload_completed && TARGET_SSE_PARTIAL_REGS - && SSE_REG_P (operands[0])" - [(const_int 0)] -{ - rtx dest; - dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); - emit_insn (gen_cvtsi2ssq (dest, dest, operands[1])); - DONE; -}) +(define_insn "*floatdisf2_i387" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))] + "TARGET_80387" + "@ + fild%z1\t%1 + #" + [(set_attr "type" "fmov,multi") + (set_attr "mode" "SF") + (set_attr "unit" "*,i387") + (set_attr "fp_int_src" "true")]) (define_expand "floathidf2" [(set (match_operand:DF 0 "register_operand" "") (float:DF (match_operand:HI 1 "nonimmediate_operand" "")))] - "TARGET_SSE2 || TARGET_80387" + "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" { - if (TARGET_SSE && TARGET_SSE_MATH) + if (TARGET_SSE2 && TARGET_SSE_MATH) { emit_insn (gen_floatsidf2 (operands[0], convert_to_mode (SImode, operands[1], 0))); @@ -4603,27 +4563,28 @@ } }) -(define_insn "*floathidf2_1" +(define_insn "*floathidf2_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") - (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] - "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)" + (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))] + "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "DF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) (define_expand "floatsidf2" [(set (match_operand:DF 0 "register_operand" "") (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_80387 || TARGET_SSE2" + "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" "") -(define_insn "*floatsidf2_i387" - [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f") +(define_insn "*floatsidf2_mixed" + [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y") (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))] - "TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)" + "TARGET_SSE2 && TARGET_MIX_SSE_I387" "@ fild%z1\t%1 # @@ -4631,40 +4592,42 @@ cvtsi2sd\t{%1, %0|%0, %1}" [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "DF") + (set_attr "unit" "*,i387,*,*") (set_attr "athlon_decode" "*,*,double,direct") (set_attr "fp_int_src" "true")]) (define_insn "*floatsidf2_sse" [(set (match_operand:DF 0 "register_operand" "=Y,Y") (float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))] - "TARGET_SSE2" + "TARGET_SSE2 && TARGET_SSE_MATH" "cvtsi2sd\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "mode" "DF") (set_attr "athlon_decode" "double,direct") (set_attr "fp_int_src" "true")]) -(define_expand "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))] - "(TARGET_64BIT && TARGET_SSE2) || TARGET_80387" - "") - -(define_insn "*floatdidf2_i387_only" - [(set (match_operand:DF 0 "register_operand" "=f,?f") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r")))] - "TARGET_80387 && (!TARGET_SSE2 || !TARGET_64BIT)" +(define_insn "*floatsidf2_i387" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))] + "TARGET_80387" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "DF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) -(define_insn "*floatdidf2_i387" - [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f") +(define_expand "floatdidf2" + [(set (match_operand:DF 0 "register_operand" "") + (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))] + "TARGET_80387 || (TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)" + "") + +(define_insn "*floatdidf2_mixed" + [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y") (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))] - "TARGET_64BIT && TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)" + "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387" "@ fild%z1\t%1 # @@ -4672,57 +4635,75 @@ cvtsi2sd{q}\t{%1, %0|%0, %1}" [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "DF") + (set_attr "unit" "*,i387,*,*") (set_attr "athlon_decode" "*,*,double,direct") (set_attr "fp_int_src" "true")]) (define_insn "*floatdidf2_sse" [(set (match_operand:DF 0 "register_operand" "=Y,Y") (float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))] - "TARGET_SSE2" + "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH" "cvtsi2sd{q}\t{%1, %0|%0, %1}" [(set_attr "type" "sseicvt") (set_attr "mode" "DF") (set_attr "athlon_decode" "double,direct") (set_attr "fp_int_src" "true")]) +(define_insn "*floatdidf2_i387" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))] + "TARGET_80387" + "@ + fild%z1\t%1 + #" + [(set_attr "type" "fmov,multi") + (set_attr "mode" "DF") + (set_attr "unit" "*,i387") + (set_attr "fp_int_src" "true")]) + (define_insn "floathixf2" [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] + (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))] "TARGET_80387" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "XF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) (define_insn "floatsixf2" [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,r")))] + (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))] "TARGET_80387" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "XF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) (define_insn "floatdixf2" [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,r")))] + (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))] "TARGET_80387" "@ fild%z1\t%1 #" [(set_attr "type" "fmov,multi") (set_attr "mode" "XF") + (set_attr "unit" "*,i387") (set_attr "fp_int_src" "true")]) ;; %%% Kill these when reload knows how to do it. (define_split [(set (match_operand 0 "fp_register_operand" "") (float (match_operand 1 "register_operand" "")))] - "reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))" + "reload_completed + && TARGET_80387 + && FLOAT_MODE_P (GET_MODE (operands[0]))" [(const_int 0)] { operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]); @@ -4735,187 +4716,61 @@ (define_expand "floatunssisf2" [(use (match_operand:SF 0 "register_operand" "")) (use (match_operand:SI 1 "register_operand" ""))] - "TARGET_SSE && TARGET_SSE_MATH && !TARGET_64BIT" + "!TARGET_64BIT && TARGET_SSE_MATH" "x86_emit_floatuns (operands); DONE;") (define_expand "floatunsdisf2" [(use (match_operand:SF 0 "register_operand" "")) (use (match_operand:DI 1 "register_operand" ""))] - "TARGET_SSE && TARGET_SSE_MATH && TARGET_64BIT" + "TARGET_64BIT && TARGET_SSE_MATH" "x86_emit_floatuns (operands); DONE;") (define_expand "floatunsdidf2" [(use (match_operand:DF 0 "register_operand" "")) (use (match_operand:DI 1 "register_operand" ""))] - "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_64BIT" + "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH" "x86_emit_floatuns (operands); DONE;") ;; SSE extract/set expanders -(define_expand "vec_setv2df" - [(match_operand:V2DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "") - (match_operand 2 "const_int_operand" "")] - "TARGET_SSE2" -{ - switch (INTVAL (operands[2])) - { - case 0: - emit_insn (gen_sse2_movsd (operands[0], operands[0], - simplify_gen_subreg (V2DFmode, operands[1], - DFmode, 0))); - break; - case 1: - { - rtx op1 = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); - - emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], op1)); - } - break; - default: - abort (); - } - DONE; -}) - -(define_expand "vec_extractv2df" - [(match_operand:DF 0 "register_operand" "") - (match_operand:V2DF 1 "register_operand" "") - (match_operand 2 "const_int_operand" "")] - "TARGET_SSE2" -{ - switch (INTVAL (operands[2])) - { - case 0: - emit_move_insn (operands[0], gen_lowpart (DFmode, operands[1])); - break; - case 1: - { - rtx dest = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); - - emit_insn (gen_sse2_unpckhpd (dest, operands[1], operands[1])); - } - break; - default: - abort (); - } - DONE; -}) - -(define_expand "vec_initv2df" - [(match_operand:V2DF 0 "register_operand" "") - (match_operand 1 "" "")] - "TARGET_SSE2" -{ - ix86_expand_vector_init (operands[0], operands[1]); - DONE; -}) - -(define_expand "vec_setv4sf" - [(match_operand:V4SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "") - (match_operand 2 "const_int_operand" "")] - "TARGET_SSE" -{ - switch (INTVAL (operands[2])) - { - case 0: - emit_insn (gen_sse_movss (operands[0], operands[0], - simplify_gen_subreg (V4SFmode, operands[1], - SFmode, 0))); - break; - case 1: - { - rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - rtx tmp = gen_reg_rtx (V4SFmode); - - emit_move_insn (tmp, operands[0]); - emit_insn (gen_sse_unpcklps (operands[0], operands[0], operands[0])); - emit_insn (gen_sse_movss (operands[0], operands[0], op1)); - emit_insn (gen_sse_shufps (operands[0], operands[0], tmp, - GEN_INT (1 + (0<<2) + (2<<4) + (3<<6)))); - } - case 2: - { - rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - rtx tmp = gen_reg_rtx (V4SFmode); - - emit_move_insn (tmp, operands[0]); - emit_insn (gen_sse_movss (tmp, tmp, op1)); - emit_insn (gen_sse_shufps (operands[0], operands[0], tmp, - GEN_INT (0 + (1<<2) + (0<<4) + (3<<6)))); - } - break; - case 3: - { - rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - rtx tmp = gen_reg_rtx (V4SFmode); + +;; Add instructions - emit_move_insn (tmp, operands[0]); - emit_insn (gen_sse_movss (tmp, tmp, op1)); - emit_insn (gen_sse_shufps (operands[0], operands[0], tmp, - GEN_INT (0 + (1<<2) + (2<<4) + (0<<6)))); - } - break; - default: - abort (); - } - DONE; -}) +;; %%% splits for addditi3 -(define_expand "vec_extractv4sf" - [(match_operand:SF 0 "register_operand" "") - (match_operand:V4SF 1 "register_operand" "") - (match_operand 2 "const_int_operand" "")] - "TARGET_SSE" -{ - switch (INTVAL (operands[2])) - { - case 0: - emit_move_insn (operands[0], gen_lowpart (SFmode, operands[1])); - break; - case 1: - { - rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - rtx tmp = gen_reg_rtx (V4SFmode); - - emit_move_insn (tmp, operands[1]); - emit_insn (gen_sse_shufps (op0, tmp, tmp, - GEN_INT (1))); - } - case 2: - { - rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - rtx tmp = gen_reg_rtx (V4SFmode); - - emit_move_insn (tmp, operands[1]); - emit_insn (gen_sse_unpckhps (op0, tmp, tmp)); - } - case 3: - { - rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - rtx tmp = gen_reg_rtx (V4SFmode); - - emit_move_insn (tmp, operands[1]); - emit_insn (gen_sse_shufps (op0, tmp, tmp, - GEN_INT (3))); - } - default: - abort (); - } - DONE; -}) +(define_expand "addti3" + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "x86_64_general_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;") + +(define_insn "*addti3_1" + [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") + (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0") + (match_operand:TI 2 "general_operand" "roiF,riF"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)" + "#") -(define_expand "vec_initv4sf" - [(match_operand:V4SF 0 "register_operand" "") - (match_operand 1 "" "")] - "TARGET_SSE" -{ - ix86_expand_vector_init (operands[0], operands[1]); - DONE; -}) - -;; Add instructions +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "general_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] + UNSPEC_ADD_CARRY)) + (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]) + (parallel [(set (match_dup 3) + (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 4)) + (match_dup 5))) + (clobber (reg:CC FLAGS_REG))])] + "split_ti (operands+0, 1, operands+0, operands+3); + split_ti (operands+1, 1, operands+1, operands+4); + split_ti (operands+2, 1, operands+2, operands+5);") ;; %%% splits for addsidi3 ; [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -4926,7 +4781,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;") @@ -4934,7 +4789,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "general_operand" "roiF,riF"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" "#") @@ -4942,16 +4797,16 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC 17) (unspec:CC [(match_dup 1) (match_dup 2)] + [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] UNSPEC_ADD_CARRY)) (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) - (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 4)) (match_dup 5))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "split_di (operands+0, 1, operands+0, operands+3); split_di (operands+1, 1, operands+1, operands+4); split_di (operands+2, 1, operands+2, operands+5);") @@ -4961,16 +4816,15 @@ (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") (match_operand:DI 1 "nonimmediate_operand" "%0,0")) (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" "adc{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "mode" "DI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "DI")]) (define_insn "*adddi3_cc_rex64" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "x86_64_general_operand" "re,rm")] UNSPEC_ADD_CARRY)) @@ -4986,39 +4840,36 @@ (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") (match_operand:QI 1 "nonimmediate_operand" "%0,0")) (match_operand:QI 2 "general_operand" "qi,qm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, QImode, operands)" "adc{b}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "mode" "QI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "QI")]) (define_insn "addhi3_carry" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") (match_operand:HI 1 "nonimmediate_operand" "%0,0")) (match_operand:HI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, HImode, operands)" "adc{w}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "mode" "HI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "HI")]) (define_insn "addsi3_carry" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 1 "nonimmediate_operand" "%0,0")) (match_operand:SI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, SImode, operands)" "adc{l}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "SI")]) (define_insn "*addsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -5026,16 +4877,15 @@ (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 1 "nonimmediate_operand" "%0")) (match_operand:SI 2 "general_operand" "rim")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" "adc{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "SI")]) (define_insn "*addsi3_cc" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")] UNSPEC_ADD_CARRY)) @@ -5047,7 +4897,7 @@ (set_attr "mode" "SI")]) (define_insn "addqi3_cc" - [(set (reg:CC 17) + [(set (reg:CC FLAGS_REG) (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qi,qm")] UNSPEC_ADD_CARRY)) @@ -5062,7 +4912,7 @@ [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;") @@ -5104,7 +4954,7 @@ (define_insn_and_split "*lea_general_1" [(set (match_operand 0 "register_operand" "=r") - (plus (plus (match_operand 1 "index_register_operand" "r") + (plus (plus (match_operand 1 "index_register_operand" "l") (match_operand 2 "register_operand" "r")) (match_operand 3 "immediate_operand" "i")))] "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode @@ -5136,7 +4986,7 @@ (define_insn_and_split "*lea_general_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "r") + (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l") (match_operand:SI 2 "register_operand" "r")) (match_operand:SI 3 "immediate_operand" "i"))))] "TARGET_64BIT" @@ -5156,7 +5006,7 @@ (define_insn_and_split "*lea_general_2" [(set (match_operand 0 "register_operand" "=r") - (plus (mult (match_operand 1 "index_register_operand" "r") + (plus (mult (match_operand 1 "index_register_operand" "l") (match_operand 2 "const248_operand" "i")) (match_operand 3 "nonmemory_operand" "ri")))] "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode @@ -5186,7 +5036,7 @@ (define_insn_and_split "*lea_general_2_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r") + (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l") (match_operand:SI 2 "const248_operand" "n")) (match_operand:SI 3 "nonmemory_operand" "ri"))))] "TARGET_64BIT" @@ -5205,7 +5055,7 @@ (define_insn_and_split "*lea_general_3" [(set (match_operand 0 "register_operand" "=r") - (plus (plus (mult (match_operand 1 "index_register_operand" "r") + (plus (plus (mult (match_operand 1 "index_register_operand" "l") (match_operand 2 "const248_operand" "i")) (match_operand 3 "register_operand" "r")) (match_operand 4 "immediate_operand" "i")))] @@ -5239,8 +5089,9 @@ (define_insn_and_split "*lea_general_3_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r") - (match_operand:SI 2 "const248_operand" "n")) + (plus:SI (plus:SI (mult:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "const248_operand" "n")) (match_operand:SI 3 "register_operand" "r")) (match_operand:SI 4 "immediate_operand" "i"))))] "TARGET_64BIT" @@ -5262,8 +5113,8 @@ (define_insn "*adddi_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r") (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:DI 2 "x86_64_general_operand" "rme,re,re"))) - (clobber (reg:CC 17))] + (match_operand:DI 2 "x86_64_general_operand" "rme,re,le"))) + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" { switch (get_attr_type (insn)) @@ -5273,18 +5124,17 @@ return "lea{q}\t{%a2, %0|%0, %a2}"; case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{q}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{q}\t%0"; else - abort (); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{q}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ @@ -5319,7 +5169,7 @@ [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "x86_64_nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(set (match_dup 0) @@ -5328,7 +5178,7 @@ "") (define_insn "*adddi_2_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "x86_64_general_operand" "rme,re")) @@ -5344,18 +5194,17 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{q}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{q}\t%0"; else - abort (); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{q}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* ???? We ought to handle there the 32bit case too - do we need new constraint? */ /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -5380,7 +5229,7 @@ (set_attr "mode" "DI")]) (define_insn "*adddi_3_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme")) (match_operand:DI 1 "x86_64_general_operand" "%0"))) (clobber (match_scratch:DI 0 "=r"))] @@ -5394,18 +5243,17 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{q}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{q}\t%0"; else - abort (); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{q}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* ???? We ought to handle there the 32bit case too - do we need new constraint? */ /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -5438,7 +5286,7 @@ ; Also carry flag is reversed compared to cmp, so this conversion is valid ; only for comparisons not depending on it. (define_insn "*adddi_4_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:DI 2 "x86_64_immediate_operand" "e"))) (clobber (match_scratch:DI 0 "=rm"))] @@ -5450,14 +5298,14 @@ case TYPE_INCDEC: if (operands[2] == constm1_rtx) return "inc{q}\t%0"; - else if (operands[2] == const1_rtx) - return "dec{q}\t%0"; else - abort(); + { + gcc_assert (operands[2] == const1_rtx); + return "dec{q}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if ((INTVAL (operands[2]) == -128 @@ -5477,7 +5325,7 @@ (set_attr "mode" "DI")]) (define_insn "*adddi_5_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0") (match_operand:DI 2 "x86_64_general_operand" "rme")) @@ -5493,18 +5341,17 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{q}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{q}\t%0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{q}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (GET_CODE (operands[2]) == CONST_INT @@ -5530,8 +5377,8 @@ (define_insn "*addsi_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:SI 2 "general_operand" "rmni,rni,rni"))) - (clobber (reg:CC 17))] + (match_operand:SI 2 "general_operand" "rmni,rni,lni"))) + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, SImode, operands)" { switch (get_attr_type (insn)) @@ -5541,18 +5388,17 @@ return "lea{l}\t{%a2, %0|%0, %a2}"; case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{l}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ @@ -5585,7 +5431,7 @@ [(set (match_operand 0 "register_operand" "") (plus (match_operand 1 "register_operand" "") (match_operand 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(const_int 0)] @@ -5615,8 +5461,8 @@ [(set (match_operand:DI 0 "register_operand" "=r,r") (zero_extend:DI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r") - (match_operand:SI 2 "general_operand" "rmni,rni")))) - (clobber (reg:CC 17))] + (match_operand:SI 2 "general_operand" "rmni,lni")))) + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" { switch (get_attr_type (insn)) @@ -5628,10 +5474,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{l}\t%k0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%k0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%k0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -5666,7 +5513,7 @@ (zero_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(set (match_dup 0) @@ -5677,7 +5524,7 @@ }) (define_insn "*addsi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "rmni,rni")) @@ -5693,18 +5540,17 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{l}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (GET_CODE (operands[2]) == CONST_INT @@ -5726,7 +5572,7 @@ ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*addsi_2_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rmni")) @@ -5744,10 +5590,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{l}\t%k0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%k0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%k0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -5770,7 +5617,7 @@ (set_attr "mode" "SI")]) (define_insn "*addsi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (neg:SI (match_operand:SI 2 "general_operand" "rmni")) (match_operand:SI 1 "nonimmediate_operand" "%0"))) (clobber (match_scratch:SI 0 "=r"))] @@ -5783,18 +5630,17 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{l}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (GET_CODE (operands[2]) == CONST_INT @@ -5816,7 +5662,7 @@ ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*addsi_3_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (neg:SI (match_operand:SI 2 "general_operand" "rmni")) (match_operand:SI 1 "nonimmediate_operand" "%0"))) (set (match_operand:DI 0 "register_operand" "=r") @@ -5832,10 +5678,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{l}\t%k0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%k0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%k0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -5866,7 +5713,7 @@ ; Also carry flag is reversed compared to cmp, so this conversion is valid ; only for comparisons not depending on it. (define_insn "*addsi_4" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))) (clobber (match_scratch:SI 0 "=rm"))] @@ -5878,14 +5725,14 @@ case TYPE_INCDEC: if (operands[2] == constm1_rtx) return "inc{l}\t%0"; - else if (operands[2] == const1_rtx) - return "dec{l}\t%0"; else - abort(); + { + gcc_assert (operands[2] == const1_rtx); + return "dec{l}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if ((INTVAL (operands[2]) == -128 @@ -5903,7 +5750,7 @@ (set_attr "mode" "SI")]) (define_insn "*addsi_5" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rmni")) @@ -5918,18 +5765,17 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) return "inc{l}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{l}\t%0"; else - abort(); + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{l}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (GET_CODE (operands[2]) == CONST_INT @@ -5953,7 +5799,7 @@ [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "") (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;") @@ -5964,8 +5810,8 @@ (define_insn "*addhi_1_lea" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:HI 2 "general_operand" "ri,rm,rni"))) - (clobber (reg:CC 17))] + (match_operand:HI 2 "general_operand" "ri,rm,lni"))) + (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (PLUS, HImode, operands)" { @@ -5976,9 +5822,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{w}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6006,7 +5854,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (PLUS, HImode, operands)" { @@ -6015,9 +5863,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{w}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6040,7 +5890,7 @@ (set_attr "mode" "HI")]) (define_insn "*addhi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "rmni,rni")) @@ -6055,9 +5905,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{w}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6080,7 +5932,7 @@ (set_attr "mode" "HI")]) (define_insn "*addhi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (neg:HI (match_operand:HI 2 "general_operand" "rmni")) (match_operand:HI 1 "nonimmediate_operand" "%0"))) (clobber (match_scratch:HI 0 "=r"))] @@ -6092,9 +5944,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{w}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6116,9 +5970,9 @@ (const_string "alu"))) (set_attr "mode" "HI")]) -; See comments above addsi_3_imm for details. +; See comments above addsi_4 for details. (define_insn "*addhi_4" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "const_int_operand" "n"))) (clobber (match_scratch:HI 0 "=rm"))] @@ -6130,14 +5984,14 @@ case TYPE_INCDEC: if (operands[2] == constm1_rtx) return "inc{w}\t%0"; - else if (operands[2] == const1_rtx) - return "dec{w}\t%0"; else - abort(); + { + gcc_assert (operands[2] == const1_rtx); + return "dec{w}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if ((INTVAL (operands[2]) == -128 @@ -6156,7 +6010,7 @@ (define_insn "*addhi_5" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0") (match_operand:HI 2 "general_operand" "rmni")) @@ -6170,9 +6024,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx) - return "dec{w}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6198,7 +6054,7 @@ [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "") (plus:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;") @@ -6206,8 +6062,8 @@ (define_insn "*addqi_1_lea" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r") (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r") - (match_operand:QI 2 "general_operand" "qn,qmn,rn,rn"))) - (clobber (reg:CC 17))] + (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln"))) + (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (PLUS, QImode, operands)" { @@ -6219,9 +6075,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else if (operands[2] == constm1_rtx) - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6255,7 +6113,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "qn,qmn,rn"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (PLUS, QImode, operands)" { @@ -6265,9 +6123,11 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else if (operands[2] == constm1_rtx) - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx); + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. @@ -6299,7 +6159,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (plus:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qn,qnm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { @@ -6308,9 +6168,11 @@ case TYPE_INCDEC: if (operands[1] == const1_rtx) return "inc{b}\t%0"; - else if (operands[1] == constm1_rtx) - return "dec{b}\t%0"; - abort(); + else + { + gcc_assert (operands[1] == constm1_rtx); + return "dec{b}\t%0"; + } default: /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. */ @@ -6334,7 +6196,7 @@ (set_attr "mode" "QI")]) (define_insn "*addqi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qmni,qni")) @@ -6349,11 +6211,13 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{b}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) - return "dec{b}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; + } default: /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */ @@ -6373,7 +6237,7 @@ (set_attr "mode" "QI")]) (define_insn "*addqi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (neg:QI (match_operand:QI 2 "general_operand" "qmni")) (match_operand:QI 1 "nonimmediate_operand" "%0"))) (clobber (match_scratch:QI 0 "=q"))] @@ -6385,11 +6249,13 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{b}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) - return "dec{b}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; + } default: /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */ @@ -6408,9 +6274,9 @@ (const_string "alu"))) (set_attr "mode" "QI")]) -; See comments above addsi_3_imm for details. +; See comments above addsi_4 for details. (define_insn "*addqi_4" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const_int_operand" "n"))) (clobber (match_scratch:QI 0 "=qm"))] @@ -6424,14 +6290,14 @@ || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)) return "inc{b}\t%0"; - else if (operands[2] == const1_rtx) - return "dec{b}\t%0"; else - abort(); + { + gcc_assert (operands[2] == const1_rtx); + return "dec{b}\t%0"; + } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (INTVAL (operands[2]) < 0) { operands[2] = GEN_INT (-INTVAL (operands[2])); @@ -6448,7 +6314,7 @@ (define_insn "*addqi_5" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0") (match_operand:QI 2 "general_operand" "qmni")) @@ -6462,11 +6328,13 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{b}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) - return "dec{b}\t%0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; + } default: /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */ @@ -6496,7 +6364,7 @@ (const_int 8) (const_int 8)) (match_operand:QI 2 "general_operand" "Qmn"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" { switch (get_attr_type (insn)) @@ -6504,11 +6372,13 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{b}\t%h0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) - return "dec{b}\t%h0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%h0"; + } default: return "add{b}\t{%2, %h0|%h0, %2}"; @@ -6530,7 +6400,7 @@ (const_int 8) (const_int 8)) (match_operand:QI 2 "nonmemory_operand" "Qn"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" { switch (get_attr_type (insn)) @@ -6538,11 +6408,13 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{b}\t%h0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) - return "dec{b}\t%h0"; - abort(); + else + { + gcc_assert (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%h0"; + } default: return "add{b}\t{%2, %h0|%h0, %2}"; @@ -6567,7 +6439,7 @@ (match_operand 2 "ext_register_operand" "Q") (const_int 8) (const_int 8)))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "add{b}\t{%h2, %h0|%h0, %h2}" [(set_attr "type" "alu") @@ -6598,13 +6470,48 @@ ;; Subtract instructions +;; %%% splits for subditi3 + +(define_expand "subti3" + [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "") + (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "x86_64_general_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT" + "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;") + +(define_insn "*subti3_1" + [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") + (minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0") + (match_operand:TI 2 "general_operand" "roiF,riF"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)" + "#") + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "general_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))]) + (parallel [(set (match_dup 3) + (minus:DI (match_dup 4) + (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 5)))) + (clobber (reg:CC FLAGS_REG))])] + "split_ti (operands+0, 1, operands+0, operands+3); + split_ti (operands+1, 1, operands+1, operands+4); + split_ti (operands+2, 1, operands+2, operands+5);") + ;; %%% splits for subsidi3 (define_expand "subdi3" [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;") @@ -6612,7 +6519,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:DI 2 "general_operand" "roiF,riF"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" "#") @@ -6620,15 +6527,15 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC 17) (compare:CC (match_dup 1) (match_dup 2))) + [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) (minus:SI (match_dup 4) - (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "split_di (operands+0, 1, operands+0, operands+3); split_di (operands+1, 1, operands+1, operands+4); split_di (operands+2, 1, operands+2, operands+5);") @@ -6638,26 +6545,25 @@ (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") (match_operand:DI 2 "x86_64_general_operand" "re,rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" "sbb{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "ppro_uops" "few") (set_attr "mode" "DI")]) (define_insn "*subdi_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" "sub{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "DI")]) (define_insn "*subdi_2_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:DI 2 "x86_64_general_operand" "re,rm")) @@ -6671,7 +6577,7 @@ (set_attr "mode" "DI")]) (define_insn "*subdi_3_rex63" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") @@ -6687,12 +6593,11 @@ (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") (match_operand:QI 2 "general_operand" "qi,qm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, QImode, operands)" "sbb{b}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "ppro_uops" "few") (set_attr "mode" "QI")]) (define_insn "subhi3_carry" @@ -6700,12 +6605,11 @@ (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") (match_operand:HI 2 "general_operand" "ri,rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, HImode, operands)" "sbb{w}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "ppro_uops" "few") (set_attr "mode" "HI")]) (define_insn "subsi3_carry" @@ -6713,12 +6617,11 @@ (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 2 "general_operand" "ri,rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, SImode, operands)" "sbb{l}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "ppro_uops" "few") (set_attr "mode" "SI")]) (define_insn "subsi3_carry_zext" @@ -6727,19 +6630,18 @@ (minus:SI (match_operand:SI 1 "register_operand" "0,0") (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 2 "general_operand" "ri,rm"))))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" "sbb{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "pent_pair" "pu") - (set_attr "ppro_uops" "few") (set_attr "mode" "SI")]) (define_expand "subsi3" [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") (minus:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;") @@ -6747,7 +6649,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:SI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, SImode, operands)" "sub{l}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") @@ -6758,14 +6660,14 @@ (zero_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "rim")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" "sub{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "*subsi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:SI 2 "general_operand" "ri,rm")) @@ -6779,7 +6681,7 @@ (set_attr "mode" "SI")]) (define_insn "*subsi_2_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "rim")) @@ -6795,7 +6697,7 @@ (set_attr "mode" "SI")]) (define_insn "*subsi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:SI 2 "general_operand" "ri,rm"))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") @@ -6807,7 +6709,7 @@ (set_attr "mode" "SI")]) (define_insn "*subsi_3_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "rim"))) (set (match_operand:DI 0 "register_operand" "=r") @@ -6816,7 +6718,7 @@ (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCmode) && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" + "sub{l}\t{%2, %1|%1, %2}" [(set_attr "type" "alu") (set_attr "mode" "DI")]) @@ -6824,7 +6726,7 @@ [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "") (minus:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;") @@ -6832,14 +6734,14 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:HI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, HImode, operands)" "sub{w}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "HI")]) (define_insn "*subhi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:HI 2 "general_operand" "ri,rm")) @@ -6853,7 +6755,7 @@ (set_attr "mode" "HI")]) (define_insn "*subhi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:HI 2 "general_operand" "ri,rm"))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") @@ -6868,7 +6770,7 @@ [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "") (minus:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;") @@ -6876,7 +6778,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "general_operand" "qn,qmn"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, QImode, operands)" "sub{b}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") @@ -6886,7 +6788,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (minus:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qn,qmn"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "sub{b}\t{%1, %0|%0, %1}" @@ -6894,7 +6796,7 @@ (set_attr "mode" "QI")]) (define_insn "*subqi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "general_operand" "qi,qm")) @@ -6908,7 +6810,7 @@ (set_attr "mode" "QI")]) (define_insn "*subqi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "general_operand" "qi,qm"))) (set (match_operand:HI 0 "nonimmediate_operand" "=qm,q") @@ -6948,7 +6850,7 @@ [(parallel [(set (match_operand:DI 0 "register_operand" "") (mult:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT" "") @@ -6956,7 +6858,7 @@ [(set (match_operand:DI 0 "register_operand" "=r,r,r") (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:DI 2 "x86_64_general_operand" "K,e,mr"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "@ @@ -6980,7 +6882,7 @@ [(parallel [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -6988,7 +6890,7 @@ [(set (match_operand:SI 0 "register_operand" "=r,r,r") (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:SI 2 "general_operand" "K,i,mr"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM" "@ imul{l}\t{%2, %1, %0|%0, %1, %2} @@ -7012,7 +6914,7 @@ (zero_extend:DI (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:SI 2 "general_operand" "K,i,mr")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "@ @@ -7036,7 +6938,7 @@ [(parallel [(set (match_operand:HI 0 "register_operand" "") (mult:HI (match_operand:HI 1 "register_operand" "") (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_HIMODE_MATH" "") @@ -7044,7 +6946,7 @@ [(set (match_operand:HI 0 "register_operand" "=r,r,r") (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:HI 2 "general_operand" "K,i,mr"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM" "@ imul{w}\t{%2, %1, %0|%0, %1, %2} @@ -7064,7 +6966,7 @@ [(parallel [(set (match_operand:QI 0 "register_operand" "") (mult:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "register_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "") @@ -7072,7 +6974,7 @@ [(set (match_operand:QI 0 "register_operand" "=a") (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0") (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "mul{b}\t%2" @@ -7090,7 +6992,7 @@ (match_operand:QI 1 "nonimmediate_operand" "")) (zero_extend:HI (match_operand:QI 2 "register_operand" "")))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "") @@ -7098,7 +7000,7 @@ [(set (match_operand:HI 0 "register_operand" "=a") (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "mul{b}\t%2" @@ -7114,7 +7016,7 @@ [(parallel [(set (match_operand:HI 0 "register_operand" "") (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")) (sign_extend:HI (match_operand:QI 2 "register_operand" "")))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "") @@ -7122,7 +7024,7 @@ [(set (match_operand:HI 0 "register_operand" "=a") (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "imul{b}\t%2" @@ -7140,7 +7042,7 @@ (match_operand:DI 1 "nonimmediate_operand" "")) (zero_extend:TI (match_operand:DI 2 "register_operand" "")))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT" "") @@ -7148,12 +7050,11 @@ [(set (match_operand:TI 0 "register_operand" "=A") (mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0")) (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "mul{q}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") @@ -7168,7 +7069,7 @@ (match_operand:SI 1 "nonimmediate_operand" "")) (zero_extend:DI (match_operand:SI 2 "register_operand" "")))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "!TARGET_64BIT" "") @@ -7176,12 +7077,11 @@ [(set (match_operand:DI 0 "register_operand" "=A") (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0")) (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "mul{l}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") @@ -7195,7 +7095,7 @@ (match_operand:DI 1 "nonimmediate_operand" "")) (sign_extend:TI (match_operand:DI 2 "register_operand" "")))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT" "") @@ -7203,7 +7103,7 @@ [(set (match_operand:TI 0 "register_operand" "=A") (mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0")) (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "imul{q}\t%2" @@ -7221,7 +7121,7 @@ (match_operand:SI 1 "nonimmediate_operand" "")) (sign_extend:DI (match_operand:SI 2 "register_operand" "")))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "!TARGET_64BIT" "") @@ -7229,7 +7129,7 @@ [(set (match_operand:DI 0 "register_operand" "=A") (mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "imul{l}\t%2" @@ -7251,7 +7151,7 @@ (match_operand:DI 2 "register_operand" ""))) (const_int 64)))) (clobber (match_scratch:DI 3 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT" "") @@ -7265,12 +7165,11 @@ (match_operand:DI 2 "nonimmediate_operand" "rm"))) (const_int 64)))) (clobber (match_scratch:DI 3 "=1")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "mul{q}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") @@ -7288,7 +7187,7 @@ (match_operand:SI 2 "register_operand" ""))) (const_int 32)))) (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -7302,11 +7201,10 @@ (match_operand:SI 2 "nonimmediate_operand" "rm"))) (const_int 32)))) (clobber (match_scratch:SI 3 "=1")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM" "mul{l}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") @@ -7324,12 +7222,11 @@ (match_operand:SI 2 "nonimmediate_operand" "rm"))) (const_int 32))))) (clobber (match_scratch:SI 3 "=1")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "mul{l}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") @@ -7347,7 +7244,7 @@ (match_operand:DI 2 "register_operand" ""))) (const_int 64)))) (clobber (match_scratch:DI 3 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT" "") @@ -7361,12 +7258,11 @@ (match_operand:DI 2 "nonimmediate_operand" "rm"))) (const_int 64)))) (clobber (match_scratch:DI 3 "=1")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "imul{q}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") (const_string "vector") @@ -7383,7 +7279,7 @@ (match_operand:SI 2 "register_operand" ""))) (const_int 32)))) (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -7397,11 +7293,10 @@ (match_operand:SI 2 "nonimmediate_operand" "rm"))) (const_int 32)))) (clobber (match_scratch:SI 3 "=1")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM" "imul{l}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") (const_string "vector") @@ -7418,12 +7313,11 @@ (match_operand:SI 2 "nonimmediate_operand" "rm"))) (const_int 32))))) (clobber (match_scratch:SI 3 "=1")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "imul{l}\t%2" [(set_attr "type" "imul") - (set_attr "ppro_uops" "few") (set (attr "athlon_decode") (if_then_else (eq_attr "cpu" "athlon") (const_string "vector") @@ -7459,23 +7353,21 @@ [(set (match_operand:QI 0 "register_operand" "=a") (div:QI (match_operand:HI 1 "register_operand" "0") (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "idiv{b}\t%2" [(set_attr "type" "idiv") - (set_attr "mode" "QI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "QI")]) (define_insn "udivqi3" [(set (match_operand:QI 0 "register_operand" "=a") (udiv:QI (match_operand:HI 1 "register_operand" "0") (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "div{b}\t%2" [(set_attr "type" "idiv") - (set_attr "mode" "QI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "QI")]) ;; The patterns that match these are at the end of this file. @@ -7508,7 +7400,7 @@ (match_operand:DI 2 "nonimmediate_operand" ""))) (set (match_operand:DI 3 "register_operand" "") (mod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_64BIT" "") @@ -7521,7 +7413,7 @@ (match_operand:DI 3 "nonimmediate_operand" "rm,rm"))) (set (match_operand:DI 1 "register_operand" "=&d,&d") (mod:DI (match_dup 2) (match_dup 3))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD" "#" [(set_attr "type" "multi")]) @@ -7532,7 +7424,7 @@ (match_operand:DI 3 "nonimmediate_operand" "rm"))) (set (match_operand:DI 1 "register_operand" "=&d") (mod:DI (match_dup 2) (match_dup 3))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)" "#" [(set_attr "type" "multi")]) @@ -7544,12 +7436,11 @@ (set (match_operand:DI 3 "register_operand" "=d") (mod:DI (match_dup 1) (match_dup 2))) (use (match_operand:DI 4 "register_operand" "3")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "idiv{q}\t%2" [(set_attr "type" "idiv") - (set_attr "mode" "DI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "DI")]) (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -7557,17 +7448,17 @@ (match_operand:DI 2 "nonimmediate_operand" ""))) (set (match_operand:DI 3 "register_operand" "") (mod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed" [(parallel [(set (match_dup 3) (ashiftrt:DI (match_dup 4) (const_int 63))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) (div:DI (reg:DI 0) (match_dup 2))) (set (match_dup 3) (mod:DI (reg:DI 0) (match_dup 2))) (use (match_dup 3)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] { /* Avoid use of cltd in favor of a mov+shift. */ if (!TARGET_USE_CLTD && !optimize_size) @@ -7580,8 +7471,7 @@ } else { - if (true_regnum (operands[1])) - abort(); + gcc_assert (!true_regnum (operands[1])); operands[4] = operands[1]; } }) @@ -7593,7 +7483,7 @@ (match_operand:SI 2 "nonimmediate_operand" ""))) (set (match_operand:SI 3 "register_operand" "") (mod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -7606,7 +7496,7 @@ (match_operand:SI 3 "nonimmediate_operand" "rm,rm"))) (set (match_operand:SI 1 "register_operand" "=&d,&d") (mod:SI (match_dup 2) (match_dup 3))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!optimize_size && !TARGET_USE_CLTD" "#" [(set_attr "type" "multi")]) @@ -7617,7 +7507,7 @@ (match_operand:SI 3 "nonimmediate_operand" "rm"))) (set (match_operand:SI 1 "register_operand" "=&d") (mod:SI (match_dup 2) (match_dup 3))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "optimize_size || TARGET_USE_CLTD" "#" [(set_attr "type" "multi")]) @@ -7629,12 +7519,11 @@ (set (match_operand:SI 3 "register_operand" "=d") (mod:SI (match_dup 1) (match_dup 2))) (use (match_operand:SI 4 "register_operand" "3")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "idiv{l}\t%2" [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "SI")]) (define_split [(set (match_operand:SI 0 "register_operand" "") @@ -7642,17 +7531,17 @@ (match_operand:SI 2 "nonimmediate_operand" ""))) (set (match_operand:SI 3 "register_operand" "") (mod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed" [(parallel [(set (match_dup 3) (ashiftrt:SI (match_dup 4) (const_int 31))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) (div:SI (reg:SI 0) (match_dup 2))) (set (match_dup 3) (mod:SI (reg:SI 0) (match_dup 2))) (use (match_dup 3)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] { /* Avoid use of cltd in favor of a mov+shift. */ if (!TARGET_USE_CLTD && !optimize_size) @@ -7665,8 +7554,7 @@ } else { - if (true_regnum (operands[1])) - abort(); + gcc_assert (!true_regnum (operands[1])); operands[4] = operands[1]; } }) @@ -7677,7 +7565,7 @@ (match_operand:HI 2 "nonimmediate_operand" "rm"))) (set (match_operand:HI 3 "register_operand" "=&d") (mod:HI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "cwtd\;idiv{w}\t%2" [(set_attr "type" "multi") @@ -7690,7 +7578,7 @@ (match_operand:DI 2 "nonimmediate_operand" "rm"))) (set (match_operand:DI 3 "register_operand" "=&d") (umod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "xor{q}\t%3, %3\;div{q}\t%2" [(set_attr "type" "multi") @@ -7704,11 +7592,10 @@ (set (match_operand:DI 3 "register_operand" "=d") (umod:DI (match_dup 1) (match_dup 2))) (use (match_dup 3)) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "div{q}\t%2" [(set_attr "type" "idiv") - (set_attr "ppro_uops" "few") (set_attr "mode" "DI")]) (define_split @@ -7717,7 +7604,7 @@ (match_operand:DI 2 "nonimmediate_operand" ""))) (set (match_operand:DI 3 "register_operand" "") (umod:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed" [(set (match_dup 3) (const_int 0)) (parallel [(set (match_dup 0) @@ -7725,7 +7612,7 @@ (set (match_dup 3) (umod:DI (match_dup 1) (match_dup 2))) (use (match_dup 3)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_insn "udivmodsi4" @@ -7734,7 +7621,7 @@ (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=&d") (umod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "xor{l}\t%3, %3\;div{l}\t%2" [(set_attr "type" "multi") @@ -7748,11 +7635,10 @@ (set (match_operand:SI 3 "register_operand" "=d") (umod:SI (match_dup 1) (match_dup 2))) (use (match_dup 3)) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "div{l}\t%2" [(set_attr "type" "idiv") - (set_attr "ppro_uops" "few") (set_attr "mode" "SI")]) (define_split @@ -7761,7 +7647,7 @@ (match_operand:SI 2 "nonimmediate_operand" ""))) (set (match_operand:SI 3 "register_operand" "") (umod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed" [(set (match_dup 3) (const_int 0)) (parallel [(set (match_dup 0) @@ -7769,7 +7655,7 @@ (set (match_dup 3) (umod:SI (match_dup 1) (match_dup 2))) (use (match_dup 3)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_expand "udivmodhi4" @@ -7780,7 +7666,7 @@ (set (match_operand:HI 3 "register_operand" "") (umod:HI (match_dup 1) (match_dup 2))) (use (match_dup 4)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_HIMODE_MATH" "operands[4] = gen_reg_rtx (HImode);") @@ -7791,14 +7677,13 @@ (set (match_operand:HI 3 "register_operand" "=d") (umod:HI (match_dup 1) (match_dup 2))) (use (match_operand:HI 4 "register_operand" "3")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "div{w}\t%2" [(set_attr "type" "idiv") - (set_attr "mode" "HI") - (set_attr "ppro_uops" "few")]) + (set_attr "mode" "HI")]) -;; We can not use div/idiv for double division, because it causes +;; We cannot use div/idiv for double division, because it causes ;; "division by zero" on the overflow and that's not what we expect ;; from truncate. Because true (non truncating) double division is ;; never generated, we can't create this insn anyway. @@ -7812,11 +7697,10 @@ ; (set (match_operand:SI 3 "register_operand" "=d") ; (truncate:SI ; (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2))))) -; (clobber (reg:CC 17))] +; (clobber (reg:CC FLAGS_REG))] ; "" ; "div{l}\t{%2, %0|%0, %2}" -; [(set_attr "type" "idiv") -; (set_attr "ppro_uops" "few")]) +; [(set_attr "type" "idiv")]) ;;- Logical AND instructions @@ -7824,7 +7708,7 @@ ;; Note that this excludes ah. (define_insn "*testdi_1_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm") (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re")) @@ -7832,10 +7716,10 @@ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ - test{l}\t{%k1, %k0|%k0, %k1} - test{l}\t{%k1, %k0|%k0, %k1} - test{q}\t{%1, %0|%0, %1} - test{q}\t{%1, %0|%0, %1} + test{l}\t{%k1, %k0|%k0, %k1} + test{l}\t{%k1, %k0|%k0, %k1} + test{q}\t{%1, %0|%0, %1} + test{q}\t{%1, %0|%0, %1} test{q}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "modrm" "0,1,0,1,1") @@ -7843,7 +7727,7 @@ (set_attr "pent_pair" "uv,np,uv,np,uv")]) (define_insn "testsi_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm") (match_operand:SI 1 "general_operand" "in,in,rin")) @@ -7857,7 +7741,7 @@ (set_attr "pent_pair" "uv,np,uv")]) (define_expand "testsi_ccno_1" - [(set (reg:CCNO 17) + [(set (reg:CCNO FLAGS_REG) (compare:CCNO (and:SI (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "nonmemory_operand" "")) @@ -7866,7 +7750,7 @@ "") (define_insn "*testhi_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm") (match_operand:HI 1 "general_operand" "n,n,rn")) (const_int 0)))] @@ -7879,7 +7763,7 @@ (set_attr "pent_pair" "uv,np,uv")]) (define_expand "testqi_ccz_1" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "") (match_operand:QI 1 "nonmemory_operand" "")) (const_int 0)))] @@ -7887,16 +7771,16 @@ "") (define_insn "*testqi_1_maybe_si" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r") (match_operand:QI 1 "general_operand" "n,n,qn,n")) (const_int 0)))] - "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && ix86_match_ccmode (insn, - GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)" + "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && ix86_match_ccmode (insn, + GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)" { if (which_alternative == 3) { @@ -7912,7 +7796,7 @@ (set_attr "pent_pair" "uv,np,uv,np")]) (define_insn "*testqi_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm") @@ -7927,7 +7811,7 @@ (set_attr "pent_pair" "uv,np,uv")]) (define_expand "testqi_ext_ccno_0" - [(set (reg:CCNO 17) + [(set (reg:CCNO FLAGS_REG) (compare:CCNO (and:SI (zero_extract:SI @@ -7940,7 +7824,7 @@ "") (define_insn "*testqi_ext_0" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (zero_extract:SI @@ -7957,7 +7841,7 @@ (set_attr "pent_pair" "np")]) (define_insn "*testqi_ext_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (zero_extract:SI @@ -7974,7 +7858,7 @@ (set_attr "mode" "QI")]) (define_insn "*testqi_ext_1_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (zero_extract:SI @@ -7990,7 +7874,7 @@ (set_attr "mode" "QI")]) (define_insn "*testqi_ext_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (zero_extract:SI @@ -8009,13 +7893,16 @@ ;; Combine likes to form bit extractions for some tests. Humor it. (define_insn "*testqi_ext_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (zero_extract:SI (match_operand 0 "nonimmediate_operand" "rm") (match_operand:SI 1 "const_int_operand" "") (match_operand:SI 2 "const_int_operand" "")) (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode) + && INTVAL (operands[1]) > 0 + && INTVAL (operands[2]) >= 0 + && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 && (GET_MODE (operands[0]) == SImode || (TARGET_64BIT && GET_MODE (operands[0]) == DImode) || GET_MODE (operands[0]) == HImode @@ -8023,7 +7910,7 @@ "#") (define_insn "*testqi_ext_3_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (zero_extract:DI (match_operand 0 "nonimmediate_operand" "rm") (match_operand:DI 1 "const_int_operand" "") @@ -8031,8 +7918,8 @@ (const_int 0)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - /* The code below cannot deal with constants outside HOST_WIDE_INT. */ - && INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT + && INTVAL (operands[1]) > 0 + && INTVAL (operands[2]) >= 0 /* Ensure that resulting mask is zero or sign extended operand. */ && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64 @@ -8087,8 +7974,11 @@ val = gen_lowpart (QImode, val); } - mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1; - mask &= ~(((HOST_WIDE_INT)1 << pos) - 1); + if (len == HOST_BITS_PER_WIDE_INT) + mask = -1; + else + mask = ((HOST_WIDE_INT)1 << len) - 1; + mask <<= pos; operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode)); }) @@ -8147,7 +8037,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (and:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "x86_64_szext_general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "ix86_expand_binary_operator (AND, DImode, operands); DONE;") @@ -8155,7 +8045,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm") (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)" { switch (get_attr_type (insn)) @@ -8164,14 +8054,14 @@ { enum machine_mode mode; - if (GET_CODE (operands[2]) != CONST_INT) - abort (); + gcc_assert (GET_CODE (operands[2]) == CONST_INT); if (INTVAL (operands[2]) == 0xff) mode = QImode; - else if (INTVAL (operands[2]) == 0xffff) - mode = HImode; else - abort (); + { + gcc_assert (INTVAL (operands[2]) == 0xffff); + mode = HImode; + } operands[1] = gen_lowpart (mode, operands[1]); if (mode == QImode) @@ -8181,8 +8071,7 @@ } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (get_attr_mode (insn) == MODE_SI) return "and{l}\t{%k2, %k0|%k0, %k2}"; else @@ -8194,7 +8083,7 @@ (set_attr "mode" "SI,DI,DI,DI")]) (define_insn "*anddi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0") (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re")) (const_int 0))) @@ -8203,8 +8092,8 @@ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) && ix86_binary_operator_ok (AND, DImode, operands)" "@ - and{l}\t{%k2, %k0|%k0, %k2} - and{q}\t{%2, %0|%0, %2} + and{l}\t{%k2, %k0|%k0, %k2} + and{q}\t{%2, %0|%0, %2} and{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI,DI,DI")]) @@ -8213,7 +8102,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (and:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (AND, SImode, operands); DONE;") @@ -8221,7 +8110,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r") (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm") (match_operand:SI 2 "general_operand" "ri,rm,L"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, SImode, operands)" { switch (get_attr_type (insn)) @@ -8230,14 +8119,14 @@ { enum machine_mode mode; - if (GET_CODE (operands[2]) != CONST_INT) - abort (); + gcc_assert (GET_CODE (operands[2]) == CONST_INT); if (INTVAL (operands[2]) == 0xff) mode = QImode; - else if (INTVAL (operands[2]) == 0xffff) - mode = HImode; else - abort (); + { + gcc_assert (INTVAL (operands[2]) == 0xffff); + mode = HImode; + } operands[1] = gen_lowpart (mode, operands[1]); if (mode == QImode) @@ -8247,8 +8136,7 @@ } default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); return "and{l}\t{%2, %0|%0, %2}"; } } @@ -8260,7 +8148,7 @@ [(set (match_operand 0 "register_operand" "") (and (match_dup 0) (const_int -65536))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)" [(set (strict_low_part (match_dup 1)) (const_int 0))] "operands[1] = gen_lowpart (HImode, operands[0]);") @@ -8269,7 +8157,7 @@ [(set (match_operand 0 "ext_register_operand" "") (and (match_dup 0) (const_int -256))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed" [(set (strict_low_part (match_dup 1)) (const_int 0))] "operands[1] = gen_lowpart (QImode, operands[0]);") @@ -8278,7 +8166,7 @@ [(set (match_operand 0 "ext_register_operand" "") (and (match_dup 0) (const_int -65281))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed" [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) @@ -8290,7 +8178,7 @@ (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]);") ;; See comment for addsi_1_zext why we do use nonimmediate_operand @@ -8299,14 +8187,14 @@ (zero_extend:DI (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)" "and{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "*andsi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "rim,ri")) (const_int 0))) @@ -8320,7 +8208,7 @@ ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*andsi_2_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")) (const_int 0))) @@ -8336,7 +8224,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (and:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (AND, HImode, operands); DONE;") @@ -8344,21 +8232,18 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm") (match_operand:HI 2 "general_operand" "ri,rm,L"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, HImode, operands)" { switch (get_attr_type (insn)) { case TYPE_IMOVX: - if (GET_CODE (operands[2]) != CONST_INT) - abort (); - if (INTVAL (operands[2]) == 0xff) - return "movz{bl|x}\t{%b1, %k0|%k0, %b1}"; - abort (); + gcc_assert (GET_CODE (operands[2]) == CONST_INT); + gcc_assert (INTVAL (operands[2]) == 0xff); + return "movz{bl|x}\t{%b1, %k0|%k0, %b1}"; default: - if (! rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (rtx_equal_p (operands[0], operands[1])); return "and{w}\t{%2, %0|%0, %2}"; } @@ -8368,7 +8253,7 @@ (set_attr "mode" "HI,HI,SI")]) (define_insn "*andhi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "rim,ri")) (const_int 0))) @@ -8384,7 +8269,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (and:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (AND, QImode, operands); DONE;") @@ -8393,7 +8278,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "qi,qmi,ri"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, QImode, operands)" "@ and{b}\t{%2, %0|%0, %2} @@ -8406,7 +8291,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (and:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qi,qmi"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "and{b}\t{%1, %0|%0, %1}" @@ -8414,7 +8299,7 @@ (set_attr "mode" "QI")]) (define_insn "*andqi_2_maybe_si" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "qim,qi,i")) @@ -8438,7 +8323,7 @@ (set_attr "mode" "QI,QI,SI")]) (define_insn "*andqi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qim,qi")) @@ -8452,7 +8337,7 @@ (set_attr "mode" "QI")]) (define_insn "*andqi_2_slp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") (match_operand:QI 1 "nonimmediate_operand" "qmi,qi")) @@ -8480,7 +8365,7 @@ (const_int 8) (const_int 8)) (match_operand 2 "const_int_operand" "n"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") @@ -8491,7 +8376,7 @@ ;; often in fp comparisons. (define_insn "*andqi_ext_0_cc" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (and:SI (zero_extract:SI @@ -8526,7 +8411,7 @@ (const_int 8)) (zero_extend:SI (match_operand:QI 2 "general_operand" "Qm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") @@ -8544,7 +8429,7 @@ (const_int 8)) (zero_extend:SI (match_operand 2 "ext_register_operand" "Q")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") @@ -8564,7 +8449,7 @@ (match_operand 2 "ext_register_operand" "Q") (const_int 8) (const_int 8)))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "and{b}\t{%h2, %h0|%h0, %h2}" [(set_attr "type" "alu") @@ -8580,7 +8465,7 @@ [(set (match_operand 0 "register_operand" "") (and (match_operand 1 "register_operand" "") (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && QI_REG_P (operands[0]) && (!TARGET_PARTIAL_REG_STALL || optimize_size) @@ -8590,7 +8475,7 @@ (and:SI (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);") @@ -8601,7 +8486,7 @@ [(set (match_operand 0 "register_operand" "") (and (match_operand 1 "general_operand" "") (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && ANY_QI_REG_P (operands[0]) && (!TARGET_PARTIAL_REG_STALL || optimize_size) @@ -8611,7 +8496,7 @@ [(parallel [(set (strict_low_part (match_dup 0)) (and:QI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (QImode, operands[0]); operands[1] = gen_lowpart (QImode, operands[1]); operands[2] = gen_lowpart (QImode, operands[2]);") @@ -8625,7 +8510,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (ior:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "ix86_expand_binary_operator (IOR, DImode, operands); DONE;") @@ -8633,7 +8518,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "x86_64_general_operand" "re,rme"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (IOR, DImode, operands)" "or{q}\t{%2, %0|%0, %2}" @@ -8641,7 +8526,7 @@ (set_attr "mode" "DI")]) (define_insn "*iordi_2_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "x86_64_general_operand" "rem,re")) (const_int 0))) @@ -8655,7 +8540,7 @@ (set_attr "mode" "DI")]) (define_insn "*iordi_3_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0") (match_operand:DI 2 "x86_64_general_operand" "rem")) (const_int 0))) @@ -8672,7 +8557,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (ior:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (IOR, SImode, operands); DONE;") @@ -8680,7 +8565,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rmi"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (IOR, SImode, operands)" "or{l}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") @@ -8692,7 +8577,7 @@ (zero_extend:DI (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)" "or{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") @@ -8702,14 +8587,14 @@ [(set (match_operand:DI 0 "register_operand" "=rm") (ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "or{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "*iorsi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "rim,ri")) (const_int 0))) @@ -8724,7 +8609,7 @@ ;; See comment for addsi_1_zext why we do use nonimmediate_operand ;; ??? Special case for immediate operand is missing - it is tricky. (define_insn "*iorsi_2_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")) (const_int 0))) @@ -8737,7 +8622,7 @@ (set_attr "mode" "SI")]) (define_insn "*iorsi_2_zext_imm" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand 2 "x86_64_zext_immediate_operand" "Z")) (const_int 0))) @@ -8750,7 +8635,7 @@ (set_attr "mode" "SI")]) (define_insn "*iorsi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")) (const_int 0))) @@ -8765,7 +8650,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (ior:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (IOR, HImode, operands); DONE;") @@ -8773,14 +8658,14 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m") (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "rmi,ri"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (IOR, HImode, operands)" "or{w}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "HI")]) (define_insn "*iorhi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "rim,ri")) (const_int 0))) @@ -8793,7 +8678,7 @@ (set_attr "mode" "HI")]) (define_insn "*iorhi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0") (match_operand:HI 2 "general_operand" "rim")) (const_int 0))) @@ -8808,7 +8693,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (ior:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (IOR, QImode, operands); DONE;") @@ -8817,7 +8702,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r") (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "qmi,qi,ri"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (IOR, QImode, operands)" "@ or{b}\t{%2, %0|%0, %2} @@ -8830,7 +8715,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m")) (ior:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qmi,qi"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "or{b}\t{%1, %0|%0, %1}" @@ -8838,7 +8723,7 @@ (set_attr "mode" "QI")]) (define_insn "*iorqi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qim,qi")) (const_int 0))) @@ -8851,7 +8736,7 @@ (set_attr "mode" "QI")]) (define_insn "*iorqi_2_slp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") (match_operand:QI 1 "general_operand" "qim,qi")) (const_int 0))) @@ -8865,7 +8750,7 @@ (set_attr "mode" "QI")]) (define_insn "*iorqi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0") (match_operand:QI 2 "general_operand" "qim")) (const_int 0))) @@ -8886,7 +8771,7 @@ (const_int 8) (const_int 8)) (match_operand 2 "const_int_operand" "n"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_size)" "or{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") @@ -8904,7 +8789,7 @@ (const_int 8)) (zero_extend:SI (match_operand:QI 2 "general_operand" "Qm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_size)" "or{b}\t{%2, %h0|%h0, %2}" @@ -8923,7 +8808,7 @@ (const_int 8)) (zero_extend:SI (match_operand 2 "ext_register_operand" "Q")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_size)" "or{b}\t{%2, %h0|%h0, %2}" @@ -8942,7 +8827,7 @@ (zero_extract:SI (match_operand 2 "ext_register_operand" "Q") (const_int 8) (const_int 8)))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_size)" "ior{b}\t{%h2, %h0|%h0, %h2}" [(set_attr "type" "alu") @@ -8953,7 +8838,7 @@ [(set (match_operand 0 "register_operand" "") (ior (match_operand 1 "register_operand" "") (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && QI_REG_P (operands[0]) && (!TARGET_PARTIAL_REG_STALL || optimize_size) @@ -8963,7 +8848,7 @@ (ior:SI (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);") @@ -8974,7 +8859,7 @@ [(set (match_operand 0 "register_operand" "") (ior (match_operand 1 "general_operand" "") (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && ANY_QI_REG_P (operands[0]) && (!TARGET_PARTIAL_REG_STALL || optimize_size) @@ -8984,7 +8869,7 @@ [(parallel [(set (strict_low_part (match_dup 0)) (ior:QI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (QImode, operands[0]); operands[1] = gen_lowpart (QImode, operands[1]); operands[2] = gen_lowpart (QImode, operands[2]);") @@ -8998,7 +8883,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (xor:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "ix86_expand_binary_operator (XOR, DImode, operands); DONE;") @@ -9006,17 +8891,17 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (XOR, DImode, operands)" "@ - xor{q}\t{%2, %0|%0, %2} + xor{q}\t{%2, %0|%0, %2} xor{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "DI,DI")]) (define_insn "*xordi_2_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") (match_operand:DI 2 "x86_64_general_operand" "rem,re")) (const_int 0))) @@ -9026,13 +8911,13 @@ && ix86_match_ccmode (insn, CCNOmode) && ix86_binary_operator_ok (XOR, DImode, operands)" "@ - xor{q}\t{%2, %0|%0, %2} + xor{q}\t{%2, %0|%0, %2} xor{q}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "DI,DI")]) (define_insn "*xordi_3_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0") (match_operand:DI 2 "x86_64_general_operand" "rem")) (const_int 0))) @@ -9048,7 +8933,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (xor:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:SI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (XOR, SImode, operands); DONE;") @@ -9056,7 +8941,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (XOR, SImode, operands)" "xor{l}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") @@ -9069,7 +8954,7 @@ (zero_extend:DI (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)" "xor{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") @@ -9079,14 +8964,14 @@ [(set (match_operand:DI 0 "register_operand" "=r") (xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)" "xor{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "*xorsi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "rim,ri")) (const_int 0))) @@ -9101,7 +8986,7 @@ ;; See comment for addsi_1_zext why we do use nonimmediate_operand ;; ??? Special case for immediate operand is missing - it is tricky. (define_insn "*xorsi_2_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")) (const_int 0))) @@ -9114,7 +8999,7 @@ (set_attr "mode" "SI")]) (define_insn "*xorsi_2_zext_imm" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand 2 "x86_64_zext_immediate_operand" "Z")) (const_int 0))) @@ -9127,7 +9012,7 @@ (set_attr "mode" "SI")]) (define_insn "*xorsi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "general_operand" "rim")) (const_int 0))) @@ -9142,7 +9027,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (xor:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:HI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (XOR, HImode, operands); DONE;") @@ -9150,14 +9035,14 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,m") (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "rmi,ri"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (XOR, HImode, operands)" "xor{w}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "mode" "HI")]) (define_insn "*xorhi_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "rim,ri")) (const_int 0))) @@ -9170,7 +9055,7 @@ (set_attr "mode" "HI")]) (define_insn "*xorhi_3" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0") (match_operand:HI 2 "general_operand" "rim")) (const_int 0))) @@ -9185,7 +9070,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (xor:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (XOR, QImode, operands); DONE;") @@ -9194,7 +9079,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r") (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "qmi,qi,ri"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (XOR, QImode, operands)" "@ xor{b}\t{%2, %0|%0, %2} @@ -9207,7 +9092,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (xor:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qi,qmi"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "xor{b}\t{%1, %0|%0, %1}" @@ -9224,7 +9109,7 @@ (const_int 8) (const_int 8)) (match_operand 2 "const_int_operand" "n"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_size)" "xor{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") @@ -9242,7 +9127,7 @@ (const_int 8)) (zero_extend:SI (match_operand:QI 2 "general_operand" "Qm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_size)" "xor{b}\t{%2, %h0|%h0, %2}" @@ -9261,7 +9146,7 @@ (const_int 8)) (zero_extend:SI (match_operand 2 "ext_register_operand" "Q")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (!TARGET_PARTIAL_REG_STALL || optimize_size)" "xor{b}\t{%2, %h0|%h0, %2}" @@ -9280,7 +9165,7 @@ (zero_extract:SI (match_operand 2 "ext_register_operand" "Q") (const_int 8) (const_int 8)))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_size)" "xor{b}\t{%h2, %h0|%h0, %h2}" [(set_attr "type" "alu") @@ -9288,7 +9173,7 @@ (set_attr "mode" "QI")]) (define_insn "*xorqi_cc_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qim,qi")) @@ -9302,7 +9187,7 @@ (set_attr "mode" "QI")]) (define_insn "*xorqi_2_slp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") (match_operand:QI 1 "general_operand" "qim,qi")) (const_int 0))) @@ -9316,7 +9201,7 @@ (set_attr "mode" "QI")]) (define_insn "*xorqi_cc_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0") (match_operand:QI 2 "general_operand" "qim")) @@ -9329,7 +9214,7 @@ (set_attr "mode" "QI")]) (define_insn "*xorqi_cc_ext_1" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:SI (zero_extract:SI @@ -9350,7 +9235,7 @@ (set_attr "mode" "QI")]) (define_insn "*xorqi_cc_ext_1_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (xor:SI (zero_extract:SI @@ -9372,7 +9257,7 @@ (define_expand "xorqi_cc_ext_1" [(parallel [ - (set (reg:CCNO 17) + (set (reg:CCNO FLAGS_REG) (compare:CCNO (xor:SI (zero_extract:SI @@ -9394,7 +9279,7 @@ [(set (match_operand 0 "register_operand" "") (xor (match_operand 1 "register_operand" "") (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && QI_REG_P (operands[0]) && (!TARGET_PARTIAL_REG_STALL || optimize_size) @@ -9404,7 +9289,7 @@ (xor:SI (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);") @@ -9415,7 +9300,7 @@ [(set (match_operand 0 "register_operand" "") (xor (match_operand 1 "general_operand" "") (match_operand 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && ANY_QI_REG_P (operands[0]) && (!TARGET_PARTIAL_REG_STALL || optimize_size) @@ -9425,24 +9310,61 @@ [(parallel [(set (strict_low_part (match_dup 0)) (xor:QI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (QImode, operands[0]); operands[1] = gen_lowpart (QImode, operands[1]); operands[2] = gen_lowpart (QImode, operands[2]);") ;; Negation instructions +(define_expand "negti2" + [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "") + (neg:TI (match_operand:TI 1 "nonimmediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT" + "ix86_expand_unary_operator (NEG, TImode, operands); DONE;") + +(define_insn "*negti2_1" + [(set (match_operand:TI 0 "nonimmediate_operand" "=ro") + (neg:TI (match_operand:TI 1 "general_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT + && ix86_unary_operator_ok (NEG, TImode, operands)" + "#") + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (neg:TI (match_operand:TI 1 "general_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(parallel + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (neg:DI (match_dup 2)) (const_int 0))) + (set (match_dup 0) (neg:DI (match_dup 2)))]) + (parallel + [(set (match_dup 1) + (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 3)) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 1) + (neg:DI (match_dup 1))) + (clobber (reg:CC FLAGS_REG))])] + "split_ti (operands+1, 1, operands+2, operands+3); + split_ti (operands+0, 1, operands+0, operands+1);") + (define_expand "negdi2" [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") (neg:DI (match_operand:DI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "ix86_expand_unary_operator (NEG, DImode, operands); DONE;") (define_insn "*negdi2_1" [(set (match_operand:DI 0 "nonimmediate_operand" "=ro") (neg:DI (match_operand:DI 1 "general_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)" "#") @@ -9450,29 +9372,29 @@ (define_split [(set (match_operand:DI 0 "nonimmediate_operand" "") (neg:DI (match_operand:DI 1 "general_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && reload_completed" [(parallel - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (neg:SI (match_dup 2)) (const_int 0))) (set (match_dup 0) (neg:SI (match_dup 2)))]) (parallel [(set (match_dup 1) - (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) (match_dup 3)) (const_int 0))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 1) (neg:SI (match_dup 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "split_di (operands+1, 1, operands+2, operands+3); split_di (operands+0, 1, operands+0, operands+1);") (define_insn "*negdi2_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)" "neg{q}\t%0" [(set_attr "type" "negnot") @@ -9483,7 +9405,7 @@ ;; flag being the only useful item. (define_insn "*negdi2_cmpz_rex64" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -9497,14 +9419,14 @@ (define_expand "negsi2" [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") (neg:SI (match_operand:SI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "ix86_expand_unary_operator (NEG, SImode, operands); DONE;") (define_insn "*negsi2_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_unary_operator_ok (NEG, SImode, operands)" "neg{l}\t%0" [(set_attr "type" "negnot") @@ -9516,7 +9438,7 @@ (lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0") (const_int 32))) (const_int 32))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)" "neg{l}\t%k0" [(set_attr "type" "negnot") @@ -9527,7 +9449,7 @@ ;; flag being the only useful item. (define_insn "*negsi2_cmpz" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") @@ -9538,7 +9460,7 @@ (set_attr "mode" "SI")]) (define_insn "*negsi2_cmpz_zext" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0") @@ -9557,21 +9479,21 @@ (define_expand "neghi2" [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "") (neg:HI (match_operand:HI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_HIMODE_MATH" "ix86_expand_unary_operator (NEG, HImode, operands); DONE;") (define_insn "*neghi2_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_unary_operator_ok (NEG, HImode, operands)" "neg{w}\t%0" [(set_attr "type" "negnot") (set_attr "mode" "HI")]) (define_insn "*neghi2_cmpz" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") @@ -9584,21 +9506,21 @@ (define_expand "negqi2" [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "") (neg:QI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "TARGET_QIMODE_MATH" "ix86_expand_unary_operator (NEG, QImode, operands); DONE;") (define_insn "*negqi2_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_unary_operator_ok (NEG, QImode, operands)" "neg{b}\t%0" [(set_attr "type" "negnot") (set_attr "mode" "QI")]) (define_insn "*negqi2_cmpz" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") @@ -9611,747 +9533,403 @@ ;; Changing of sign for FP values is doable using integer unit too. (define_expand "negsf2" - [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") - (neg:SF (match_operand:SF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + [(set (match_operand:SF 0 "nonimmediate_operand" "") + (neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))] "TARGET_80387 || TARGET_SSE_MATH" - "if (TARGET_SSE_MATH) - { - /* In case operand is in memory, we will not use SSE. */ - if (memory_operand (operands[0], VOIDmode) - && rtx_equal_p (operands[0], operands[1])) - emit_insn (gen_negsf2_memory (operands[0], operands[1])); - else - { - /* Using SSE is tricky, since we need bitwise negation of -0 - in register. */ - rtx reg = gen_reg_rtx (SFmode); - rtx dest = operands[0]; - rtx imm = gen_lowpart (SFmode, gen_int_mode (0x80000000, SImode)); - - operands[1] = force_reg (SFmode, operands[1]); - operands[0] = force_reg (SFmode, operands[0]); - reg = force_reg (V4SFmode, - gen_rtx_CONST_VECTOR (V4SFmode, - gen_rtvec (4, imm, CONST0_RTX (SFmode), - CONST0_RTX (SFmode), - CONST0_RTX (SFmode)))); - emit_insn (gen_negsf2_ifs (operands[0], operands[1], reg)); - if (dest != operands[0]) - emit_move_insn (dest, operands[0]); - } - DONE; - } - ix86_expand_unary_operator (NEG, SFmode, operands); DONE;") + "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;") -(define_insn "negsf2_memory" - [(set (match_operand:SF 0 "memory_operand" "=m") - (neg:SF (match_operand:SF 1 "memory_operand" "0"))) - (clobber (reg:CC 17))] - "ix86_unary_operator_ok (NEG, SFmode, operands)" +(define_expand "abssf2" + [(set (match_operand:SF 0 "nonimmediate_operand" "") + (abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))] + "TARGET_80387 || TARGET_SSE_MATH" + "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;") + +(define_insn "*absnegsf2_mixed" + [(set (match_operand:SF 0 "nonimmediate_operand" "=x ,x,f,rm") + (match_operator:SF 3 "absneg_operator" + [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0,0 ")])) + (use (match_operand:V4SF 2 "nonimmediate_operand" "xm ,0,X,X ")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_SSE_MATH && TARGET_MIX_SSE_I387 + && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)" "#") -(define_insn "negsf2_ifs" - [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,x#fr,f#xr,rm#xf") - (neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,x#fr,0,0"))) - (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,xm*r,xm*r")) - (clobber (reg:CC 17))] - "TARGET_SSE - && (reload_in_progress || reload_completed - || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" +(define_insn "*absnegsf2_sse" + [(set (match_operand:SF 0 "nonimmediate_operand" "=x,x,rm") + (match_operator:SF 3 "absneg_operator" + [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")])) + (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,X")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_SSE_MATH + && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)" "#") -(define_split - [(set (match_operand:SF 0 "memory_operand" "") - (neg:SF (match_operand:SF 1 "memory_operand" ""))) - (use (match_operand:SF 2 "" "")) - (clobber (reg:CC 17))] - "" - [(parallel [(set (match_dup 0) - (neg:SF (match_dup 1))) - (clobber (reg:CC 17))])]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (neg:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:V4SF 2 "" "")) - (clobber (reg:CC 17))] - "reload_completed && !SSE_REG_P (operands[0])" - [(parallel [(set (match_dup 0) - (neg:SF (match_dup 1))) - (clobber (reg:CC 17))])]) +(define_insn "*absnegsf2_i387" + [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm") + (match_operator:SF 3 "absneg_operator" + [(match_operand:SF 1 "nonimmediate_operand" "0,0")])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_80387 && !TARGET_SSE_MATH + && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)" + "#") -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (neg:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:V4SF 2 "nonimmediate_operand" "")) - (clobber (reg:CC 17))] - "reload_completed && SSE_REG_P (operands[0])" - [(set (match_dup 0) - (xor:V4SF (match_dup 1) - (match_dup 2)))] +(define_expand "copysignsf3" + [(match_operand:SF 0 "register_operand" "") + (match_operand:SF 1 "nonmemory_operand" "") + (match_operand:SF 2 "register_operand" "")] + "TARGET_SSE_MATH" { - operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - operands[1] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); - if (operands_match_p (operands[0], operands[2])) - { - rtx tmp; - tmp = operands[1]; - operands[1] = operands[2]; - operands[2] = tmp; - } + ix86_expand_copysign (operands); + DONE; }) +(define_insn_and_split "copysignsf3_const" + [(set (match_operand:SF 0 "register_operand" "=x") + (unspec:SF + [(match_operand:V4SF 1 "vector_move_operand" "xmC") + (match_operand:SF 2 "register_operand" "0") + (match_operand:V4SF 3 "nonimmediate_operand" "xm")] + UNSPEC_COPYSIGN))] + "TARGET_SSE_MATH" + "#" + "&& reload_completed" + [(const_int 0)] +{ + ix86_split_copysign_const (operands); + DONE; +}) -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*negsf2_if" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,rm#f") - (neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_80387 - && ix86_unary_operator_ok (NEG, SFmode, operands)" +(define_insn "copysignsf3_var" + [(set (match_operand:SF 0 "register_operand" "=x, x, x, x,x") + (unspec:SF + [(match_operand:SF 2 "register_operand" " x, 0, 0, x,x") + (match_operand:SF 3 "register_operand" " 1, 1, x, 1,x") + (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0") + (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch:V4SF 1 "=x, x, x, x,x"))] + "TARGET_SSE_MATH" "#") (define_split - [(set (match_operand:SF 0 "fp_register_operand" "") - (neg:SF (match_operand:SF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (neg:SF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_and_not_fp_reg_operand" "") - (neg:SF (match_operand:SF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] - "operands[1] = gen_int_mode (0x80000000, SImode); - operands[0] = gen_lowpart (SImode, operands[0]);") - -(define_split - [(set (match_operand 0 "memory_operand" "") - (neg (match_operand 1 "memory_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))" - [(parallel [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] + [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF + [(match_operand:SF 2 "register_operand" "") + (match_operand:SF 3 "register_operand" "") + (match_operand:V4SF 4 "" "") + (match_operand:V4SF 5 "" "")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch:V4SF 1 ""))] + "TARGET_SSE_MATH && reload_completed" + [(const_int 0)] { - int size = GET_MODE_SIZE (GET_MODE (operands[1])); - - if (GET_MODE (operands[1]) == XFmode) - size = 10; - operands[0] = adjust_address (operands[0], QImode, size - 1); - operands[1] = gen_int_mode (0x80, QImode); + ix86_split_copysign_var (operands); + DONE; }) (define_expand "negdf2" - [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))] "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" - "if (TARGET_SSE2 && TARGET_SSE_MATH) - { - /* In case operand is in memory, we will not use SSE. */ - if (memory_operand (operands[0], VOIDmode) - && rtx_equal_p (operands[0], operands[1])) - emit_insn (gen_negdf2_memory (operands[0], operands[1])); - else - { - /* Using SSE is tricky, since we need bitwise negation of -0 - in register. */ - rtx reg; -#if HOST_BITS_PER_WIDE_INT >= 64 - rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode); -#else - rtx imm = immed_double_const (0, 0x80000000, DImode); -#endif - rtx dest = operands[0]; - - operands[1] = force_reg (DFmode, operands[1]); - operands[0] = force_reg (DFmode, operands[0]); - imm = gen_lowpart (DFmode, imm); - reg = force_reg (V2DFmode, - gen_rtx_CONST_VECTOR (V2DFmode, - gen_rtvec (2, imm, CONST0_RTX (DFmode)))); - emit_insn (gen_negdf2_ifs (operands[0], operands[1], reg)); - if (dest != operands[0]) - emit_move_insn (dest, operands[0]); - } - DONE; - } - ix86_expand_unary_operator (NEG, DFmode, operands); DONE;") + "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;") -(define_insn "negdf2_memory" - [(set (match_operand:DF 0 "memory_operand" "=m") - (neg:DF (match_operand:DF 1 "memory_operand" "0"))) - (clobber (reg:CC 17))] - "ix86_unary_operator_ok (NEG, DFmode, operands)" +(define_expand "absdf2" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))] + "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" + "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;") + +(define_insn "*absnegdf2_mixed" + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,f,rm") + (match_operator:DF 3 "absneg_operator" + [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")])) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X,X")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 + && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)" "#") -(define_insn "negdf2_ifs" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,f#Yr,rm#Yf") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0"))) - (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r,Ym*r")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_SSE2 - && (reload_in_progress || reload_completed - || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" +(define_insn "*absnegdf2_sse" + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,rm") + (match_operator:DF 3 "absneg_operator" + [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")])) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X ")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_SSE2 && TARGET_SSE_MATH + && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)" "#") -(define_insn "*negdf2_ifs_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,fm#Y") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0"))) - (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r")) - (clobber (reg:CC 17))] - "TARGET_64BIT && TARGET_SSE2 - && (reload_in_progress || reload_completed - || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" +(define_insn "*absnegdf2_i387" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm") + (match_operator:DF 3 "absneg_operator" + [(match_operand:DF 1 "nonimmediate_operand" "0,0")])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) + && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)" "#") -(define_split - [(set (match_operand:DF 0 "memory_operand" "") - (neg:DF (match_operand:DF 1 "memory_operand" ""))) - (use (match_operand:V2DF 2 "" "")) - (clobber (reg:CC 17))] - "" - [(parallel [(set (match_dup 0) - (neg:DF (match_dup 1))) - (clobber (reg:CC 17))])]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:V2DF 2 "" "")) - (clobber (reg:CC 17))] - "reload_completed && !SSE_REG_P (operands[0]) - && (!TARGET_64BIT || FP_REG_P (operands[0]))" - [(parallel [(set (match_dup 0) - (neg:DF (match_dup 1))) - (clobber (reg:CC 17))])]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:V2DF 2 "" "")) - (clobber (reg:CC 17))] - "TARGET_64BIT && reload_completed && GENERAL_REG_P (operands[0])" - [(parallel [(set (match_dup 0) - (xor:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] - "operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, operands[1]); - operands[2] = gen_lowpart (DImode, operands[2]);") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:V2DF 2 "nonimmediate_operand" "")) - (clobber (reg:CC 17))] - "reload_completed && SSE_REG_P (operands[0])" - [(set (match_dup 0) - (xor:V2DF (match_dup 1) - (match_dup 2)))] -{ - operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); - operands[1] = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); - /* Avoid possible reformatting on the operands. */ - if (TARGET_SSE_PARTIAL_REGS && !optimize_size) - emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], operands[0])); - if (operands_match_p (operands[0], operands[2])) - { - rtx tmp; - tmp = operands[1]; - operands[1] = operands[2]; - operands[2] = tmp; - } +(define_expand "copysigndf3" + [(match_operand:DF 0 "register_operand" "") + (match_operand:DF 1 "nonmemory_operand" "") + (match_operand:DF 2 "register_operand" "")] + "TARGET_SSE2 && TARGET_SSE_MATH" +{ + ix86_expand_copysign (operands); + DONE; }) -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*negdf2_if" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,rm#f") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_80387 - && ix86_unary_operator_ok (NEG, DFmode, operands)" - "#") +(define_insn_and_split "copysigndf3_const" + [(set (match_operand:DF 0 "register_operand" "=x") + (unspec:DF + [(match_operand:V2DF 1 "vector_move_operand" "xmC") + (match_operand:DF 2 "register_operand" "0") + (match_operand:V2DF 3 "nonimmediate_operand" "xm")] + UNSPEC_COPYSIGN))] + "TARGET_SSE2 && TARGET_SSE_MATH" + "#" + "&& reload_completed" + [(const_int 0)] +{ + ix86_split_copysign_const (operands); + DONE; +}) -;; FIXME: We should to allow integer registers here. Problem is that -;; we need another scratch register to get constant from. -;; Forcing constant to mem if no register available in peep2 should be -;; safe even for PIC mode, because of RIP relative addressing. -(define_insn "*negdf2_if_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,mf") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_64BIT && TARGET_80387 - && ix86_unary_operator_ok (NEG, DFmode, operands)" +(define_insn "copysigndf3_var" + [(set (match_operand:DF 0 "register_operand" "=x, x, x, x,x") + (unspec:DF + [(match_operand:DF 2 "register_operand" " x, 0, 0, x,x") + (match_operand:DF 3 "register_operand" " 1, 1, x, 1,x") + (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0") + (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch:V2DF 1 "=x, x, x, x,x"))] + "TARGET_SSE2 && TARGET_SSE_MATH" "#") (define_split - [(set (match_operand:DF 0 "fp_register_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (neg:DF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_and_not_fp_reg_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 3) (xor:SI (match_dup 3) (match_dup 4))) - (clobber (reg:CC 17))])] - "operands[4] = gen_int_mode (0x80000000, SImode); - split_di (operands+0, 1, operands+2, operands+3);") + [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF + [(match_operand:DF 2 "register_operand" "") + (match_operand:DF 3 "register_operand" "") + (match_operand:V2DF 4 "" "") + (match_operand:V2DF 5 "" "")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch:V2DF 1 ""))] + "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed" + [(const_int 0)] +{ + ix86_split_copysign_var (operands); + DONE; +}) (define_expand "negxf2" - [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "") - (neg:XF (match_operand:XF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] - "TARGET_80387" - "ix86_expand_unary_operator (NEG, XFmode, operands); DONE;") - -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*negxf2_if" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,rm#f") - (neg:XF (match_operand:XF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_80387 - && ix86_unary_operator_ok (NEG, XFmode, operands)" - "#") - -(define_split - [(set (match_operand:XF 0 "fp_register_operand" "") - (neg:XF (match_operand:XF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (neg:XF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_and_not_fp_reg_operand" "") - (neg:XF (match_operand:XF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] - "operands[1] = GEN_INT (0x8000); - operands[0] = gen_rtx_REG (SImode, - true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));") - -;; Conditionalize these after reload. If they matches before reload, we -;; lose the clobber and ability to use integer instructions. - -(define_insn "*negsf2_1" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "SF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negdf2_1" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "DF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negextendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (float_extend:DF - (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "DF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negxf2_1" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negextenddfxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF - (match_operand:DF 1 "register_operand" "0"))))] + [(set (match_operand:XF 0 "nonimmediate_operand" "") + (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))] "TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF") - (set_attr "ppro_uops" "few")]) + "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;") -(define_insn "*negextendsfxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF - (match_operand:SF 1 "register_operand" "0"))))] +(define_expand "absxf2" + [(set (match_operand:XF 0 "nonimmediate_operand" "") + (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))] "TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF") - (set_attr "ppro_uops" "few")]) - -;; Absolute value instructions - -(define_expand "abssf2" - [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") - (neg:SF (match_operand:SF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] - "TARGET_80387 || TARGET_SSE_MATH" - "if (TARGET_SSE_MATH) - { - /* In case operand is in memory, we will not use SSE. */ - if (memory_operand (operands[0], VOIDmode) - && rtx_equal_p (operands[0], operands[1])) - emit_insn (gen_abssf2_memory (operands[0], operands[1])); - else - { - /* Using SSE is tricky, since we need bitwise negation of -0 - in register. */ - rtx reg = gen_reg_rtx (V4SFmode); - rtx dest = operands[0]; - rtx imm; - - operands[1] = force_reg (SFmode, operands[1]); - operands[0] = force_reg (SFmode, operands[0]); - imm = gen_lowpart (SFmode, gen_int_mode(~0x80000000, SImode)); - reg = force_reg (V4SFmode, - gen_rtx_CONST_VECTOR (V4SFmode, - gen_rtvec (4, imm, CONST0_RTX (SFmode), - CONST0_RTX (SFmode), - CONST0_RTX (SFmode)))); - emit_insn (gen_abssf2_ifs (operands[0], operands[1], reg)); - if (dest != operands[0]) - emit_move_insn (dest, operands[0]); - } - DONE; - } - ix86_expand_unary_operator (ABS, SFmode, operands); DONE;") - -(define_insn "abssf2_memory" - [(set (match_operand:SF 0 "memory_operand" "=m") - (abs:SF (match_operand:SF 1 "memory_operand" "0"))) - (clobber (reg:CC 17))] - "ix86_unary_operator_ok (ABS, SFmode, operands)" - "#") - -(define_insn "abssf2_ifs" - [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,x#fr,f#xr,rm#xf") - (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,x#fr,0,0"))) - (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,xm*r,xm*r")) - (clobber (reg:CC 17))] - "TARGET_SSE - && (reload_in_progress || reload_completed - || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" + "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;") + +(define_insn "*absnegxf2_i387" + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm") + (match_operator:XF 3 "absneg_operator" + [(match_operand:XF 1 "nonimmediate_operand" "0,0")])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_80387 + && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)" "#") -(define_split - [(set (match_operand:SF 0 "memory_operand" "") - (abs:SF (match_operand:SF 1 "memory_operand" ""))) - (use (match_operand:V4SF 2 "" "")) - (clobber (reg:CC 17))] - "" - [(parallel [(set (match_dup 0) - (abs:SF (match_dup 1))) - (clobber (reg:CC 17))])]) +;; Splitters for fp abs and neg. (define_split - [(set (match_operand:SF 0 "register_operand" "") - (abs:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:V4SF 2 "" "")) - (clobber (reg:CC 17))] - "reload_completed && !SSE_REG_P (operands[0])" - [(parallel [(set (match_dup 0) - (abs:SF (match_dup 1))) - (clobber (reg:CC 17))])]) + [(set (match_operand 0 "fp_register_operand" "") + (match_operator 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "reload_completed" + [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))]) (define_split - [(set (match_operand:SF 0 "register_operand" "") - (abs:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:V4SF 2 "nonimmediate_operand" "")) - (clobber (reg:CC 17))] + [(set (match_operand 0 "register_operand" "") + (match_operator 3 "absneg_operator" + [(match_operand 1 "register_operand" "")])) + (use (match_operand 2 "nonimmediate_operand" "")) + (clobber (reg:CC FLAGS_REG))] "reload_completed && SSE_REG_P (operands[0])" - [(set (match_dup 0) - (and:V4SF (match_dup 1) - (match_dup 2)))] + [(set (match_dup 0) (match_dup 3))] { - operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - operands[1] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + enum machine_mode mode = GET_MODE (operands[0]); + enum machine_mode vmode = GET_MODE (operands[2]); + rtx tmp; + + operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0); + operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0); if (operands_match_p (operands[0], operands[2])) { - rtx tmp; tmp = operands[1]; operands[1] = operands[2]; operands[2] = tmp; } + if (GET_CODE (operands[3]) == ABS) + tmp = gen_rtx_AND (vmode, operands[1], operands[2]); + else + tmp = gen_rtx_XOR (vmode, operands[1], operands[2]); + operands[3] = tmp; }) -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*abssf2_if" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,rm#f") - (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_80387 && ix86_unary_operator_ok (ABS, SFmode, operands)" - "#") - (define_split - [(set (match_operand:SF 0 "fp_register_operand" "") - (abs:SF (match_operand:SF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (abs:SF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_and_not_fp_reg_operand" "") - (abs:SF (match_operand:SF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] - "operands[1] = gen_int_mode (~0x80000000, SImode); - operands[0] = gen_lowpart (SImode, operands[0]);") + [(set (match_operand:SF 0 "register_operand" "") + (match_operator:SF 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand:V4SF 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + rtx tmp; + operands[0] = gen_lowpart (SImode, operands[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); + } + operands[1] = tmp; +}) (define_split - [(set (match_operand 0 "memory_operand" "") - (abs (match_operand 1 "memory_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))" - [(parallel [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] + [(set (match_operand:DF 0 "register_operand" "") + (match_operator:DF 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] { - int size = GET_MODE_SIZE (GET_MODE (operands[1])); - - if (GET_MODE (operands[1]) == XFmode) - size = 10; - operands[0] = adjust_address (operands[0], QImode, size - 1); - operands[1] = gen_int_mode (~0x80, QImode); -}) + rtx tmp; + if (TARGET_64BIT) + { + tmp = gen_lowpart (DImode, operands[0]); + tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63)); + operands[0] = tmp; -(define_expand "absdf2" - [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] - "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" - "if (TARGET_SSE2 && TARGET_SSE_MATH) - { - /* In case operand is in memory, we will not use SSE. */ - if (memory_operand (operands[0], VOIDmode) - && rtx_equal_p (operands[0], operands[1])) - emit_insn (gen_absdf2_memory (operands[0], operands[1])); - else + if (GET_CODE (operands[1]) == ABS) + tmp = const0_rtx; + else + tmp = gen_rtx_NOT (DImode, tmp); + } + else + { + operands[0] = gen_highpart (SImode, operands[0]); + if (GET_CODE (operands[1]) == ABS) { - /* Using SSE is tricky, since we need bitwise negation of -0 - in register. */ - rtx reg = gen_reg_rtx (V2DFmode); -#if HOST_BITS_PER_WIDE_INT >= 64 - rtx imm = gen_int_mode (~(((HOST_WIDE_INT)1) << 63), DImode); -#else - rtx imm = immed_double_const (~0, ~0x80000000, DImode); -#endif - rtx dest = operands[0]; - - operands[1] = force_reg (DFmode, operands[1]); - operands[0] = force_reg (DFmode, operands[0]); - - /* Produce LONG_DOUBLE with the proper immediate argument. */ - imm = gen_lowpart (DFmode, imm); - reg = force_reg (V2DFmode, - gen_rtx_CONST_VECTOR (V2DFmode, - gen_rtvec (2, imm, CONST0_RTX (DFmode)))); - emit_insn (gen_absdf2_ifs (operands[0], operands[1], reg)); - if (dest != operands[0]) - emit_move_insn (dest, operands[0]); + tmp = gen_int_mode (0x7fffffff, SImode); + tmp = gen_rtx_AND (SImode, operands[0], tmp); } - DONE; - } - ix86_expand_unary_operator (ABS, DFmode, operands); DONE;") - -(define_insn "absdf2_memory" - [(set (match_operand:DF 0 "memory_operand" "=m") - (abs:DF (match_operand:DF 1 "memory_operand" "0"))) - (clobber (reg:CC 17))] - "ix86_unary_operator_ok (ABS, DFmode, operands)" - "#") - -(define_insn "absdf2_ifs" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,mf#Yr,mr#Yf") - (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0"))) - (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r,Ym*r")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_SSE2 - && (reload_in_progress || reload_completed - || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" - "#") - -(define_insn "*absdf2_ifs_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,mf#Yr") - (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0"))) - (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r")) - (clobber (reg:CC 17))] - "TARGET_64BIT && TARGET_SSE2 - && (reload_in_progress || reload_completed - || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" - "#") + else + { + tmp = gen_int_mode (0x80000000, SImode); + tmp = gen_rtx_XOR (SImode, operands[0], tmp); + } + } + operands[1] = tmp; +}) (define_split - [(set (match_operand:DF 0 "memory_operand" "") - (abs:DF (match_operand:DF 1 "memory_operand" ""))) - (use (match_operand:V2DF 2 "" "")) - (clobber (reg:CC 17))] - "" - [(parallel [(set (match_dup 0) - (abs:DF (match_dup 1))) - (clobber (reg:CC 17))])]) + [(set (match_operand:XF 0 "register_operand" "") + (match_operator:XF 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + rtx tmp; + operands[0] = gen_rtx_REG (SImode, + true_regnum (operands[0]) + + (TARGET_64BIT ? 1 : 2)); + if (GET_CODE (operands[1]) == ABS) + { + tmp = GEN_INT (0x7fff); + tmp = gen_rtx_AND (SImode, operands[0], tmp); + } + else + { + tmp = GEN_INT (0x8000); + tmp = gen_rtx_XOR (SImode, operands[0], tmp); + } + operands[1] = tmp; +}) (define_split - [(set (match_operand:DF 0 "register_operand" "") - (abs:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:V2DF 2 "" "")) - (clobber (reg:CC 17))] - "reload_completed && !SSE_REG_P (operands[0])" - [(parallel [(set (match_dup 0) - (abs:DF (match_dup 1))) - (clobber (reg:CC 17))])]) + [(set (match_operand 0 "memory_operand" "") + (match_operator 1 "absneg_operator" [(match_dup 0)])) + (use (match_operand 2 "" "")) + (clobber (reg:CC FLAGS_REG))] + "reload_completed" + [(parallel [(set (match_dup 0) (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + enum machine_mode mode = GET_MODE (operands[0]); + int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode); + rtx tmp; -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (abs:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:V2DF 2 "nonimmediate_operand" "")) - (clobber (reg:CC 17))] - "reload_completed && SSE_REG_P (operands[0])" - [(set (match_dup 0) - (and:V2DF (match_dup 1) - (match_dup 2)))] -{ - operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); - operands[1] = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); - /* Avoid possible reformatting on the operands. */ - if (TARGET_SSE_PARTIAL_REGS && !optimize_size) - emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], operands[0])); - if (operands_match_p (operands[0], operands[2])) + operands[0] = adjust_address (operands[0], QImode, size - 1); + if (GET_CODE (operands[1]) == ABS) { - rtx tmp; - tmp = operands[1]; - operands[1] = operands[2]; - operands[2] = tmp; + 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; }) +;; Conditionalize these after reload. If they match before reload, we +;; lose the clobber and ability to use integer instructions. -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*absdf2_if" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,rm#f") - (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_80387 - && ix86_unary_operator_ok (ABS, DFmode, operands)" - "#") - -;; FIXME: We should to allow integer registers here. Problem is that -;; we need another scratch register to get constant from. -;; Forcing constant to mem if no register available in peep2 should be -;; safe even for PIC mode, because of RIP relative addressing. -(define_insn "*absdf2_if_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,mf") - (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_64BIT && TARGET_80387 - && ix86_unary_operator_ok (ABS, DFmode, operands)" - "#") - -(define_split - [(set (match_operand:DF 0 "fp_register_operand" "") - (abs:DF (match_operand:DF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (abs:DF (match_dup 1)))] - "") +(define_insn "*negsf2_1" + [(set (match_operand:SF 0 "register_operand" "=f") + (neg:SF (match_operand:SF 1 "register_operand" "0")))] + "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)" + "fchs" + [(set_attr "type" "fsgn") + (set_attr "mode" "SF")]) -(define_split - [(set (match_operand:DF 0 "register_and_not_fp_reg_operand" "") - (abs:DF (match_operand:DF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 3) (and:SI (match_dup 3) (match_dup 4))) - (clobber (reg:CC 17))])] - "operands[4] = gen_int_mode (~0x80000000, SImode); - split_di (operands+0, 1, operands+2, operands+3);") +(define_insn "*negdf2_1" + [(set (match_operand:DF 0 "register_operand" "=f") + (neg:DF (match_operand:DF 1 "register_operand" "0")))] + "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))" + "fchs" + [(set_attr "type" "fsgn") + (set_attr "mode" "DF")]) -(define_expand "absxf2" - [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "") - (neg:XF (match_operand:XF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] +(define_insn "*negxf2_1" + [(set (match_operand:XF 0 "register_operand" "=f") + (neg:XF (match_operand:XF 1 "register_operand" "0")))] "TARGET_80387" - "ix86_expand_unary_operator (ABS, XFmode, operands); DONE;") - -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*absxf2_if" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,rm#f") - (abs:XF (match_operand:XF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_80387 - && ix86_unary_operator_ok (ABS, XFmode, operands)" - "#") - -(define_split - [(set (match_operand:XF 0 "fp_register_operand" "") - (abs:XF (match_operand:XF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (abs:XF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_and_not_fp_reg_operand" "") - (abs:XF (match_operand:XF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] - "operands[1] = GEN_INT (~0x8000); - operands[0] = gen_rtx_REG (SImode, - true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));") + "fchs" + [(set_attr "type" "fsgn") + (set_attr "mode" "XF")]) (define_insn "*abssf2_1" [(set (match_operand:SF 0 "register_operand" "=f") (abs:SF (match_operand:SF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "SF")]) @@ -10359,24 +9937,51 @@ (define_insn "*absdf2_1" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) -(define_insn "*absextendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (float_extend:DF - (match_operand:SF 1 "register_operand" "0"))))] +(define_insn "*absxf2_1" + [(set (match_operand:XF 0 "register_operand" "=f") + (abs:XF (match_operand:XF 1 "register_operand" "0")))] "TARGET_80387" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) -(define_insn "*absxf2_1" +(define_insn "*negextendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (neg:DF (float_extend:DF + (match_operand:SF 1 "register_operand" "0"))))] + "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" + "fchs" + [(set_attr "type" "fsgn") + (set_attr "mode" "DF")]) + +(define_insn "*negextenddfxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + (neg:XF (float_extend:XF + (match_operand:DF 1 "register_operand" "0"))))] + "TARGET_80387" + "fchs" + [(set_attr "type" "fsgn") + (set_attr "mode" "XF")]) + +(define_insn "*negextendsfxf2" + [(set (match_operand:XF 0 "register_operand" "=f") + (neg:XF (float_extend:XF + (match_operand:SF 1 "register_operand" "0"))))] + "TARGET_80387" + "fchs" + [(set_attr "type" "fsgn") + (set_attr "mode" "XF")]) + +(define_insn "*absextendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (abs:DF (float_extend:DF + (match_operand:SF 1 "register_operand" "0"))))] + "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) @@ -10416,7 +10021,7 @@ (set_attr "mode" "DI")]) (define_insn "*one_cmpldi2_2_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -10467,7 +10072,7 @@ (set_attr "mode" "SI")]) (define_insn "*one_cmplsi2_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") @@ -10495,7 +10100,7 @@ ;; ??? Currently never generated - xor is used instead. (define_insn "*one_cmplsi2_2_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (not:SI (match_operand:SI 1 "register_operand" "0")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") @@ -10536,7 +10141,7 @@ (set_attr "mode" "HI")]) (define_insn "*one_cmplhi2_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") @@ -10580,7 +10185,7 @@ (set_attr "mode" "QI,SI")]) (define_insn "*one_cmplqi2_2" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") @@ -10630,42 +10235,116 @@ ;; shift pair, instead using moves and sign extension for counts greater ;; than 31. -(define_expand "ashldi3" - [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "") - (ashift:DI (match_operand:DI 1 "shiftdi_operand" "") +(define_expand "ashlti3" + [(parallel [(set (match_operand:TI 0 "register_operand" "") + (ashift:TI (match_operand:TI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))])] - "" + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT" { - if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode)) + if (! immediate_operand (operands[2], QImode)) { - emit_insn (gen_ashldi3_1 (operands[0], operands[1], operands[2])); + emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2])); DONE; } - ix86_expand_binary_operator (ASHIFT, DImode, operands); + ix86_expand_binary_operator (ASHIFT, TImode, operands); DONE; }) +(define_insn "ashlti3_1" + [(set (match_operand:TI 0 "register_operand" "=r") + (ashift:TI (match_operand:TI 1 "register_operand" "0") + (match_operand:QI 2 "register_operand" "c"))) + (clobber (match_scratch:DI 3 "=&r")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "#" + [(set_attr "type" "multi")]) + +(define_insn "*ashlti3_2" + [(set (match_operand:TI 0 "register_operand" "=r") + (ashift:TI (match_operand:TI 1 "register_operand" "0") + (match_operand:QI 2 "immediate_operand" "O"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "#" + [(set_attr "type" "multi")]) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (ashift:TI (match_operand:TI 1 "nonmemory_operand" "") + (match_operand:QI 2 "register_operand" ""))) + (clobber (match_scratch:DI 3 "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] + "ix86_split_ashl (operands, operands[3], TImode); DONE;") + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (ashift:TI (match_operand:TI 1 "register_operand" "") + (match_operand:QI 2 "immediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] + "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;") + +(define_insn "x86_64_shld" + [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m") + (ior:DI (ashift:DI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand" "J,c")) + (lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r") + (minus:QI (const_int 64) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "@ + shld{q}\t{%2, %1, %0|%0, %1, %2} + shld{q}\t{%s2%1, %0|%0, %1, %2}" + [(set_attr "type" "ishift") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI") + (set_attr "athlon_decode" "vector")]) + +(define_expand "x86_64_shift_adj" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") + (const_int 64)) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (match_operand:DI 1 "register_operand" "") + (match_dup 0))) + (set (match_dup 1) + (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (match_operand:DI 3 "register_operand" "r") + (match_dup 1)))] + "TARGET_64BIT" + "") + +(define_expand "ashldi3" + [(set (match_operand:DI 0 "shiftdi_operand" "") + (ashift:DI (match_operand:DI 1 "ashldi_input_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;") + (define_insn "*ashldi3_1_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,r") + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l") (match_operand:QI 2 "nonmemory_operand" "cJ,M"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); - if (!rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (operands[2] == const1_rtx); + gcc_assert (rtx_equal_p (operands[0], operands[1])); return "add{q}\t{%0, %0|%0, %0}"; case TYPE_LEA: - if (GET_CODE (operands[2]) != CONST_INT - || (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 3) - abort (); + gcc_assert (GET_CODE (operands[2]) == CONST_INT); + gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3); operands[1] = gen_rtx_MULT (DImode, operands[1], GEN_INT (1 << INTVAL (operands[2]))); return "lea{q}\t{%a1, %0|%0, %a1}"; @@ -10673,8 +10352,7 @@ default: if (REG_P (operands[2])) return "sal{q}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{q}\t%0"; else @@ -10696,9 +10374,9 @@ ;; Convert lea to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") + (ashift:DI (match_operand:DI 1 "index_register_operand" "") (match_operand:QI 2 "immediate_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(set (match_dup 0) @@ -10710,7 +10388,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashldi3_cmp_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "immediate_operand" "e")) @@ -10718,20 +10396,23 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashift:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, DImode, operands)" + && ix86_binary_operator_ok (ASHIFT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{q}\t{%0, %0|%0, %0}"; default: if (REG_P (operands[2])) return "sal{q}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{q}\t%0"; else @@ -10748,43 +10429,79 @@ (const_string "ishift"))) (set_attr "mode" "DI")]) -(define_insn "ashldi3_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Jc"))) - (clobber (match_scratch:SI 3 "=&r")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_CMOVE" - "#" - [(set_attr "type" "multi")]) +(define_insn "*ashldi3_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "immediate_operand" "e")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{q}\t{%0, %0|%0, %0}"; -(define_insn "*ashldi3_2" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Jc"))) - (clobber (reg:CC 17))] + default: + if (REG_P (operands[2])) + return "sal{q}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{q}\t%0"; + else + return "sal{q}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "DI")]) + +(define_insn "*ashldi3_1" + [(set (match_operand:DI 0 "register_operand" "=&r,r") + (ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0") + (match_operand:QI 2 "nonmemory_operand" "Jc,Jc"))) + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" "#" [(set_attr "type" "multi")]) -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_CMOVE && reload_completed" +;; By default we don't ask for a scratch register, because when DImode +;; values are manipulated, registers are already at a premium. But if +;; we have one handy, we won't turn it away. +(define_peephole2 + [(match_scratch:SI 3 "r") + (parallel [(set (match_operand:DI 0 "register_operand" "") + (ashift:DI (match_operand:DI 1 "nonmemory_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (clobber (reg:CC FLAGS_REG))]) + (match_dup 3)] + "!TARGET_64BIT && TARGET_CMOVE" [(const_int 0)] - "ix86_split_ashldi (operands, operands[3]); DONE;") + "ix86_split_ashl (operands, operands[3], DImode); DONE;") (define_split [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") + (ashift:DI (match_operand:DI 1 "nonmemory_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && reload_completed" + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) + ? flow2_completed : reload_completed)" [(const_int 0)] - "ix86_split_ashldi (operands, NULL_RTX); DONE;") + "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;") (define_insn "x86_shld_1" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m") @@ -10792,7 +10509,7 @@ (match_operand:QI 2 "nonmemory_operand" "I,c")) (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") (minus:QI (const_int 32) (match_dup 2))))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "@ shld{l}\t{%2, %1, %0|%0, %1, %2} @@ -10801,20 +10518,19 @@ (set_attr "prefix_0f" "1") (set_attr "mode" "SI") (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + (set_attr "athlon_decode" "vector")]) (define_expand "x86_shift_adj_1" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") (const_int 32)) (const_int 0))) (set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (ne (reg:CCZ 17) (const_int 0)) + (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0)) (match_operand:SI 1 "register_operand" "") (match_dup 0))) (set (match_dup 1) - (if_then_else:SI (ne (reg:CCZ 17) (const_int 0)) + (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0)) (match_operand:SI 3 "register_operand" "r") (match_dup 1)))] "TARGET_CMOVE" @@ -10840,7 +10556,7 @@ JUMP_LABEL (tmp) = label; emit_move_insn (operands[0], operands[1]); - emit_move_insn (operands[1], const0_rtx); + ix86_expand_clear (operands[1]); emit_label (label); LABEL_NUSES (label) = 1; @@ -10852,24 +10568,22 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;") (define_insn "*ashlsi3_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r") + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l") (match_operand:QI 2 "nonmemory_operand" "cI,M"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFT, SImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); - if (!rtx_equal_p (operands[0], operands[1])) - abort (); + gcc_assert (operands[2] == const1_rtx); + gcc_assert (rtx_equal_p (operands[0], operands[1])); return "add{l}\t{%0, %0|%0, %0}"; case TYPE_LEA: @@ -10878,8 +10592,7 @@ default: if (REG_P (operands[2])) return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%0"; else @@ -10903,15 +10616,21 @@ [(set (match_operand 0 "register_operand" "") (ashift (match_operand 1 "index_register_operand" "") (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" + && true_regnum (operands[0]) != true_regnum (operands[1]) + && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4" [(const_int 0)] { rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); + enum machine_mode mode = GET_MODE (operands[0]); + + if (GET_MODE_SIZE (mode) < 4) + operands[0] = gen_lowpart (SImode, operands[0]); + if (mode != Pmode) + operands[1] = gen_lowpart (Pmode, operands[1]); operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); + pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); if (Pmode != SImode) pat = gen_rtx_SUBREG (SImode, pat, 0); @@ -10924,13 +10643,13 @@ [(set (match_operand 0 "register_operand" "") (ashift (match_operand 1 "register_operand" "") (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(const_int 0)] { rtx pat, clob; - emit_move_insn (operands[1], operands[0]); + emit_move_insn (operands[0], operands[1]); pat = gen_rtx_SET (VOIDmode, operands[0], gen_rtx_ASHIFT (GET_MODE (operands[0]), operands[0], operands[2])); @@ -10941,16 +10660,15 @@ (define_insn "*ashlsi3_1_zext" [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,r") + (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l") (match_operand:QI 2 "nonmemory_operand" "cI,M")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{l}\t{%k0, %k0|%k0, %k0}"; case TYPE_LEA: @@ -10959,8 +10677,7 @@ default: if (REG_P (operands[2])) return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%k0"; else @@ -10983,7 +10700,7 @@ [(set (match_operand:DI 0 "register_operand" "") (zero_extend:DI (ashift (match_operand 1 "register_operand" "") (match_operand:QI 2 "const_int_operand" "")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(set (match_dup 0) (zero_extend:DI @@ -10998,28 +10715,72 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashlsi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashift:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{l}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{l}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{l}\t%0"; + else + return "sal{l}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "SI")]) + +(define_insn "*ashlsi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{l}\t{%0, %0|%0, %0}"; default: if (REG_P (operands[2])) return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%0"; else @@ -11037,28 +10798,31 @@ (set_attr "mode" "SI")]) (define_insn "*ashlsi3_cmp_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{l}\t{%k0, %k0|%k0, %k0}"; default: if (REG_P (operands[2])) return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%k0"; else @@ -11078,15 +10842,15 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;") (define_insn "*ashlhi3_1_lea" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l") (match_operand:QI 2 "nonmemory_operand" "cI,M"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (ASHIFT, HImode, operands)" { @@ -11095,15 +10859,13 @@ case TYPE_LEA: return "#"; case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{w}\t{%0, %0|%0, %0}"; default: if (REG_P (operands[2])) return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{w}\t%0"; else @@ -11126,22 +10888,20 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (ASHIFT, HImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{w}\t{%0, %0|%0, %0}"; default: if (REG_P (operands[2])) return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{w}\t%0"; else @@ -11162,28 +10922,72 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashlhi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashift:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" + && ix86_binary_operator_ok (ASHIFT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{w}\t{%0, %0|%0, %0}"; default: if (REG_P (operands[2])) return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{w}\t%0"; + else + return "sal{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "HI")]) + +(define_insn "*ashlhi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{w}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{w}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{w}\t%0"; else @@ -11204,7 +11008,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;") @@ -11212,9 +11016,9 @@ (define_insn "*ashlqi3_1_lea" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,r") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l") (match_operand:QI 2 "nonmemory_operand" "cI,cI,M"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (ASHIFT, QImode, operands)" { @@ -11223,8 +11027,7 @@ case TYPE_LEA: return "#"; case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) return "add{l}\t{%k0, %k0|%k0, %k0}"; else @@ -11238,8 +11041,7 @@ else return "sal{b}\t{%b2, %0|%0, %b2}"; } - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) { if (get_attr_mode (insn) == MODE_SI) @@ -11272,15 +11074,14 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "cI,cI"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_PARTIAL_REG_STALL && ix86_binary_operator_ok (ASHIFT, QImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) return "add{l}\t{%k0, %k0|%k0, %k0}"; else @@ -11294,8 +11095,7 @@ else return "sal{b}\t{%b2, %0|%0, %b2}"; } - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) { if (get_attr_mode (insn) == MODE_SI) @@ -11326,28 +11126,72 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashlqi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashift:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + && ix86_binary_operator_ok (ASHIFT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" { switch (get_attr_type (insn)) { case TYPE_ALU: - if (operands[2] != const1_rtx) - abort (); + gcc_assert (operands[2] == const1_rtx); return "add{b}\t{%0, %0|%0, %0}"; default: if (REG_P (operands[2])) return "sal{b}\t{%b2, %0|%0, %b2}"; - else if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 1 + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{b}\t%0"; + else + return "sal{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "QI")]) + +(define_insn "*ashlqi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{b}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{b}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_size)) return "sal{b}\t%0"; else @@ -11366,28 +11210,90 @@ ;; See comment above `ashldi3' about how this works. -(define_expand "ashrdi3" - [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "") - (ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "") +(define_expand "ashrti3" + [(parallel [(set (match_operand:TI 0 "register_operand" "") + (ashiftrt:TI (match_operand:TI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))])] - "" + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT" { - if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode)) + if (! immediate_operand (operands[2], QImode)) { - emit_insn (gen_ashrdi3_1 (operands[0], operands[1], operands[2])); + emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2])); DONE; } - ix86_expand_binary_operator (ASHIFTRT, DImode, operands); + ix86_expand_binary_operator (ASHIFTRT, TImode, operands); DONE; }) -(define_insn "ashrdi3_63_rex64" +(define_insn "ashrti3_1" + [(set (match_operand:TI 0 "register_operand" "=r") + (ashiftrt:TI (match_operand:TI 1 "register_operand" "0") + (match_operand:QI 2 "register_operand" "c"))) + (clobber (match_scratch:DI 3 "=&r")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "#" + [(set_attr "type" "multi")]) + +(define_insn "*ashrti3_2" + [(set (match_operand:TI 0 "register_operand" "=r") + (ashiftrt:TI (match_operand:TI 1 "register_operand" "0") + (match_operand:QI 2 "immediate_operand" "O"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "#" + [(set_attr "type" "multi")]) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (ashiftrt:TI (match_operand:TI 1 "register_operand" "") + (match_operand:QI 2 "register_operand" ""))) + (clobber (match_scratch:DI 3 "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] + "ix86_split_ashr (operands, operands[3], TImode); DONE;") + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (ashiftrt:TI (match_operand:TI 1 "register_operand" "") + (match_operand:QI 2 "immediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] + "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;") + +(define_insn "x86_64_shrd" + [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m") + (ior:DI (ashiftrt:DI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand" "J,c")) + (ashift:DI (match_operand:DI 1 "register_operand" "r,r") + (minus:QI (const_int 64) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "@ + shrd{q}\t{%2, %1, %0|%0, %1, %2} + shrd{q}\t{%s2%1, %0|%0, %1, %2}" + [(set_attr "type" "ishift") + (set_attr "prefix_0f" "1") + (set_attr "mode" "DI") + (set_attr "athlon_decode" "vector")]) + +(define_expand "ashrdi3" + [(set (match_operand:DI 0 "shiftdi_operand" "") + (ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;") + +(define_insn "*ashrdi3_63_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm") (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0") (match_operand:DI 2 "const_int_operand" "i,i"))) - (clobber (reg:CC 17))] - "TARGET_64BIT && INTVAL (operands[2]) == 63 && (TARGET_USE_CLTD || optimize_size) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && INTVAL (operands[2]) == 63 + && (TARGET_USE_CLTD || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "@ {cqto|cqo} @@ -11402,7 +11308,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) && (TARGET_SHIFT1 || optimize_size)" "sar{q}\t%0" @@ -11416,7 +11322,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "J,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "@ sar{q}\t{%2, %0|%0, %2} @@ -11428,7 +11334,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrdi3_one_bit_cmp_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -11445,11 +11351,25 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrdi3_one_bit_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" + "sar{q}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrdi3_cmp_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const_int_operand" "n")) @@ -11457,49 +11377,60 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashiftrt:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{q}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "DI")]) +(define_insn "*ashrdi3_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_int_operand" "n")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{q}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "DI")]) -(define_insn "ashrdi3_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Jc"))) - (clobber (match_scratch:SI 3 "=&r")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_CMOVE" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*ashrdi3_2" +(define_insn "*ashrdi3_1" [(set (match_operand:DI 0 "register_operand" "=r") (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "nonmemory_operand" "Jc"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" "#" [(set_attr "type" "multi")]) -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_CMOVE && reload_completed" +;; By default we don't ask for a scratch register, because when DImode +;; values are manipulated, registers are already at a premium. But if +;; we have one handy, we won't turn it away. +(define_peephole2 + [(match_scratch:SI 3 "r") + (parallel [(set (match_operand:DI 0 "register_operand" "") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (clobber (reg:CC FLAGS_REG))]) + (match_dup 3)] + "!TARGET_64BIT && TARGET_CMOVE" [(const_int 0)] - "ix86_split_ashrdi (operands, operands[3]); DONE;") + "ix86_split_ashr (operands, operands[3], DImode); DONE;") (define_split [(set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && reload_completed" + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) + ? flow2_completed : reload_completed)" [(const_int 0)] - "ix86_split_ashrdi (operands, NULL_RTX); DONE;") + "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;") (define_insn "x86_shrd_1" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m") @@ -11507,7 +11438,7 @@ (match_operand:QI 2 "nonmemory_operand" "I,c")) (ashift:SI (match_operand:SI 1 "register_operand" "r,r") (minus:QI (const_int 32) (match_dup 2))))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "@ shrd{l}\t{%2, %1, %0|%0, %1, %2} @@ -11515,7 +11446,6 @@ [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "pent_pair" "np") - (set_attr "ppro_uops" "few") (set_attr "mode" "SI")]) (define_expand "x86_shift_adj_3" @@ -11550,7 +11480,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm") (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0") (match_operand:SI 2 "const_int_operand" "i,i"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "@ @@ -11566,7 +11496,7 @@ [(set (match_operand:DI 0 "register_operand" "=*d,r") (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0") (match_operand:SI 2 "const_int_operand" "i,i")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && (TARGET_USE_CLTD || optimize_size) && INTVAL (operands[2]) == 31 && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" @@ -11583,7 +11513,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;") @@ -11591,7 +11521,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" "sar{l}\t%0" @@ -11605,7 +11535,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:QI 2 "const1_operand" "")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" "sar{l}\t%k0" @@ -11616,7 +11546,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "@ sar{l}\t{%2, %0|%0, %2} @@ -11628,7 +11558,7 @@ [(set (match_operand:DI 0 "register_operand" "=r,r") (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "@ sar{l}\t{%2, %k0|%k0, %2} @@ -11640,7 +11570,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrsi3_one_bit_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -11657,8 +11587,22 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrsi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" + "sar{l}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + (define_insn "*ashrsi3_one_bit_cmp_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -11676,29 +11620,48 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrsi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashiftrt:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{l}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "SI")]) + +(define_insn "*ashrsi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{l}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) (define_insn "*ashrsi3_cmp_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) @@ -11707,7 +11670,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;") @@ -11715,7 +11678,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "sar{w}\t%0" @@ -11729,7 +11692,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" "@ sar{w}\t{%2, %0|%0, %2} @@ -11741,7 +11704,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrhi3_one_bit_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -11758,19 +11721,50 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrhi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" + "sar{w}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrhi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashiftrt:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{w}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "HI")]) + +(define_insn "*ashrhi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{w}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "HI")]) @@ -11779,7 +11773,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;") @@ -11787,7 +11781,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" "sar{b}\t%0" @@ -11801,7 +11795,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (ashiftrt:QI (match_dup 0) (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, QImode, operands) && (! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" @@ -11816,7 +11810,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" "@ sar{b}\t{%2, %0|%0, %2} @@ -11828,7 +11822,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) (ashiftrt:QI (match_dup 0) (match_operand:QI 1 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ @@ -11841,7 +11835,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrqi3_one_bit_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "I")) @@ -11858,48 +11852,125 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrqi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" + "sar{b}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*ashrqi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashiftrt:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{b}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "QI")]) + +(define_insn "*ashrqi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{b}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "QI")]) + ;; Logical shift instructions ;; See comment above `ashldi3' about how this works. -(define_expand "lshrdi3" - [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "") - (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "") +(define_expand "lshrti3" + [(parallel [(set (match_operand:TI 0 "register_operand" "") + (lshiftrt:TI (match_operand:TI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))])] - "" + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT" { - if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode)) + if (! immediate_operand (operands[2], QImode)) { - emit_insn (gen_lshrdi3_1 (operands[0], operands[1], operands[2])); + emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2])); DONE; } - ix86_expand_binary_operator (LSHIFTRT, DImode, operands); + ix86_expand_binary_operator (LSHIFTRT, TImode, operands); DONE; }) +(define_insn "lshrti3_1" + [(set (match_operand:TI 0 "register_operand" "=r") + (lshiftrt:TI (match_operand:TI 1 "register_operand" "0") + (match_operand:QI 2 "register_operand" "c"))) + (clobber (match_scratch:DI 3 "=&r")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "#" + [(set_attr "type" "multi")]) + +(define_insn "*lshrti3_2" + [(set (match_operand:TI 0 "register_operand" "=r") + (lshiftrt:TI (match_operand:TI 1 "register_operand" "0") + (match_operand:QI 2 "immediate_operand" "O"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "#" + [(set_attr "type" "multi")]) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (lshiftrt:TI (match_operand:TI 1 "register_operand" "") + (match_operand:QI 2 "register_operand" ""))) + (clobber (match_scratch:DI 3 "")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] + "ix86_split_lshr (operands, operands[3], TImode); DONE;") + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (lshiftrt:TI (match_operand:TI 1 "register_operand" "") + (match_operand:QI 2 "immediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed" + [(const_int 0)] + "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;") + +(define_expand "lshrdi3" + [(set (match_operand:DI 0 "shiftdi_operand" "") + (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;") + (define_insn "*lshrdi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "shr{q}\t%0" @@ -11913,7 +11984,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "J,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "@ shr{q}\t{%2, %0|%0, %2} @@ -11925,7 +11996,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrdi3_cmp_one_bit_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -11942,11 +12013,25 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrdi3_cconly_one_bit_rex64" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "shr{q}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrdi3_cmp_rex64" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const_int_operand" "e")) @@ -11954,54 +12039,66 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (lshiftrt:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{q}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "DI")]) -(define_insn "lshrdi3_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "Jc"))) - (clobber (match_scratch:SI 3 "=&r")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_CMOVE" - "#" - [(set_attr "type" "multi")]) +(define_insn "*lshrdi3_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_int_operand" "e")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{q}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "DI")]) -(define_insn "*lshrdi3_2" +(define_insn "*lshrdi3_1" [(set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "nonmemory_operand" "Jc"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" "#" [(set_attr "type" "multi")]) -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_CMOVE && reload_completed" +;; By default we don't ask for a scratch register, because when DImode +;; values are manipulated, registers are already at a premium. But if +;; we have one handy, we won't turn it away. +(define_peephole2 + [(match_scratch:SI 3 "r") + (parallel [(set (match_operand:DI 0 "register_operand" "") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (clobber (reg:CC FLAGS_REG))]) + (match_dup 3)] + "!TARGET_64BIT && TARGET_CMOVE" [(const_int 0)] - "ix86_split_lshrdi (operands, operands[3]); DONE;") + "ix86_split_lshr (operands, operands[3], DImode); DONE;") (define_split [(set (match_operand:DI 0 "register_operand" "") (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] - "!TARGET_64BIT && reload_completed" + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) + ? flow2_completed : reload_completed)" [(const_int 0)] - "ix86_split_lshrdi (operands, NULL_RTX); DONE;") + "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;") (define_expand "lshrsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "") (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;") @@ -12009,7 +12106,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "shr{l}\t%0" @@ -12023,7 +12120,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0")) (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "shr{l}\t%k0" @@ -12034,7 +12131,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "@ shr{l}\t{%2, %0|%0, %2} @@ -12047,7 +12144,7 @@ (zero_extend:DI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "@ shr{l}\t{%2, %k0|%k0, %2} @@ -12059,7 +12156,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrsi3_one_bit_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -12076,8 +12173,22 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrsi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "shr{l}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + (define_insn "*lshrsi3_cmp_one_bit_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -12095,29 +12206,48 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrsi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (lshiftrt:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{l}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "SI")]) + +(define_insn "*lshrsi3_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{l}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) (define_insn "*lshrsi3_cmp_zext" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) @@ -12126,7 +12256,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;") @@ -12134,7 +12264,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "shr{w}\t%0" @@ -12148,7 +12278,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "@ shr{w}\t{%2, %0|%0, %2} @@ -12160,7 +12290,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrhi3_one_bit_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -12177,19 +12307,50 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrhi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "shr{w}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrhi3_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (lshiftrt:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{w}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "HI")]) + +(define_insn "*lshrhi3_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{w}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "HI")]) @@ -12198,7 +12359,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;") @@ -12206,7 +12367,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (LSHIFTRT, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" "shr{b}\t%0" @@ -12220,7 +12381,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (lshiftrt:QI (match_dup 0) (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" "shr{b}\t%0" @@ -12234,7 +12395,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" "@ shr{b}\t{%2, %0|%0, %2} @@ -12246,7 +12407,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) (lshiftrt:QI (match_dup 0) (match_operand:QI 1 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ @@ -12259,7 +12420,7 @@ ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrqi2_one_bit_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" "")) @@ -12276,19 +12437,50 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrqi2_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" + "shr{b}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. (define_insn "*lshrqi2_cmp" - [(set (reg 17) + [(set (reg FLAGS_REG) (compare (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_31_operand" "I")) + (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (lshiftrt:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{b}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "QI")]) + +(define_insn "*lshrqi2_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{b}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "QI")]) @@ -12296,18 +12488,54 @@ ;; Rotate instructions (define_expand "rotldi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "") + [(set (match_operand:DI 0 "shiftdi_operand" "") + (rotate:DI (match_operand:DI 1 "shiftdi_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_64BIT" - "ix86_expand_binary_operator (ROTATE, DImode, operands); DONE;") + (clobber (reg:CC FLAGS_REG))] + "" +{ + if (TARGET_64BIT) + { + ix86_expand_binary_operator (ROTATE, DImode, operands); + DONE; + } + if (!const_1_to_31_operand (operands[2], VOIDmode)) + FAIL; + emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2])); + DONE; +}) +;; Implement rotation using two double-precision shift instructions +;; and a scratch register. +(define_insn_and_split "ix86_rotldi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (rotate:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I"))) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_scratch:SI 3 "=&r"))] + "!TARGET_64BIT" + "" + "&& reload_completed" + [(set (match_dup 3) (match_dup 4)) + (parallel + [(set (match_dup 4) + (ior:SI (ashift:SI (match_dup 4) (match_dup 2)) + (lshiftrt:SI (match_dup 5) + (minus:QI (const_int 32) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 5) + (ior:SI (ashift:SI (match_dup 5) (match_dup 2)) + (lshiftrt:SI (match_dup 3) + (minus:QI (const_int 32) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))])] + "split_di (operands, 1, operands + 4, operands + 5);") + (define_insn "*rotlsi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands) && (TARGET_SHIFT1 || optimize_size)" "rol{q}\t%0" @@ -12321,7 +12549,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "e,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)" "@ rol{q}\t{%2, %0|%0, %2} @@ -12333,7 +12561,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;") @@ -12341,7 +12569,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATE, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" "rol{l}\t%0" @@ -12356,7 +12584,7 @@ (zero_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "0") (match_operand:QI 2 "const1_operand" "")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" "rol{l}\t%k0" @@ -12367,7 +12595,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATE, SImode, operands)" "@ rol{l}\t{%2, %0|%0, %2} @@ -12380,7 +12608,7 @@ (zero_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)" "@ rol{l}\t{%2, %k0|%k0, %2} @@ -12392,7 +12620,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;") @@ -12400,7 +12628,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATE, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "rol{w}\t%0" @@ -12414,7 +12642,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATE, HImode, operands)" "@ rol{w}\t{%2, %0|%0, %2} @@ -12426,7 +12654,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;") @@ -12434,7 +12662,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (rotate:QI (match_dup 0) (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" "rol{b}\t%0" @@ -12448,7 +12676,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATE, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" "rol{b}\t%0" @@ -12462,7 +12690,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) (rotate:QI (match_dup 0) (match_operand:QI 1 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ @@ -12475,7 +12703,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATE, QImode, operands)" "@ rol{b}\t{%2, %0|%0, %2} @@ -12484,18 +12712,54 @@ (set_attr "mode" "QI")]) (define_expand "rotrdi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_64BIT" - "ix86_expand_binary_operator (ROTATERT, DImode, operands); DONE;") + [(set (match_operand:DI 0 "shiftdi_operand" "") + (rotate:DI (match_operand:DI 1 "shiftdi_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "" +{ + if (TARGET_64BIT) + { + ix86_expand_binary_operator (ROTATERT, DImode, operands); + DONE; + } + if (!const_1_to_31_operand (operands[2], VOIDmode)) + FAIL; + emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2])); + DONE; +}) + +;; Implement rotation using two double-precision shift instructions +;; and a scratch register. +(define_insn_and_split "ix86_rotrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (rotatert:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I"))) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_scratch:SI 3 "=&r"))] + "!TARGET_64BIT" + "" + "&& reload_completed" + [(set (match_dup 3) (match_dup 4)) + (parallel + [(set (match_dup 4) + (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2)) + (ashift:SI (match_dup 5) + (minus:QI (const_int 32) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 5) + (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2)) + (ashift:SI (match_dup 3) + (minus:QI (const_int 32) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))])] + "split_di (operands, 1, operands + 4, operands + 5);") (define_insn "*rotrdi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands) && (TARGET_SHIFT1 || optimize_size)" "ror{q}\t%0" @@ -12509,7 +12773,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm") (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "J,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)" "@ ror{q}\t{%2, %0|%0, %2} @@ -12521,7 +12785,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;") @@ -12529,7 +12793,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATERT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" "ror{l}\t%0" @@ -12544,7 +12808,7 @@ (zero_extend:DI (rotatert:SI (match_operand:SI 1 "register_operand" "0") (match_operand:QI 2 "const1_operand" "")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" "ror{l}\t%k0" @@ -12558,7 +12822,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATERT, SImode, operands)" "@ ror{l}\t{%2, %0|%0, %2} @@ -12571,7 +12835,7 @@ (zero_extend:DI (rotatert:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)" "@ ror{l}\t{%2, %k0|%k0, %2} @@ -12583,7 +12847,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "") (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;") @@ -12591,7 +12855,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATERT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" "ror{w}\t%0" @@ -12605,7 +12869,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm") (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATERT, HImode, operands)" "@ ror{w}\t{%2, %0|%0, %2} @@ -12617,7 +12881,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "") (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "") (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;") @@ -12625,7 +12889,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATERT, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" "ror{b}\t%0" @@ -12639,7 +12903,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (rotatert:QI (match_dup 0) (match_operand:QI 1 "const1_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" "ror{b}\t%0" @@ -12653,7 +12917,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (ROTATERT, QImode, operands)" "@ ror{b}\t{%2, %0|%0, %2} @@ -12665,7 +12929,7 @@ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm")) (rotatert:QI (match_dup 0) (match_operand:QI 1 "nonmemory_operand" "I,c"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ @@ -12679,8 +12943,8 @@ (define_expand "extv" [(set (match_operand:SI 0 "register_operand" "") (sign_extract:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + (match_operand:SI 2 "const8_operand" "") + (match_operand:SI 3 "const8_operand" "")))] "" { /* Handle extractions from %ah et al. */ @@ -12689,15 +12953,15 @@ /* From mips.md: extract_bit_field doesn't verify that our source matches the predicate, so check it again here. */ - if (! register_operand (operands[1], VOIDmode)) + if (! ext_register_operand (operands[1], VOIDmode)) FAIL; }) (define_expand "extzv" [(set (match_operand:SI 0 "register_operand" "") (zero_extract:SI (match_operand 1 "ext_register_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + (match_operand:SI 2 "const8_operand" "") + (match_operand:SI 3 "const8_operand" "")))] "" { /* Handle extractions from %ah et al. */ @@ -12706,24 +12970,24 @@ /* From mips.md: extract_bit_field doesn't verify that our source matches the predicate, so check it again here. */ - if (! register_operand (operands[1], VOIDmode)) + if (! ext_register_operand (operands[1], VOIDmode)) FAIL; }) (define_expand "insv" [(set (zero_extract (match_operand 0 "ext_register_operand" "") - (match_operand 1 "immediate_operand" "") - (match_operand 2 "immediate_operand" "")) + (match_operand 1 "const8_operand" "") + (match_operand 2 "const8_operand" "")) (match_operand 3 "register_operand" ""))] "" { - /* Handle extractions from %ah et al. */ + /* Handle insertions to %ah et al. */ if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8) FAIL; /* From mips.md: insert_bit_field doesn't verify that our source matches the predicate, so check it again here. */ - if (! register_operand (operands[0], VOIDmode)) + if (! ext_register_operand (operands[0], VOIDmode)) FAIL; if (TARGET_64BIT) @@ -12735,6 +12999,146 @@ }) ;; %%% bts, btr, btc, bt. +;; In general these instructions are *slow* when applied to memory, +;; since they enforce atomic operation. When applied to registers, +;; it depends on the cpu implementation. They're never faster than +;; the corresponding and/ior/xor operations, so with 32-bit there's +;; no point. But in 64-bit, we can't hold the relevant immediates +;; within the instruction itself, so operating on bits in the high +;; 32-bits of a register becomes easier. +;; +;; These are slow on Nocona, but fast on Athlon64. We do require the use +;; of btrq and btcq for corner cases of post-reload expansion of absdf and +;; negdf respectively, so they can never be disabled entirely. + +(define_insn "*btsq" + [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") + (const_int 1) + (match_operand:DI 1 "const_0_to_63_operand" "")) + (const_int 1)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" + "bts{q} %1,%0" + [(set_attr "type" "alu1")]) + +(define_insn "*btrq" + [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") + (const_int 1) + (match_operand:DI 1 "const_0_to_63_operand" "")) + (const_int 0)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" + "btr{q} %1,%0" + [(set_attr "type" "alu1")]) + +(define_insn "*btcq" + [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") + (const_int 1) + (match_operand:DI 1 "const_0_to_63_operand" "")) + (not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1)))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && (TARGET_USE_BT || reload_completed)" + "btc{q} %1,%0" + [(set_attr "type" "alu1")]) + +;; Allow Nocona to avoid these instructions if a register is available. + +(define_peephole2 + [(match_scratch:DI 2 "r") + (parallel [(set (zero_extract:DI + (match_operand:DI 0 "register_operand" "") + (const_int 1) + (match_operand:DI 1 "const_0_to_63_operand" "")) + (const_int 1)) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT && !TARGET_USE_BT" + [(const_int 0)] +{ + HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo; + rtx op1; + + if (HOST_BITS_PER_WIDE_INT >= 64) + lo = (HOST_WIDE_INT)1 << i, hi = 0; + else if (i < HOST_BITS_PER_WIDE_INT) + lo = (HOST_WIDE_INT)1 << i, hi = 0; + else + lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT); + + op1 = immed_double_const (lo, hi, DImode); + if (i >= 31) + { + emit_move_insn (operands[2], op1); + op1 = operands[2]; + } + + emit_insn (gen_iordi3 (operands[0], operands[0], op1)); + DONE; +}) + +(define_peephole2 + [(match_scratch:DI 2 "r") + (parallel [(set (zero_extract:DI + (match_operand:DI 0 "register_operand" "") + (const_int 1) + (match_operand:DI 1 "const_0_to_63_operand" "")) + (const_int 0)) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT && !TARGET_USE_BT" + [(const_int 0)] +{ + HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo; + rtx op1; + + if (HOST_BITS_PER_WIDE_INT >= 64) + lo = (HOST_WIDE_INT)1 << i, hi = 0; + else if (i < HOST_BITS_PER_WIDE_INT) + lo = (HOST_WIDE_INT)1 << i, hi = 0; + else + lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT); + + op1 = immed_double_const (~lo, ~hi, DImode); + if (i >= 32) + { + emit_move_insn (operands[2], op1); + op1 = operands[2]; + } + + emit_insn (gen_anddi3 (operands[0], operands[0], op1)); + DONE; +}) + +(define_peephole2 + [(match_scratch:DI 2 "r") + (parallel [(set (zero_extract:DI + (match_operand:DI 0 "register_operand" "") + (const_int 1) + (match_operand:DI 1 "const_0_to_63_operand" "")) + (not:DI (zero_extract:DI + (match_dup 0) (const_int 1) (match_dup 1)))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT && !TARGET_USE_BT" + [(const_int 0)] +{ + HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo; + rtx op1; + + if (HOST_BITS_PER_WIDE_INT >= 64) + lo = (HOST_WIDE_INT)1 << i, hi = 0; + else if (i < HOST_BITS_PER_WIDE_INT) + lo = (HOST_WIDE_INT)1 << i, hi = 0; + else + lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT); + + op1 = immed_double_const (lo, hi, DImode); + if (i >= 31) + { + emit_move_insn (operands[2], op1); + op1 = operands[2]; + } + + emit_insn (gen_xordi3 (operands[0], operands[0], op1)); + DONE; +}) ;; Store-flag instructions. @@ -12747,125 +13151,125 @@ (define_expand "seq" [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (reg:CC 17) (const_int 0)))] + (eq:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;") (define_expand "sne" [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (reg:CC 17) (const_int 0)))] + (ne:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;") (define_expand "sgt" [(set (match_operand:QI 0 "register_operand" "") - (gt:QI (reg:CC 17) (const_int 0)))] + (gt:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;") (define_expand "sgtu" [(set (match_operand:QI 0 "register_operand" "") - (gtu:QI (reg:CC 17) (const_int 0)))] + (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;") (define_expand "slt" [(set (match_operand:QI 0 "register_operand" "") - (lt:QI (reg:CC 17) (const_int 0)))] + (lt:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;") (define_expand "sltu" [(set (match_operand:QI 0 "register_operand" "") - (ltu:QI (reg:CC 17) (const_int 0)))] + (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;") (define_expand "sge" [(set (match_operand:QI 0 "register_operand" "") - (ge:QI (reg:CC 17) (const_int 0)))] + (ge:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;") (define_expand "sgeu" [(set (match_operand:QI 0 "register_operand" "") - (geu:QI (reg:CC 17) (const_int 0)))] + (geu:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;") (define_expand "sle" [(set (match_operand:QI 0 "register_operand" "") - (le:QI (reg:CC 17) (const_int 0)))] + (le:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;") (define_expand "sleu" [(set (match_operand:QI 0 "register_operand" "") - (leu:QI (reg:CC 17) (const_int 0)))] + (leu:QI (reg:CC FLAGS_REG) (const_int 0)))] "" "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;") (define_expand "sunordered" [(set (match_operand:QI 0 "register_operand" "") - (unordered:QI (reg:CC 17) (const_int 0)))] + (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;") (define_expand "sordered" [(set (match_operand:QI 0 "register_operand" "") - (ordered:QI (reg:CC 17) (const_int 0)))] + (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387" "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;") (define_expand "suneq" [(set (match_operand:QI 0 "register_operand" "") - (uneq:QI (reg:CC 17) (const_int 0)))] + (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;") (define_expand "sunge" [(set (match_operand:QI 0 "register_operand" "") - (unge:QI (reg:CC 17) (const_int 0)))] + (unge:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;") (define_expand "sungt" [(set (match_operand:QI 0 "register_operand" "") - (ungt:QI (reg:CC 17) (const_int 0)))] + (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;") (define_expand "sunle" [(set (match_operand:QI 0 "register_operand" "") - (unle:QI (reg:CC 17) (const_int 0)))] + (unle:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;") (define_expand "sunlt" [(set (match_operand:QI 0 "register_operand" "") - (unlt:QI (reg:CC 17) (const_int 0)))] + (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;") (define_expand "sltgt" [(set (match_operand:QI 0 "register_operand" "") - (ltgt:QI (reg:CC 17) (const_int 0)))] + (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))] "TARGET_80387 || TARGET_SSE" "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;") (define_insn "*setcc_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (match_operator:QI 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]))] + [(reg FLAGS_REG) (const_int 0)]))] "" "set%C1\t%0" [(set_attr "type" "setcc") (set_attr "mode" "QI")]) -(define_insn "setcc_2" +(define_insn "*setcc_2" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (match_operator:QI 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]))] + [(reg FLAGS_REG) (const_int 0)]))] "" "set%C1\t%0" [(set_attr "type" "setcc") @@ -12882,7 +13286,7 @@ (define_split [(set (match_operand:QI 0 "nonimmediate_operand" "") (ne:QI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (const_int 0)))] "" [(set (match_dup 0) (match_dup 1))] @@ -12893,7 +13297,7 @@ (define_split [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "")) (ne:QI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (const_int 0)))] "" [(set (match_dup 0) (match_dup 1))] @@ -12904,7 +13308,7 @@ (define_split [(set (match_operand:QI 0 "nonimmediate_operand" "") (eq:QI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (const_int 0)))] "" [(set (match_dup 0) (match_dup 1))] @@ -12912,8 +13316,8 @@ rtx new_op1 = copy_rtx (operands[1]); operands[1] = new_op1; PUT_MODE (new_op1, QImode); - PUT_CODE (new_op1, REVERSE_CONDITION (GET_CODE (new_op1), - GET_MODE (XEXP (new_op1, 0)))); + PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1), + GET_MODE (XEXP (new_op1, 0)))); /* Make sure that (a) the CCmode we have for the flags is strong enough for the reversed compare or (b) we have a valid FP compare. */ @@ -12924,7 +13328,7 @@ (define_split [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "")) (eq:QI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (const_int 0)))] "" [(set (match_dup 0) (match_dup 1))] @@ -12932,8 +13336,8 @@ rtx new_op1 = copy_rtx (operands[1]); operands[1] = new_op1; PUT_MODE (new_op1, QImode); - PUT_CODE (new_op1, REVERSE_CONDITION (GET_CODE (new_op1), - GET_MODE (XEXP (new_op1, 0)))); + PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1), + GET_MODE (XEXP (new_op1, 0)))); /* Make sure that (a) the CCmode we have for the flags is strong enough for the reversed compare or (b) we have a valid FP compare. */ @@ -12944,17 +13348,14 @@ ;; The SSE store flag instructions saves 0 or 0xffffffff to the result. ;; subsequent logical operations are used to imitate conditional moves. ;; 0xffffffff is NaN, but not in normalized form, so we can't represent -;; it directly. Further holding this value in pseudo register might bring -;; problem in implicit normalization in spill code. -;; So we don't define FLOAT_STORE_FLAG_VALUE and create these -;; instructions after reload by splitting the conditional move patterns. +;; it directly. (define_insn "*sse_setccsf" [(set (match_operand:SF 0 "register_operand" "=x") (match_operator:SF 1 "sse_comparison_operator" [(match_operand:SF 2 "register_operand" "0") (match_operand:SF 3 "nonimmediate_operand" "xm")]))] - "TARGET_SSE && reload_completed" + "TARGET_SSE" "cmp%D1ss\t{%3, %0|%0, %3}" [(set_attr "type" "ssecmp") (set_attr "mode" "SF")]) @@ -12964,7 +13365,7 @@ (match_operator:DF 1 "sse_comparison_operator" [(match_operand:DF 2 "register_operand" "0") (match_operand:DF 3 "nonimmediate_operand" "Ym")]))] - "TARGET_SSE2 && reload_completed" + "TARGET_SSE2" "cmp%D1sd\t{%3, %0|%0, %3}" [(set_attr "type" "ssecmp") (set_attr "mode" "DF")]) @@ -12973,7 +13374,7 @@ ;; We ignore the overflow flag for signed branch instructions. ;; For all bCOND expanders, also expand the compare or test insn that -;; generates reg 17. Generate an equality comparison if `beq' or `bne'. +;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'. (define_expand "beq" [(set (pc) @@ -13060,7 +13461,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (UNORDERED, operands[0]); DONE;") (define_expand "bordered" @@ -13068,7 +13469,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (ORDERED, operands[0]); DONE;") (define_expand "buneq" @@ -13076,7 +13477,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (UNEQ, operands[0]); DONE;") (define_expand "bunge" @@ -13084,7 +13485,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (UNGE, operands[0]); DONE;") (define_expand "bungt" @@ -13092,7 +13493,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (UNGT, operands[0]); DONE;") (define_expand "bunle" @@ -13100,7 +13501,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (UNLE, operands[0]); DONE;") (define_expand "bunlt" @@ -13108,7 +13509,7 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (UNLT, operands[0]); DONE;") (define_expand "bltgt" @@ -13116,13 +13517,13 @@ (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_80387 || TARGET_SSE" + "TARGET_80387 || TARGET_SSE_MATH" "ix86_expand_branch (LTGT, operands[0]); DONE;") (define_insn "*jcc_1" [(set (pc) (if_then_else (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "" @@ -13140,7 +13541,7 @@ (define_insn "*jcc_2" [(set (pc) (if_then_else (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "" @@ -13166,7 +13567,7 @@ (define_split [(set (pc) (if_then_else (ne (match_operator 0 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -13182,7 +13583,7 @@ (define_split [(set (pc) (if_then_else (eq (match_operator 0 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -13195,8 +13596,8 @@ rtx new_op0 = copy_rtx (operands[0]); operands[0] = new_op0; PUT_MODE (new_op0, VOIDmode); - PUT_CODE (new_op0, REVERSE_CONDITION (GET_CODE (new_op0), - GET_MODE (XEXP (new_op0, 0)))); + PUT_CODE (new_op0, ix86_reverse_condition (GET_CODE (new_op0), + GET_MODE (XEXP (new_op0, 0)))); /* Make sure that (a) the CCmode we have for the flags is strong enough for the reversed compare or (b) we have a valid FP compare. */ @@ -13208,18 +13609,17 @@ ;; during early optimization. Splitting the operation apart early makes ;; for bad code when we want to reverse the operation. -(define_insn "*fp_jcc_1" +(define_insn "*fp_jcc_1_mixed" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")]) + [(match_operand 1 "register_operand" "f,x") + (match_operand 2 "nonimmediate_operand" "f,xm")]) (label_ref (match_operand 3 "" "")) (pc))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] - "TARGET_CMOVE && TARGET_80387 - && !SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && FLOAT_MODE_P (GET_MODE (operands[1])) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] + "TARGET_MIX_SSE_I387 + && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") @@ -13227,44 +13627,44 @@ (define_insn "*fp_jcc_1_sse" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f#x,x#f") - (match_operand 2 "nonimmediate_operand" "f#x,xm#f")]) + [(match_operand 1 "register_operand" "x") + (match_operand 2 "nonimmediate_operand" "xm")]) (label_ref (match_operand 3 "" "")) (pc))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] - "TARGET_80387 + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] + "TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_1_sse_only" +(define_insn "*fp_jcc_1_387" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "x") - (match_operand 2 "nonimmediate_operand" "xm")]) + [(match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f")]) (label_ref (match_operand 3 "" "")) (pc))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] - "SSE_FLOAT_MODE_P (GET_MODE (operands[1])) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] + "TARGET_CMOVE && TARGET_80387 + && FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_2" +(define_insn "*fp_jcc_2_mixed" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")]) + [(match_operand 1 "register_operand" "f,x") + (match_operand 2 "nonimmediate_operand" "f,xm")]) (pc) (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] - "TARGET_CMOVE && TARGET_80387 - && !SSE_FLOAT_MODE_P (GET_MODE (operands[1])) - && FLOAT_MODE_P (GET_MODE (operands[1])) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] + "TARGET_MIX_SSE_I387 + && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") @@ -13272,41 +13672,42 @@ (define_insn "*fp_jcc_2_sse" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f#x,x#f") - (match_operand 2 "nonimmediate_operand" "f#x,xm#f")]) + [(match_operand 1 "register_operand" "x") + (match_operand 2 "nonimmediate_operand" "xm")]) (pc) (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] - "TARGET_80387 + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] + "TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_2_sse_only" +(define_insn "*fp_jcc_2_387" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "x") - (match_operand 2 "nonimmediate_operand" "xm")]) + [(match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f")]) (pc) (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] - "SSE_FLOAT_MODE_P (GET_MODE (operands[1])) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] + "TARGET_CMOVE && TARGET_80387 + && FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_3" +(define_insn "*fp_jcc_3_387" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "nonimmediate_operand" "fm")]) (label_ref (match_operand 3 "" "")) (pc))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17)) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 4 "=a"))] "TARGET_80387 && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) @@ -13317,15 +13718,15 @@ && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_4" +(define_insn "*fp_jcc_4_387" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "nonimmediate_operand" "fm")]) (pc) (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17)) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 4 "=a"))] "TARGET_80387 && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode) @@ -13336,15 +13737,15 @@ && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_5" +(define_insn "*fp_jcc_5_387" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "register_operand" "f")]) (label_ref (match_operand 3 "" "")) (pc))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17)) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 4 "=a"))] "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) @@ -13352,22 +13753,65 @@ && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") -(define_insn "*fp_jcc_6" +(define_insn "*fp_jcc_6_387" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand 1 "register_operand" "f") (match_operand 2 "register_operand" "f")]) (pc) (label_ref (match_operand 3 "" "")))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17)) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) + (clobber (match_scratch:HI 4 "=a"))] + "TARGET_80387 + && FLOAT_MODE_P (GET_MODE (operands[1])) + && GET_MODE (operands[1]) == GET_MODE (operands[2]) + && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" + "#") + +(define_insn "*fp_jcc_7_387" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand 1 "register_operand" "f") + (match_operand 2 "const0_operand" "X")]) + (label_ref (match_operand 3 "" "")) + (pc))) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 4 "=a"))] "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2]) + && !ix86_use_fcomi_compare (GET_CODE (operands[0])) + && SELECT_CC_MODE (GET_CODE (operands[0]), + operands[1], operands[2]) == CCFPmode && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" "#") +;; The order of operands in *fp_jcc_8_387 is forced by combine in +;; simplify_comparison () function. Float operator is treated as RTX_OBJ +;; with a precedence over other operators and is always put in the first +;; place. Swap condition and operands to match ficom instruction. + +(define_insn "*fp_jcc_8<mode>_387" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operator 1 "float_operator" + [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")]) + (match_operand 3 "register_operand" "f,f")]) + (label_ref (match_operand 4 "" "")) + (pc))) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) + (clobber (match_scratch:HI 5 "=a,a"))] + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP + && FLOAT_MODE_P (GET_MODE (operands[3])) + && GET_MODE (operands[1]) == GET_MODE (operands[3]) + && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0]))) + && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode + && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))" + "#") + (define_split [(set (pc) (if_then_else (match_operator 0 "comparison_operator" @@ -13375,13 +13819,13 @@ (match_operand 2 "nonimmediate_operand" "")]) (match_operand 3 "" "") (match_operand 4 "" ""))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17))] + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG))] "reload_completed" [(const_int 0)] { ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2], - operands[3], operands[4], NULL_RTX); + operands[3], operands[4], NULL_RTX, NULL_RTX); DONE; }) @@ -13389,20 +13833,61 @@ [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand 1 "register_operand" "") - (match_operand 2 "nonimmediate_operand" "")]) + (match_operand 2 "general_operand" "")]) (match_operand 3 "" "") (match_operand 4 "" ""))) - (clobber (reg:CCFP 18)) - (clobber (reg:CCFP 17)) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 5 "=a"))] "reload_completed" - [(set (pc) - (if_then_else (match_dup 6) - (match_dup 3) - (match_dup 4)))] + [(const_int 0)] { ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2], - operands[3], operands[4], operands[5]); + operands[3], operands[4], operands[5], NULL_RTX); + DONE; +}) + +(define_split + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operator 1 "float_operator" + [(match_operand:X87MODEI12 2 "memory_operand" "")]) + (match_operand 3 "register_operand" "")]) + (match_operand 4 "" "") + (match_operand 5 "" ""))) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) + (clobber (match_scratch:HI 6 "=a"))] + "reload_completed" + [(const_int 0)] +{ + operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]); + ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])), + operands[3], operands[7], + operands[4], operands[5], operands[6], NULL_RTX); + DONE; +}) + +;; %%% Kill this when reload knows how to do it. +(define_split + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operator 1 "float_operator" + [(match_operand:X87MODEI12 2 "register_operand" "")]) + (match_operand 3 "register_operand" "")]) + (match_operand 4 "" "") + (match_operand 5 "" ""))) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:CCFP FLAGS_REG)) + (clobber (match_scratch:HI 6 "=a"))] + "reload_completed" + [(const_int 0)] +{ + operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]); + operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]); + ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])), + operands[3], operands[7], + operands[4], operands[5], operands[6], operands[2]); DONE; }) @@ -13494,119 +13979,13 @@ [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) -;; Loop instruction -;; -;; This is all complicated by the fact that since this is a jump insn -;; we must handle our own reloads. - -(define_expand "doloop_end" - [(use (match_operand 0 "" "")) ; loop pseudo - (use (match_operand 1 "" "")) ; iterations; zero if unknown - (use (match_operand 2 "" "")) ; max iterations - (use (match_operand 3 "" "")) ; loop level - (use (match_operand 4 "" ""))] ; label - "!TARGET_64BIT && TARGET_USE_LOOP" - " -{ - /* Only use cloop on innermost loops. */ - if (INTVAL (operands[3]) > 1) - FAIL; - if (GET_MODE (operands[0]) != SImode) - FAIL; - emit_jump_insn (gen_doloop_end_internal (operands[4], operands[0], - operands[0])); - DONE; -}") - -(define_insn "doloop_end_internal" - [(set (pc) - (if_then_else (ne (match_operand:SI 1 "register_operand" "c,?*r,?*r") - (const_int 1)) - (label_ref (match_operand 0 "" "")) - (pc))) - (set (match_operand:SI 2 "register_operand" "=1,1,*m*r") - (plus:SI (match_dup 1) - (const_int -1))) - (clobber (match_scratch:SI 3 "=X,X,r")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_USE_LOOP" -{ - if (which_alternative != 0) - return "#"; - if (get_attr_length (insn) == 2) - return "%+loop\t%l0"; - else - return "dec{l}\t%1\;%+jne\t%l0"; -} - [(set_attr "ppro_uops" "many") - (set (attr "length") - (if_then_else (and (eq_attr "alternative" "0") - (and (ge (minus (match_dup 0) (pc)) - (const_int -126)) - (lt (minus (match_dup 0) (pc)) - (const_int 128)))) - (const_int 2) - (const_int 16))) - ;; We don't know the type before shorten branches. Optimistically expect - ;; the loop instruction to match. - (set (attr "type") (const_string "ibr"))]) - -(define_split - [(set (pc) - (if_then_else (ne (match_operand:SI 1 "register_operand" "") - (const_int 1)) - (match_operand 0 "" "") - (pc))) - (set (match_dup 1) - (plus:SI (match_dup 1) - (const_int -1))) - (clobber (match_scratch:SI 2 "")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_USE_LOOP - && reload_completed - && REGNO (operands[1]) != 2" - [(parallel [(set (reg:CCZ 17) - (compare:CCZ (plus:SI (match_dup 1) (const_int -1)) - (const_int 0))) - (set (match_dup 1) (plus:SI (match_dup 1) (const_int -1)))]) - (set (pc) (if_then_else (ne (reg:CCZ 17) (const_int 0)) - (match_dup 0) - (pc)))] - "") - -(define_split - [(set (pc) - (if_then_else (ne (match_operand:SI 1 "register_operand" "") - (const_int 1)) - (match_operand 0 "" "") - (pc))) - (set (match_operand:SI 2 "nonimmediate_operand" "") - (plus:SI (match_dup 1) - (const_int -1))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_USE_LOOP - && reload_completed - && (! REG_P (operands[2]) - || ! rtx_equal_p (operands[1], operands[2]))" - [(set (match_dup 3) (match_dup 1)) - (parallel [(set (reg:CCZ 17) - (compare:CCZ (plus:SI (match_dup 3) (const_int -1)) - (const_int 0))) - (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))]) - (set (match_dup 2) (match_dup 3)) - (set (pc) (if_then_else (ne (reg:CCZ 17) (const_int 0)) - (match_dup 0) - (pc)))] - "") - ;; Convert setcc + movzbl to xor + setcc if operands don't overlap. (define_peephole2 - [(set (reg 17) (match_operand 0 "" "")) + [(set (reg FLAGS_REG) (match_operand 0 "" "")) (set (match_operand:QI 1 "register_operand" "") (match_operator:QI 2 "ix86_comparison_operator" - [(reg 17) (const_int 0)])) + [(reg FLAGS_REG) (const_int 0)])) (set (match_operand 3 "q_regs_operand" "") (zero_extend (match_dup 1)))] "(peep2_reg_dead_p (3, operands[1]) @@ -13616,7 +13995,7 @@ (set (strict_low_part (match_dup 5)) (match_dup 2))] { - operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17); + operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); operands[5] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) @@ -13624,13 +14003,13 @@ ;; Similar, but match zero_extendhisi2_and, which adds a clobber. (define_peephole2 - [(set (reg 17) (match_operand 0 "" "")) + [(set (reg FLAGS_REG) (match_operand 0 "" "")) (set (match_operand:QI 1 "register_operand" "") (match_operator:QI 2 "ix86_comparison_operator" - [(reg 17) (const_int 0)])) + [(reg FLAGS_REG) (const_int 0)])) (parallel [(set (match_operand 3 "q_regs_operand" "") (zero_extend (match_dup 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "(peep2_reg_dead_p (3, operands[1]) || operands_match_p (operands[1], operands[3])) && ! reg_overlap_mentioned_p (operands[3], operands[0])" @@ -13638,7 +14017,7 @@ (set (strict_low_part (match_dup 5)) (match_dup 2))] { - operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17); + operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); operands[5] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) @@ -13654,8 +14033,8 @@ (define_expand "call_pop" [(parallel [(call (match_operand:QI 0 "" "") (match_operand:SI 1 "" "")) - (set (reg:SI 7) - (plus:SI (reg:SI 7) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (match_operand:SI 3 "" "")))])] "!TARGET_64BIT" { @@ -13666,7 +14045,7 @@ (define_insn "*call_pop_0" [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" "")) (match_operand:SI 1 "" "")) - (set (reg:SI 7) (plus:SI (reg:SI 7) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 2 "immediate_operand" "")))] "!TARGET_64BIT" { @@ -13680,7 +14059,7 @@ (define_insn "*call_pop_1" [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm")) (match_operand:SI 1 "" "")) - (set (reg:SI 7) (plus:SI (reg:SI 7) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 2 "immediate_operand" "i")))] "!TARGET_64BIT" { @@ -13735,7 +14114,7 @@ (match_operand 1 "" ""))] "!SIBLING_CALL_P (insn) && !TARGET_64BIT" { - if (constant_call_address_operand (operands[0], QImode)) + if (constant_call_address_operand (operands[0], Pmode)) return "call\t%P0"; return "call\t%A0"; } @@ -13746,7 +14125,7 @@ (match_operand 1 "" ""))] "SIBLING_CALL_P (insn) && !TARGET_64BIT" { - if (constant_call_address_operand (operands[0], QImode)) + if (constant_call_address_operand (operands[0], Pmode)) return "jmp\t%P0"; return "jmp\t%A0"; } @@ -13757,7 +14136,7 @@ (match_operand 1 "" ""))] "!SIBLING_CALL_P (insn) && TARGET_64BIT" { - if (constant_call_address_operand (operands[0], QImode)) + if (constant_call_address_operand (operands[0], Pmode)) return "call\t%P0"; return "call\t%A0"; } @@ -13784,8 +14163,8 @@ [(parallel [(set (match_operand 0 "" "") (call (match_operand:QI 1 "" "") (match_operand:SI 2 "" ""))) - (set (reg:SI 7) - (plus:SI (reg:SI 7) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (match_operand:SI 4 "" "")))])] "!TARGET_64BIT" { @@ -13925,8 +14304,7 @@ "nop" [(set_attr "length" "1") (set_attr "length_immediate" "0") - (set_attr "modrm" "0") - (set_attr "ppro_uops" "one")]) + (set_attr "modrm" "0")]) ;; Align to 16-byte boundary, max skip in op0. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte @@ -13941,7 +14319,7 @@ #else /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that. The align insn is used to avoid 3 jump instructions in the row to improve - branch prediction and the benefits hardly outweight the cost of extra 8 + branch prediction and the benefits hardly outweigh the cost of extra 8 nops on the average inserted by full alignment pseudo operation. */ #endif return ""; @@ -13956,12 +14334,30 @@ (define_insn "set_got" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT" + { return output_set_got (operands[0], NULL_RTX); } + [(set_attr "type" "multi") + (set_attr "length" "12")]) + +(define_insn "set_got_labelled" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(label_ref (match_operand 1 "" ""))] + UNSPEC_SET_GOT)) + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" - { return output_set_got (operands[0]); } + { return output_set_got (operands[0], operands[1]); } [(set_attr "type" "multi") (set_attr "length" "12")]) +(define_insn "set_got_rex64" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(const_int 0)] UNSPEC_SET_GOT))] + "TARGET_64BIT" + "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0" + [(set_attr "type" "lea") + (set_attr "length" "6")]) + (define_expand "epilogue" [(const_int 1)] "" @@ -13987,16 +14383,17 @@ emit_move_insn (tmp, ra); if (Pmode == SImode) - emit_insn (gen_eh_return_si (sa)); + emit_jump_insn (gen_eh_return_si (sa)); else - emit_insn (gen_eh_return_di (sa)); + emit_jump_insn (gen_eh_return_di (sa)); emit_barrier (); DONE; }) (define_insn_and_split "eh_return_si" - [(unspec_volatile [(match_operand:SI 0 "register_operand" "c")] - UNSPECV_EH_RETURN)] + [(set (pc) + (unspec [(match_operand:SI 0 "register_operand" "c")] + UNSPEC_EH_RETURN))] "!TARGET_64BIT" "#" "reload_completed" @@ -14004,8 +14401,9 @@ "ix86_expand_epilogue (2); DONE;") (define_insn_and_split "eh_return_di" - [(unspec_volatile [(match_operand:DI 0 "register_operand" "c")] - UNSPECV_EH_RETURN)] + [(set (pc) + (unspec [(match_operand:DI 0 "register_operand" "c")] + UNSPEC_EH_RETURN))] "TARGET_64BIT" "#" "reload_completed" @@ -14013,16 +14411,16 @@ "ix86_expand_epilogue (2); DONE;") (define_insn "leave" - [(set (reg:SI 7) (plus:SI (reg:SI 6) (const_int 4))) - (set (reg:SI 6) (mem:SI (reg:SI 6))) + [(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4))) + (set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG))) (clobber (mem:BLK (scratch)))] "!TARGET_64BIT" "leave" [(set_attr "type" "leave")]) (define_insn "leave_rex64" - [(set (reg:DI 7) (plus:DI (reg:DI 6) (const_int 8))) - (set (reg:DI 6) (mem:DI (reg:DI 6))) + [(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8))) + (set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG))) (clobber (mem:BLK (scratch)))] "TARGET_64BIT" "leave" @@ -14033,7 +14431,7 @@ [(set (match_operand:SI 0 "register_operand" "") (ffs:SI (match_operand:SI 1 "nonimmediate_operand" ""))) (clobber (match_scratch:SI 2 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -14041,73 +14439,118 @@ [(set (match_operand:SI 0 "register_operand" "=r") (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) (clobber (match_scratch:SI 2 "=&r")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_CMOVE" "#" "&& reload_completed" [(set (match_dup 2) (const_int -1)) - (parallel [(set (reg:CCZ 17) (compare:CCZ (match_dup 1) (const_int 0))) + (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0))) (set (match_dup 0) (ctz:SI (match_dup 1)))]) (set (match_dup 0) (if_then_else:SI - (eq (reg:CCZ 17) (const_int 0)) + (eq (reg:CCZ FLAGS_REG) (const_int 0)) (match_dup 2) (match_dup 0))) (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_insn_and_split "*ffs_no_cmove" [(set (match_operand:SI 0 "nonimmediate_operand" "=r") (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) (clobber (match_scratch:SI 2 "=&q")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "#" "reload_completed" - [(parallel [(set (reg:CCZ 17) (compare:CCZ (match_dup 1) (const_int 0))) + [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0))) (set (match_dup 0) (ctz:SI (match_dup 1)))]) (set (strict_low_part (match_dup 3)) - (eq:QI (reg:CCZ 17) (const_int 0))) + (eq:QI (reg:CCZ FLAGS_REG) (const_int 0))) (parallel [(set (match_dup 2) (neg:SI (match_dup 2))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] { operands[3] = gen_lowpart (QImode, operands[2]); ix86_expand_clear (operands[2]); }) (define_insn "*ffssi_1" - [(set (reg:CCZ 17) + [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm") (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (ctz:SI (match_dup 1)))] "" "bsf{l}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1") - (set_attr "ppro_uops" "few")]) + [(set_attr "prefix_0f" "1")]) + +(define_expand "ffsdi2" + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (ffs:DI (match_operand:DI 1 "nonimmediate_operand" ""))) + (clobber (match_scratch:DI 2 "")) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT && TARGET_CMOVE" + "") + +(define_insn_and_split "*ffs_rex64" + [(set (match_operand:DI 0 "register_operand" "=r") + (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))) + (clobber (match_scratch:DI 2 "=&r")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_CMOVE" + "#" + "&& reload_completed" + [(set (match_dup 2) (const_int -1)) + (parallel [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (match_dup 1) (const_int 0))) + (set (match_dup 0) (ctz:DI (match_dup 1)))]) + (set (match_dup 0) (if_then_else:DI + (eq (reg:CCZ FLAGS_REG) (const_int 0)) + (match_dup 2) + (match_dup 0))) + (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1))) + (clobber (reg:CC FLAGS_REG))])] + "") + +(define_insn "*ffsdi_1" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm") + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (ctz:DI (match_dup 1)))] + "TARGET_64BIT" + "bsf{q}\t{%1, %0|%0, %1}" + [(set_attr "prefix_0f" "1")]) (define_insn "ctzsi2" [(set (match_operand:SI 0 "register_operand" "=r") (ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "bsf{l}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1") - (set_attr "ppro_uops" "few")]) + [(set_attr "prefix_0f" "1")]) + +(define_insn "ctzdi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "bsf{q}\t{%1, %0|%0, %1}" + [(set_attr "prefix_0f" "1")]) (define_expand "clzsi2" [(parallel [(set (match_operand:SI 0 "register_operand" "") (minus:SI (const_int 31) (clz:SI (match_operand:SI 1 "nonimmediate_operand" "")))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -14115,11 +14558,31 @@ [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (const_int 31) (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "bsr{l}\t{%1, %0|%0, %1}" - [(set_attr "prefix_0f" "1") - (set_attr "ppro_uops" "few")]) + [(set_attr "prefix_0f" "1")]) + +(define_expand "clzdi2" + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (minus:DI (const_int 63) + (clz:DI (match_operand:DI 1 "nonimmediate_operand" "")))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT" + "") + +(define_insn "*bsr_rex64" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (const_int 63) + (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "bsr{q}\t{%1, %0|%0, %1}" + [(set_attr "prefix_0f" "1")]) ;; Thread-local storage patterns for ELF. ;; @@ -14134,7 +14597,7 @@ UNSPEC_TLS_GD)) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3" [(set_attr "type" "multi") @@ -14148,7 +14611,7 @@ UNSPEC_TLS_GD)) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_SUN_TLS" "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]} push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop" @@ -14164,7 +14627,7 @@ UNSPEC_TLS_GD)) (clobber (match_scratch:SI 4 "")) (clobber (match_scratch:SI 5 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" { if (flag_pic) @@ -14174,13 +14637,19 @@ operands[2] = gen_reg_rtx (Pmode); emit_insn (gen_set_got (operands[2])); } + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_32 + (operands[0], operands[1], operands[2])); + DONE; + } operands[3] = ix86_tls_get_addr (); }) (define_insn "*tls_global_dynamic_64" [(set (match_operand:DI 0 "register_operand" "=a") - (call (mem:QI (match_operand:DI 2 "call_insn_operand" "")) - (match_operand:DI 3 "" ""))) + (call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" "")) + (match_operand:DI 3 "" ""))) (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" @@ -14190,11 +14659,17 @@ (define_expand "tls_global_dynamic_64" [(parallel [(set (match_operand:DI 0 "register_operand" "") - (call (mem:QI (match_dup 2)) (const_int 0))) + (call:DI (mem:QI (match_dup 2)) (const_int 0))) (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)])] "" { + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_64 + (operands[0], operands[1])); + DONE; + } operands[2] = ix86_tls_get_addr (); }) @@ -14205,7 +14680,7 @@ UNSPEC_TLS_LD_BASE)) (clobber (match_scratch:SI 3 "=d")) (clobber (match_scratch:SI 4 "=c")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_GNU_TLS" "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2" [(set_attr "type" "multi") @@ -14218,7 +14693,7 @@ UNSPEC_TLS_LD_BASE)) (clobber (match_scratch:SI 3 "=d")) (clobber (match_scratch:SI 4 "=c")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_SUN_TLS" "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]} push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3" @@ -14231,7 +14706,7 @@ UNSPEC_TLS_LD_BASE)) (clobber (match_scratch:SI 3 "")) (clobber (match_scratch:SI 4 "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" { if (flag_pic) @@ -14241,13 +14716,19 @@ operands[1] = gen_reg_rtx (Pmode); emit_insn (gen_set_got (operands[1])); } + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_32 + (operands[0], ix86_tls_module_base (), operands[1])); + DONE; + } operands[2] = ix86_tls_get_addr (); }) (define_insn "*tls_local_dynamic_base_64" [(set (match_operand:DI 0 "register_operand" "=a") - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "")) - (match_operand:DI 2 "" ""))) + (call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" "")) + (match_operand:DI 2 "" ""))) (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)] "TARGET_64BIT" "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1" @@ -14256,10 +14737,16 @@ (define_expand "tls_local_dynamic_base_64" [(parallel [(set (match_operand:DI 0 "register_operand" "") - (call (mem:QI (match_dup 1)) (const_int 0))) + (call:DI (mem:QI (match_dup 1)) (const_int 0))) (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])] "" { + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_64 + (operands[0], ix86_tls_module_base ())); + DONE; + } operands[1] = ix86_tls_get_addr (); }) @@ -14276,7 +14763,7 @@ UNSPEC_DTPOFF)))) (clobber (match_scratch:SI 4 "=d")) (clobber (match_scratch:SI 5 "=c")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "#" "" @@ -14285,7 +14772,7 @@ UNSPEC_TLS_GD)) (clobber (match_dup 4)) (clobber (match_dup 5)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") ;; Load and add the thread base pointer from %gs:0. @@ -14305,7 +14792,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) (match_operand:SI 1 "register_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}" [(set_attr "type" "alu") @@ -14329,7 +14816,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP) (match_operand:DI 1 "register_operand" "0"))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}" [(set_attr "type" "alu") @@ -14337,6 +14824,136 @@ (set_attr "length" "7") (set_attr "memory" "load") (set_attr "imm_disp" "false")]) + +;; GNU2 TLS patterns can be split. + +(define_expand "tls_dynamic_gnu2_32" + [(set (match_dup 3) + (plus:SI (match_operand:SI 2 "register_operand" "") + (const:SI + (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC)))) + (parallel + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI [(match_dup 1) (match_dup 3) + (match_dup 2) (reg:SI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))])] + "!TARGET_64BIT && TARGET_GNU2_TLS" +{ + operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + ix86_tls_descriptor_calls_expanded_in_cfun = true; +}) + +(define_insn "*tls_dynamic_lea_32" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "register_operand" "b") + (const:SI + (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC))))] + "!TARGET_64BIT && TARGET_GNU2_TLS" + "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}" + [(set_attr "type" "lea") + (set_attr "mode" "SI") + (set_attr "length" "6") + (set_attr "length_address" "4")]) + +(define_insn "*tls_dynamic_call_32" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "") + (match_operand:SI 2 "register_operand" "0") + ;; we have to make sure %ebx still points to the GOT + (match_operand:SI 3 "register_operand" "b") + (reg:SI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && TARGET_GNU2_TLS" + "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}" + [(set_attr "type" "call") + (set_attr "length" "2") + (set_attr "length_address" "0")]) + +(define_insn_and_split "*tls_dynamic_gnu2_combine_32" + [(set (match_operand:SI 0 "register_operand" "=&a") + (plus:SI + (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "") + (match_operand:SI 4 "" "") + (match_operand:SI 2 "register_operand" "b") + (reg:SI SP_REG)] + UNSPEC_TLSDESC) + (const:SI (unspec:SI + [(match_operand:SI 1 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && TARGET_GNU2_TLS" + "#" + "" + [(set (match_dup 0) (match_dup 5))] +{ + operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2])); +}) + +(define_expand "tls_dynamic_gnu2_64" + [(set (match_dup 2) + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC)) + (parallel + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT && TARGET_GNU2_TLS" +{ + operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + ix86_tls_descriptor_calls_expanded_in_cfun = true; +}) + +(define_insn "*tls_dynamic_lea_64" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC))] + "TARGET_64BIT && TARGET_GNU2_TLS" + "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}" + [(set_attr "type" "lea") + (set_attr "mode" "DI") + (set_attr "length" "7") + (set_attr "length_address" "4")]) + +(define_insn "*tls_dynamic_call_64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "") + (match_operand:DI 2 "register_operand" "0") + (reg:DI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_GNU2_TLS" + "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}" + [(set_attr "type" "call") + (set_attr "length" "2") + (set_attr "length_address" "0")]) + +(define_insn_and_split "*tls_dynamic_gnu2_combine_64" + [(set (match_operand:DI 0 "register_operand" "=&a") + (plus:DI + (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "") + (match_operand:DI 3 "" "") + (reg:DI SP_REG)] + UNSPEC_TLSDESC) + (const:DI (unspec:DI + [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_GNU2_TLS" + "#" + "" + [(set (match_dup 0) (match_dup 4))] +{ + operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1])); +}) + +;; ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and @@ -14348,28 +14965,14 @@ ;; Gcc is slightly more smart about handling normal two address instructions ;; so use special patterns for add and mull. -(define_insn "*fop_sf_comm_nosse" - [(set (match_operand:SF 0 "register_operand" "=f") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "%0") - (match_operand:SF 2 "nonimmediate_operand" "fm")]))] - "TARGET_80387 && !TARGET_SSE_MATH - && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c' - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (match_operand:SF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop"))) - (set_attr "mode" "SF")]) -(define_insn "*fop_sf_comm" - [(set (match_operand:SF 0 "register_operand" "=f#x,x#f") +(define_insn "*fop_sf_comm_mixed" + [(set (match_operand:SF 0 "register_operand" "=f,x") (match_operator:SF 3 "binary_fp_operator" [(match_operand:SF 1 "nonimmediate_operand" "%0,0") - (match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))] - "TARGET_80387 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 - && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c' + (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))] + "TARGET_MIX_SSE_I387 + && COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -14387,7 +14990,8 @@ (match_operator:SF 3 "binary_fp_operator" [(match_operand:SF 1 "nonimmediate_operand" "%0") (match_operand:SF 2 "nonimmediate_operand" "xm")]))] - "TARGET_SSE_MATH && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c' + "TARGET_SSE_MATH + && COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -14396,94 +15000,28 @@ (const_string "sseadd"))) (set_attr "mode" "SF")]) -(define_insn "*fop_df_comm_nosse" - [(set (match_operand:DF 0 "register_operand" "=f") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "%0") - (match_operand:DF 2 "nonimmediate_operand" "fm")]))] - "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH) - && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c' +(define_insn "*fop_sf_comm_i387" + [(set (match_operand:SF 0 "register_operand" "=f") + (match_operator:SF 3 "binary_fp_operator" + [(match_operand:SF 1 "nonimmediate_operand" "%0") + (match_operand:SF 2 "nonimmediate_operand" "fm")]))] + "TARGET_80387 + && COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (if_then_else (match_operand:SF 3 "mult_operator" "") (const_string "fmul") (const_string "fop"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_df_comm" - [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "%0,0") - (match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))] - "TARGET_80387 && TARGET_SSE_MATH && TARGET_SSE2 && TARGET_MIX_SSE_I387 - && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c' - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (eq_attr "alternative" "1") - (if_then_else (match_operand:SF 3 "mult_operator" "") - (const_string "ssemul") - (const_string "sseadd")) - (if_then_else (match_operand:SF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop")))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_df_comm_sse" - [(set (match_operand:DF 0 "register_operand" "=Y") - (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "%0") - (match_operand:DF 2 "nonimmediate_operand" "Ym")]))] - "TARGET_SSE2 && TARGET_SSE_MATH - && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c' - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (match_operand:SF 3 "mult_operator" "") - (const_string "ssemul") - (const_string "sseadd"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_xf_comm" - [(set (match_operand:XF 0 "register_operand" "=f") - (match_operator:XF 3 "binary_fp_operator" - [(match_operand:XF 1 "register_operand" "%0") - (match_operand:XF 2 "register_operand" "f")]))] - "TARGET_80387 - && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (match_operand:XF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop"))) - (set_attr "mode" "XF")]) - -(define_insn "*fop_sf_1_nosse" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (match_operator:SF 3 "binary_fp_operator" - [(match_operand:SF 1 "nonimmediate_operand" "0,fm") - (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387 && !TARGET_SSE_MATH - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c' - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:SF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:SF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_sf_1" +(define_insn "*fop_sf_1_mixed" [(set (match_operand:SF 0 "register_operand" "=f,f,x") (match_operator:SF 3 "binary_fp_operator" [(match_operand:SF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))] - "TARGET_80387 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c' + (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))] + "TARGET_MIX_SSE_I387 + && !COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -14509,7 +15047,7 @@ [(match_operand:SF 1 "register_operand" "0") (match_operand:SF 2 "nonimmediate_operand" "xm")]))] "TARGET_SSE_MATH - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" + && !COMMUTATIVE_ARITH_P (operands[3])" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:SF 3 "mult_operator" "") @@ -14520,13 +15058,32 @@ (const_string "sseadd"))) (set_attr "mode" "SF")]) +;; This pattern is not fully shadowed by the pattern above. +(define_insn "*fop_sf_1_i387" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (match_operator:SF 3 "binary_fp_operator" + [(match_operand:SF 1 "nonimmediate_operand" "0,fm") + (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] + "TARGET_80387 && !TARGET_SSE_MATH + && !COMMUTATIVE_ARITH_P (operands[3]) + && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:SF 3 "mult_operator" "") + (const_string "fmul") + (match_operand:SF 3 "div_operator" "") + (const_string "fdiv") + ] + (const_string "fop"))) + (set_attr "mode" "SF")]) + ;; ??? Add SSE splitters for these! -(define_insn "*fop_sf_2" +(define_insn "*fop_sf_2<mode>_i387" [(set (match_operand:SF 0 "register_operand" "=f,f") (match_operator:SF 3 "binary_fp_operator" - [(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")) + [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:SF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE_MATH" + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:SF 3 "mult_operator" "") @@ -14536,15 +15093,14 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "ppro_uops" "many") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) -(define_insn "*fop_sf_3" +(define_insn "*fop_sf_3<mode>_i387" [(set (match_operand:SF 0 "register_operand" "=f,f") (match_operator:SF 3 "binary_fp_operator" [(match_operand:SF 1 "register_operand" "0,0") - (float:SF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE_MATH" + (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:SF 3 "mult_operator" "") @@ -14554,43 +15110,72 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "ppro_uops" "many") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) -(define_insn "*fop_df_1_nosse" - [(set (match_operand:DF 0 "register_operand" "=f,f") +(define_insn "*fop_df_comm_mixed" + [(set (match_operand:DF 0 "register_operand" "=f,Y") (match_operator:DF 3 "binary_fp_operator" - [(match_operand:DF 1 "nonimmediate_operand" "0,fm") - (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH) - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c' + [(match_operand:DF 1 "nonimmediate_operand" "%0,0") + (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))] + "TARGET_SSE2 && TARGET_MIX_SSE_I387 + && COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(match_operand:DF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:DF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) + (if_then_else (eq_attr "alternative" "1") + (if_then_else (match_operand:DF 3 "mult_operator" "") + (const_string "ssemul") + (const_string "sseadd")) + (if_then_else (match_operand:DF 3 "mult_operator" "") + (const_string "fmul") + (const_string "fop")))) + (set_attr "mode" "DF")]) + +(define_insn "*fop_df_comm_sse" + [(set (match_operand:DF 0 "register_operand" "=Y") + (match_operator:DF 3 "binary_fp_operator" + [(match_operand:DF 1 "nonimmediate_operand" "%0") + (match_operand:DF 2 "nonimmediate_operand" "Ym")]))] + "TARGET_SSE2 && TARGET_SSE_MATH + && COMMUTATIVE_ARITH_P (operands[3]) + && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (if_then_else (match_operand:DF 3 "mult_operator" "") + (const_string "ssemul") + (const_string "sseadd"))) (set_attr "mode" "DF")]) +(define_insn "*fop_df_comm_i387" + [(set (match_operand:DF 0 "register_operand" "=f") + (match_operator:DF 3 "binary_fp_operator" + [(match_operand:DF 1 "nonimmediate_operand" "%0") + (match_operand:DF 2 "nonimmediate_operand" "fm")]))] + "TARGET_80387 + && COMMUTATIVE_ARITH_P (operands[3]) + && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (if_then_else (match_operand:DF 3 "mult_operator" "") + (const_string "fmul") + (const_string "fop"))) + (set_attr "mode" "DF")]) -(define_insn "*fop_df_1" - [(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f") +(define_insn "*fop_df_1_mixed" + [(set (match_operand:DF 0 "register_operand" "=f,f,Y") (match_operator:DF 3 "binary_fp_operator" [(match_operand:DF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))] - "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c' + (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))] + "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 + && !COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(and (eq_attr "alternative" "2") - (match_operand:SF 3 "mult_operator" "")) + (match_operand:DF 3 "mult_operator" "")) (const_string "ssemul") (and (eq_attr "alternative" "2") - (match_operand:SF 3 "div_operator" "")) + (match_operand:DF 3 "div_operator" "")) (const_string "ssediv") (eq_attr "alternative" "2") (const_string "sseadd") @@ -14608,24 +15193,44 @@ [(match_operand:DF 1 "register_operand" "0") (match_operand:DF 2 "nonimmediate_operand" "Ym")]))] "TARGET_SSE2 && TARGET_SSE_MATH - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" + && !COMMUTATIVE_ARITH_P (operands[3])" "* return output_387_binary_op (insn, operands);" [(set_attr "mode" "DF") (set (attr "type") - (cond [(match_operand:SF 3 "mult_operator" "") + (cond [(match_operand:DF 3 "mult_operator" "") (const_string "ssemul") - (match_operand:SF 3 "div_operator" "") + (match_operand:DF 3 "div_operator" "") (const_string "ssediv") ] (const_string "sseadd")))]) +;; This pattern is not fully shadowed by the pattern above. +(define_insn "*fop_df_1_i387" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (match_operator:DF 3 "binary_fp_operator" + [(match_operand:DF 1 "nonimmediate_operand" "0,fm") + (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] + "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) + && !COMMUTATIVE_ARITH_P (operands[3]) + && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "mult_operator" "") + (const_string "fmul") + (match_operand:DF 3 "div_operator" "") + (const_string "fdiv") + ] + (const_string "fop"))) + (set_attr "mode" "DF")]) + ;; ??? Add SSE splitters for these! -(define_insn "*fop_df_2" +(define_insn "*fop_df_2<mode>_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" - [(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")) + [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:DF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_FIOP && !(TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP + && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") @@ -14635,15 +15240,15 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "ppro_uops" "many") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) -(define_insn "*fop_df_3" +(define_insn "*fop_df_3<mode>_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" [(match_operand:DF 1 "register_operand" "0,0") - (float:DF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_FIOP && !(TARGET_SSE2 && TARGET_SSE_MATH)" + (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP + && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") @@ -14653,15 +15258,14 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "ppro_uops" "many") - (set_attr "mode" "SI")]) + (set_attr "mode" "<MODE>")]) -(define_insn "*fop_df_4" +(define_insn "*fop_df_4_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) (match_operand:DF 2 "register_operand" "0,f")]))] - "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH) + "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -14673,7 +15277,7 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_df_5" +(define_insn "*fop_df_5_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" [(match_operand:DF 1 "register_operand" "0,f") @@ -14690,7 +15294,7 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_df_6" +(define_insn "*fop_df_6_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" [(float_extend:DF @@ -14708,13 +15312,27 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_xf_1" +(define_insn "*fop_xf_comm_i387" + [(set (match_operand:XF 0 "register_operand" "=f") + (match_operator:XF 3 "binary_fp_operator" + [(match_operand:XF 1 "register_operand" "%0") + (match_operand:XF 2 "register_operand" "f")]))] + "TARGET_80387 + && COMMUTATIVE_ARITH_P (operands[3])" + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (if_then_else (match_operand:XF 3 "mult_operator" "") + (const_string "fmul") + (const_string "fop"))) + (set_attr "mode" "XF")]) + +(define_insn "*fop_xf_1_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "0,f") (match_operand:XF 2 "register_operand" "f,0")]))] "TARGET_80387 - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" + && !COMMUTATIVE_ARITH_P (operands[3])" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14725,12 +15343,12 @@ (const_string "fop"))) (set_attr "mode" "XF")]) -(define_insn "*fop_xf_2" +(define_insn "*fop_xf_2<mode>_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" - [(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")) + [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:XF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_FIOP" + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14740,15 +15358,14 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "many")]) + (set_attr "mode" "<MODE>")]) -(define_insn "*fop_xf_3" +(define_insn "*fop_xf_3<mode>_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "0,0") - (float:XF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_FIOP" + (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] + "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14758,10 +15375,9 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "many")]) + (set_attr "mode" "<MODE>")]) -(define_insn "*fop_xf_4" +(define_insn "*fop_xf_4_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0")) @@ -14777,7 +15393,7 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_xf_5" +(define_insn "*fop_xf_5_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "0,f") @@ -14794,7 +15410,7 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_xf_6" +(define_insn "*fop_xf_6_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(float_extend:XF @@ -14815,7 +15431,7 @@ (define_split [(set (match_operand 0 "register_operand" "") (match_operator 3 "binary_fp_operator" - [(float (match_operand:SI 1 "register_operand" "")) + [(float (match_operand:X87MODEI12 1 "register_operand" "")) (match_operand 2 "register_operand" "")]))] "TARGET_80387 && reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))" @@ -14836,7 +15452,7 @@ [(set (match_operand 0 "register_operand" "") (match_operator 3 "binary_fp_operator" [(match_operand 1 "register_operand" "") - (float (match_operand:SI 2 "register_operand" ""))]))] + (float (match_operand:X87MODEI12 2 "register_operand" ""))]))] "TARGET_80387 && reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))" [(const_int 0)] @@ -14857,17 +15473,16 @@ (define_expand "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "") (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "")))] - "(! TARGET_NO_FANCY_MATH_387 && TARGET_80387) || TARGET_SSE_MATH" + "TARGET_USE_FANCY_MATH_387 || TARGET_SSE_MATH" { if (!TARGET_SSE_MATH) operands[1] = force_reg (SFmode, operands[1]); }) -(define_insn "sqrtsf2_1" - [(set (match_operand:SF 0 "register_operand" "=f#x,x#f") - (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0#x,xm#f")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_SSE_MATH && TARGET_MIX_SSE_I387)" +(define_insn "*sqrtsf2_mixed" + [(set (match_operand:SF 0 "register_operand" "=f,x") + (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))] + "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387" "@ fsqrt sqrtss\t{%1, %0|%0, %1}" @@ -14875,20 +15490,19 @@ (set_attr "mode" "SF,SF") (set_attr "athlon_decode" "direct,*")]) -(define_insn "sqrtsf2_1_sse_only" +(define_insn "*sqrtsf2_sse" [(set (match_operand:SF 0 "register_operand" "=x") (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "xm")))] - "TARGET_SSE_MATH && (!TARGET_80387 || !TARGET_MIX_SSE_I387)" + "TARGET_SSE_MATH" "sqrtss\t{%1, %0|%0, %1}" [(set_attr "type" "sse") (set_attr "mode" "SF") (set_attr "athlon_decode" "*")]) -(define_insn "sqrtsf2_i387" +(define_insn "*sqrtsf2_i387" [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && !TARGET_SSE_MATH" + "TARGET_USE_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "SF") @@ -14897,18 +15511,16 @@ (define_expand "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "") (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))] - "(! TARGET_NO_FANCY_MATH_387 && TARGET_80387) - || (TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_USE_FANCY_MATH_387 || (TARGET_SSE2 && TARGET_SSE_MATH)" { - if (!TARGET_SSE2 || !TARGET_SSE_MATH) + if (!(TARGET_SSE2 && TARGET_SSE_MATH)) operands[1] = force_reg (DFmode, operands[1]); }) -(define_insn "sqrtdf2_1" - [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f") - (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387)" +(define_insn "*sqrtdf2_mixed" + [(set (match_operand:DF 0 "register_operand" "=f,Y") + (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))] + "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387" "@ fsqrt sqrtsd\t{%1, %0|%0, %1}" @@ -14916,31 +15528,30 @@ (set_attr "mode" "DF,DF") (set_attr "athlon_decode" "direct,*")]) -(define_insn "sqrtdf2_1_sse_only" +(define_insn "*sqrtdf2_sse" [(set (match_operand:DF 0 "register_operand" "=Y") (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))] - "TARGET_SSE2 && TARGET_SSE_MATH && (!TARGET_80387 || !TARGET_MIX_SSE_I387)" + "TARGET_SSE2 && TARGET_SSE_MATH" "sqrtsd\t{%1, %0|%0, %1}" [(set_attr "type" "sse") (set_attr "mode" "DF") (set_attr "athlon_decode" "*")]) -(define_insn "sqrtdf2_i387" +(define_insn "*sqrtdf2_i387" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (match_operand:DF 1 "register_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (!TARGET_SSE2 || !TARGET_SSE_MATH)" + "TARGET_USE_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "DF") (set_attr "athlon_decode" "direct")]) -(define_insn "*sqrtextendsfdf2" +(define_insn "*sqrtextendsfdf2_i387" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && !(TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "DF") @@ -14949,46 +15560,217 @@ (define_insn "sqrtxf2" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387 && !TARGET_NO_FANCY_MATH_387 - && (TARGET_IEEE_FP || flag_unsafe_math_optimizations) " + "TARGET_USE_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "XF") (set_attr "athlon_decode" "direct")]) -(define_insn "*sqrtextenddfxf2" +(define_insn "*sqrtextendsfxf2_i387" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF - (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387 && !TARGET_NO_FANCY_MATH_387" + (match_operand:SF 1 "register_operand" "0"))))] + "TARGET_USE_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "XF") (set_attr "athlon_decode" "direct")]) -(define_insn "*sqrtextendsfxf2" +(define_insn "*sqrtextenddfxf2_i387" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF - (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387 && !TARGET_NO_FANCY_MATH_387" + (match_operand:DF 1 "register_operand" "0"))))] + "TARGET_USE_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "XF") (set_attr "athlon_decode" "direct")]) -(define_insn "sindf2" +(define_insn "fpremxf4" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 3 "register_operand" "1")] + UNSPEC_FPREM_F)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2) (match_dup 3)] + UNSPEC_FPREM_U)) + (set (reg:CCFP FPSR_REG) + (unspec:CCFP [(const_int 0)] UNSPEC_NOP))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fprem" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_expand "fmodsf3" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" "")) + (use (match_operand:SF 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx label = gen_label_rtx (); + + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); + + emit_insn(gen_extendsfxf2 (op1, operands[1])); + emit_insn(gen_extendsfxf2 (op2, operands[2])); + + emit_label (label); + + emit_insn (gen_fpremxf4 (op1, op2, op1, op2)); + ix86_emit_fp_unordered_jump (label); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1)); + DONE; +}) + +(define_expand "fmoddf3" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DF 1 "register_operand" "")) + (use (match_operand:DF 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx label = gen_label_rtx (); + + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_extenddfxf2 (op2, operands[2])); + + emit_label (label); + + emit_insn (gen_fpremxf4 (op1, op2, op1, op2)); + ix86_emit_fp_unordered_jump (label); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1)); + DONE; +}) + +(define_expand "fmodxf3" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" "")) + (use (match_operand:XF 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + rtx label = gen_label_rtx (); + + emit_label (label); + + emit_insn (gen_fpremxf4 (operands[1], operands[2], + operands[1], operands[2])); + ix86_emit_fp_unordered_jump (label); + + emit_move_insn (operands[0], operands[1]); + DONE; +}) + +(define_insn "fprem1xf4" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 3 "register_operand" "1")] + UNSPEC_FPREM1_F)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2) (match_dup 3)] + UNSPEC_FPREM1_U)) + (set (reg:CCFP FPSR_REG) + (unspec:CCFP [(const_int 0)] UNSPEC_NOP))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fprem1" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_expand "dremsf3" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" "")) + (use (match_operand:SF 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx label = gen_label_rtx (); + + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); + + emit_insn(gen_extendsfxf2 (op1, operands[1])); + emit_insn(gen_extendsfxf2 (op2, operands[2])); + + emit_label (label); + + emit_insn (gen_fprem1xf4 (op1, op2, op1, op2)); + ix86_emit_fp_unordered_jump (label); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1)); + DONE; +}) + +(define_expand "dremdf3" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DF 1 "register_operand" "")) + (use (match_operand:DF 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx label = gen_label_rtx (); + + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_extenddfxf2 (op2, operands[2])); + + emit_label (label); + + emit_insn (gen_fprem1xf4 (op1, op2, op1, op2)); + ix86_emit_fp_unordered_jump (label); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1)); + DONE; +}) + +(define_expand "dremxf3" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" "")) + (use (match_operand:XF 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + rtx label = gen_label_rtx (); + + emit_label (label); + + emit_insn (gen_fprem1xf4 (operands[1], operands[2], + operands[1], operands[2])); + ix86_emit_fp_unordered_jump (label); + + emit_move_insn (operands[0], operands[1]); + DONE; +}) + +(define_insn "*sindf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fsin" [(set_attr "type" "fpspc") (set_attr "mode" "DF")]) -(define_insn "sinsf2" +(define_insn "*sinsf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fsin" [(set_attr "type" "fpspc") @@ -14999,34 +15781,37 @@ (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] UNSPEC_SIN))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fsin" [(set_attr "type" "fpspc") (set_attr "mode" "DF")]) -(define_insn "sinxf2" +(define_insn "*sinxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))] - "TARGET_80387 && !TARGET_NO_FANCY_MATH_387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "fsin" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) -(define_insn "cosdf2" +(define_insn "*cosdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fcos" [(set_attr "type" "fpspc") (set_attr "mode" "DF")]) -(define_insn "cossf2" +(define_insn "*cossf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fcos" [(set_attr "type" "fpspc") @@ -15037,38 +15822,324 @@ (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] UNSPEC_COS))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fcos" [(set_attr "type" "fpspc") (set_attr "mode" "DF")]) -(define_insn "cosxf2" +(define_insn "*cosxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "fcos" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) +;; With sincos pattern defined, sin and cos builtin function will be +;; expanded to sincos pattern with one of its outputs left unused. +;; Cse pass will detected, if two sincos patterns can be combined, +;; otherwise sincos pattern will be split back to sin or cos pattern, +;; depending on the unused output. + +(define_insn "sincosdf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:DF 2 "register_operand" "0")] + UNSPEC_SINCOS_COS)) + (set (match_operand:DF 1 "register_operand" "=u") + (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "fsincos" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + +(define_split + [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_operand:DF 2 "register_operand" "")] + UNSPEC_SINCOS_COS)) + (set (match_operand:DF 1 "register_operand" "") + (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_SIN))] + "") + +(define_split + [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_operand:DF 2 "register_operand" "")] + UNSPEC_SINCOS_COS)) + (set (match_operand:DF 1 "register_operand" "") + (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_COS))] + "") + +(define_insn "sincossf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:SF 2 "register_operand" "0")] + UNSPEC_SINCOS_COS)) + (set (match_operand:SF 1 "register_operand" "=u") + (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "fsincos" + [(set_attr "type" "fpspc") + (set_attr "mode" "SF")]) + +(define_split + [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_operand:SF 2 "register_operand" "")] + UNSPEC_SINCOS_COS)) + (set (match_operand:SF 1 "register_operand" "") + (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_SIN))] + "") + +(define_split + [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_operand:SF 2 "register_operand" "")] + UNSPEC_SINCOS_COS)) + (set (match_operand:SF 1 "register_operand" "") + (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_COS))] + "") + +(define_insn "*sincosextendsfdf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(float_extend:DF + (match_operand:SF 2 "register_operand" "0"))] + UNSPEC_SINCOS_COS)) + (set (match_operand:DF 1 "register_operand" "=u") + (unspec:DF [(float_extend:DF + (match_dup 2))] UNSPEC_SINCOS_SIN))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "fsincos" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + +(define_split + [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(float_extend:DF + (match_operand:SF 2 "register_operand" ""))] + UNSPEC_SINCOS_COS)) + (set (match_operand:DF 1 "register_operand" "") + (unspec:DF [(float_extend:DF + (match_dup 2))] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 1) (unspec:DF [(float_extend:DF + (match_dup 2))] UNSPEC_SIN))] + "") + +(define_split + [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(float_extend:DF + (match_operand:SF 2 "register_operand" ""))] + UNSPEC_SINCOS_COS)) + (set (match_operand:DF 1 "register_operand" "") + (unspec:DF [(float_extend:DF + (match_dup 2))] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 0) (unspec:DF [(float_extend:DF + (match_dup 2))] UNSPEC_COS))] + "") + +(define_insn "sincosxf3" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0")] + UNSPEC_SINCOS_COS)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fsincos" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_split + [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 2 "register_operand" "")] + UNSPEC_SINCOS_COS)) + (set (match_operand:XF 1 "register_operand" "") + (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))] + "") + +(define_split + [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 2 "register_operand" "")] + UNSPEC_SINCOS_COS)) + (set (match_operand:XF 1 "register_operand" "") + (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))] + "find_regno_note (insn, REG_UNUSED, REGNO (operands[1])) + && !reload_completed && !reload_in_progress" + [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))] + "") + +(define_insn "*tandf3_1" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:DF 2 "register_operand" "0")] + UNSPEC_TAN_ONE)) + (set (match_operand:DF 1 "register_operand" "=u") + (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "fptan" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + +;; optimize sequence: fptan +;; fstp %st(0) +;; fld1 +;; into fptan insn. + +(define_peephole2 + [(parallel[(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_operand:DF 2 "register_operand" "")] + UNSPEC_TAN_ONE)) + (set (match_operand:DF 1 "register_operand" "") + (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))]) + (set (match_dup 0) + (match_operand:DF 3 "immediate_operand" ""))] + "standard_80387_constant_p (operands[3]) == 2" + [(parallel[(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_TAN_ONE)) + (set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])] + "") + +(define_expand "tandf2" + [(parallel [(set (match_dup 2) + (unspec:DF [(match_operand:DF 1 "register_operand" "")] + UNSPEC_TAN_ONE)) + (set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_dup 1)] UNSPEC_TAN_TAN))])] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (DFmode); +}) + +(define_insn "*tansf3_1" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:SF 2 "register_operand" "0")] + UNSPEC_TAN_ONE)) + (set (match_operand:SF 1 "register_operand" "=u") + (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "fptan" + [(set_attr "type" "fpspc") + (set_attr "mode" "SF")]) + +;; optimize sequence: fptan +;; fstp %st(0) +;; fld1 +;; into fptan insn. + +(define_peephole2 + [(parallel[(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_operand:SF 2 "register_operand" "")] + UNSPEC_TAN_ONE)) + (set (match_operand:SF 1 "register_operand" "") + (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))]) + (set (match_dup 0) + (match_operand:SF 3 "immediate_operand" ""))] + "standard_80387_constant_p (operands[3]) == 2" + [(parallel[(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_TAN_ONE)) + (set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])] + "") + +(define_expand "tansf2" + [(parallel [(set (match_dup 2) + (unspec:SF [(match_operand:SF 1 "register_operand" "")] + UNSPEC_TAN_ONE)) + (set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_dup 1)] UNSPEC_TAN_TAN))])] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (SFmode); +}) + +(define_insn "*tanxf3_1" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0")] + UNSPEC_TAN_ONE)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fptan" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +;; optimize sequence: fptan +;; fstp %st(0) +;; fld1 +;; into fptan insn. + +(define_peephole2 + [(parallel[(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 2 "register_operand" "")] + UNSPEC_TAN_ONE)) + (set (match_operand:XF 1 "register_operand" "") + (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))]) + (set (match_dup 0) + (match_operand:XF 3 "immediate_operand" ""))] + "standard_80387_constant_p (operands[3]) == 2" + [(parallel[(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_TAN_ONE)) + (set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])] + "") + +(define_expand "tanxf2" + [(parallel [(set (match_dup 2) + (unspec:XF [(match_operand:XF 1 "register_operand" "")] + UNSPEC_TAN_ONE)) + (set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 1)] UNSPEC_TAN_TAN))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); +}) + (define_insn "atan2df3_1" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 2 "register_operand" "0") (match_operand:DF 1 "register_operand" "u")] UNSPEC_FPATAN)) (clobber (match_scratch:DF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fpatan" [(set_attr "type" "fpspc") (set_attr "mode" "DF")]) (define_expand "atan2df3" - [(use (match_operand:DF 0 "register_operand" "=f")) - (use (match_operand:DF 2 "register_operand" "0")) - (use (match_operand:DF 1 "register_operand" "u"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DF 2 "register_operand" "")) + (use (match_operand:DF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { rtx copy = gen_reg_rtx (DFmode); @@ -15077,23 +16148,39 @@ DONE; }) +(define_expand "atandf2" + [(parallel [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_dup 2) + (match_operand:DF 1 "register_operand" "")] + UNSPEC_FPATAN)) + (clobber (match_scratch:DF 3 ""))])] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (DFmode); + emit_move_insn (operands[2], CONST1_RTX (DFmode)); /* fld1 */ +}) + (define_insn "atan2sf3_1" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 2 "register_operand" "0") (match_operand:SF 1 "register_operand" "u")] UNSPEC_FPATAN)) (clobber (match_scratch:SF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" "fpatan" [(set_attr "type" "fpspc") (set_attr "mode" "SF")]) (define_expand "atan2sf3" - [(use (match_operand:SF 0 "register_operand" "=f")) - (use (match_operand:SF 2 "register_operand" "0")) - (use (match_operand:SF 1 "register_operand" "u"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 2 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { rtx copy = gen_reg_rtx (SFmode); @@ -15102,23 +16189,37 @@ DONE; }) +(define_expand "atansf2" + [(parallel [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_dup 2) + (match_operand:SF 1 "register_operand" "")] + UNSPEC_FPATAN)) + (clobber (match_scratch:SF 3 ""))])] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (SFmode); + emit_move_insn (operands[2], CONST1_RTX (SFmode)); /* fld1 */ +}) + (define_insn "atan2xf3_1" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 2 "register_operand" "0") (match_operand:XF 1 "register_operand" "u")] UNSPEC_FPATAN)) (clobber (match_scratch:XF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "fpatan" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) (define_expand "atan2xf3" - [(use (match_operand:XF 0 "register_operand" "=f")) - (use (match_operand:XF 2 "register_operand" "0")) - (use (match_operand:XF 1 "register_operand" "u"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 2 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" { rtx copy = gen_reg_rtx (XFmode); @@ -15127,70 +16228,213 @@ DONE; }) -(define_insn "*fyl2x_sfxf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:SF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FYL2X)) - (clobber (match_scratch:SF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_expand "atanxf2" + [(parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 2) + (match_operand:XF 1 "register_operand" "")] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 3 ""))])] + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "fyl2x" - [(set_attr "type" "fpspc") - (set_attr "mode" "SF")]) +{ + operands[2] = gen_reg_rtx (XFmode); + emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */ +}) -(define_insn "*fyl2x_dfxf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:DF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FYL2X)) - (clobber (match_scratch:DF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_expand "asindf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2))) + (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3))) + (set (match_dup 6) (sqrt:XF (match_dup 5))) + (parallel [(set (match_dup 7) + (unspec:XF [(match_dup 6) (match_dup 2)] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 8 ""))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 7)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" - "fyl2x" - [(set_attr "type" "fpspc") - (set_attr "mode" "DF")]) +{ + int i; + + for (i=2; i<8; i++) + operands[i] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "asinsf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2))) + (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3))) + (set (match_dup 6) (sqrt:XF (match_dup 5))) + (parallel [(set (match_dup 7) + (unspec:XF [(match_dup 6) (match_dup 2)] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 8 ""))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 7)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<8; i++) + operands[i] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */ +}) -(define_insn "*fyl2x_xf3" +(define_expand "asinxf2" + [(set (match_dup 2) + (mult:XF (match_operand:XF 1 "register_operand" "") + (match_dup 1))) + (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2))) + (set (match_dup 5) (sqrt:XF (match_dup 4))) + (parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 5) (match_dup 1)] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 6 ""))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<6; i++) + operands[i] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "acosdf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2))) + (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3))) + (set (match_dup 6) (sqrt:XF (match_dup 5))) + (parallel [(set (match_dup 7) + (unspec:XF [(match_dup 2) (match_dup 6)] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 8 ""))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 7)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<8; i++) + operands[i] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "acossf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2))) + (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3))) + (set (match_dup 6) (sqrt:XF (match_dup 5))) + (parallel [(set (match_dup 7) + (unspec:XF [(match_dup 2) (match_dup 6)] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 8 ""))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 7)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<8; i++) + operands[i] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "acosxf2" + [(set (match_dup 2) + (mult:XF (match_operand:XF 1 "register_operand" "") + (match_dup 1))) + (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2))) + (set (match_dup 5) (sqrt:XF (match_dup 4))) + (parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 1) (match_dup 5)] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 6 ""))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<6; i++) + operands[i] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_insn "fyl2x_xf3" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 2 "register_operand" "0") (match_operand:XF 1 "register_operand" "u")] UNSPEC_FYL2X)) (clobber (match_scratch:XF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "fyl2x" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) (define_expand "logsf2" - [(parallel [(set (match_operand:SF 0 "register_operand" "") - (unspec:SF [(match_operand:SF 1 "register_operand" "") - (match_dup 2)] UNSPEC_FYL2X)) - (clobber (match_scratch:SF 3 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (parallel [(set (match_dup 4) + (unspec:XF [(match_dup 2) + (match_dup 3)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 5 ""))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { rtx temp; operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (4); /* fldln2 */ - emit_move_insn (operands[2], temp); + emit_move_insn (operands[3], temp); }) (define_expand "logdf2" - [(parallel [(set (match_operand:DF 0 "register_operand" "") - (unspec:DF [(match_operand:DF 1 "register_operand" "") - (match_dup 2)] UNSPEC_FYL2X)) - (clobber (match_scratch:DF 3 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (parallel [(set (match_dup 4) + (unspec:XF [(match_dup 2) + (match_dup 3)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 5 ""))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { rtx temp; operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (4); /* fldln2 */ - emit_move_insn (operands[2], temp); + emit_move_insn (operands[3], temp); }) (define_expand "logxf2" @@ -15198,7 +16442,7 @@ (unspec:XF [(match_operand:XF 1 "register_operand" "") (match_dup 2)] UNSPEC_FYL2X)) (clobber (match_scratch:XF 3 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" { rtx temp; @@ -15208,62 +16452,274 @@ emit_move_insn (operands[2], temp); }) -(define_insn "*fscale_sfxf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:XF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FSCALE)) - (clobber (match_scratch:SF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_expand "log10sf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (parallel [(set (match_dup 4) + (unspec:XF [(match_dup 2) + (match_dup 3)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 5 ""))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" - "fscale\;fstp\t%y1" - [(set_attr "type" "fpspc") - (set_attr "mode" "SF")]) +{ + rtx temp; -(define_insn "*fscale_dfxf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:XF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FSCALE)) - (clobber (match_scratch:DF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); + + temp = standard_80387_constant_rtx (3); /* fldlg2 */ + emit_move_insn (operands[3], temp); +}) + +(define_expand "log10df2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (parallel [(set (match_dup 4) + (unspec:XF [(match_dup 2) + (match_dup 3)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 5 ""))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" - "fscale\;fstp\t%y1" - [(set_attr "type" "fpspc") - (set_attr "mode" "DF")]) +{ + rtx temp; -(define_insn "*fscale_xf3" + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); + + temp = standard_80387_constant_rtx (3); /* fldlg2 */ + emit_move_insn (operands[3], temp); +}) + +(define_expand "log10xf2" + [(parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 1 "register_operand" "") + (match_dup 2)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 3 ""))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + + operands[2] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (3); /* fldlg2 */ + emit_move_insn (operands[2], temp); +}) + +(define_expand "log2sf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (parallel [(set (match_dup 4) + (unspec:XF [(match_dup 2) + (match_dup 3)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 5 ""))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "log2df2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (parallel [(set (match_dup 4) + (unspec:XF [(match_dup 2) + (match_dup 3)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 5 ""))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); + + emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "log2xf2" + [(parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 1 "register_operand" "") + (match_dup 2)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 3 ""))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_insn "fyl2xp1_xf3" [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FSCALE)) + UNSPEC_FYL2XP1)) (clobber (match_scratch:XF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "fscale\;fstp\t%y1" + "fyl2xp1" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) -(define_insn "*frndintxf2" +(define_expand "log1psf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extendsfxf2 (op1, operands[1])); + ix86_emit_i387_log1p (op0, op1); + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "log1pdf2" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + ix86_emit_i387_log1p (op0, op1); + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "log1pxf2" + [(use (match_operand:XF 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + ix86_emit_i387_log1p (operands[0], operands[1]); + DONE; +}) + +(define_insn "*fxtractxf3" [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 1 "register_operand" "0")] - UNSPEC_FRNDINT))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + (unspec:XF [(match_operand:XF 2 "register_operand" "0")] + UNSPEC_XTRACT_FRACT)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))] + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" - "frndint" + "fxtract" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) +(define_expand "logbsf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (parallel [(set (match_dup 3) + (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT)) + (set (match_dup 4) + (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); +}) + +(define_expand "logbdf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (parallel [(set (match_dup 3) + (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT)) + (set (match_dup 4) + (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 4)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); + operands[4] = gen_reg_rtx (XFmode); +}) + +(define_expand "logbxf2" + [(parallel [(set (match_dup 2) + (unspec:XF [(match_operand:XF 1 "register_operand" "")] + UNSPEC_XTRACT_FRACT)) + (set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); +}) + +(define_expand "ilogbsi2" + [(parallel [(set (match_dup 2) + (unspec:XF [(match_operand:XF 1 "register_operand" "")] + UNSPEC_XTRACT_FRACT)) + (set (match_operand:XF 3 "register_operand" "") + (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))]) + (parallel [(set (match_operand:SI 0 "register_operand" "") + (fix:SI (match_dup 3))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + operands[3] = gen_reg_rtx (XFmode); +}) + (define_insn "*f2xm1xf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_F2XM1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" "f2xm1" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) +(define_insn "*fscalexf4" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 3 "register_operand" "1")] + UNSPEC_FSCALE_FRACT)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2) (match_dup 3)] + UNSPEC_FSCALE_EXP))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fscale" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + (define_expand "expsf2" [(set (match_dup 2) (float_extend:XF (match_operand:SF 1 "register_operand" ""))) @@ -15272,16 +16728,22 @@ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) - (parallel [(set (match_operand:SF 0 "register_operand" "") - (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) - (clobber (match_scratch:SF 5 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 10)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<10; i++) + for (i=2; i<12; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (5); /* fldl2e */ emit_move_insn (operands[3], temp); @@ -15296,16 +16758,22 @@ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) - (parallel [(set (match_operand:DF 0 "register_operand" "") - (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) - (clobber (match_scratch:DF 5 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 10)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<10; i++) + for (i=2; i<12; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (5); /* fldl2e */ emit_move_insn (operands[3], temp); @@ -15320,89 +16788,1231 @@ (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1)) (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7))) (parallel [(set (match_operand:XF 0 "register_operand" "") - (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE)) - (clobber (match_scratch:XF 5 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_EXP))])] + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<9; i++) + for (i=2; i<10; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (5); /* fldl2e */ emit_move_insn (operands[2], temp); emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */ }) -(define_expand "atansf2" - [(parallel [(set (match_operand:SF 0 "register_operand" "") - (unspec:SF [(match_dup 2) - (match_operand:SF 1 "register_operand" "")] - UNSPEC_FPATAN)) - (clobber (match_scratch:SF 3 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_expand "exp10sf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) + (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) + (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) + (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 10)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { - operands[2] = gen_reg_rtx (SFmode); - emit_move_insn (operands[2], CONST1_RTX (SFmode)); /* fld1 */ + rtx temp; + int i; + + for (i=2; i<12; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (6); /* fldl2t */ + emit_move_insn (operands[3], temp); + emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */ }) -(define_expand "atandf2" - [(parallel [(set (match_operand:DF 0 "register_operand" "") - (unspec:DF [(match_dup 2) - (match_operand:DF 1 "register_operand" "")] - UNSPEC_FPATAN)) - (clobber (match_scratch:DF 3 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_expand "exp10df2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) + (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) + (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) + (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 10)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) && flag_unsafe_math_optimizations" { - operands[2] = gen_reg_rtx (DFmode); - emit_move_insn (operands[2], CONST1_RTX (DFmode)); /* fld1 */ + rtx temp; + int i; + + for (i=2; i<12; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (6); /* fldl2t */ + emit_move_insn (operands[3], temp); + emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */ }) -(define_expand "atanxf2" - [(parallel [(set (match_operand:XF 0 "register_operand" "") - (unspec:XF [(match_dup 2) - (match_operand:XF 1 "register_operand" "")] - UNSPEC_FPATAN)) - (clobber (match_scratch:XF 3 ""))])] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_expand "exp10xf2" + [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "") + (match_dup 2))) + (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT)) + (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4))) + (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1)) + (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7))) + (parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_EXP))])] + "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" { - operands[2] = gen_reg_rtx (XFmode); - emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */ + rtx temp; + int i; + + for (i=2; i<10; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (6); /* fldl2t */ + emit_move_insn (operands[2], temp); + emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "exp2sf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT)) + (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1)) + (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6))) + (parallel [(set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 8)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<10; i++) + operands[i] = gen_reg_rtx (XFmode); + emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "exp2df2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT)) + (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1)) + (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6))) + (parallel [(set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 8)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<10; i++) + operands[i] = gen_reg_rtx (XFmode); + emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "exp2xf2" + [(set (match_dup 2) (match_operand:XF 1 "register_operand" "")) + (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT)) + (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1)) + (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6))) + (parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_EXP))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=2; i<9; i++) + operands[i] = gen_reg_rtx (XFmode); + emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "expm1df2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) + (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) + (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) + (parallel [(set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 7) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (parallel [(set (match_dup 11) + (unspec:XF [(match_dup 10) (match_dup 9)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 12) + (unspec:XF [(match_dup 10) (match_dup 9)] + UNSPEC_FSCALE_EXP))]) + (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10))) + (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8))) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 14)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx temp; + int i; + + for (i=2; i<15; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (5); /* fldl2e */ + emit_move_insn (operands[3], temp); + emit_move_insn (operands[10], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "expm1sf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) + (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) + (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) + (parallel [(set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 7) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (parallel [(set (match_dup 11) + (unspec:XF [(match_dup 10) (match_dup 9)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 12) + (unspec:XF [(match_dup 10) (match_dup 9)] + UNSPEC_FSCALE_EXP))]) + (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10))) + (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8))) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 14)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx temp; + int i; + + for (i=2; i<15; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (5); /* fldl2e */ + emit_move_insn (operands[3], temp); + emit_move_insn (operands[10], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "expm1xf2" + [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "") + (match_dup 2))) + (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT)) + (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4))) + (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1)) + (parallel [(set (match_dup 7) + (unspec:XF [(match_dup 6) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 8) + (unspec:XF [(match_dup 6) (match_dup 4)] + UNSPEC_FSCALE_EXP))]) + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 8)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 8)] + UNSPEC_FSCALE_EXP))]) + (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9))) + (set (match_operand:XF 0 "register_operand" "") + (plus:XF (match_dup 12) (match_dup 7)))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + int i; + + for (i=2; i<13; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (5); /* fldl2e */ + emit_move_insn (operands[2], temp); + emit_move_insn (operands[9], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "ldexpdf3" + [(set (match_dup 3) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 4) + (float:XF (match_operand:SI 2 "register_operand" ""))) + (parallel [(set (match_dup 5) + (unspec:XF [(match_dup 3) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 6) + (unspec:XF [(match_dup 3) (match_dup 4)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 5)))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=3; i<7; i++) + operands[i] = gen_reg_rtx (XFmode); +}) + +(define_expand "ldexpsf3" + [(set (match_dup 3) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 4) + (float:XF (match_operand:SI 2 "register_operand" ""))) + (parallel [(set (match_dup 5) + (unspec:XF [(match_dup 3) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 6) + (unspec:XF [(match_dup 3) (match_dup 4)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 5)))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=3; i<7; i++) + operands[i] = gen_reg_rtx (XFmode); +}) + +(define_expand "ldexpxf3" + [(set (match_dup 3) + (float:XF (match_operand:SI 2 "register_operand" ""))) + (parallel [(set (match_operand:XF 0 " register_operand" "") + (unspec:XF [(match_operand:XF 1 "register_operand" "") + (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 4) + (unspec:XF [(match_dup 1) (match_dup 3)] + UNSPEC_FSCALE_EXP))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" +{ + int i; + + for (i=3; i<5; i++) + operands[i] = gen_reg_rtx (XFmode); }) + +(define_insn "frndintxf2" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "frndint" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_expand "rintdf2" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2 (op0, op1)); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "rintsf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extendsfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2 (op0, op1)); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "rintxf2" + [(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 (operands[0], operands[1])); + DONE; +}) + +(define_insn_and_split "*fistdi2_1" + [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") + (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] +{ + if (memory_operand (operands[0], VOIDmode)) + emit_insn (gen_fistdi2 (operands[0], operands[1])); + else + { + operands[2] = assign_386_stack_local (DImode, SLOT_TEMP); + emit_insn (gen_fistdi2_with_temp (operands[0], operands[1], + operands[2])); + } + DONE; +} + [(set_attr "type" "fpspc") + (set_attr "mode" "DI")]) + +(define_insn "fistdi2" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST)) + (clobber (match_scratch:XF 2 "=&1f"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "* return output_fix_trunc (insn, operands, 0);" + [(set_attr "type" "fpspc") + (set_attr "mode" "DI")]) + +(define_insn "fistdi2_with_temp" + [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") + (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST)) + (clobber (match_operand:DI 2 "memory_operand" "=m,m")) + (clobber (match_scratch:XF 3 "=&1f,&1f"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "#" + [(set_attr "type" "fpspc") + (set_attr "mode" "DI")]) + +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST)) + (clobber (match_operand:DI 2 "memory_operand" "")) + (clobber (match_scratch 3 ""))] + "reload_completed" + [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST)) + (clobber (match_dup 3))]) + (set (match_dup 0) (match_dup 2))] + "") + +(define_split + [(set (match_operand:DI 0 "memory_operand" "") + (unspec:DI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST)) + (clobber (match_operand:DI 2 "memory_operand" "")) + (clobber (match_scratch 3 ""))] + "reload_completed" + [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST)) + (clobber (match_dup 3))])] + "") + +(define_insn_and_split "*fist<mode>2_1" + [(set (match_operand:X87MODEI12 0 "register_operand" "=r") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] +{ + operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP); + emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1], + operands[2])); + DONE; +} + [(set_attr "type" "fpspc") + (set_attr "mode" "<MODE>")]) + +(define_insn "fist<mode>2" + [(set (match_operand:X87MODEI12 0 "memory_operand" "=m") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "* return output_fix_trunc (insn, operands, 0);" + [(set_attr "type" "fpspc") + (set_attr "mode" "<MODE>")]) + +(define_insn "fist<mode>2_with_temp" + [(set (match_operand:X87MODEI12 0 "register_operand" "=r") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST)) + (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "#" + [(set_attr "type" "fpspc") + (set_attr "mode" "<MODE>")]) + +(define_split + [(set (match_operand:X87MODEI12 0 "register_operand" "") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST)) + (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))] + "reload_completed" + [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)] + UNSPEC_FIST)) + (set (match_dup 0) (match_dup 2))] + "") + +(define_split + [(set (match_operand:X87MODEI12 0 "memory_operand" "") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST)) + (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))] + "reload_completed" + [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)] + UNSPEC_FIST))] + "") + +(define_expand "lrint<mode>2" + [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "") + (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "") + +;; 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[I387_FLOOR] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR); + + 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)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fldcw\t%3\n\tfrndint\n\tfldcw\t%2" + [(set_attr "type" "frndint") + (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" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_floor (op0, op1)); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "floorsf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extendsfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_floor (op0, op1)); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_insn_and_split "*fist<mode>2_floor_1" + [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r") + (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST_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[I387_FLOOR] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR); + if (memory_operand (operands[0], VOIDmode)) + emit_insn (gen_fist<mode>2_floor (operands[0], operands[1], + operands[2], operands[3])); + else + { + operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP); + emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1], + operands[2], operands[3], + operands[4])); + } + DONE; +} + [(set_attr "type" "fistp") + (set_attr "i387_cw" "floor") + (set_attr "mode" "<MODE>")]) + +(define_insn "fistdi2_floor" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST_FLOOR)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m")) + (clobber (match_scratch:XF 4 "=&1f"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "* return output_fix_trunc (insn, operands, 0);" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "floor") + (set_attr "mode" "DI")]) + +(define_insn "fistdi2_floor_with_temp" + [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") + (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST_FLOOR)) + (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:XF 5 "=&1f,&1f"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "#" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "floor") + (set_attr "mode" "DI")]) + +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_FLOOR)) + (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) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR)) + (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" "") + (unspec:DI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_FLOOR)) + (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) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR)) + (use (match_dup 2)) + (use (match_dup 3)) + (clobber (match_dup 5))])] + "") + +(define_insn "fist<mode>2_floor" + [(set (match_operand:X87MODEI12 0 "memory_operand" "=m") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST_FLOOR)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "* return output_fix_trunc (insn, operands, 0);" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "floor") + (set_attr "mode" "<MODE>")]) + +(define_insn "fist<mode>2_floor_with_temp" + [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST_FLOOR)) + (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_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "#" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "floor") + (set_attr "mode" "<MODE>")]) + +(define_split + [(set (match_operand:X87MODEI12 0 "register_operand" "") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_FLOOR)) + (use (match_operand:HI 2 "memory_operand" "")) + (use (match_operand:HI 3 "memory_operand" "")) + (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))] + "reload_completed" + [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)] + UNSPEC_FIST_FLOOR)) + (use (match_dup 2)) + (use (match_dup 3))]) + (set (match_dup 0) (match_dup 4))] + "") + +(define_split + [(set (match_operand:X87MODEI12 0 "memory_operand" "") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_FLOOR)) + (use (match_operand:HI 2 "memory_operand" "")) + (use (match_operand:HI 3 "memory_operand" "")) + (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))] + "reload_completed" + [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)] + UNSPEC_FIST_FLOOR)) + (use (match_dup 2)) + (use (match_dup 3))])] + "") + +(define_expand "lfloor<mode>2" + [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "") + (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_FLOOR)) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "") + +;; 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 + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] +{ + ix86_optimize_mode_switching[I387_CEIL] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL); + + 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_i387" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_CEIL)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fldcw\t%3\n\tfrndint\n\tfldcw\t%2" + [(set_attr "type" "frndint") + (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" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_ceil (op0, op1)); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "ceilsf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extendsfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_ceil (op0, op1)); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_insn_and_split "*fist<mode>2_ceil_1" + [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r") + (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST_CEIL)) + (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[I387_CEIL] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL); + if (memory_operand (operands[0], VOIDmode)) + emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1], + operands[2], operands[3])); + else + { + operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP); + emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1], + operands[2], operands[3], + operands[4])); + } + DONE; +} + [(set_attr "type" "fistp") + (set_attr "i387_cw" "ceil") + (set_attr "mode" "<MODE>")]) + +(define_insn "fistdi2_ceil" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST_CEIL)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m")) + (clobber (match_scratch:XF 4 "=&1f"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "* return output_fix_trunc (insn, operands, 0);" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "ceil") + (set_attr "mode" "DI")]) + +(define_insn "fistdi2_ceil_with_temp" + [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") + (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST_CEIL)) + (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:XF 5 "=&1f,&1f"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "#" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "ceil") + (set_attr "mode" "DI")]) + +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_CEIL)) + (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) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL)) + (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" "") + (unspec:DI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_CEIL)) + (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) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL)) + (use (match_dup 2)) + (use (match_dup 3)) + (clobber (match_dup 5))])] + "") + +(define_insn "fist<mode>2_ceil" + [(set (match_operand:X87MODEI12 0 "memory_operand" "=m") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] + UNSPEC_FIST_CEIL)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "* return output_fix_trunc (insn, operands, 0);" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "ceil") + (set_attr "mode" "<MODE>")]) + +(define_insn "fist<mode>2_ceil_with_temp" + [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")] + UNSPEC_FIST_CEIL)) + (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_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "#" + [(set_attr "type" "fistp") + (set_attr "i387_cw" "ceil") + (set_attr "mode" "<MODE>")]) + +(define_split + [(set (match_operand:X87MODEI12 0 "register_operand" "") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_CEIL)) + (use (match_operand:HI 2 "memory_operand" "")) + (use (match_operand:HI 3 "memory_operand" "")) + (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))] + "reload_completed" + [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)] + UNSPEC_FIST_CEIL)) + (use (match_dup 2)) + (use (match_dup 3))]) + (set (match_dup 0) (match_dup 4))] + "") + +(define_split + [(set (match_operand:X87MODEI12 0 "memory_operand" "") + (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_CEIL)) + (use (match_operand:HI 2 "memory_operand" "")) + (use (match_operand:HI 3 "memory_operand" "")) + (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))] + "reload_completed" + [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)] + UNSPEC_FIST_CEIL)) + (use (match_dup 2)) + (use (match_dup 3))])] + "") + +(define_expand "lceil<mode>2" + [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "") + (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST_CEIL)) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" + "") + +;; 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 + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] +{ + ix86_optimize_mode_switching[I387_TRUNC] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC); + + 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_i387" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_TRUNC)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fldcw\t%3\n\tfrndint\n\tfldcw\t%2" + [(set_attr "type" "frndint") + (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" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_trunc (op0, op1)); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "btruncsf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extendsfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_trunc (op0, op1)); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); + DONE; +}) + +;; 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 + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(const_int 0)] +{ + ix86_optimize_mode_switching[I387_MASK_PM] = 1; + + operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED); + operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM); + + 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_i387" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT_MASK_PM)) + (use (match_operand:HI 2 "memory_operand" "m")) + (use (match_operand:HI 3 "memory_operand" "m"))] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations" + "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2" + [(set_attr "type" "frndint") + (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" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extenddfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_mask_pm (op0, op1)); + + emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0)); + DONE; +}) + +(define_expand "nearbyintsf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + + emit_insn (gen_extendsfxf2 (op1, operands[1])); + emit_insn (gen_frndintxf2_mask_pm (op0, op1)); + + emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0)); + DONE; +}) + + ;; Block operation instructions (define_insn "cld" - [(set (reg:SI 19) (const_int 0))] + [(set (reg:SI DIRFLAG_REG) (const_int 0))] "" "cld" [(set_attr "type" "cld")]) -(define_expand "movstrsi" +(define_expand "movmemsi" [(use (match_operand:BLK 0 "memory_operand" "")) (use (match_operand:BLK 1 "memory_operand" "")) (use (match_operand:SI 2 "nonmemory_operand" "")) (use (match_operand:SI 3 "const_int_operand" ""))] - "! optimize_size" + "! optimize_size || TARGET_INLINE_ALL_STRINGOPS" { - if (ix86_expand_movstr (operands[0], operands[1], operands[2], operands[3])) + if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3])) DONE; else FAIL; }) -(define_expand "movstrdi" +(define_expand "movmemdi" [(use (match_operand:BLK 0 "memory_operand" "")) (use (match_operand:BLK 1 "memory_operand" "")) (use (match_operand:DI 2 "nonmemory_operand" "")) (use (match_operand:DI 3 "const_int_operand" ""))] "TARGET_64BIT" { - if (ix86_expand_movstr (operands[0], operands[1], operands[2], operands[3])) + if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3])) DONE; else FAIL; @@ -15415,9 +18025,9 @@ [(set (match_dup 4) (match_operand 3 "memory_operand" "")) (set (match_operand 1 "memory_operand" "") (match_dup 4)) (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5)) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" { rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))); @@ -15445,7 +18055,7 @@ (match_operand 4 "" "")) (set (match_operand 2 "register_operand" "") (match_operand 5 "" "")) - (use (reg:SI 19))])] + (use (reg:SI DIRFLAG_REG))])] "TARGET_SINGLE_STRINGOP || optimize_size" "") @@ -15458,7 +18068,7 @@ (set (match_operand:DI 1 "register_operand" "=S") (plus:DI (match_dup 3) (const_int 8))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "movsq" [(set_attr "type" "str") @@ -15474,7 +18084,7 @@ (set (match_operand:SI 1 "register_operand" "=S") (plus:SI (match_dup 3) (const_int 4))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "{movsl|movsd}" [(set_attr "type" "str") @@ -15490,7 +18100,7 @@ (set (match_operand:DI 1 "register_operand" "=S") (plus:DI (match_dup 3) (const_int 4))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "{movsl|movsd}" [(set_attr "type" "str") @@ -15506,7 +18116,7 @@ (set (match_operand:SI 1 "register_operand" "=S") (plus:SI (match_dup 3) (const_int 2))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "movsw" [(set_attr "type" "str") @@ -15522,7 +18132,7 @@ (set (match_operand:DI 1 "register_operand" "=S") (plus:DI (match_dup 3) (const_int 2))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "movsw" [(set_attr "type" "str") @@ -15538,7 +18148,7 @@ (set (match_operand:SI 1 "register_operand" "=S") (plus:SI (match_dup 3) (const_int 1))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "movsb" [(set_attr "type" "str") @@ -15554,7 +18164,7 @@ (set (match_operand:DI 1 "register_operand" "=S") (plus:DI (match_dup 3) (const_int 1))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "movsb" [(set_attr "type" "str") @@ -15570,7 +18180,7 @@ (set (match_operand 1 "memory_operand" "") (match_operand 3 "memory_operand" "")) (use (match_dup 4)) - (use (reg:SI 19))])] + (use (reg:SI DIRFLAG_REG))])] "" "") @@ -15586,7 +18196,7 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT" "{rep\;movsq|rep movsq}" [(set_attr "type" "str") @@ -15606,7 +18216,7 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT" "{rep\;movsl|rep movsd}" [(set_attr "type" "str") @@ -15626,7 +18236,7 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT" "{rep\;movsl|rep movsd}" [(set_attr "type" "str") @@ -15644,7 +18254,7 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT" "{rep\;movsb|rep movsb}" [(set_attr "type" "str") @@ -15662,7 +18272,7 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT" "{rep\;movsb|rep movsb}" [(set_attr "type" "str") @@ -15670,25 +18280,35 @@ (set_attr "memory" "both") (set_attr "mode" "SI")]) -(define_expand "clrstrsi" +(define_expand "setmemsi" [(use (match_operand:BLK 0 "memory_operand" "")) (use (match_operand:SI 1 "nonmemory_operand" "")) - (use (match_operand 2 "const_int_operand" ""))] + (use (match_operand 2 "const_int_operand" "")) + (use (match_operand 3 "const_int_operand" ""))] "" { - if (ix86_expand_clrstr (operands[0], operands[1], operands[2])) + /* If value to set is not zero, use the library routine. */ + if (operands[2] != const0_rtx) + FAIL; + + if (ix86_expand_clrmem (operands[0], operands[1], operands[3])) DONE; else FAIL; }) -(define_expand "clrstrdi" +(define_expand "setmemdi" [(use (match_operand:BLK 0 "memory_operand" "")) (use (match_operand:DI 1 "nonmemory_operand" "")) - (use (match_operand 2 "const_int_operand" ""))] + (use (match_operand 2 "const_int_operand" "")) + (use (match_operand 3 "const_int_operand" ""))] "TARGET_64BIT" { - if (ix86_expand_clrstr (operands[0], operands[1], operands[2])) + /* If value to set is not zero, use the library routine. */ + if (operands[2] != const0_rtx) + FAIL; + + if (ix86_expand_clrmem (operands[0], operands[1], operands[3])) DONE; else FAIL; @@ -15702,7 +18322,7 @@ (match_operand 2 "register_operand" "")) (parallel [(set (match_operand 0 "register_operand" "") (match_dup 3)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" { if (GET_MODE (operands[1]) != GET_MODE (operands[2])) @@ -15726,17 +18346,17 @@ (match_operand 2 "register_operand" "")) (set (match_operand 0 "register_operand" "") (match_operand 3 "" "")) - (use (reg:SI 19))])] + (use (reg:SI DIRFLAG_REG))])] "TARGET_SINGLE_STRINGOP || optimize_size" "") (define_insn "*strsetdi_rex_1" - [(set (mem:SI (match_operand:DI 1 "register_operand" "0")) - (match_operand:SI 2 "register_operand" "a")) + [(set (mem:DI (match_operand:DI 1 "register_operand" "0")) + (match_operand:DI 2 "register_operand" "a")) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (match_dup 1) (const_int 8))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "stosq" [(set_attr "type" "str") @@ -15749,7 +18369,7 @@ (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (match_dup 1) (const_int 4))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "{stosl|stosd}" [(set_attr "type" "str") @@ -15762,7 +18382,7 @@ (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (match_dup 1) (const_int 4))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "{stosl|stosd}" [(set_attr "type" "str") @@ -15775,7 +18395,7 @@ (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (match_dup 1) (const_int 2))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "stosw" [(set_attr "type" "str") @@ -15788,7 +18408,7 @@ (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (match_dup 1) (const_int 2))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "stosw" [(set_attr "type" "str") @@ -15801,7 +18421,7 @@ (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (match_dup 1) (const_int 1))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "stosb" [(set_attr "type" "str") @@ -15814,7 +18434,7 @@ (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (match_dup 1) (const_int 1))) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)" "stosb" [(set_attr "type" "str") @@ -15828,7 +18448,7 @@ (set (match_operand 2 "memory_operand" "") (const_int 0)) (use (match_operand 3 "register_operand" "")) (use (match_dup 1)) - (use (reg:SI 19))])] + (use (reg:SI DIRFLAG_REG))])] "" "") @@ -15842,7 +18462,7 @@ (const_int 0)) (use (match_operand:DI 2 "register_operand" "a")) (use (match_dup 4)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT" "{rep\;stosq|rep stosq}" [(set_attr "type" "str") @@ -15860,7 +18480,7 @@ (const_int 0)) (use (match_operand:SI 2 "register_operand" "a")) (use (match_dup 4)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT" "{rep\;stosl|rep stosd}" [(set_attr "type" "str") @@ -15878,7 +18498,7 @@ (const_int 0)) (use (match_operand:SI 2 "register_operand" "a")) (use (match_dup 4)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT" "{rep\;stosl|rep stosd}" [(set_attr "type" "str") @@ -15895,7 +18515,7 @@ (const_int 0)) (use (match_operand:QI 2 "register_operand" "a")) (use (match_dup 4)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "!TARGET_64BIT" "{rep\;stosb|rep stosb}" [(set_attr "type" "str") @@ -15912,7 +18532,7 @@ (const_int 0)) (use (match_operand:QI 2 "register_operand" "a")) (use (match_dup 4)) - (use (reg:SI 19))] + (use (reg:SI DIRFLAG_REG))] "TARGET_64BIT" "{rep\;stosb|rep stosb}" [(set_attr "type" "str") @@ -15920,7 +18540,7 @@ (set_attr "memory" "store") (set_attr "mode" "QI")]) -(define_expand "cmpstrsi" +(define_expand "cmpstrnsi" [(set (match_operand:SI 0 "register_operand" "") (compare:SI (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) @@ -15961,8 +18581,8 @@ emit_move_insn (operands[0], const0_rtx); DONE; } - emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align, - operands[1], operands[2])); + emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align, + operands[1], operands[2])); } else { @@ -15970,8 +18590,8 @@ emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); else emit_insn (gen_cmpsi_1 (countreg, countreg)); - emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align, - operands[1], operands[2])); + emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align, + operands[1], operands[2])); } outlow = gen_lowpart (QImode, out); @@ -15988,13 +18608,13 @@ (define_expand "cmpintqi" [(set (match_dup 1) - (gtu:QI (reg:CC 17) (const_int 0))) + (gtu:QI (reg:CC FLAGS_REG) (const_int 0))) (set (match_dup 2) - (ltu:QI (reg:CC 17) (const_int 0))) + (ltu:QI (reg:CC FLAGS_REG) (const_int 0))) (parallel [(set (match_operand:QI 0 "register_operand" "") (minus:QI (match_dup 1) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "operands[1] = gen_reg_rtx (QImode); operands[2] = gen_reg_rtx (QImode);") @@ -16002,26 +18622,26 @@ ;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is ;; zero. Emit extra code to make sure that a zero-length compare is EQ. -(define_expand "cmpstrqi_nz_1" - [(parallel [(set (reg:CC 17) +(define_expand "cmpstrnqi_nz_1" + [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_operand 4 "memory_operand" "") (match_operand 5 "memory_operand" ""))) (use (match_operand 2 "register_operand" "")) (use (match_operand:SI 3 "immediate_operand" "")) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand 0 "register_operand" "")) (clobber (match_operand 1 "register_operand" "")) (clobber (match_dup 2))])] "" "") -(define_insn "*cmpstrqi_nz_1" - [(set (reg:CC 17) +(define_insn "*cmpstrnqi_nz_1" + [(set (reg:CC FLAGS_REG) (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0")) (mem:BLK (match_operand:SI 5 "register_operand" "1")))) (use (match_operand:SI 6 "register_operand" "2")) (use (match_operand:SI 3 "immediate_operand" "i")) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:SI 0 "register_operand" "=S")) (clobber (match_operand:SI 1 "register_operand" "=D")) (clobber (match_operand:SI 2 "register_operand" "=c"))] @@ -16031,13 +18651,13 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "*cmpstrqi_nz_rex_1" - [(set (reg:CC 17) +(define_insn "*cmpstrnqi_nz_rex_1" + [(set (reg:CC FLAGS_REG) (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0")) (mem:BLK (match_operand:DI 5 "register_operand" "1")))) (use (match_operand:DI 6 "register_operand" "2")) (use (match_operand:SI 3 "immediate_operand" "i")) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:DI 0 "register_operand" "=S")) (clobber (match_operand:DI 1 "register_operand" "=D")) (clobber (match_operand:DI 2 "register_operand" "=c"))] @@ -16049,32 +18669,32 @@ ;; The same, but the count is not known to not be zero. -(define_expand "cmpstrqi_1" - [(parallel [(set (reg:CC 17) +(define_expand "cmpstrnqi_1" + [(parallel [(set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand 2 "register_operand" "") (const_int 0)) (compare:CC (match_operand 4 "memory_operand" "") (match_operand 5 "memory_operand" "")) (const_int 0))) (use (match_operand:SI 3 "immediate_operand" "")) - (use (reg:CC 17)) - (use (reg:SI 19)) + (use (reg:CC FLAGS_REG)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand 0 "register_operand" "")) (clobber (match_operand 1 "register_operand" "")) (clobber (match_dup 2))])] "" "") -(define_insn "*cmpstrqi_1" - [(set (reg:CC 17) +(define_insn "*cmpstrnqi_1" + [(set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2") (const_int 0)) (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0")) (mem:BLK (match_operand:SI 5 "register_operand" "1"))) (const_int 0))) (use (match_operand:SI 3 "immediate_operand" "i")) - (use (reg:CC 17)) - (use (reg:SI 19)) + (use (reg:CC FLAGS_REG)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:SI 0 "register_operand" "=S")) (clobber (match_operand:SI 1 "register_operand" "=D")) (clobber (match_operand:SI 2 "register_operand" "=c"))] @@ -16084,16 +18704,16 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "*cmpstrqi_rex_1" - [(set (reg:CC 17) +(define_insn "*cmpstrnqi_rex_1" + [(set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2") (const_int 0)) (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0")) (mem:BLK (match_operand:DI 5 "register_operand" "1"))) (const_int 0))) (use (match_operand:SI 3 "immediate_operand" "i")) - (use (reg:CC 17)) - (use (reg:SI 19)) + (use (reg:CC FLAGS_REG)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:DI 0 "register_operand" "=S")) (clobber (match_operand:DI 1 "register_operand" "=D")) (clobber (match_operand:DI 2 "register_operand" "=c"))] @@ -16131,9 +18751,9 @@ (define_expand "strlenqi_1" [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" "")) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand 1 "register_operand" "")) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") @@ -16143,9 +18763,9 @@ (match_operand:QI 2 "register_operand" "a") (match_operand:SI 3 "immediate_operand" "i") (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS)) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:SI 1 "register_operand" "=D")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" "repnz{\;| }scasb" [(set_attr "type" "str") @@ -16158,18 +18778,18 @@ (match_operand:QI 2 "register_operand" "a") (match_operand:DI 3 "immediate_operand" "i") (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS)) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:DI 1 "register_operand" "=D")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "repnz{\;| }scasb" [(set_attr "type" "str") (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -;; Peephole optimizations to clean up after cmpstr*. This should be +;; Peephole optimizations to clean up after cmpstrn*. This should be ;; handled in combine, but it is not currently up to the task. -;; When used for their truth value, the cmpstr* expanders generate +;; When used for their truth value, the cmpstrn* expanders generate ;; code like this: ;; ;; repz cmpsb @@ -16180,71 +18800,71 @@ ;; ;; The intermediate three instructions are unnecessary. -;; This one handles cmpstr*_nz_1... +;; This one handles cmpstrn*_nz_1... (define_peephole2 [(parallel[ - (set (reg:CC 17) + (set (reg:CC FLAGS_REG) (compare:CC (mem:BLK (match_operand 4 "register_operand" "")) (mem:BLK (match_operand 5 "register_operand" "")))) (use (match_operand 6 "register_operand" "")) (use (match_operand:SI 3 "immediate_operand" "")) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand 0 "register_operand" "")) (clobber (match_operand 1 "register_operand" "")) (clobber (match_operand 2 "register_operand" ""))]) (set (match_operand:QI 7 "register_operand" "") - (gtu:QI (reg:CC 17) (const_int 0))) + (gtu:QI (reg:CC FLAGS_REG) (const_int 0))) (set (match_operand:QI 8 "register_operand" "") - (ltu:QI (reg:CC 17) (const_int 0))) - (set (reg 17) + (ltu:QI (reg:CC FLAGS_REG) (const_int 0))) + (set (reg FLAGS_REG) (compare (match_dup 7) (match_dup 8))) ] "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])" [(parallel[ - (set (reg:CC 17) + (set (reg:CC FLAGS_REG) (compare:CC (mem:BLK (match_dup 4)) (mem:BLK (match_dup 5)))) (use (match_dup 6)) (use (match_dup 3)) - (use (reg:SI 19)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_dup 0)) (clobber (match_dup 1)) (clobber (match_dup 2))])] "") -;; ...and this one handles cmpstr*_1. +;; ...and this one handles cmpstrn*_1. (define_peephole2 [(parallel[ - (set (reg:CC 17) + (set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand 6 "register_operand" "") (const_int 0)) (compare:CC (mem:BLK (match_operand 4 "register_operand" "")) (mem:BLK (match_operand 5 "register_operand" ""))) (const_int 0))) (use (match_operand:SI 3 "immediate_operand" "")) - (use (reg:CC 17)) - (use (reg:SI 19)) + (use (reg:CC FLAGS_REG)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_operand 0 "register_operand" "")) (clobber (match_operand 1 "register_operand" "")) (clobber (match_operand 2 "register_operand" ""))]) (set (match_operand:QI 7 "register_operand" "") - (gtu:QI (reg:CC 17) (const_int 0))) + (gtu:QI (reg:CC FLAGS_REG) (const_int 0))) (set (match_operand:QI 8 "register_operand" "") - (ltu:QI (reg:CC 17) (const_int 0))) - (set (reg 17) + (ltu:QI (reg:CC FLAGS_REG) (const_int 0))) + (set (reg FLAGS_REG) (compare (match_dup 7) (match_dup 8))) ] "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])" [(parallel[ - (set (reg:CC 17) + (set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_dup 6) (const_int 0)) (compare:CC (mem:BLK (match_dup 4)) (mem:BLK (match_dup 5))) (const_int 0))) (use (match_dup 3)) - (use (reg:CC 17)) - (use (reg:SI 19)) + (use (reg:CC FLAGS_REG)) + (use (reg:SI DIRFLAG_REG)) (clobber (match_dup 0)) (clobber (match_dup 1)) (clobber (match_dup 2))])] @@ -16267,7 +18887,7 @@ (if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "") (const_int -1) (const_int 0))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" "sbb{q}\t%0, %0" ; Since we don't have the proper number of operands for an alu insn, @@ -16279,10 +18899,10 @@ (set_attr "mode" "DI") (set_attr "length_immediate" "0")]) -(define_insn "movdicc_c_rex64" +(define_insn "*movdicc_c_rex64" [(set (match_operand:DI 0 "register_operand" "=r,r") (if_then_else:DI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (match_operand:DI 2 "nonimmediate_operand" "rm,0") (match_operand:DI 3 "nonimmediate_operand" "0,rm")))] "TARGET_64BIT && TARGET_CMOVE @@ -16310,7 +18930,7 @@ (if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "") (const_int -1) (const_int 0))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "" "sbb{l}\t%0, %0" ; Since we don't have the proper number of operands for an alu insn, @@ -16325,7 +18945,7 @@ (define_insn "*movsicc_noc" [(set (match_operand:SI 0 "register_operand" "=r,r") (if_then_else:SI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (match_operand:SI 2 "nonimmediate_operand" "rm,0") (match_operand:SI 3 "nonimmediate_operand" "0,rm")))] "TARGET_CMOVE @@ -16347,7 +18967,7 @@ (define_insn "*movhicc_noc" [(set (match_operand:HI 0 "register_operand" "=r,r") (if_then_else:HI (match_operator 1 "ix86_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (match_operand:HI 2 "nonimmediate_operand" "rm,0") (match_operand:HI 3 "nonimmediate_operand" "0,rm")))] "TARGET_CMOVE @@ -16369,7 +18989,8 @@ (define_insn_and_split "*movqicc_noc" [(set (match_operand:QI 0 "register_operand" "=r,r") (if_then_else:QI (match_operator 1 "ix86_comparison_operator" - [(match_operand 4 "flags_reg_operand" "") (const_int 0)]) + [(match_operand 4 "flags_reg_operand" "") + (const_int 0)]) (match_operand:QI 2 "register_operand" "r,0") (match_operand:QI 3 "register_operand" "0,r")))] "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL" @@ -16390,16 +19011,16 @@ (if_then_else:SF (match_operand 1 "comparison_operator" "") (match_operand:SF 2 "register_operand" "") (match_operand:SF 3 "register_operand" "")))] - "TARGET_CMOVE" + "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH" "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") -(define_insn "*movsfcc_1" - [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f") +(define_insn "*movsfcc_1_387" + [(set (match_operand:SF 0 "register_operand" "=f,f,r,r") (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" - [(reg 17) (const_int 0)]) - (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0") - (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] - "TARGET_CMOVE + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0") + (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))] + "TARGET_80387 && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ fcmov%F1\t{%2, %0|%0, %2} @@ -16414,16 +19035,16 @@ (if_then_else:DF (match_operand 1 "comparison_operator" "") (match_operand:DF 2 "register_operand" "") (match_operand:DF 3 "register_operand" "")))] - "TARGET_CMOVE" + "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)" "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") (define_insn "*movdfcc_1" - [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f") + [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" - [(reg 17) (const_int 0)]) - (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0") - (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] - "!TARGET_64BIT && TARGET_CMOVE + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0") + (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))] + "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ fcmov%F1\t{%2, %0|%0, %2} @@ -16434,12 +19055,12 @@ (set_attr "mode" "DF")]) (define_insn "*movdfcc_1_rex64" - [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f") + [(set (match_operand:DF 0 "register_operand" "=f,f,r,r") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" - [(reg 17) (const_int 0)]) - (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f") - (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))] - "TARGET_64BIT && TARGET_CMOVE + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0") + (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))] + "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ fcmov%F1\t{%2, %0|%0, %2} @@ -16452,7 +19073,8 @@ (define_split [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" - [(match_operand 4 "flags_reg_operand" "") (const_int 0)]) + [(match_operand 4 "flags_reg_operand" "") + (const_int 0)]) (match_operand:DF 2 "nonimmediate_operand" "") (match_operand:DF 3 "nonimmediate_operand" "")))] "!TARGET_64BIT && reload_completed" @@ -16473,71 +19095,134 @@ (if_then_else:XF (match_operand 1 "comparison_operator" "") (match_operand:XF 2 "register_operand" "") (match_operand:XF 3 "register_operand" "")))] - "TARGET_CMOVE" + "TARGET_80387 && TARGET_CMOVE" "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") (define_insn "*movxfcc_1" [(set (match_operand:XF 0 "register_operand" "=f,f") (if_then_else:XF (match_operator 1 "fcmov_comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (match_operand:XF 2 "register_operand" "f,0") (match_operand:XF 3 "register_operand" "0,f")))] - "TARGET_CMOVE" + "TARGET_80387 && TARGET_CMOVE" "@ fcmov%F1\t{%2, %0|%0, %2} fcmov%f1\t{%3, %0|%0, %3}" [(set_attr "type" "fcmov") (set_attr "mode" "XF")]) -(define_expand "minsf3" - [(parallel [ - (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))])] - "TARGET_SSE" - "") +;; These versions of the min/max patterns are intentionally ignorant of +;; their behavior wrt -0.0 and NaN (via the commutative operand mark). +;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator +;; are undefined in this condition, we're certain this is correct. -(define_insn "*minsf" - [(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x") - (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "0,0,f#x") - (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x,0")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE && TARGET_IEEE_FP" - "#") +(define_insn "sminsf3" + [(set (match_operand:SF 0 "register_operand" "=x") + (smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0") + (match_operand:SF 2 "nonimmediate_operand" "xm")))] + "TARGET_SSE_MATH" + "minss\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "SF")]) -(define_insn "*minsf_nonieee" - [(set (match_operand:SF 0 "register_operand" "=x#f,f#x") - (if_then_else:SF (lt (match_operand:SF 1 "nonimmediate_operand" "%0,0") - (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE && !TARGET_IEEE_FP - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "#") +(define_insn "smaxsf3" + [(set (match_operand:SF 0 "register_operand" "=x") + (smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0") + (match_operand:SF 2 "nonimmediate_operand" "xm")))] + "TARGET_SSE_MATH" + "maxss\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "SF")]) -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")) - (match_operand:SF 3 "register_operand" "") - (match_operand:SF 4 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] - "SSE_REG_P (operands[0]) && reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (match_dup 0) - (if_then_else:SF (lt (match_dup 1) - (match_dup 2)) - (match_dup 1) - (match_dup 2)))]) +(define_insn "smindf3" + [(set (match_operand:DF 0 "register_operand" "=x") + (smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0") + (match_operand:DF 2 "nonimmediate_operand" "xm")))] + "TARGET_SSE2 && TARGET_SSE_MATH" + "minsd\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "DF")]) + +(define_insn "smaxdf3" + [(set (match_operand:DF 0 "register_operand" "=x") + (smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0") + (match_operand:DF 2 "nonimmediate_operand" "xm")))] + "TARGET_SSE2 && TARGET_SSE_MATH" + "maxsd\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "DF")]) + +;; These versions of the min/max patterns implement exactly the operations +;; min = (op1 < op2 ? op1 : op2) +;; max = (!(op1 < op2) ? op1 : op2) +;; Their operands are not commutative, and thus they may be used in the +;; presence of -0.0 and NaN. + +(define_insn "*ieee_sminsf3" + [(set (match_operand:SF 0 "register_operand" "=x") + (unspec:SF [(match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "nonimmediate_operand" "xm")] + UNSPEC_IEEE_MIN))] + "TARGET_SSE_MATH" + "minss\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "SF")]) + +(define_insn "*ieee_smaxsf3" + [(set (match_operand:SF 0 "register_operand" "=x") + (unspec:SF [(match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "nonimmediate_operand" "xm")] + UNSPEC_IEEE_MAX))] + "TARGET_SSE_MATH" + "maxss\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "SF")]) + +(define_insn "*ieee_smindf3" + [(set (match_operand:DF 0 "register_operand" "=x") + (unspec:DF [(match_operand:DF 1 "register_operand" "0") + (match_operand:DF 2 "nonimmediate_operand" "xm")] + UNSPEC_IEEE_MIN))] + "TARGET_SSE2 && TARGET_SSE_MATH" + "minsd\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "DF")]) + +(define_insn "*ieee_smaxdf3" + [(set (match_operand:DF 0 "register_operand" "=x") + (unspec:DF [(match_operand:DF 1 "register_operand" "0") + (match_operand:DF 2 "nonimmediate_operand" "xm")] + UNSPEC_IEEE_MAX))] + "TARGET_SSE2 && TARGET_SSE_MATH" + "maxsd\t{%2, %0|%0, %2}" + [(set_attr "type" "sseadd") + (set_attr "mode" "DF")]) + +;; Make two stack loads independent: +;; fld aa fld aa +;; fld %st(0) -> fld bb +;; fmul bb fmul %st(1), %st +;; +;; Actually we only match the last two instructions for simplicity. +(define_peephole2 + [(set (match_operand 0 "fp_register_operand" "") + (match_operand 1 "fp_register_operand" "")) + (set (match_dup 0) + (match_operator 2 "binary_fp_operator" + [(match_dup 0) + (match_operand 3 "memory_operand" "")]))] + "REGNO (operands[0]) != REGNO (operands[1])" + [(set (match_dup 0) (match_dup 3)) + (set (match_dup 0) (match_dup 4))] + + ;; The % modifier is not operational anymore in peephole2's, so we have to + ;; swap the operands manually in the case of addition and multiplication. + "if (COMMUTATIVE_ARITH_P (operands[2])) + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]), + operands[0], operands[1]); + else + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]), + operands[1], operands[0]);") ;; Conditional addition patterns (define_expand "addqicc" @@ -16572,282 +19257,6 @@ "TARGET_64BIT" "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") -;; We can't represent the LT test directly. Do this by swapping the operands. - -(define_split - [(set (match_operand:SF 0 "fp_register_operand" "") - (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "register_operand" "")) - (match_operand:SF 3 "register_operand" "") - (match_operand:SF 4 "register_operand" ""))) - (clobber (reg:CC 17))] - "reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (reg:CCFP 17) - (compare:CCFP (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (if_then_else:SF (ge (reg:CCFP 17) (const_int 0)) - (match_dup 1) - (match_dup 2)))]) - -(define_insn "*minsf_sse" - [(set (match_operand:SF 0 "register_operand" "=x") - (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (match_dup 2)))] - "TARGET_SSE && reload_completed" - "minss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -(define_expand "mindf3" - [(parallel [ - (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))])] - "TARGET_SSE2 && TARGET_SSE_MATH" - "#") - -(define_insn "*mindf" - [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y,f#Y") - (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "0,0,f#Y") - (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y,0")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE2 && TARGET_IEEE_FP && TARGET_SSE_MATH" - "#") - -(define_insn "*mindf_nonieee" - [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y") - (if_then_else:DF (lt (match_operand:DF 1 "nonimmediate_operand" "%0,0") - (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "#") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")) - (match_operand:DF 3 "register_operand" "") - (match_operand:DF 4 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] - "SSE_REG_P (operands[0]) && reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (match_dup 0) - (if_then_else:DF (lt (match_dup 1) - (match_dup 2)) - (match_dup 1) - (match_dup 2)))]) - -;; We can't represent the LT test directly. Do this by swapping the operands. -(define_split - [(set (match_operand:DF 0 "fp_register_operand" "") - (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "register_operand" "")) - (match_operand:DF 3 "register_operand" "") - (match_operand:DF 4 "register_operand" ""))) - (clobber (reg:CC 17))] - "reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (reg:CCFP 17) - (compare:CCFP (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (if_then_else:DF (ge (reg:CCFP 17) (const_int 0)) - (match_dup 1) - (match_dup 2)))]) - -(define_insn "*mindf_sse" - [(set (match_operand:DF 0 "register_operand" "=Y") - (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "nonimmediate_operand" "Ym")) - (match_dup 1) - (match_dup 2)))] - "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed" - "minsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "DF")]) - -(define_expand "maxsf3" - [(parallel [ - (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))])] - "TARGET_SSE" - "#") - -(define_insn "*maxsf" - [(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x") - (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "0,0,f#x") - (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x,0")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE && TARGET_IEEE_FP" - "#") - -(define_insn "*maxsf_nonieee" - [(set (match_operand:SF 0 "register_operand" "=x#f,f#x") - (if_then_else:SF (gt (match_operand:SF 1 "nonimmediate_operand" "%0,0") - (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE && !TARGET_IEEE_FP - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "#") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")) - (match_operand:SF 3 "register_operand" "") - (match_operand:SF 4 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] - "SSE_REG_P (operands[0]) && reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (match_dup 0) - (if_then_else:SF (gt (match_dup 1) - (match_dup 2)) - (match_dup 1) - (match_dup 2)))]) - -(define_split - [(set (match_operand:SF 0 "fp_register_operand" "") - (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "register_operand" "")) - (match_operand:SF 3 "register_operand" "") - (match_operand:SF 4 "register_operand" ""))) - (clobber (reg:CC 17))] - "reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (reg:CCFP 17) - (compare:CCFP (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (if_then_else:SF (gt (reg:CCFP 17) (const_int 0)) - (match_dup 1) - (match_dup 2)))]) - -(define_insn "*maxsf_sse" - [(set (match_operand:SF 0 "register_operand" "=x") - (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (match_dup 2)))] - "TARGET_SSE && reload_completed" - "maxss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -(define_expand "maxdf3" - [(parallel [ - (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))])] - "TARGET_SSE2 && TARGET_SSE_MATH" - "#") - -(define_insn "*maxdf" - [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y,f#Y") - (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "0,0,f#Y") - (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y,0")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_IEEE_FP" - "#") - -(define_insn "*maxdf_nonieee" - [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y") - (if_then_else:DF (gt (match_operand:DF 1 "nonimmediate_operand" "%0,0") - (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y")) - (match_dup 1) - (match_dup 2))) - (clobber (reg:CC 17))] - "TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "#") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")) - (match_operand:DF 3 "register_operand" "") - (match_operand:DF 4 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))] - "SSE_REG_P (operands[0]) && reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (match_dup 0) - (if_then_else:DF (gt (match_dup 1) - (match_dup 2)) - (match_dup 1) - (match_dup 2)))]) - -(define_split - [(set (match_operand:DF 0 "fp_register_operand" "") - (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "register_operand" "")) - (match_operand:DF 3 "register_operand" "") - (match_operand:DF 4 "register_operand" ""))) - (clobber (reg:CC 17))] - "reload_completed - && ((operands_match_p (operands[1], operands[3]) - && operands_match_p (operands[2], operands[4])) - || (operands_match_p (operands[1], operands[4]) - && operands_match_p (operands[2], operands[3])))" - [(set (reg:CCFP 17) - (compare:CCFP (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (if_then_else:DF (gt (reg:CCFP 17) (const_int 0)) - (match_dup 1) - (match_dup 2)))]) - -(define_insn "*maxdf_sse" - [(set (match_operand:DF 0 "register_operand" "=Y") - (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "nonimmediate_operand" "Ym")) - (match_dup 1) - (match_dup 2)))] - "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed" - "maxsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "DF")]) ;; Misc patterns (?) @@ -16864,7 +19273,7 @@ [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (match_operand:SI 1 "register_operand" "0,r") (match_operand:SI 2 "immediate_operand" "i,i"))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] "!TARGET_64BIT" { @@ -16889,7 +19298,7 @@ return "lea{l}\t{%a2, %0|%0, %a2}"; default: - abort (); + gcc_unreachable (); } } [(set (attr "type") @@ -16905,7 +19314,7 @@ [(set (match_operand:DI 0 "register_operand" "=r,r") (plus:DI (match_operand:DI 1 "register_operand" "0,r") (match_operand:DI 2 "x86_64_immediate_operand" "e,e"))) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] "TARGET_64BIT" { @@ -16932,7 +19341,7 @@ return "lea{q}\t{%a2, %0|%0, %a2}"; default: - abort (); + gcc_unreachable (); } } [(set (attr "type") @@ -16949,7 +19358,7 @@ (plus:DI (match_operand:DI 1 "register_operand" "0,r") (match_operand:DI 3 "immediate_operand" "i,i"))) (use (match_operand:DI 2 "register_operand" "r,r")) - (clobber (reg:CC 17)) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] "TARGET_64BIT" { @@ -16963,372 +19372,12 @@ return "lea{q}\t{%a2, %0|%0, %a2}"; default: - abort (); + gcc_unreachable (); } } [(set_attr "type" "alu,lea") (set_attr "mode" "DI")]) -;; Placeholder for the conditional moves. This one is split either to SSE -;; based moves emulation or to usual cmove sequence. Little bit unfortunate -;; fact is that compares supported by the cmp??ss instructions are exactly -;; swapped of those supported by cmove sequence. -;; The EQ/NE comparisons also needs bit care, since they are not directly -;; supported by i387 comparisons and we do need to emit two conditional moves -;; in tandem. - -(define_insn "sse_movsfcc" - [(set (match_operand:SF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?f#xr,?f#xr,?r#xf,?r#xf,?r#xf,?r#xf") - (if_then_else:SF (match_operator 1 "sse_comparison_operator" - [(match_operand:SF 4 "nonimmediate_operand" "0#fx,x#fx,f#x,f#x,xm#f,xm#f,f#x,f#x,xm#f,xm#f") - (match_operand:SF 5 "nonimmediate_operand" "xm#f,xm#f,f#x,f#x,x#f,x#f,f#x,f#x,x#f,x#f")]) - (match_operand:SF 2 "nonimmediate_operand" "x#fr,0#fr,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx,0#rx") - (match_operand:SF 3 "nonimmediate_operand" "x#fr,x#fr,0#fx,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx"))) - (clobber (match_scratch:SF 6 "=2,&4,X,X,X,X,X,X,X,X")) - (clobber (reg:CC 17))] - "TARGET_SSE - && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM) - /* Avoid combine from being smart and converting min/max - instruction patterns into conditional moves. */ - && ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT - && GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE) - || !rtx_equal_p (operands[4], operands[2]) - || !rtx_equal_p (operands[5], operands[3])) - && (!TARGET_IEEE_FP - || (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))" - "#") - -(define_insn "sse_movsfcc_eq" - [(set (match_operand:SF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?r#xf,?r#xf") - (if_then_else:SF (eq (match_operand:SF 3 "nonimmediate_operand" "%0#fx,x#fx,f#x,xm#f,f#x,xm#f") - (match_operand:SF 4 "nonimmediate_operand" "xm#f,xm#f,f#x,x#f,f#x,x#f")) - (match_operand:SF 1 "nonimmediate_operand" "x#fr,0#fr,0#fx,0#fx,0#rx,0#rx") - (match_operand:SF 2 "nonimmediate_operand" "x#fr,x#fr,f#fx,f#fx,rm#rx,rm#rx"))) - (clobber (match_scratch:SF 5 "=1,&3,X,X,X,X")) - (clobber (reg:CC 17))] - "TARGET_SSE - && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" - "#") - -(define_insn "sse_movdfcc" - [(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?f#Yr,?f#Yr,?r#Yf,?r#Yf,?r#Yf,?r#Yf") - (if_then_else:DF (match_operator 1 "sse_comparison_operator" - [(match_operand:DF 4 "nonimmediate_operand" "0#fY,Y#fY,f#Y,f#Y,Ym#f,Ym#f,f#Y,f#Y,Ym#f,Ym#f") - (match_operand:DF 5 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,f#Y,Y#f,Y#f,f#Y,f#Y,Y#f,Y#f")]) - (match_operand:DF 2 "nonimmediate_operand" "Y#fr,0#fr,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY,0#rY") - (match_operand:DF 3 "nonimmediate_operand" "Y#fr,Y#fr,0#fY,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY"))) - (clobber (match_scratch:DF 6 "=2,&4,X,X,X,X,X,X,X,X")) - (clobber (reg:CC 17))] - "TARGET_SSE2 - && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM) - /* Avoid combine from being smart and converting min/max - instruction patterns into conditional moves. */ - && ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT - && GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE) - || !rtx_equal_p (operands[4], operands[2]) - || !rtx_equal_p (operands[5], operands[3])) - && (!TARGET_IEEE_FP - || (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))" - "#") - -(define_insn "sse_movdfcc_eq" - [(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?r#Yf,?r#Yf") - (if_then_else:DF (eq (match_operand:DF 3 "nonimmediate_operand" "%0#fY,Y#fY,f#Y,Ym#f,f#Y,Ym#f") - (match_operand:DF 4 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,Y#f,f#Y,Y#f")) - (match_operand:DF 1 "nonimmediate_operand" "Y#fr,0#fr,0#fY,0#fY,0#rY,0#rY") - (match_operand:DF 2 "nonimmediate_operand" "Y#fr,Y#fr,f#fY,f#fY,rm#rY,rm#rY"))) - (clobber (match_scratch:DF 5 "=1,&3,X,X,X,X")) - (clobber (reg:CC 17))] - "TARGET_SSE - && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" - "#") - -;; For non-sse moves just expand the usual cmove sequence. -(define_split - [(set (match_operand 0 "register_operand" "") - (if_then_else (match_operator 1 "comparison_operator" - [(match_operand 4 "nonimmediate_operand" "") - (match_operand 5 "register_operand" "")]) - (match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "nonimmediate_operand" ""))) - (clobber (match_operand 6 "" "")) - (clobber (reg:CC 17))] - "!SSE_REG_P (operands[0]) && reload_completed - && (GET_MODE (operands[0]) == SFmode - || (TARGET_SSE2 && GET_MODE (operands[0]) == DFmode))" - [(const_int 0)] -{ - ix86_compare_op0 = operands[5]; - ix86_compare_op1 = operands[4]; - operands[1] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])), - VOIDmode, operands[5], operands[4]); - ix86_expand_fp_movcc (operands); - DONE; -}) - -;; Split SSE based conditional move into sequence: -;; cmpCC op0, op4 - set op0 to 0 or ffffffff depending on the comparison -;; and op2, op0 - zero op2 if comparison was false -;; nand op0, op3 - load op3 to op0 if comparison was false -;; or op2, op0 - get the nonzero one into the result. -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operator 1 "sse_comparison_operator" - [(match_operand:SF 4 "register_operand" "") - (match_operand:SF 5 "nonimmediate_operand" "")]) - (match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "register_operand" ""))) - (clobber (match_operand 6 "" "")) - (clobber (reg:CC 17))] - "SSE_REG_P (operands[0]) && reload_completed" - [(set (match_dup 4) (match_op_dup 1 [(match_dup 4) (match_dup 5)])) - (set (match_dup 2) (and:V4SF (match_dup 2) - (match_dup 8))) - (set (match_dup 8) (and:V4SF (not:V4SF (match_dup 8)) - (match_dup 3))) - (set (match_dup 0) (ior:V4SF (match_dup 6) - (match_dup 7)))] -{ - /* If op2 == op3, op3 would be clobbered before it is used. */ - if (operands_match_p (operands[2], operands[3])) - { - emit_move_insn (operands[0], operands[2]); - DONE; - } - - PUT_MODE (operands[1], GET_MODE (operands[0])); - if (operands_match_p (operands[0], operands[4])) - operands[6] = operands[4], operands[7] = operands[2]; - else - operands[6] = operands[2], operands[7] = operands[4]; - operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - operands[2] = simplify_gen_subreg (V4SFmode, operands[2], SFmode, 0); - operands[3] = simplify_gen_subreg (V4SFmode, operands[3], SFmode, 0); - operands[8] = simplify_gen_subreg (V4SFmode, operands[4], SFmode, 0); - operands[6] = simplify_gen_subreg (V4SFmode, operands[6], SFmode, 0); - operands[7] = simplify_gen_subreg (V4SFmode, operands[7], SFmode, 0); -}) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operator 1 "sse_comparison_operator" - [(match_operand:DF 4 "register_operand" "") - (match_operand:DF 5 "nonimmediate_operand" "")]) - (match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "register_operand" ""))) - (clobber (match_operand 6 "" "")) - (clobber (reg:CC 17))] - "SSE_REG_P (operands[0]) && reload_completed" - [(set (match_dup 4) (match_op_dup 1 [(match_dup 4) (match_dup 5)])) - (set (match_dup 2) (and:V2DF (match_dup 2) - (match_dup 8))) - (set (match_dup 8) (and:V2DF (not:V2DF (match_dup 8)) - (match_dup 3))) - (set (match_dup 0) (ior:V2DF (match_dup 6) - (match_dup 7)))] -{ - if (GET_MODE (operands[2]) == DFmode - && TARGET_SSE_PARTIAL_REGS && !optimize_size) - { - rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0); - emit_insn (gen_sse2_unpcklpd (op, op, op)); - op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0); - emit_insn (gen_sse2_unpcklpd (op, op, op)); - } - - /* If op2 == op3, op3 would be clobbered before it is used. */ - if (operands_match_p (operands[2], operands[3])) - { - emit_move_insn (operands[0], operands[2]); - DONE; - } - - PUT_MODE (operands[1], GET_MODE (operands[0])); - if (operands_match_p (operands[0], operands[4])) - operands[6] = operands[4], operands[7] = operands[2]; - else - operands[6] = operands[2], operands[7] = operands[4]; - operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); - operands[2] = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0); - operands[3] = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0); - operands[8] = simplify_gen_subreg (V2DFmode, operands[4], DFmode, 0); - operands[6] = simplify_gen_subreg (V2DFmode, operands[6], DFmode, 0); - operands[7] = simplify_gen_subreg (V2DFmode, operands[7], DFmode, 0); -}) - -;; Special case of conditional move we can handle effectively. -;; Do not brother with the integer/floating point case, since these are -;; bot considerably slower, unlike in the generic case. -(define_insn "*sse_movsfcc_const0_1" - [(set (match_operand:SF 0 "register_operand" "=&x") - (if_then_else:SF (match_operator 1 "sse_comparison_operator" - [(match_operand:SF 4 "register_operand" "0") - (match_operand:SF 5 "nonimmediate_operand" "xm")]) - (match_operand:SF 2 "register_operand" "x") - (match_operand:SF 3 "const0_operand" "X")))] - "TARGET_SSE" - "#") - -(define_insn "*sse_movsfcc_const0_2" - [(set (match_operand:SF 0 "register_operand" "=&x") - (if_then_else:SF (match_operator 1 "sse_comparison_operator" - [(match_operand:SF 4 "register_operand" "0") - (match_operand:SF 5 "nonimmediate_operand" "xm")]) - (match_operand:SF 2 "const0_operand" "X") - (match_operand:SF 3 "register_operand" "x")))] - "TARGET_SSE" - "#") - -(define_insn "*sse_movsfcc_const0_3" - [(set (match_operand:SF 0 "register_operand" "=&x") - (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" - [(match_operand:SF 4 "nonimmediate_operand" "xm") - (match_operand:SF 5 "register_operand" "0")]) - (match_operand:SF 2 "register_operand" "x") - (match_operand:SF 3 "const0_operand" "X")))] - "TARGET_SSE" - "#") - -(define_insn "*sse_movsfcc_const0_4" - [(set (match_operand:SF 0 "register_operand" "=&x") - (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" - [(match_operand:SF 4 "nonimmediate_operand" "xm") - (match_operand:SF 5 "register_operand" "0")]) - (match_operand:SF 2 "const0_operand" "X") - (match_operand:SF 3 "register_operand" "x")))] - "TARGET_SSE" - "#") - -(define_insn "*sse_movdfcc_const0_1" - [(set (match_operand:DF 0 "register_operand" "=&Y") - (if_then_else:DF (match_operator 1 "sse_comparison_operator" - [(match_operand:DF 4 "register_operand" "0") - (match_operand:DF 5 "nonimmediate_operand" "Ym")]) - (match_operand:DF 2 "register_operand" "Y") - (match_operand:DF 3 "const0_operand" "X")))] - "TARGET_SSE2" - "#") - -(define_insn "*sse_movdfcc_const0_2" - [(set (match_operand:DF 0 "register_operand" "=&Y") - (if_then_else:DF (match_operator 1 "sse_comparison_operator" - [(match_operand:DF 4 "register_operand" "0") - (match_operand:DF 5 "nonimmediate_operand" "Ym")]) - (match_operand:DF 2 "const0_operand" "X") - (match_operand:DF 3 "register_operand" "Y")))] - "TARGET_SSE2" - "#") - -(define_insn "*sse_movdfcc_const0_3" - [(set (match_operand:DF 0 "register_operand" "=&Y") - (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" - [(match_operand:DF 4 "nonimmediate_operand" "Ym") - (match_operand:DF 5 "register_operand" "0")]) - (match_operand:DF 2 "register_operand" "Y") - (match_operand:DF 3 "const0_operand" "X")))] - "TARGET_SSE2" - "#") - -(define_insn "*sse_movdfcc_const0_4" - [(set (match_operand:DF 0 "register_operand" "=&Y") - (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" - [(match_operand:DF 4 "nonimmediate_operand" "Ym") - (match_operand:DF 5 "register_operand" "0")]) - (match_operand:DF 2 "const0_operand" "X") - (match_operand:DF 3 "register_operand" "Y")))] - "TARGET_SSE2" - "#") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand:SF 4 "nonimmediate_operand" "") - (match_operand:SF 5 "nonimmediate_operand" "")]) - (match_operand:SF 2 "nonmemory_operand" "") - (match_operand:SF 3 "nonmemory_operand" "")))] - "SSE_REG_P (operands[0]) && reload_completed - && (const0_operand (operands[2], GET_MODE (operands[0])) - || const0_operand (operands[3], GET_MODE (operands[0])))" - [(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)])) - (set (match_dup 8) (and:V4SF (match_dup 6) (match_dup 7)))] -{ - PUT_MODE (operands[1], GET_MODE (operands[0])); - if (!sse_comparison_operator (operands[1], VOIDmode) - || !rtx_equal_p (operands[0], operands[4])) - { - rtx tmp = operands[5]; - operands[5] = operands[4]; - operands[4] = tmp; - PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1]))); - } - if (!rtx_equal_p (operands[0], operands[4])) - abort (); - operands[8] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); - if (const0_operand (operands[2], GET_MODE (operands[2]))) - { - operands[7] = operands[3]; - operands[6] = gen_rtx_NOT (V4SFmode, operands[5]); - } - else - { - operands[7] = operands[2]; - operands[6] = operands[8]; - } - operands[7] = simplify_gen_subreg (V4SFmode, operands[7], SFmode, 0); -}) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand:DF 4 "nonimmediate_operand" "") - (match_operand:DF 5 "nonimmediate_operand" "")]) - (match_operand:DF 2 "nonmemory_operand" "") - (match_operand:DF 3 "nonmemory_operand" "")))] - "SSE_REG_P (operands[0]) && reload_completed - && (const0_operand (operands[2], GET_MODE (operands[0])) - || const0_operand (operands[3], GET_MODE (operands[0])))" - [(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)])) - (set (match_dup 8) (and:V2DF (match_dup 6) (match_dup 7)))] -{ - if (TARGET_SSE_PARTIAL_REGS && !optimize_size - && GET_MODE (operands[2]) == DFmode) - { - if (REG_P (operands[2])) - { - rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0); - emit_insn (gen_sse2_unpcklpd (op, op, op)); - } - if (REG_P (operands[3])) - { - rtx op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0); - emit_insn (gen_sse2_unpcklpd (op, op, op)); - } - } - PUT_MODE (operands[1], GET_MODE (operands[0])); - if (!sse_comparison_operator (operands[1], VOIDmode) - || !rtx_equal_p (operands[0], operands[4])) - { - rtx tmp = operands[5]; - operands[5] = operands[4]; - operands[4] = tmp; - PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1]))); - } - if (!rtx_equal_p (operands[0], operands[4])) - abort (); - operands[8] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); - if (const0_operand (operands[2], GET_MODE (operands[2]))) - { - operands[7] = operands[3]; - operands[6] = gen_rtx_NOT (V2DFmode, operands[8]); - } - else - { - operands[7] = operands[2]; - operands[6] = operands[8]; - } - operands[7] = simplify_gen_subreg (V2DFmode, operands[7], DFmode, 0); -}) - (define_expand "allocate_stack_worker" [(match_operand:SI 0 "register_operand" "")] "TARGET_STACK_PROBE" @@ -17353,9 +19402,9 @@ (define_insn "allocate_stack_worker_1" [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")] UNSPECV_STACK_PROBE) - (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) + (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0))) (clobber (match_scratch:SI 1 "=0")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_STACK_PROBE" "call\t__alloca" [(set_attr "type" "multi") @@ -17364,18 +19413,18 @@ (define_expand "allocate_stack_worker_postreload" [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")] UNSPECV_STACK_PROBE) - (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) + (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0))) (clobber (match_dup 0)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") (define_insn "allocate_stack_worker_rex64" [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")] UNSPECV_STACK_PROBE) - (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0))) + (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0))) (clobber (match_scratch:DI 1 "=0")) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && TARGET_STACK_PROBE" "call\t__alloca" [(set_attr "type" "multi") @@ -17384,20 +19433,20 @@ (define_expand "allocate_stack_worker_rex64_postreload" [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")] UNSPECV_STACK_PROBE) - (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0))) + (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0))) (clobber (match_dup 0)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "" "") (define_expand "allocate_stack" [(parallel [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (reg:SI 7) + (minus:SI (reg:SI SP_REG) (match_operand:SI 1 "general_operand" ""))) - (clobber (reg:CC 17))]) - (parallel [(set (reg:SI 7) - (minus:SI (reg:SI 7) (match_dup 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))]) + (parallel [(set (reg:SI SP_REG) + (minus:SI (reg:SI SP_REG) (match_dup 1))) + (clobber (reg:CC FLAGS_REG))])] "TARGET_STACK_PROBE" { #ifdef CHECK_STACK_LIMIT @@ -17418,7 +19467,21 @@ [(label_ref (match_operand 0 "" ""))] "!TARGET_64BIT && flag_pic" { - emit_insn (gen_set_got (pic_offset_table_rtx)); + if (TARGET_MACHO) + { + rtx xops[3]; + rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); + rtx label_rtx = gen_label_rtx (); + emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx)); + xops[0] = xops[1] = picreg; + xops[2] = gen_rtx_CONST (SImode, + gen_rtx_MINUS (SImode, + gen_rtx_LABEL_REF (SImode, label_rtx), + gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME))); + ix86_expand_binary_operator (MINUS, SImode, xops); + } + else + emit_insn (gen_set_got (pic_offset_table_rtx)); DONE; }) @@ -17429,17 +19492,18 @@ (match_operator 3 "promotable_binary_operator" [(match_operand 1 "register_operand" "") (match_operand 2 "aligned_operand" "")])) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "! TARGET_PARTIAL_REG_STALL && reload_completed && ((GET_MODE (operands[0]) == HImode && ((!optimize_size && !TARGET_FAST_PREFIX) + /* ??? next two lines just !satisfies_constraint_K (...) */ || GET_CODE (operands[2]) != CONST_INT - || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))) + || satisfies_constraint_K (operands[2]))) || (GET_MODE (operands[0]) == QImode && (TARGET_PROMOTE_QImode || optimize_size)))" [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); if (GET_CODE (operands[3]) != ASHIFT) @@ -17505,14 +19569,14 @@ (define_split [(set (match_operand 0 "register_operand" "") (neg (match_operand 1 "register_operand" ""))) - (clobber (reg:CC 17))] + (clobber (reg:CC FLAGS_REG))] "! TARGET_PARTIAL_REG_STALL && reload_completed && (GET_MODE (operands[0]) == HImode || (GET_MODE (operands[0]) == QImode && (TARGET_PROMOTE_QImode || optimize_size)))" [(parallel [(set (match_dup 0) (neg:SI (match_dup 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]);") @@ -17531,7 +19595,7 @@ (define_split [(set (match_operand 0 "register_operand" "") (if_then_else (match_operator 1 "comparison_operator" - [(reg 17) (const_int 0)]) + [(reg FLAGS_REG) (const_int 0)]) (match_operand 2 "register_operand" "") (match_operand 3 "register_operand" "")))] "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE @@ -17553,7 +19617,8 @@ [(set (match_operand:SI 0 "push_operand" "") (match_operand:SI 1 "memory_operand" "")) (match_scratch:SI 2 "r")] - "! optimize_size && ! TARGET_PUSH_MEMORY" + "!optimize_size && !TARGET_PUSH_MEMORY + && !RTX_FRAME_RELATED_P (peep2_next_insn (0))" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "") @@ -17562,7 +19627,8 @@ [(set (match_operand:DI 0 "push_operand" "") (match_operand:DI 1 "memory_operand" "")) (match_scratch:DI 2 "r")] - "! optimize_size && ! TARGET_PUSH_MEMORY" + "!optimize_size && !TARGET_PUSH_MEMORY + && !RTX_FRAME_RELATED_P (peep2_next_insn (0))" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "") @@ -17573,7 +19639,8 @@ [(set (match_operand:SF 0 "push_operand" "") (match_operand:SF 1 "memory_operand" "")) (match_scratch:SF 2 "r")] - "! optimize_size && ! TARGET_PUSH_MEMORY" + "!optimize_size && !TARGET_PUSH_MEMORY + && !RTX_FRAME_RELATED_P (peep2_next_insn (0))" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "") @@ -17582,7 +19649,8 @@ [(set (match_operand:HI 0 "push_operand" "") (match_operand:HI 1 "memory_operand" "")) (match_scratch:HI 2 "r")] - "! optimize_size && ! TARGET_PUSH_MEMORY" + "!optimize_size && !TARGET_PUSH_MEMORY + && !RTX_FRAME_RELATED_P (peep2_next_insn (0))" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "") @@ -17591,7 +19659,8 @@ [(set (match_operand:QI 0 "push_operand" "") (match_operand:QI 1 "memory_operand" "")) (match_scratch:QI 2 "q")] - "! optimize_size && ! TARGET_PUSH_MEMORY" + "!optimize_size && !TARGET_PUSH_MEMORY + && !RTX_FRAME_RELATED_P (peep2_next_insn (0))" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "") @@ -17608,7 +19677,7 @@ && get_attr_length (insn) >= ix86_cost->large_insn && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 1) (const_int 0)) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) (match_dup 1))] "") @@ -17622,7 +19691,7 @@ && get_attr_length (insn) >= ix86_cost->large_insn && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 2) (const_int 0)) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) (match_dup 1))] "operands[2] = gen_lowpart (SImode, operands[1]);") @@ -17636,7 +19705,7 @@ && get_attr_length (insn) >= ix86_cost->large_insn && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 2) (const_int 0)) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) (match_dup 1))] "operands[2] = gen_lowpart (SImode, operands[1]);") @@ -17687,7 +19756,7 @@ ;; Don't split NOTs with a displacement operand, because resulting XOR ;; will not be pairable anyway. ;; -;; On AMD K6, NOT is vector decoded with memory operand that can not be +;; On AMD K6, NOT is vector decoded with memory operand that cannot be ;; represented using a modRM byte. The XOR replacement is long decoded, ;; so this split helps here as well. ;; @@ -17705,7 +19774,7 @@ || (TARGET_K6 && long_memory_operand (operands[0], SImode)))" [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (const_int -1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -17719,7 +19788,7 @@ || (TARGET_K6 && long_memory_operand (operands[0], HImode)))" [(parallel [(set (match_dup 0) (xor:HI (match_dup 1) (const_int -1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -17733,7 +19802,7 @@ || (TARGET_K6 && long_memory_operand (operands[0], QImode)))" [(parallel [(set (match_dup 0) (xor:QI (match_dup 1) (const_int -1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") ;; Non pairable "test imm, reg" instructions can be translated to @@ -17751,8 +19820,7 @@ (const_int 0)]))] "ix86_match_ccmode (insn, CCNOmode) && (true_regnum (operands[2]) != 0 - || (GET_CODE (operands[3]) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'K'))) + || satisfies_constraint_K (operands[3])) && peep2_reg_dead_p (1, operands[2])" [(parallel [(set (match_dup 0) @@ -17824,12 +19892,12 @@ (match_operator:SI 3 "arith_or_logical_operator" [(match_dup 0) (match_operand:SI 1 "memory_operand" "")])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "! optimize_size && ! TARGET_READ_MODIFY" [(set (match_dup 2) (match_dup 1)) (parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 2)])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -17838,12 +19906,12 @@ (match_operator:SI 3 "arith_or_logical_operator" [(match_operand:SI 1 "memory_operand" "") (match_dup 0)])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "! optimize_size && ! TARGET_READ_MODIFY" [(set (match_dup 2) (match_dup 1)) (parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 2) (match_dup 0)])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") ; Don't do logical operations with memory outputs @@ -17858,12 +19926,12 @@ (match_operator:SI 3 "arith_or_logical_operator" [(match_dup 0) (match_operand:SI 1 "nonmemory_operand" "")])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "! optimize_size && ! TARGET_READ_MODIFY_WRITE" [(set (match_dup 2) (match_dup 0)) (parallel [(set (match_dup 2) (match_op_dup 3 [(match_dup 2) (match_dup 1)])) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) (match_dup 2))] "") @@ -17873,29 +19941,28 @@ (match_operator:SI 3 "arith_or_logical_operator" [(match_operand:SI 1 "nonmemory_operand" "") (match_dup 0)])) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "! optimize_size && ! TARGET_READ_MODIFY_WRITE" [(set (match_dup 2) (match_dup 0)) (parallel [(set (match_dup 2) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) (match_dup 2))] "") ;; 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 17))])] - "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode, - operands[0]);") + (clobber (reg:CC FLAGS_REG))])] +{ + operands[0] = gen_lowpart (word_mode, operands[0]); +}) (define_peephole2 [(set (strict_low_part (match_operand 0 "register_operand" "")) @@ -17905,7 +19972,7 @@ && (! TARGET_USE_MOV0 || optimize_size) && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (strict_low_part (match_dup 0)) (const_int 0)) - (clobber (reg:CC 17))])]) + (clobber (reg:CC FLAGS_REG))])]) ;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg. (define_peephole2 @@ -17917,7 +19984,7 @@ && (optimize_size || TARGET_PENTIUM) && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (const_int -1)) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode, operands[0]);") @@ -17929,7 +19996,7 @@ (match_operand:SI 1 "nonmemory_operand" "")))] "peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -17938,7 +20005,7 @@ (match_operand:DI 2 "nonmemory_operand" "")) 0))] "peep2_regno_dead_p (0, FLAGS_REG) && REGNO (operands[0]) == REGNO (operands[1])" [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[2] = gen_lowpart (SImode, operands[2]);") (define_peephole2 @@ -17947,7 +20014,7 @@ (match_operand:DI 1 "x86_64_general_operand" "")))] "peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -17957,7 +20024,7 @@ "exact_log2 (INTVAL (operands[1])) >= 0 && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));") (define_peephole2 @@ -17967,7 +20034,7 @@ "exact_log2 (INTVAL (operands[1])) >= 0 && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));") (define_peephole2 @@ -17978,7 +20045,7 @@ && REGNO (operands[0]) == REGNO (operands[1]) && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));") ;; The ESP adjustments can be done by the push and pop instructions. Resulting @@ -18002,52 +20069,52 @@ (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4))) - (clobber (reg:CC 17)) + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_SUB_ESP_4" [(clobber (match_dup 0)) - (parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0)) + (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0)) (clobber (mem:BLK (scratch)))])]) (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (clobber (reg:CC 17)) + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_SUB_ESP_8" [(clobber (match_dup 0)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0)) - (parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0)) + (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0)) + (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0)) (clobber (mem:BLK (scratch)))])]) ;; Convert esp subtractions to push. (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) + (clobber (reg:CC FLAGS_REG))])] "optimize_size || !TARGET_SUB_ESP_4" [(clobber (match_dup 0)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))]) + (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))]) (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) + (clobber (reg:CC FLAGS_REG))])] "optimize_size || !TARGET_SUB_ESP_8" [(clobber (match_dup 0)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))]) + (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0)) + (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))]) ;; Convert epilogue deallocator to pop. (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4))) - (clobber (reg:CC 17)) + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_ADD_ESP_4" - [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4))) + [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) (clobber (mem:BLK (scratch)))])] "") @@ -18056,38 +20123,38 @@ (define_peephole2 [(match_scratch:SI 0 "r") (match_scratch:SI 1 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8))) - (clobber (reg:CC 17)) + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_ADD_ESP_8" - [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4))) + [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) (clobber (mem:BLK (scratch)))]) - (parallel [(set (match_dup 1) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])] + (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])] "") (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8))) - (clobber (reg:CC 17)) + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size" - [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4))) + [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) (clobber (mem:BLK (scratch)))]) - (parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])] + (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])] "") ;; Convert esp additions to pop. (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) + (clobber (reg:CC FLAGS_REG))])] "" - [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])] + [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])] "") ;; Two pops case is tricky, since pop causes dependency on destination register. @@ -18095,24 +20162,24 @@ (define_peephole2 [(match_scratch:SI 0 "r") (match_scratch:SI 1 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8))) + (clobber (reg:CC FLAGS_REG))])] "" - [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))]) - (parallel [(set (match_dup 1) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])] + [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))]) + (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])] "") (define_peephole2 [(match_scratch:SI 0 "r") - (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8))) + (clobber (reg:CC FLAGS_REG))])] "optimize_size" - [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))]) - (parallel [(set (match_dup 0) (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])] + [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))]) + (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])] "") ;; Convert compares with 1 to shorter inc/dec operations when CF is not @@ -18134,52 +20201,52 @@ (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8))) - (clobber (reg:CC 17)) + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_SUB_ESP_4" [(clobber (match_dup 0)) - (parallel [(set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0)) + (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0)) (clobber (mem:BLK (scratch)))])]) (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) - (clobber (reg:CC 17)) + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_SUB_ESP_8" [(clobber (match_dup 0)) - (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0)) - (parallel [(set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0)) + (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0)) + (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0)) (clobber (mem:BLK (scratch)))])]) ;; Convert esp subtractions to push. (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8))) + (clobber (reg:CC FLAGS_REG))])] "optimize_size || !TARGET_SUB_ESP_4" [(clobber (match_dup 0)) - (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))]) + (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))]) (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16))) + (clobber (reg:CC FLAGS_REG))])] "optimize_size || !TARGET_SUB_ESP_8" [(clobber (match_dup 0)) - (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0)) - (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))]) + (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0)) + (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))]) ;; Convert epilogue deallocator to pop. (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8))) - (clobber (reg:CC 17)) + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_ADD_ESP_4" - [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8))) + [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8))) (clobber (mem:BLK (scratch)))])] "") @@ -18188,38 +20255,38 @@ (define_peephole2 [(match_scratch:DI 0 "r") (match_scratch:DI 1 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16))) - (clobber (reg:CC 17)) + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size || !TARGET_ADD_ESP_8" - [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8))) + [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8))) (clobber (mem:BLK (scratch)))]) - (parallel [(set (match_dup 1) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])] + (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])] "") (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16))) - (clobber (reg:CC 17)) + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16))) + (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))])] "optimize_size" - [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8))) + [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8))) (clobber (mem:BLK (scratch)))]) - (parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])] + (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])] "") ;; Convert esp additions to pop. (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8))) + (clobber (reg:CC FLAGS_REG))])] "" - [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])] + [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])] "") ;; Two pops case is tricky, since pop causes dependency on destination register. @@ -18227,26 +20294,89 @@ (define_peephole2 [(match_scratch:DI 0 "r") (match_scratch:DI 1 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16))) + (clobber (reg:CC FLAGS_REG))])] "" - [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))]) - (parallel [(set (match_dup 1) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])] + [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))]) + (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])] "") (define_peephole2 [(match_scratch:DI 0 "r") - (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16))) - (clobber (reg:CC 17))])] + (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16))) + (clobber (reg:CC FLAGS_REG))])] "optimize_size" - [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))]) - (parallel [(set (match_dup 0) (mem:DI (reg:DI 7))) - (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])] + [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))]) + (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG))) + (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])] "") +;; Convert imul by three, five and nine into lea +(define_peephole2 + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "INTVAL (operands[2]) == 3 + || INTVAL (operands[2]) == 5 + || INTVAL (operands[2]) == 9" + [(set (match_dup 0) + (plus:SI (mult:SI (match_dup 1) (match_dup 2)) + (match_dup 1)))] + { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); }) + +(define_peephole2 + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "!optimize_size + && (INTVAL (operands[2]) == 3 + || INTVAL (operands[2]) == 5 + || INTVAL (operands[2]) == 9)" + [(set (match_dup 0) (match_dup 1)) + (set (match_dup 0) + (plus:SI (mult:SI (match_dup 0) (match_dup 2)) + (match_dup 0)))] + { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); }) + +(define_peephole2 + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (mult:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT + && (INTVAL (operands[2]) == 3 + || INTVAL (operands[2]) == 5 + || INTVAL (operands[2]) == 9)" + [(set (match_dup 0) + (plus:DI (mult:DI (match_dup 1) (match_dup 2)) + (match_dup 1)))] + { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); }) + +(define_peephole2 + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (mult:DI (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT + && !optimize_size + && (INTVAL (operands[2]) == 3 + || INTVAL (operands[2]) == 5 + || INTVAL (operands[2]) == 9)" + [(set (match_dup 0) (match_dup 1)) + (set (match_dup 0) + (plus:DI (mult:DI (match_dup 0) (match_dup 2)) + (match_dup 0)))] + { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); }) + ;; Imul $32bit_imm, mem, reg is vector decoded, while ;; imul $32bit_imm, reg, reg is direct decoded. (define_peephole2 @@ -18254,13 +20384,12 @@ (parallel [(set (match_operand:DI 0 "register_operand" "") (mult:DI (match_operand:DI 1 "memory_operand" "") (match_operand:DI 2 "immediate_operand" ""))) - (clobber (reg:CC 17))])] - "TARGET_K8 && !optimize_size - && (GET_CODE (operands[2]) != CONST_INT - || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + (clobber (reg:CC FLAGS_REG))])] + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && !satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -18268,13 +20397,12 @@ (parallel [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "memory_operand" "") (match_operand:SI 2 "immediate_operand" ""))) - (clobber (reg:CC 17))])] - "TARGET_K8 && !optimize_size - && (GET_CODE (operands[2]) != CONST_INT - || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + (clobber (reg:CC FLAGS_REG))])] + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && !satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") (define_peephole2 @@ -18283,13 +20411,12 @@ (zero_extend:DI (mult:SI (match_operand:SI 1 "memory_operand" "") (match_operand:SI 2 "immediate_operand" "")))) - (clobber (reg:CC 17))])] - "TARGET_K8 && !optimize_size - && (GET_CODE (operands[2]) != CONST_INT - || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + (clobber (reg:CC FLAGS_REG))])] + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && !satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2)))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] "") ;; imul $8/16bit_imm, regmem, reg is vector decoded. @@ -18300,13 +20427,13 @@ [(parallel [(set (match_operand:DI 0 "register_operand" "") (mult:DI (match_operand:DI 1 "nonimmediate_operand" "") (match_operand:DI 2 "const_int_operand" ""))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (match_scratch:DI 3 "r")] - "TARGET_K8 && !optimize_size - && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 2)) (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] { if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); @@ -18316,13 +20443,13 @@ [(parallel [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "nonimmediate_operand" "") (match_operand:SI 2 "const_int_operand" ""))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (match_scratch:SI 3 "r")] - "TARGET_K8 && !optimize_size - && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 2)) (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] { if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); @@ -18332,16 +20459,74 @@ [(parallel [(set (match_operand:HI 0 "register_operand" "") (mult:HI (match_operand:HI 1 "nonimmediate_operand" "") (match_operand:HI 2 "immediate_operand" ""))) - (clobber (reg:CC 17))]) + (clobber (reg:CC FLAGS_REG))]) (match_scratch:HI 3 "r")] - "TARGET_K8 && !optimize_size" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size" [(set (match_dup 3) (match_dup 2)) (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3))) - (clobber (reg:CC 17))])] + (clobber (reg:CC FLAGS_REG))])] { if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); }) + +;; After splitting up read-modify operations, array accesses with memory +;; operands might end up in form: +;; sall $2, %eax +;; movl 4(%esp), %edx +;; addl %edx, %eax +;; instead of pre-splitting: +;; sall $2, %eax +;; addl 4(%esp), %eax +;; Turn it into: +;; movl 4(%esp), %edx +;; leal (%edx,%eax,4), %eax + +(define_peephole2 + [(parallel [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "register_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))]) + (set (match_operand 3 "register_operand") + (match_operand 4 "x86_64_general_operand" "")) + (parallel [(set (match_operand 5 "register_operand" "") + (plus (match_operand 6 "register_operand" "") + (match_operand 7 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3 + /* Validate MODE for lea. */ + && ((!TARGET_PARTIAL_REG_STALL + && (GET_MODE (operands[0]) == QImode + || GET_MODE (operands[0]) == HImode)) + || GET_MODE (operands[0]) == SImode + || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)) + /* We reorder load and the shift. */ + && !rtx_equal_p (operands[1], operands[3]) + && !reg_overlap_mentioned_p (operands[0], operands[4]) + /* Last PLUS must consist of operand 0 and 3. */ + && !rtx_equal_p (operands[0], operands[3]) + && (rtx_equal_p (operands[3], operands[6]) + || rtx_equal_p (operands[3], operands[7])) + && (rtx_equal_p (operands[0], operands[6]) + || rtx_equal_p (operands[0], operands[7])) + /* The intermediate operand 0 must die or be same as output. */ + && (rtx_equal_p (operands[0], operands[5]) + || peep2_reg_dead_p (3, operands[0]))" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (match_dup 1))] +{ + enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode; + int scale = 1 << INTVAL (operands[2]); + rtx index = gen_lowpart (Pmode, operands[1]); + rtx base = gen_lowpart (Pmode, operands[3]); + rtx dest = gen_lowpart (mode, operands[5]); + + operands[1] = gen_rtx_PLUS (Pmode, base, + gen_rtx_MULT (Pmode, index, GEN_INT (scale))); + if (mode != Pmode) + operands[1] = gen_rtx_SUBREG (mode, operands[1], 0); + operands[0] = dest; +}) ;; Call-value patterns last so that the wildcard operand does not ;; disrupt insn-recog's switch tables. @@ -18350,7 +20535,7 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "")) (match_operand:SI 2 "" ""))) - (set (reg:SI 7) (plus:SI (reg:SI 7) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 3 "immediate_operand" "")))] "!TARGET_64BIT" { @@ -18365,11 +20550,11 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm")) (match_operand:SI 2 "" ""))) - (set (reg:SI 7) (plus:SI (reg:SI 7) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 3 "immediate_operand" "i")))] "!TARGET_64BIT" { - if (constant_call_address_operand (operands[1], QImode)) + if (constant_call_address_operand (operands[1], Pmode)) { if (SIBLING_CALL_P (insn)) return "jmp\t%P1"; @@ -18415,7 +20600,7 @@ (match_operand:SI 2 "" "")))] "!SIBLING_CALL_P (insn) && !TARGET_64BIT" { - if (constant_call_address_operand (operands[1], QImode)) + if (constant_call_address_operand (operands[1], Pmode)) return "call\t%P1"; return "call\t%A1"; } @@ -18427,7 +20612,7 @@ (match_operand:SI 2 "" "")))] "SIBLING_CALL_P (insn) && !TARGET_64BIT" { - if (constant_call_address_operand (operands[1], QImode)) + if (constant_call_address_operand (operands[1], Pmode)) return "jmp\t%P1"; return "jmp\t%A1"; } @@ -18439,7 +20624,7 @@ (match_operand:DI 2 "" "")))] "!SIBLING_CALL_P (insn) && TARGET_64BIT" { - if (constant_call_address_operand (operands[1], QImode)) + if (constant_call_address_operand (operands[1], Pmode)) return "call\t%P1"; return "call\t%A1"; } @@ -18461,2402 +20646,16 @@ "jmp\t*%%r11" [(set_attr "type" "callv")]) +;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5. +;; That, however, is usually mapped by the OS to SIGSEGV, which is often +;; caught for use by garbage collectors and the like. Using an insn that +;; maps to SIGILL makes it more likely the program will rightfully die. +;; Keeping with tradition, "6" is in honor of #UD. (define_insn "trap" - [(trap_if (const_int 1) (const_int 5))] + [(trap_if (const_int 1) (const_int 6))] "" - "int\t$5") - -;;; ix86 doesn't have conditional trap instructions, but we fake them -;;; for the sake of bounds checking. By emitting bounds checks as -;;; conditional traps rather than as conditional jumps around -;;; unconditional traps we avoid introducing spurious basic-block -;;; boundaries and facilitate elimination of redundant checks. In -;;; honor of the too-inflexible-for-BPs `bound' instruction, we use -;;; interrupt 5. -;;; -;;; FIXME: Static branch prediction rules for ix86 are such that -;;; forward conditional branches predict as untaken. As implemented -;;; below, pseudo conditional traps violate that rule. We should use -;;; .pushsection/.popsection to place all of the `int 5's in a special -;;; section loaded at the end of the text segment and branch forward -;;; there on bounds-failure, and then jump back immediately (in case -;;; the system chooses to ignore bounds violations, or to report -;;; violations and continue execution). - -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "comparison_operator" - [(match_dup 2) (const_int 0)]) - (match_operand 1 "const_int_operand" ""))] - "" -{ - emit_insn (gen_rtx_TRAP_IF (VOIDmode, - ix86_expand_compare (GET_CODE (operands[0]), - NULL, NULL), - operands[1])); - DONE; -}) - -(define_insn "*conditional_trap_1" - [(trap_if (match_operator 0 "comparison_operator" - [(reg 17) (const_int 0)]) - (match_operand 1 "const_int_operand" ""))] - "" -{ - operands[2] = gen_label_rtx (); - output_asm_insn ("j%c0\t%l2\; int\t%1", operands); - (*targetm.asm_out.internal_label) (asm_out_file, "L", - CODE_LABEL_NUMBER (operands[2])); - RET; -}) - - ;; Pentium III SIMD instructions. - -;; Moves for SSE/MMX regs. - -(define_insn "*movv4sf_internal" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - xorps\t%0, %0 - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "V4SF")]) - -(define_split - [(set (match_operand:V4SF 0 "register_operand" "") - (match_operand:V4SF 1 "zero_extended_scalar_load_operand" ""))] - "TARGET_SSE && reload_completed" - [(set (match_dup 0) - (vec_merge:V4SF - (vec_duplicate:V4SF (match_dup 1)) - (match_dup 2) - (const_int 1)))] -{ - operands[1] = simplify_gen_subreg (SFmode, operands[1], V4SFmode, 0); - operands[2] = CONST0_RTX (V4SFmode); -}) - -(define_insn "*movv4si_internal" - [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V4SI 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 1: - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "0,1") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "2") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "TI"))] - (const_string "TI")))]) - -(define_insn "*movv2di_internal" - [(set (match_operand:V2DI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V2DI 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 1: - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "0,1") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "2") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "TI"))] - (const_string "TI")))]) - -(define_split - [(set (match_operand:V2DF 0 "register_operand" "") - (match_operand:V2DF 1 "zero_extended_scalar_load_operand" ""))] - "TARGET_SSE2 && reload_completed" - [(set (match_dup 0) - (vec_merge:V2DF - (vec_duplicate:V2DF (match_dup 1)) - (match_dup 2) - (const_int 1)))] -{ - operands[1] = simplify_gen_subreg (DFmode, operands[1], V2DFmode, 0); - operands[2] = CONST0_RTX (V2DFmode); -}) - -(define_insn "*movv2si_internal" - [(set (match_operand:V2SI 0 "nonimmediate_operand" - "=y,y ,m,!y,!*Y,*x,?*x,?m") - (match_operand:V2SI 1 "vector_move_operand" - "C ,ym,y,*Y,y ,C ,*xm,*x"))] - "TARGET_MMX - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1} - movdq2q\t{%1, %0|%0, %1} - movq2dq\t{%1, %0|%0, %1} - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov") - (set_attr "mode" "DI")]) - -(define_insn "*movv4hi_internal" - [(set (match_operand:V4HI 0 "nonimmediate_operand" - "=y,y ,m,!y,!*Y,*x,?*x,?m") - (match_operand:V4HI 1 "vector_move_operand" - "C ,ym,y,*Y,y ,C ,*xm,*x"))] - "TARGET_MMX - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1} - movdq2q\t{%1, %0|%0, %1} - movq2dq\t{%1, %0|%0, %1} - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov") - (set_attr "mode" "DI")]) - -(define_insn "*movv8qi_internal" - [(set (match_operand:V8QI 0 "nonimmediate_operand" - "=y,y ,m,!y,!*Y,*x,?*x,?m") - (match_operand:V8QI 1 "vector_move_operand" - "C ,ym,y,*Y,y ,C ,*xm,*x"))] - "TARGET_MMX - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1} - movdq2q\t{%1, %0|%0, %1} - movq2dq\t{%1, %0|%0, %1} - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov") - (set_attr "mode" "DI")]) - -(define_insn "*movv2sf_internal" - [(set (match_operand:V2SF 0 "nonimmediate_operand" - "=y,y ,m,!y,!*Y,*x,?*x,?m") - (match_operand:V2SF 1 "vector_move_operand" - "C ,ym,y,*Y,y ,C ,*xm,*x"))] - "TARGET_MMX - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - pxor\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1} - movdq2q\t{%1, %0|%0, %1} - movq2dq\t{%1, %0|%0, %1} - xorps\t%0, %0 - movq\t{%1, %0|%0, %1} - movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov") - (set_attr "mode" "DI")]) - -(define_expand "movti" - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "nonimmediate_operand" ""))] - "TARGET_SSE || TARGET_64BIT" -{ - if (TARGET_64BIT) - ix86_expand_move (TImode, operands); - else - ix86_expand_vector_move (TImode, operands); - DONE; -}) - -(define_expand "movtf" - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (match_operand:TF 1 "nonimmediate_operand" ""))] - "TARGET_64BIT" -{ - ix86_expand_move (TFmode, operands); - DONE; -}) - -(define_insn "*movv2df_internal" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V2DF 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "xorpd\t%0, %0"; - case 1: - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movapd\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "ssemov") - (set (attr "mode") - (cond [(eq (symbol_ref "TARGET_SSE2") (const_int 0)) - (const_string "V4SF") - (eq_attr "alternative" "0,1") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "V2DF")) - (eq_attr "alternative" "2") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "V2DF"))] - (const_string "V2DF")))]) - -(define_insn "*movv8hi_internal" - [(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V8HI 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 1: - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "0,1") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "2") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "TI"))] - (const_string "TI")))]) - -(define_insn "*movv16qi_internal" - [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V16QI 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 1: - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "0,1") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "2") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "TI"))] - (const_string "TI")))]) - -(define_expand "movv2df" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "") - (match_operand:V2DF 1 "nonimmediate_operand" ""))] - "TARGET_SSE" -{ - ix86_expand_vector_move (V2DFmode, operands); - DONE; -}) - -(define_expand "movv8hi" - [(set (match_operand:V8HI 0 "nonimmediate_operand" "") - (match_operand:V8HI 1 "nonimmediate_operand" ""))] - "TARGET_SSE" -{ - ix86_expand_vector_move (V8HImode, operands); - DONE; -}) - -(define_expand "movv16qi" - [(set (match_operand:V16QI 0 "nonimmediate_operand" "") - (match_operand:V16QI 1 "nonimmediate_operand" ""))] - "TARGET_SSE" -{ - ix86_expand_vector_move (V16QImode, operands); - DONE; -}) - -(define_expand "movv4sf" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "") - (match_operand:V4SF 1 "nonimmediate_operand" ""))] - "TARGET_SSE" -{ - ix86_expand_vector_move (V4SFmode, operands); - DONE; -}) - -(define_expand "movv4si" - [(set (match_operand:V4SI 0 "nonimmediate_operand" "") - (match_operand:V4SI 1 "nonimmediate_operand" ""))] - "TARGET_SSE" -{ - ix86_expand_vector_move (V4SImode, operands); - DONE; -}) - -(define_expand "movv2di" - [(set (match_operand:V2DI 0 "nonimmediate_operand" "") - (match_operand:V2DI 1 "nonimmediate_operand" ""))] - "TARGET_SSE" -{ - ix86_expand_vector_move (V2DImode, operands); - DONE; -}) - -(define_expand "movv2si" - [(set (match_operand:V2SI 0 "nonimmediate_operand" "") - (match_operand:V2SI 1 "nonimmediate_operand" ""))] - "TARGET_MMX" -{ - ix86_expand_vector_move (V2SImode, operands); - DONE; -}) - -(define_expand "movv4hi" - [(set (match_operand:V4HI 0 "nonimmediate_operand" "") - (match_operand:V4HI 1 "nonimmediate_operand" ""))] - "TARGET_MMX" -{ - ix86_expand_vector_move (V4HImode, operands); - DONE; -}) - -(define_expand "movv8qi" - [(set (match_operand:V8QI 0 "nonimmediate_operand" "") - (match_operand:V8QI 1 "nonimmediate_operand" ""))] - "TARGET_MMX" -{ - ix86_expand_vector_move (V8QImode, operands); - DONE; -}) - -(define_expand "movv2sf" - [(set (match_operand:V2SF 0 "nonimmediate_operand" "") - (match_operand:V2SF 1 "nonimmediate_operand" ""))] - "TARGET_MMX" -{ - ix86_expand_vector_move (V2SFmode, operands); - DONE; -}) - -(define_insn "*pushti" - [(set (match_operand:TI 0 "push_operand" "=<") - (match_operand:TI 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv2df" - [(set (match_operand:V2DF 0 "push_operand" "=<") - (match_operand:V2DF 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv2di" - [(set (match_operand:V2DI 0 "push_operand" "=<") - (match_operand:V2DI 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv8hi" - [(set (match_operand:V8HI 0 "push_operand" "=<") - (match_operand:V8HI 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv16qi" - [(set (match_operand:V16QI 0 "push_operand" "=<") - (match_operand:V16QI 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv4sf" - [(set (match_operand:V4SF 0 "push_operand" "=<") - (match_operand:V4SF 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv4si" - [(set (match_operand:V4SI 0 "push_operand" "=<") - (match_operand:V4SI 1 "register_operand" "x"))] - "TARGET_SSE" - "#") - -(define_insn "*pushv2si" - [(set (match_operand:V2SI 0 "push_operand" "=<") - (match_operand:V2SI 1 "register_operand" "y"))] - "TARGET_MMX" - "#") - -(define_insn "*pushv4hi" - [(set (match_operand:V4HI 0 "push_operand" "=<") - (match_operand:V4HI 1 "register_operand" "y"))] - "TARGET_MMX" - "#") - -(define_insn "*pushv8qi" - [(set (match_operand:V8QI 0 "push_operand" "=<") - (match_operand:V8QI 1 "register_operand" "y"))] - "TARGET_MMX" - "#") - -(define_insn "*pushv2sf" - [(set (match_operand:V2SF 0 "push_operand" "=<") - (match_operand:V2SF 1 "register_operand" "y"))] - "TARGET_MMX" - "#") - -(define_split - [(set (match_operand 0 "push_operand" "") - (match_operand 1 "register_operand" ""))] - "!TARGET_64BIT && reload_completed - && (SSE_REG_P (operands[1]) || MMX_REG_P (operands[1]))" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 3))) - (set (match_dup 2) (match_dup 1))] - "operands[2] = change_address (operands[0], GET_MODE (operands[0]), - stack_pointer_rtx); - operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));") - -(define_split - [(set (match_operand 0 "push_operand" "") - (match_operand 1 "register_operand" ""))] - "TARGET_64BIT && reload_completed - && (SSE_REG_P (operands[1]) || MMX_REG_P (operands[1]))" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 3))) - (set (match_dup 2) (match_dup 1))] - "operands[2] = change_address (operands[0], GET_MODE (operands[0]), - stack_pointer_rtx); - operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));") - - -(define_insn "*movti_internal" - [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:TI 1 "vector_move_operand" "C,xm,x"))] - "TARGET_SSE && !TARGET_64BIT - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 1: - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "ssemov,ssemov,ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "0,1") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "2") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI"))] - (const_string "TI")))]) - -(define_insn "*movti_rex64" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm") - (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))] - "TARGET_64BIT - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - case 1: - return "#"; - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 3: - case 4: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "*,*,ssemov,ssemov,ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "2,3") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "4") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "TI"))] - (const_string "DI")))]) - -(define_insn "*movtf_rex64" - [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm") - (match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))] - "TARGET_64BIT - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - case 1: - return "#"; - case 2: - if (get_attr_mode (insn) == MODE_V4SF) - return "xorps\t%0, %0"; - else - return "pxor\t%0, %0"; - case 3: - case 4: - if (get_attr_mode (insn) == MODE_V4SF) - return "movaps\t{%1, %0|%0, %1}"; - else - return "movdqa\t{%1, %0|%0, %1}"; - default: - abort (); - } -} - [(set_attr "type" "*,*,ssemov,ssemov,ssemov") - (set (attr "mode") - (cond [(eq_attr "alternative" "2,3") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")) - (eq_attr "alternative" "4") - (if_then_else - (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") - (const_int 0)) - (ne (symbol_ref "optimize_size") - (const_int 0))) - (const_string "V4SF") - (const_string "TI"))] - (const_string "DI")))]) - -(define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "general_operand" ""))] - "reload_completed && !SSE_REG_P (operands[0]) - && !SSE_REG_P (operands[1])" - [(const_int 0)] - "ix86_split_long_move (operands); DONE;") - -(define_split - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (match_operand:TF 1 "general_operand" ""))] - "reload_completed && !SSE_REG_P (operands[0]) - && !SSE_REG_P (operands[1])" - [(const_int 0)] - "ix86_split_long_move (operands); DONE;") - -;; These two patterns are useful for specifying exactly whether to use -;; movaps or movups -(define_expand "sse_movaps" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "") - (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")] - UNSPEC_MOVA))] - "TARGET_SSE" -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - { - rtx tmp = gen_reg_rtx (V4SFmode); - emit_insn (gen_sse_movaps (tmp, operands[1])); - emit_move_insn (operands[0], tmp); - DONE; - } -}) - -(define_insn "*sse_movaps_1" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")] - UNSPEC_MOVA))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "movaps\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov,ssemov") - (set_attr "mode" "V4SF")]) - -(define_expand "sse_movups" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "") - (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")] - UNSPEC_MOVU))] - "TARGET_SSE" -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - { - rtx tmp = gen_reg_rtx (V4SFmode); - emit_insn (gen_sse_movups (tmp, operands[1])); - emit_move_insn (operands[0], tmp); - DONE; - } -}) - -(define_insn "*sse_movups_1" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")] - UNSPEC_MOVU))] - "TARGET_SSE - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "movups\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt,ssecvt") - (set_attr "mode" "V4SF")]) - -;; SSE Strange Moves. - -(define_insn "sse_movmskps" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:V4SF 1 "register_operand" "x")] - UNSPEC_MOVMSK))] - "TARGET_SSE" - "movmskps\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "mmx_pmovmskb" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")] - UNSPEC_MOVMSK))] - "TARGET_SSE || TARGET_3DNOW_A" - "pmovmskb\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - - -(define_insn "mmx_maskmovq" - [(set (mem:V8QI (match_operand:SI 0 "register_operand" "D")) - (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y") - (match_operand:V8QI 2 "register_operand" "y")] - UNSPEC_MASKMOV))] - "(TARGET_SSE || TARGET_3DNOW_A) && !TARGET_64BIT" - ;; @@@ check ordering of operands in intel/nonintel syntax - "maskmovq\t{%2, %1|%1, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_maskmovq_rex" - [(set (mem:V8QI (match_operand:DI 0 "register_operand" "D")) - (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y") - (match_operand:V8QI 2 "register_operand" "y")] - UNSPEC_MASKMOV))] - "(TARGET_SSE || TARGET_3DNOW_A) && TARGET_64BIT" - ;; @@@ check ordering of operands in intel/nonintel syntax - "maskmovq\t{%2, %1|%1, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "sse_movntv4sf" - [(set (match_operand:V4SF 0 "memory_operand" "=m") - (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "x")] - UNSPEC_MOVNT))] - "TARGET_SSE" - "movntps\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "V4SF")]) - -(define_insn "sse_movntdi" - [(set (match_operand:DI 0 "memory_operand" "=m") - (unspec:DI [(match_operand:DI 1 "register_operand" "y")] - UNSPEC_MOVNT))] - "TARGET_SSE || TARGET_3DNOW_A" - "movntq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxmov") - (set_attr "mode" "DI")]) - -(define_insn "sse_movhlps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0") - (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x") - (parallel [(const_int 2) - (const_int 3) - (const_int 0) - (const_int 1)])) - (const_int 3)))] - "TARGET_SSE" - "movhlps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "sse_movlhps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0") - (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x") - (parallel [(const_int 2) - (const_int 3) - (const_int 0) - (const_int 1)])) - (const_int 12)))] - "TARGET_SSE" - "movlhps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "sse_movhps" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (vec_merge:V4SF - (match_operand:V4SF 1 "nonimmediate_operand" "0,0") - (match_operand:V4SF 2 "nonimmediate_operand" "m,x") - (const_int 12)))] - "TARGET_SSE - && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" - "movhps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "sse_movlps" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (vec_merge:V4SF - (match_operand:V4SF 1 "nonimmediate_operand" "0,0") - (match_operand:V4SF 2 "nonimmediate_operand" "m,x") - (const_int 3)))] - "TARGET_SSE - && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" - "movlps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_expand "sse_loadss" - [(match_operand:V4SF 0 "register_operand" "") - (match_operand:SF 1 "memory_operand" "")] - "TARGET_SSE" -{ - emit_insn (gen_sse_loadss_1 (operands[0], operands[1], - CONST0_RTX (V4SFmode))); - DONE; -}) - -(define_insn "sse_loadss_1" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (vec_duplicate:V4SF (match_operand:SF 1 "memory_operand" "m")) - (match_operand:V4SF 2 "const0_operand" "X") - (const_int 1)))] - "TARGET_SSE" - "movss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "SF")]) - -(define_insn "sse_movss" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "register_operand" "x") - (const_int 1)))] - "TARGET_SSE" - "movss\t{%2, %0|%0, %2}" - [(set_attr "type" "ssemov") - (set_attr "mode" "SF")]) - -(define_insn "sse_storess" - [(set (match_operand:SF 0 "memory_operand" "=m") - (vec_select:SF - (match_operand:V4SF 1 "register_operand" "x") - (parallel [(const_int 0)])))] - "TARGET_SSE" - "movss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "SF")]) - -(define_insn "sse_shufps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm") - (match_operand:SI 3 "immediate_operand" "i")] - UNSPEC_SHUFFLE))] - "TARGET_SSE" - ;; @@@ check operand order for intel/nonintel syntax - "shufps\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - - -;; SSE arithmetic - -(define_insn "addv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (plus:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "addps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V4SF")]) - -(define_insn "vmaddv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (plus:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE" - "addss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "SF")]) - -(define_insn "subv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (minus:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "subps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V4SF")]) - -(define_insn "vmsubv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (minus:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE" - "subss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "SF")]) - -(define_insn "mulv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (mult:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "mulps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssemul") - (set_attr "mode" "V4SF")]) - -(define_insn "vmmulv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (mult:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE" - "mulss\t{%2, %0|%0, %2}" - [(set_attr "type" "ssemul") - (set_attr "mode" "SF")]) - -(define_insn "divv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (div:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "divps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssediv") - (set_attr "mode" "V4SF")]) - -(define_insn "vmdivv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (div:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE" - "divss\t{%2, %0|%0, %2}" - [(set_attr "type" "ssediv") - (set_attr "mode" "SF")]) - - -;; SSE square root/reciprocal - -(define_insn "rcpv4sf2" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))] - "TARGET_SSE" - "rcpps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "vmrcpv4sf2" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] - UNSPEC_RCP) - (match_operand:V4SF 2 "register_operand" "0") - (const_int 1)))] - "TARGET_SSE" - "rcpss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -(define_insn "rsqrtv4sf2" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))] - "TARGET_SSE" - "rsqrtps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "vmrsqrtv4sf2" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] - UNSPEC_RSQRT) - (match_operand:V4SF 2 "register_operand" "0") - (const_int 1)))] - "TARGET_SSE" - "rsqrtss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -(define_insn "sqrtv4sf2" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "sqrtps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "vmsqrtv4sf2" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")) - (match_operand:V4SF 2 "register_operand" "0") - (const_int 1)))] - "TARGET_SSE" - "sqrtss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -;; SSE logical operations. - -;; SSE defines logical operations on floating point values. This brings -;; interesting challenge to RTL representation where logicals are only valid -;; on integral types. We deal with this by representing the floating point -;; logical as logical on arguments casted to TImode as this is what hardware -;; really does. Unfortunately hardware requires the type information to be -;; present and thus we must avoid subregs from being simplified and eliminated -;; in later compilation phases. -;; -;; We have following variants from each instruction: -;; sse_andsf3 - the operation taking V4SF vector operands -;; and doing TImode cast on them -;; *sse_andsf3_memory - the operation taking one memory operand casted to -;; TImode, since backend insist on eliminating casts -;; on memory operands -;; sse_andti3_sf_1 - the operation taking SF scalar operands. -;; We can not accept memory operand here as instruction reads -;; whole scalar. This is generated only post reload by GCC -;; scalar float operations that expands to logicals (fabs) -;; sse_andti3_sf_2 - the operation taking SF scalar input and TImode -;; memory operand. Eventually combine can be able -;; to synthesize these using splitter. -;; sse2_anddf3, *sse2_anddf3_memory -;; -;; -;; These are not called andti3 etc. because we really really don't want -;; the compiler to widen DImode ands to TImode ands and then try to move -;; into DImode subregs of SSE registers, and them together, and move out -;; of DImode subregs again! -;; SSE1 single precision floating point logical operation -(define_expand "sse_andv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "") - (and:V4SF (match_operand:V4SF 1 "register_operand" "") - (match_operand:V4SF 2 "nonimmediate_operand" "")))] - "TARGET_SSE" - "") - -(define_insn "*sse_andv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (and:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "andps\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V4SF")]) - -(define_expand "sse_nandv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "") - (and:V4SF (not:V4SF (match_operand:V4SF 1 "register_operand" "")) - (match_operand:V4SF 2 "nonimmediate_operand" "")))] - "TARGET_SSE" - "") - -(define_insn "*sse_nandv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (and:V4SF (not:V4SF (match_operand:V4SF 1 "register_operand" "0")) - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "andnps\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V4SF")]) - -(define_expand "sse_iorv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "") - (ior:V4SF (match_operand:V4SF 1 "register_operand" "") - (match_operand:V4SF 2 "nonimmediate_operand" "")))] - "TARGET_SSE" - "") - -(define_insn "*sse_iorv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (ior:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "orps\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V4SF")]) - -(define_expand "sse_xorv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "") - (xor:V4SF (match_operand:V4SF 1 "register_operand" "") - (match_operand:V4SF 2 "nonimmediate_operand" "")))] - "TARGET_SSE" - "") - -(define_insn "*sse_xorv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (xor:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "xorps\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V4SF")]) - -;; SSE2 double precision floating point logical operation - -(define_expand "sse2_andv2df3" - [(set (match_operand:V2DF 0 "register_operand" "") - (and:V2DF (match_operand:V2DF 1 "register_operand" "") - (match_operand:V2DF 2 "nonimmediate_operand" "")))] - "TARGET_SSE2" - "") - -(define_insn "*sse2_andv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (and:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "andpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V2DF")]) - -(define_expand "sse2_nandv2df3" - [(set (match_operand:V2DF 0 "register_operand" "") - (and:V2DF (not:V2DF (match_operand:V2DF 1 "register_operand" "")) - (match_operand:V2DF 2 "nonimmediate_operand" "")))] - "TARGET_SSE2" - "") - -(define_insn "*sse2_nandv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (and:V2DF (not:V2DF (match_operand:V2DF 1 "register_operand" "0")) - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "andnpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V2DF")]) - -(define_expand "sse2_iorv2df3" - [(set (match_operand:V2DF 0 "register_operand" "") - (ior:V2DF (match_operand:V2DF 1 "register_operand" "") - (match_operand:V2DF 2 "nonimmediate_operand" "")))] - "TARGET_SSE2" - "") - -(define_insn "*sse2_iorv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (ior:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "orpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V2DF")]) - -(define_expand "sse2_xorv2df3" - [(set (match_operand:V2DF 0 "register_operand" "") - (xor:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "") - (match_operand:V2DF 2 "nonimmediate_operand" "")))] - "TARGET_SSE2" - "") - -(define_insn "*sse2_xorv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (xor:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "xorpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "V2DF")]) - -;; SSE2 integral logicals. These patterns must always come after floating -;; point ones since we don't want compiler to use integer opcodes on floating -;; point SSE values to avoid matching of subregs in the match_operand. -(define_insn "*sse2_andti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0") - (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "pand\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "sse2_andv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (and:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0") - (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "pand\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "*sse2_nandti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) - (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pandn\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "sse2_nandv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (and:V2DI (not:V2DI (match_operand:V2DI 1 "register_operand" "0")) - (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "pandn\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "*sse2_iorti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0") - (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "por\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "sse2_iorv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (ior:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0") - (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "por\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "*sse2_xorti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0") - (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "pxor\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -(define_insn "sse2_xorv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (xor:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0") - (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 - && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "pxor\t{%2, %0|%0, %2}" - [(set_attr "type" "sselog") - (set_attr "mode" "TI")]) - -;; Use xor, but don't show input operands so they aren't live before -;; this insn. -(define_insn "sse_clrv4sf" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (match_operand:V4SF 1 "const0_operand" "X"))] - "TARGET_SSE" -{ - if (get_attr_mode (insn) == MODE_TI) - return "pxor\t{%0, %0|%0, %0}"; - else - return "xorps\t{%0, %0|%0, %0}"; -} - [(set_attr "type" "sselog") - (set_attr "memory" "none") - (set (attr "mode") - (if_then_else - (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") - (const_int 0)) - (ne (symbol_ref "TARGET_SSE2") - (const_int 0))) - (eq (symbol_ref "optimize_size") - (const_int 0))) - (const_string "TI") - (const_string "V4SF")))]) - -;; Use xor, but don't show input operands so they aren't live before -;; this insn. -(define_insn "sse_clrv2df" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (unspec:V2DF [(const_int 0)] UNSPEC_NOP))] - "TARGET_SSE2" - "xorpd\t{%0, %0|%0, %0}" - [(set_attr "type" "sselog") - (set_attr "memory" "none") - (set_attr "mode" "V4SF")]) - -;; SSE mask-generating compares - -(define_insn "maskcmpv4sf3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (match_operator:V4SI 3 "sse_comparison_operator" - [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "register_operand" "x")]))] - "TARGET_SSE" - "cmp%D3ps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "V4SF")]) - -(define_insn "maskncmpv4sf3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (not:V4SI - (match_operator:V4SI 3 "sse_comparison_operator" - [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "register_operand" "x")])))] - "TARGET_SSE" -{ - if (GET_CODE (operands[3]) == UNORDERED) - return "cmpordps\t{%2, %0|%0, %2}"; - else - return "cmpn%D3ps\t{%2, %0|%0, %2}"; -} - [(set_attr "type" "ssecmp") - (set_attr "mode" "V4SF")]) - -(define_insn "vmmaskcmpv4sf3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_merge:V4SI - (match_operator:V4SI 3 "sse_comparison_operator" - [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "register_operand" "x")]) - (subreg:V4SI (match_dup 1) 0) - (const_int 1)))] - "TARGET_SSE" - "cmp%D3ss\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "SF")]) - -(define_insn "vmmaskncmpv4sf3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_merge:V4SI - (not:V4SI - (match_operator:V4SI 3 "sse_comparison_operator" - [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "register_operand" "x")])) - (subreg:V4SI (match_dup 1) 0) - (const_int 1)))] - "TARGET_SSE" -{ - if (GET_CODE (operands[3]) == UNORDERED) - return "cmpordss\t{%2, %0|%0, %2}"; - else - return "cmpn%D3ss\t{%2, %0|%0, %2}"; -} - [(set_attr "type" "ssecmp") - (set_attr "mode" "SF")]) - -(define_insn "sse_comi" - [(set (reg:CCFP 17) - (compare:CCFP (vec_select:SF - (match_operand:V4SF 0 "register_operand" "x") - (parallel [(const_int 0)])) - (vec_select:SF - (match_operand:V4SF 1 "register_operand" "x") - (parallel [(const_int 0)]))))] - "TARGET_SSE" - "comiss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecomi") - (set_attr "mode" "SF")]) - -(define_insn "sse_ucomi" - [(set (reg:CCFPU 17) - (compare:CCFPU (vec_select:SF - (match_operand:V4SF 0 "register_operand" "x") - (parallel [(const_int 0)])) - (vec_select:SF - (match_operand:V4SF 1 "register_operand" "x") - (parallel [(const_int 0)]))))] - "TARGET_SSE" - "ucomiss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecomi") - (set_attr "mode" "SF")]) - - -;; SSE unpack - -(define_insn "sse_unpckhps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "0") - (parallel [(const_int 2) - (const_int 0) - (const_int 3) - (const_int 1)])) - (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x") - (parallel [(const_int 0) - (const_int 2) - (const_int 1) - (const_int 3)])) - (const_int 5)))] - "TARGET_SSE" - "unpckhps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "sse_unpcklps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "0") - (parallel [(const_int 0) - (const_int 2) - (const_int 1) - (const_int 3)])) - (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x") - (parallel [(const_int 2) - (const_int 0) - (const_int 3) - (const_int 1)])) - (const_int 5)))] - "TARGET_SSE" - "unpcklps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - - -;; SSE min/max - -(define_insn "smaxv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (smax:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "maxps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "vmsmaxv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (smax:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE" - "maxss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -(define_insn "sminv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (smin:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "minps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "vmsminv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (smin:V4SF (match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE" - "minss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -;; SSE <-> integer/MMX conversions - -(define_insn "cvtpi2ps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0") - (vec_duplicate:V4SF - (float:V2SF (match_operand:V2SI 2 "nonimmediate_operand" "ym"))) - (const_int 12)))] - "TARGET_SSE" - "cvtpi2ps\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "cvtps2pi" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (vec_select:V2SI - (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")) - (parallel [(const_int 0) (const_int 1)])))] - "TARGET_SSE" - "cvtps2pi\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "cvttps2pi" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (vec_select:V2SI - (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] - UNSPEC_FIX) - (parallel [(const_int 0) (const_int 1)])))] - "TARGET_SSE" - "cvttps2pi\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "SF")]) - -(define_insn "cvtsi2ss" - [(set (match_operand:V4SF 0 "register_operand" "=x,x") - (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0,0") - (vec_duplicate:V4SF - (float:SF (match_operand:SI 2 "nonimmediate_operand" "r,rm"))) - (const_int 14)))] - "TARGET_SSE" - "cvtsi2ss\t{%2, %0|%0, %2}" - [(set_attr "type" "sseicvt") - (set_attr "athlon_decode" "vector,double") - (set_attr "mode" "SF")]) - -(define_insn "cvtsi2ssq" - [(set (match_operand:V4SF 0 "register_operand" "=x,x") - (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0,0") - (vec_duplicate:V4SF - (float:SF (match_operand:DI 2 "nonimmediate_operand" "r,rm"))) - (const_int 14)))] - "TARGET_SSE && TARGET_64BIT" - "cvtsi2ssq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseicvt") - (set_attr "athlon_decode" "vector,double") - (set_attr "mode" "SF")]) - -(define_insn "cvtss2si" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (vec_select:SI - (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "x,m")) - (parallel [(const_int 0)])))] - "TARGET_SSE" - "cvtss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "athlon_decode" "double,vector") - (set_attr "mode" "SI")]) - -(define_insn "cvtss2siq" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (vec_select:DI - (fix:V4DI (match_operand:V4SF 1 "nonimmediate_operand" "x,m")) - (parallel [(const_int 0)])))] - "TARGET_SSE" - "cvtss2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "athlon_decode" "double,vector") - (set_attr "mode" "DI")]) - -(define_insn "cvttss2si" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (vec_select:SI - (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "x,xm")] - UNSPEC_FIX) - (parallel [(const_int 0)])))] - "TARGET_SSE" - "cvttss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "double,vector")]) - -(define_insn "cvttss2siq" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (vec_select:DI - (unspec:V4DI [(match_operand:V4SF 1 "nonimmediate_operand" "x,xm")] - UNSPEC_FIX) - (parallel [(const_int 0)])))] - "TARGET_SSE && TARGET_64BIT" - "cvttss2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SF") - (set_attr "athlon_decode" "double,vector")]) - - -;; MMX insns - -;; MMX arithmetic - -(define_insn "addv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (plus:V8QI (match_operand:V8QI 1 "register_operand" "%0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "addv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (plus:V4HI (match_operand:V4HI 1 "register_operand" "%0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "addv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (plus:V2SI (match_operand:V2SI 1 "register_operand" "%0") - (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "mmx_adddi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(plus:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "nonimmediate_operand" "ym"))] - UNSPEC_NOP))] - "TARGET_MMX" - "paddq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "ssaddv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (ss_plus:V8QI (match_operand:V8QI 1 "register_operand" "%0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddsb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "ssaddv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (ss_plus:V4HI (match_operand:V4HI 1 "register_operand" "%0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddsw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "usaddv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (us_plus:V8QI (match_operand:V8QI 1 "register_operand" "%0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddusb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "usaddv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (us_plus:V4HI (match_operand:V4HI 1 "register_operand" "%0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "paddusw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "subv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (minus:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "subv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (minus:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "subv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (minus:V2SI (match_operand:V2SI 1 "register_operand" "0") - (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "mmx_subdi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(minus:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "nonimmediate_operand" "ym"))] - UNSPEC_NOP))] - "TARGET_MMX" - "psubq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "sssubv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (ss_minus:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubsb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "sssubv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (ss_minus:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "ussubv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (us_minus:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubusb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "ussubv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (us_minus:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "psubusw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "mulv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (mult:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pmullw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxmul") - (set_attr "mode" "DI")]) - -(define_insn "smulv4hi3_highpart" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (truncate:V4HI - (lshiftrt:V4SI - (mult:V4SI (sign_extend:V4SI - (match_operand:V4HI 1 "register_operand" "0")) - (sign_extend:V4SI - (match_operand:V4HI 2 "nonimmediate_operand" "ym"))) - (const_int 16))))] - "TARGET_MMX" - "pmulhw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxmul") - (set_attr "mode" "DI")]) - -(define_insn "umulv4hi3_highpart" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (truncate:V4HI - (lshiftrt:V4SI - (mult:V4SI (zero_extend:V4SI - (match_operand:V4HI 1 "register_operand" "0")) - (zero_extend:V4SI - (match_operand:V4HI 2 "nonimmediate_operand" "ym"))) - (const_int 16))))] - "TARGET_SSE || TARGET_3DNOW_A" - "pmulhuw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxmul") - (set_attr "mode" "DI")]) - -(define_insn "mmx_pmaddwd" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (plus:V2SI - (mult:V2SI - (sign_extend:V2SI - (vec_select:V2HI (match_operand:V4HI 1 "register_operand" "0") - (parallel [(const_int 0) (const_int 2)]))) - (sign_extend:V2SI - (vec_select:V2HI (match_operand:V4HI 2 "nonimmediate_operand" "ym") - (parallel [(const_int 0) (const_int 2)])))) - (mult:V2SI - (sign_extend:V2SI (vec_select:V2HI (match_dup 1) - (parallel [(const_int 1) - (const_int 3)]))) - (sign_extend:V2SI (vec_select:V2HI (match_dup 2) - (parallel [(const_int 1) - (const_int 3)]))))))] - "TARGET_MMX" - "pmaddwd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxmul") - (set_attr "mode" "DI")]) - - -;; MMX logical operations -;; Note we don't want to declare these as regular iordi3 insns to prevent -;; normal code that also wants to use the FPU from getting broken. -;; The UNSPECs are there to prevent the combiner from getting overly clever. -(define_insn "mmx_iordi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(ior:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "nonimmediate_operand" "ym"))] - UNSPEC_NOP))] - "TARGET_MMX" - "por\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "mmx_xordi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(xor:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "nonimmediate_operand" "ym"))] - UNSPEC_NOP))] - "TARGET_MMX" - "pxor\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI") - (set_attr "memory" "none")]) - -;; Same as pxor, but don't show input operands so that we don't think -;; they are live. -(define_insn "mmx_clrdi" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI [(const_int 0)] UNSPEC_NOP))] - "TARGET_MMX" - "pxor\t{%0, %0|%0, %0}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI") - (set_attr "memory" "none")]) - -(define_insn "mmx_anddi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(and:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "nonimmediate_operand" "ym"))] - UNSPEC_NOP))] - "TARGET_MMX" - "pand\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "mmx_nanddi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(and:DI (not:DI (match_operand:DI 1 "register_operand" "0")) - (match_operand:DI 2 "nonimmediate_operand" "ym"))] - UNSPEC_NOP))] - "TARGET_MMX" - "pandn\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - - -;; MMX unsigned averages/sum of absolute differences - -(define_insn "mmx_uavgv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (ashiftrt:V8QI - (plus:V8QI (plus:V8QI - (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")) - (const_vector:V8QI [(const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1)])) - (const_int 1)))] - "TARGET_SSE || TARGET_3DNOW_A" - "pavgb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "mmx_uavgv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (ashiftrt:V4HI - (plus:V4HI (plus:V4HI - (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")) - (const_vector:V4HI [(const_int 1) - (const_int 1) - (const_int 1) - (const_int 1)])) - (const_int 1)))] - "TARGET_SSE || TARGET_3DNOW_A" - "pavgw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "mmx_psadbw" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI [(match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")] - UNSPEC_PSADBW))] - "TARGET_SSE || TARGET_3DNOW_A" - "psadbw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - - -;; MMX insert/extract/shuffle - -(define_insn "mmx_pinsrw" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (vec_merge:V4HI (match_operand:V4HI 1 "register_operand" "0") - (vec_duplicate:V4HI - (truncate:HI (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (match_operand:SI 3 "const_0_to_15_operand" "N")))] - "TARGET_SSE || TARGET_3DNOW_A" - "pinsrw\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_pextrw" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (vec_select:HI (match_operand:V4HI 1 "register_operand" "y") - (parallel - [(match_operand:SI 2 "const_0_to_3_operand" "N")]))))] - "TARGET_SSE || TARGET_3DNOW_A" - "pextrw\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_pshufw" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")] - UNSPEC_SHUFFLE))] - "TARGET_SSE || TARGET_3DNOW_A" - "pshufw\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - - -;; MMX mask-generating comparisons - -(define_insn "eqv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (eq:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pcmpeqb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "DI")]) - -(define_insn "eqv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (eq:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pcmpeqw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "DI")]) - -(define_insn "eqv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (eq:V2SI (match_operand:V2SI 1 "register_operand" "0") - (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pcmpeqd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "DI")]) - -(define_insn "gtv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (gt:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pcmpgtb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "DI")]) - -(define_insn "gtv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (gt:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pcmpgtw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "DI")]) - -(define_insn "gtv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (gt:V2SI (match_operand:V2SI 1 "register_operand" "0") - (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] - "TARGET_MMX" - "pcmpgtd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "DI")]) - - -;; MMX max/min insns - -(define_insn "umaxv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (umax:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE || TARGET_3DNOW_A" - "pmaxub\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "smaxv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (smax:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE || TARGET_3DNOW_A" - "pmaxsw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "uminv8qi3" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (umin:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE || TARGET_3DNOW_A" - "pminub\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - -(define_insn "sminv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (smin:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE || TARGET_3DNOW_A" - "pminsw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "DI")]) - - -;; MMX shifts - -(define_insn "ashrv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (ashiftrt:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi")))] - "TARGET_MMX" - "psraw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "ashrv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (ashiftrt:V2SI (match_operand:V2SI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi")))] - "TARGET_MMX" - "psrad\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "lshrv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (lshiftrt:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi")))] - "TARGET_MMX" - "psrlw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "lshrv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (lshiftrt:V2SI (match_operand:V2SI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi")))] - "TARGET_MMX" - "psrld\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -;; See logical MMX insns. -(define_insn "mmx_lshrdi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi"))] - UNSPEC_NOP))] - "TARGET_MMX" - "psrlq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "ashlv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (ashift:V4HI (match_operand:V4HI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi")))] - "TARGET_MMX" - "psllw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "ashlv2si3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (ashift:V2SI (match_operand:V2SI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi")))] - "TARGET_MMX" - "pslld\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -;; See logical MMX insns. -(define_insn "mmx_ashldi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (unspec:DI - [(ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "nonmemory_operand" "yi"))] - UNSPEC_NOP))] - "TARGET_MMX" - "psllq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - - -;; MMX pack/unpack insns. - -(define_insn "mmx_packsswb" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (vec_concat:V8QI - (ss_truncate:V4QI (match_operand:V4HI 1 "register_operand" "0")) - (ss_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))] - "TARGET_MMX" - "packsswb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "mmx_packssdw" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (vec_concat:V4HI - (ss_truncate:V2HI (match_operand:V2SI 1 "register_operand" "0")) - (ss_truncate:V2HI (match_operand:V2SI 2 "register_operand" "y"))))] - "TARGET_MMX" - "packssdw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "mmx_packuswb" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (vec_concat:V8QI - (us_truncate:V4QI (match_operand:V4HI 1 "register_operand" "0")) - (us_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))] - "TARGET_MMX" - "packuswb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "DI")]) - -(define_insn "mmx_punpckhbw" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (vec_merge:V8QI - (vec_select:V8QI (match_operand:V8QI 1 "register_operand" "0") - (parallel [(const_int 4) - (const_int 0) - (const_int 5) - (const_int 1) - (const_int 6) - (const_int 2) - (const_int 7) - (const_int 3)])) - (vec_select:V8QI (match_operand:V8QI 2 "register_operand" "y") - (parallel [(const_int 0) - (const_int 4) - (const_int 1) - (const_int 5) - (const_int 2) - (const_int 6) - (const_int 3) - (const_int 7)])) - (const_int 85)))] - "TARGET_MMX" - "punpckhbw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_punpckhwd" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (vec_merge:V4HI - (vec_select:V4HI (match_operand:V4HI 1 "register_operand" "0") - (parallel [(const_int 0) - (const_int 2) - (const_int 1) - (const_int 3)])) - (vec_select:V4HI (match_operand:V4HI 2 "register_operand" "y") - (parallel [(const_int 2) - (const_int 0) - (const_int 3) - (const_int 1)])) - (const_int 5)))] - "TARGET_MMX" - "punpckhwd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_punpckhdq" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (vec_merge:V2SI - (match_operand:V2SI 1 "register_operand" "0") - (vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y") - (parallel [(const_int 1) - (const_int 0)])) - (const_int 1)))] - "TARGET_MMX" - "punpckhdq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_punpcklbw" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (vec_merge:V8QI - (vec_select:V8QI (match_operand:V8QI 1 "register_operand" "0") - (parallel [(const_int 0) - (const_int 4) - (const_int 1) - (const_int 5) - (const_int 2) - (const_int 6) - (const_int 3) - (const_int 7)])) - (vec_select:V8QI (match_operand:V8QI 2 "register_operand" "y") - (parallel [(const_int 4) - (const_int 0) - (const_int 5) - (const_int 1) - (const_int 6) - (const_int 2) - (const_int 7) - (const_int 3)])) - (const_int 85)))] - "TARGET_MMX" - "punpcklbw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_punpcklwd" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (vec_merge:V4HI - (vec_select:V4HI (match_operand:V4HI 1 "register_operand" "0") - (parallel [(const_int 2) - (const_int 0) - (const_int 3) - (const_int 1)])) - (vec_select:V4HI (match_operand:V4HI 2 "register_operand" "y") - (parallel [(const_int 0) - (const_int 2) - (const_int 1) - (const_int 3)])) - (const_int 5)))] - "TARGET_MMX" - "punpcklwd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - -(define_insn "mmx_punpckldq" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (vec_merge:V2SI - (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "0") - (parallel [(const_int 1) - (const_int 0)])) - (match_operand:V2SI 2 "register_operand" "y") - (const_int 1)))] - "TARGET_MMX" - "punpckldq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "DI")]) - - -;; Miscellaneous stuff - -(define_insn "emms" - [(unspec_volatile [(const_int 0)] UNSPECV_EMMS) - (clobber (reg:XF 8)) - (clobber (reg:XF 9)) - (clobber (reg:XF 10)) - (clobber (reg:XF 11)) - (clobber (reg:XF 12)) - (clobber (reg:XF 13)) - (clobber (reg:XF 14)) - (clobber (reg:XF 15)) - (clobber (reg:DI 29)) - (clobber (reg:DI 30)) - (clobber (reg:DI 31)) - (clobber (reg:DI 32)) - (clobber (reg:DI 33)) - (clobber (reg:DI 34)) - (clobber (reg:DI 35)) - (clobber (reg:DI 36))] - "TARGET_MMX" - "emms" - [(set_attr "type" "mmx") - (set_attr "memory" "unknown")]) - -(define_insn "ldmxcsr" - [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] - UNSPECV_LDMXCSR)] - "TARGET_SSE" - "ldmxcsr\t%0" - [(set_attr "type" "sse") - (set_attr "memory" "load")]) - -(define_insn "stmxcsr" - [(set (match_operand:SI 0 "memory_operand" "=m") - (unspec_volatile:SI [(const_int 0)] UNSPECV_STMXCSR))] - "TARGET_SSE" - "stmxcsr\t%0" - [(set_attr "type" "sse") - (set_attr "memory" "store")]) - -(define_expand "sfence" - [(set (match_dup 0) - (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))] - "TARGET_SSE || TARGET_3DNOW_A" -{ - operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); - MEM_VOLATILE_P (operands[0]) = 1; -}) - -(define_insn "*sfence_insn" - [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))] - "TARGET_SSE || TARGET_3DNOW_A" - "sfence" - [(set_attr "type" "sse") - (set_attr "memory" "unknown")]) + { return ASM_SHORT "0x0b0f"; } + [(set_attr "length" "2")]) (define_expand "sse_prologue_save" [(parallel [(set (match_operand:BLK 0 "" "") @@ -20919,311 +20718,6 @@ (set_attr "modrm" "0") (set_attr "mode" "DI")]) -;; 3Dnow! instructions - -(define_insn "addv2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (plus:V2SF (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfadd\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "subv2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (minus:V2SF (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfsub\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "subrv2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (minus:V2SF (match_operand:V2SF 2 "nonimmediate_operand" "ym") - (match_operand:V2SF 1 "register_operand" "0")))] - "TARGET_3DNOW" - "pfsubr\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "gtv2sf3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (gt:V2SI (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfcmpgt\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "V2SF")]) - -(define_insn "gev2sf3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (ge:V2SI (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfcmpge\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "V2SF")]) - -(define_insn "eqv2sf3" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (eq:V2SI (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfcmpeq\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxcmp") - (set_attr "mode" "V2SF")]) - -(define_insn "pfmaxv2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (smax:V2SF (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfmax\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "pfminv2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (smin:V2SF (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfmin\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "mulv2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (mult:V2SF (match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pfmul\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxmul") - (set_attr "mode" "V2SF")]) - -(define_insn "femms" - [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS) - (clobber (reg:XF 8)) - (clobber (reg:XF 9)) - (clobber (reg:XF 10)) - (clobber (reg:XF 11)) - (clobber (reg:XF 12)) - (clobber (reg:XF 13)) - (clobber (reg:XF 14)) - (clobber (reg:XF 15)) - (clobber (reg:DI 29)) - (clobber (reg:DI 30)) - (clobber (reg:DI 31)) - (clobber (reg:DI 32)) - (clobber (reg:DI 33)) - (clobber (reg:DI 34)) - (clobber (reg:DI 35)) - (clobber (reg:DI 36))] - "TARGET_3DNOW" - "femms" - [(set_attr "type" "mmx") - (set_attr "memory" "none")]) - -(define_insn "pf2id" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pf2id\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "V2SF")]) - -(define_insn "pf2iw" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (sign_extend:V2SI - (ss_truncate:V2HI - (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))] - "TARGET_3DNOW_A" - "pf2iw\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "V2SF")]) - -(define_insn "pfacc" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (vec_concat:V2SF - (plus:SF - (vec_select:SF (match_operand:V2SF 1 "register_operand" "0") - (parallel [(const_int 0)])) - (vec_select:SF (match_dup 1) - (parallel [(const_int 1)]))) - (plus:SF - (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y") - (parallel [(const_int 0)])) - (vec_select:SF (match_dup 2) - (parallel [(const_int 1)])))))] - "TARGET_3DNOW" - "pfacc\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "pfnacc" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (vec_concat:V2SF - (minus:SF - (vec_select:SF (match_operand:V2SF 1 "register_operand" "0") - (parallel [(const_int 0)])) - (vec_select:SF (match_dup 1) - (parallel [(const_int 1)]))) - (minus:SF - (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y") - (parallel [(const_int 0)])) - (vec_select:SF (match_dup 2) - (parallel [(const_int 1)])))))] - "TARGET_3DNOW_A" - "pfnacc\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "pfpnacc" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (vec_concat:V2SF - (minus:SF - (vec_select:SF (match_operand:V2SF 1 "register_operand" "0") - (parallel [(const_int 0)])) - (vec_select:SF (match_dup 1) - (parallel [(const_int 1)]))) - (plus:SF - (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y") - (parallel [(const_int 0)])) - (vec_select:SF (match_dup 2) - (parallel [(const_int 1)])))))] - "TARGET_3DNOW_A" - "pfpnacc\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxadd") - (set_attr "mode" "V2SF")]) - -(define_insn "pi2fw" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (float:V2SF - (vec_concat:V2SI - (sign_extend:SI - (truncate:HI - (vec_select:SI (match_operand:V2SI 1 "nonimmediate_operand" "ym") - (parallel [(const_int 0)])))) - (sign_extend:SI - (truncate:HI - (vec_select:SI (match_dup 1) - (parallel [(const_int 1)])))))))] - "TARGET_3DNOW_A" - "pi2fw\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "V2SF")]) - -(define_insn "floatv2si2" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))] - "TARGET_3DNOW" - "pi2fd\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "V2SF")]) - -;; This insn is identical to pavgb in operation, but the opcode is -;; different. To avoid accidentally matching pavgb, use an unspec. - -(define_insn "pavgusb" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (unspec:V8QI - [(match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")] - UNSPEC_PAVGUSB))] - "TARGET_3DNOW" - "pavgusb\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxshft") - (set_attr "mode" "TI")]) - -;; 3DNow reciprocal and sqrt - -(define_insn "pfrcpv2sf2" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] - UNSPEC_PFRCP))] - "TARGET_3DNOW" - "pfrcp\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx") - (set_attr "mode" "TI")]) - -(define_insn "pfrcpit1v2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")] - UNSPEC_PFRCPIT1))] - "TARGET_3DNOW" - "pfrcpit1\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx") - (set_attr "mode" "TI")]) - -(define_insn "pfrcpit2v2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")] - UNSPEC_PFRCPIT2))] - "TARGET_3DNOW" - "pfrcpit2\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx") - (set_attr "mode" "TI")]) - -(define_insn "pfrsqrtv2sf2" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] - UNSPEC_PFRSQRT))] - "TARGET_3DNOW" - "pfrsqrt\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx") - (set_attr "mode" "TI")]) - -(define_insn "pfrsqit1v2sf3" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0") - (match_operand:V2SF 2 "nonimmediate_operand" "ym")] - UNSPEC_PFRSQIT1))] - "TARGET_3DNOW" - "pfrsqit1\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx") - (set_attr "mode" "TI")]) - -(define_insn "pmulhrwv4hi3" - [(set (match_operand:V4HI 0 "register_operand" "=y") - (truncate:V4HI - (lshiftrt:V4SI - (plus:V4SI - (mult:V4SI - (sign_extend:V4SI - (match_operand:V4HI 1 "register_operand" "0")) - (sign_extend:V4SI - (match_operand:V4HI 2 "nonimmediate_operand" "ym"))) - (const_vector:V4SI [(const_int 32768) - (const_int 32768) - (const_int 32768) - (const_int 32768)])) - (const_int 16))))] - "TARGET_3DNOW" - "pmulhrw\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmxmul") - (set_attr "mode" "TI")]) - -(define_insn "pswapdv2si2" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (vec_select:V2SI (match_operand:V2SI 1 "nonimmediate_operand" "ym") - (parallel [(const_int 1) (const_int 0)])))] - "TARGET_3DNOW_A" - "pswapd\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "TI")]) - -(define_insn "pswapdv2sf2" - [(set (match_operand:V2SF 0 "register_operand" "=y") - (vec_select:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "ym") - (parallel [(const_int 1) (const_int 0)])))] - "TARGET_3DNOW_A" - "pswapd\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmxcvt") - (set_attr "mode" "TI")]) - (define_expand "prefetch" [(prefetch (match_operand 0 "address_operand" "") (match_operand:SI 1 "const_int_operand" "") @@ -21233,15 +20727,13 @@ int rw = INTVAL (operands[1]); int locality = INTVAL (operands[2]); - if (rw != 0 && rw != 1) - abort (); - if (locality < 0 || locality > 3) - abort (); - if (GET_MODE (operands[0]) != Pmode && GET_MODE (operands[0]) != VOIDmode) - abort (); + gcc_assert (rw == 0 || rw == 1); + gcc_assert (locality >= 0 && locality <= 3); + gcc_assert (GET_MODE (operands[0]) == Pmode + || GET_MODE (operands[0]) == VOIDmode); /* Use 3dNOW prefetch in case we are asking for write prefetch not - suported by SSE counterpart or the SSE prefetch is not available + supported by SSE counterpart or the SSE prefetch is not available (K6 machines). Otherwise use SSE prefetch as it allows specifying of locality. */ if (TARGET_3DNOW && (!TARGET_PREFETCH_SSE || rw)) @@ -21261,8 +20753,7 @@ }; int locality = INTVAL (operands[1]); - if (locality < 0 || locality > 3) - abort (); + gcc_assert (locality >= 0 && locality <= 3); return patterns[locality]; } @@ -21280,8 +20771,7 @@ }; int locality = INTVAL (operands[1]); - if (locality < 0 || locality > 3) - abort (); + gcc_assert (locality >= 0 && locality <= 3); return patterns[locality]; } @@ -21316,1706 +20806,147 @@ [(set_attr "type" "mmx") (set_attr "memory" "none")]) -;; SSE2 support - -(define_insn "addv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (plus:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "addpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "vmaddv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (plus:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE2" - "addsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) - -(define_insn "subv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (minus:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "subpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "vmsubv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (minus:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE2" - "subsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) - -(define_insn "mulv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (mult:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "mulpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssemul") - (set_attr "mode" "V2DF")]) - -(define_insn "vmmulv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (mult:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE2" - "mulsd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssemul") - (set_attr "mode" "DF")]) - -(define_insn "divv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (div:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "divpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssediv") - (set_attr "mode" "V2DF")]) - -(define_insn "vmdivv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (div:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE2" - "divsd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssediv") - (set_attr "mode" "DF")]) - -;; SSE min/max - -(define_insn "smaxv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (smax:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "maxpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "vmsmaxv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (smax:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE2" - "maxsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) - -(define_insn "sminv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (smin:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "minpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "vmsminv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (smin:V2DF (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")) - (match_dup 1) - (const_int 1)))] - "TARGET_SSE2" - "minsd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "DF")]) -;; SSE2 square root. There doesn't appear to be an extension for the -;; reciprocal/rsqrt instructions if the Intel manual is to be believed. - -(define_insn "sqrtv2df2" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm")))] - "TARGET_SSE2" - "sqrtpd\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "V2DF")]) - -(define_insn "vmsqrtv2df2" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm")) - (match_operand:V2DF 2 "register_operand" "0") - (const_int 1)))] - "TARGET_SSE2" - "sqrtsd\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "SF")]) - -;; SSE mask-generating compares - -(define_insn "maskcmpv2df3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (match_operator:V2DI 3 "sse_comparison_operator" - [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "x")]))] - "TARGET_SSE2" - "cmp%D3pd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "V2DF")]) - -(define_insn "maskncmpv2df3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (not:V2DI - (match_operator:V2DI 3 "sse_comparison_operator" - [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "x")])))] - "TARGET_SSE2" +(define_expand "stack_protect_set" + [(match_operand 0 "memory_operand" "") + (match_operand 1 "memory_operand" "")] + "" { - if (GET_CODE (operands[3]) == UNORDERED) - return "cmpordps\t{%2, %0|%0, %2}"; +#ifdef TARGET_THREAD_SSP_OFFSET + if (TARGET_64BIT) + emit_insn (gen_stack_tls_protect_set_di (operands[0], + GEN_INT (TARGET_THREAD_SSP_OFFSET))); else - return "cmpn%D3pd\t{%2, %0|%0, %2}"; -} - [(set_attr "type" "ssecmp") - (set_attr "mode" "V2DF")]) - -(define_insn "vmmaskcmpv2df3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (vec_merge:V2DI - (match_operator:V2DI 3 "sse_comparison_operator" - [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "x")]) - (subreg:V2DI (match_dup 1) 0) - (const_int 1)))] - "TARGET_SSE2" - "cmp%D3sd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "DF")]) - -(define_insn "vmmaskncmpv2df3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (vec_merge:V2DI - (not:V2DI - (match_operator:V2DI 3 "sse_comparison_operator" - [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "x")])) - (subreg:V2DI (match_dup 1) 0) - (const_int 1)))] - "TARGET_SSE2" -{ - if (GET_CODE (operands[3]) == UNORDERED) - return "cmpordsd\t{%2, %0|%0, %2}"; + emit_insn (gen_stack_tls_protect_set_si (operands[0], + GEN_INT (TARGET_THREAD_SSP_OFFSET))); +#else + if (TARGET_64BIT) + emit_insn (gen_stack_protect_set_di (operands[0], operands[1])); else - return "cmpn%D3sd\t{%2, %0|%0, %2}"; -} - [(set_attr "type" "ssecmp") - (set_attr "mode" "DF")]) - -(define_insn "sse2_comi" - [(set (reg:CCFP 17) - (compare:CCFP (vec_select:DF - (match_operand:V2DF 0 "register_operand" "x") - (parallel [(const_int 0)])) - (vec_select:DF - (match_operand:V2DF 1 "register_operand" "x") - (parallel [(const_int 0)]))))] - "TARGET_SSE2" - "comisd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecomi") - (set_attr "mode" "DF")]) - -(define_insn "sse2_ucomi" - [(set (reg:CCFPU 17) - (compare:CCFPU (vec_select:DF - (match_operand:V2DF 0 "register_operand" "x") - (parallel [(const_int 0)])) - (vec_select:DF - (match_operand:V2DF 1 "register_operand" "x") - (parallel [(const_int 0)]))))] - "TARGET_SSE2" - "ucomisd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecomi") - (set_attr "mode" "DF")]) - -;; SSE Strange Moves. - -(define_insn "sse2_movmskpd" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:V2DF 1 "register_operand" "x")] - UNSPEC_MOVMSK))] - "TARGET_SSE2" - "movmskpd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_pmovmskb" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:V16QI 1 "register_operand" "x")] - UNSPEC_MOVMSK))] - "TARGET_SSE2" - "pmovmskb\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_maskmovdqu" - [(set (mem:V16QI (match_operand:SI 0 "register_operand" "D")) - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x") - (match_operand:V16QI 2 "register_operand" "x")] - UNSPEC_MASKMOV))] - "TARGET_SSE2" - ;; @@@ check ordering of operands in intel/nonintel syntax - "maskmovdqu\t{%2, %1|%1, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_maskmovdqu_rex64" - [(set (mem:V16QI (match_operand:DI 0 "register_operand" "D")) - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x") - (match_operand:V16QI 2 "register_operand" "x")] - UNSPEC_MASKMOV))] - "TARGET_SSE2" - ;; @@@ check ordering of operands in intel/nonintel syntax - "maskmovdqu\t{%2, %1|%1, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movntv2df" - [(set (match_operand:V2DF 0 "memory_operand" "=m") - (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "x")] - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movntpd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_movntv2di" - [(set (match_operand:V2DI 0 "memory_operand" "=m") - (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "x")] - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movntdq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) + emit_insn (gen_stack_protect_set_si (operands[0], operands[1])); +#endif + DONE; +}) -(define_insn "sse2_movntsi" +(define_insn "stack_protect_set_si" [(set (match_operand:SI 0 "memory_operand" "=m") - (unspec:SI [(match_operand:SI 1 "register_operand" "r")] - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movnti\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -;; SSE <-> integer/MMX conversions - -;; Conversions between SI and SF - -(define_insn "cvtdq2ps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "cvtdq2ps\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "cvtps2dq" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "cvtps2dq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "cvttps2dq" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] - UNSPEC_FIX))] - "TARGET_SSE2" - "cvttps2dq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -;; Conversions between SI and DF - -(define_insn "cvtdq2pd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (float:V2DF (vec_select:V2SI - (match_operand:V4SI 1 "nonimmediate_operand" "xm") - (parallel - [(const_int 0) - (const_int 1)]))))] - "TARGET_SSE2" - "cvtdq2pd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "cvtpd2dq" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_concat:V4SI - (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm")) - (const_vector:V2SI [(const_int 0) (const_int 0)])))] - "TARGET_SSE2" - "cvtpd2dq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "cvttpd2dq" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_concat:V4SI - (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")] - UNSPEC_FIX) - (const_vector:V2SI [(const_int 0) (const_int 0)])))] - "TARGET_SSE2" - "cvttpd2dq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "cvtpd2pi" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "cvtpd2pi\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "cvttpd2pi" - [(set (match_operand:V2SI 0 "register_operand" "=y") - (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")] - UNSPEC_FIX))] - "TARGET_SSE2" - "cvttpd2pi\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "cvtpi2pd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (float:V2DF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))] - "TARGET_SSE2" - "cvtpi2pd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -;; Conversions between SI and DF - -(define_insn "cvtsd2si" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (fix:SI (vec_select:DF (match_operand:V2DF 1 "register_operand" "x,m") - (parallel [(const_int 0)]))))] - "TARGET_SSE2" - "cvtsd2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "athlon_decode" "double,vector") - (set_attr "mode" "SI")]) - -(define_insn "cvtsd2siq" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (fix:DI (vec_select:DF (match_operand:V2DF 1 "register_operand" "x,m") - (parallel [(const_int 0)]))))] - "TARGET_SSE2 && TARGET_64BIT" - "cvtsd2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "athlon_decode" "double,vector") - (set_attr "mode" "DI")]) - -(define_insn "cvttsd2si" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (unspec:SI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "x,xm") - (parallel [(const_int 0)]))] UNSPEC_FIX))] - "TARGET_SSE2" - "cvttsd2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "SI") - (set_attr "athlon_decode" "double,vector")]) - -(define_insn "cvttsd2siq" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (unspec:DI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "x,xm") - (parallel [(const_int 0)]))] UNSPEC_FIX))] - "TARGET_SSE2 && TARGET_64BIT" - "cvttsd2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "DI") - (set_attr "athlon_decode" "double,vector")]) - -(define_insn "cvtsi2sd" - [(set (match_operand:V2DF 0 "register_operand" "=x,x") - (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0,0") - (vec_duplicate:V2DF - (float:DF - (match_operand:SI 2 "nonimmediate_operand" "r,rm"))) - (const_int 2)))] - "TARGET_SSE2" - "cvtsi2sd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "DF") - (set_attr "athlon_decode" "double,direct")]) - -(define_insn "cvtsi2sdq" - [(set (match_operand:V2DF 0 "register_operand" "=x,x") - (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0,0") - (vec_duplicate:V2DF - (float:DF - (match_operand:DI 2 "nonimmediate_operand" "r,rm"))) - (const_int 2)))] - "TARGET_SSE2 && TARGET_64BIT" - "cvtsi2sdq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseicvt") - (set_attr "mode" "DF") - (set_attr "athlon_decode" "double,direct")]) - -;; Conversions between SF and DF - -(define_insn "cvtsd2ss" - [(set (match_operand:V4SF 0 "register_operand" "=x,x") - (vec_merge:V4SF (match_operand:V4SF 1 "register_operand" "0,0") - (vec_duplicate:V4SF - (float_truncate:V2SF - (match_operand:V2DF 2 "nonimmediate_operand" "x,xm"))) - (const_int 14)))] - "TARGET_SSE2" - "cvtsd2ss\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "athlon_decode" "vector,double") - (set_attr "mode" "SF")]) - -(define_insn "cvtss2sd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0") - (float_extend:V2DF - (vec_select:V2SF - (match_operand:V4SF 2 "nonimmediate_operand" "xm") - (parallel [(const_int 0) - (const_int 1)]))) - (const_int 2)))] - "TARGET_SSE2" - "cvtss2sd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) + (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) + (set (match_scratch:SI 2 "=&r") (const_int 0)) + (clobber (reg:CC FLAGS_REG))] + "" + "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2" + [(set_attr "type" "multi")]) -(define_insn "cvtpd2ps" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (subreg:V4SF - (vec_concat:V4SI - (subreg:V2SI (float_truncate:V2SF - (match_operand:V2DF 1 "nonimmediate_operand" "xm")) 0) - (const_vector:V2SI [(const_int 0) (const_int 0)])) 0))] - "TARGET_SSE2" - "cvtpd2ps\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V4SF")]) - -(define_insn "cvtps2pd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (float_extend:V2DF - (vec_select:V2SF (match_operand:V4SF 1 "nonimmediate_operand" "xm") - (parallel [(const_int 0) - (const_int 1)]))))] - "TARGET_SSE2" - "cvtps2pd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) +(define_insn "stack_protect_set_di" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET)) + (set (match_scratch:DI 2 "=&r") (const_int 0)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" + [(set_attr "type" "multi")]) -;; SSE2 variants of MMX insns +(define_insn "stack_tls_protect_set_si" + [(set (match_operand:SI 0 "memory_operand" "=m") + (unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET)) + (set (match_scratch:SI 2 "=&r") (const_int 0)) + (clobber (reg:CC FLAGS_REG))] + "" + "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2" + [(set_attr "type" "multi")]) -;; MMX arithmetic +(define_insn "stack_tls_protect_set_di" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET)) + (set (match_scratch:DI 2 "=&r") (const_int 0)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT" + { + /* The kernel uses a different segment register for performance reasons; a + system call would not have to trash the userspace segment register, + which would be expensive */ + if (ix86_cmodel != CM_KERNEL) + return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"; + else + return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"; + } + [(set_attr "type" "multi")]) -(define_insn "addv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (plus:V16QI (match_operand:V16QI 1 "register_operand" "%0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "addv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (plus:V8HI (match_operand:V8HI 1 "register_operand" "%0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "addv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (plus:V4SI (match_operand:V4SI 1 "register_operand" "%0") - (match_operand:V4SI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "addv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (plus:V2DI (match_operand:V2DI 1 "register_operand" "%0") - (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "ssaddv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (ss_plus:V16QI (match_operand:V16QI 1 "register_operand" "%0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddsb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "ssaddv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ss_plus:V8HI (match_operand:V8HI 1 "register_operand" "%0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "usaddv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (us_plus:V16QI (match_operand:V16QI 1 "register_operand" "%0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddusb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "usaddv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (us_plus:V8HI (match_operand:V8HI 1 "register_operand" "%0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "paddusw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "subv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (minus:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "subv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (minus:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "subv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (minus:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:V4SI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "subv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (minus:V2DI (match_operand:V2DI 1 "register_operand" "0") - (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "sssubv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (ss_minus:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubsb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "sssubv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ss_minus:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "ussubv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (us_minus:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubusb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "ussubv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (us_minus:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "psubusw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "mulv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (mult:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pmullw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseimul") - (set_attr "mode" "TI")]) - -(define_insn "smulv8hi3_highpart" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (truncate:V8HI - (lshiftrt:V8SI - (mult:V8SI (sign_extend:V8SI (match_operand:V8HI 1 "register_operand" "0")) - (sign_extend:V8SI (match_operand:V8HI 2 "nonimmediate_operand" "xm"))) - (const_int 16))))] - "TARGET_SSE2" - "pmulhw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseimul") - (set_attr "mode" "TI")]) - -(define_insn "umulv8hi3_highpart" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (truncate:V8HI - (lshiftrt:V8SI - (mult:V8SI (zero_extend:V8SI (match_operand:V8HI 1 "register_operand" "0")) - (zero_extend:V8SI (match_operand:V8HI 2 "nonimmediate_operand" "xm"))) - (const_int 16))))] - "TARGET_SSE2" - "pmulhuw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseimul") - (set_attr "mode" "TI")]) - -(define_insn "sse2_umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=y") - (mult:DI (zero_extend:DI (vec_select:SI - (match_operand:V2SI 1 "register_operand" "0") - (parallel [(const_int 0)]))) - (zero_extend:DI (vec_select:SI - (match_operand:V2SI 2 "nonimmediate_operand" "ym") - (parallel [(const_int 0)])))))] - "TARGET_SSE2" - "pmuludq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseimul") - (set_attr "mode" "TI")]) - -(define_insn "sse2_umulv2siv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (mult:V2DI (zero_extend:V2DI - (vec_select:V2SI - (match_operand:V4SI 1 "register_operand" "0") - (parallel [(const_int 0) (const_int 2)]))) - (zero_extend:V2DI - (vec_select:V2SI - (match_operand:V4SI 2 "nonimmediate_operand" "xm") - (parallel [(const_int 0) (const_int 2)])))))] - "TARGET_SSE2" - "pmuludq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseimul") - (set_attr "mode" "TI")]) - -(define_insn "sse2_pmaddwd" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (plus:V4SI - (mult:V4SI - (sign_extend:V4SI (vec_select:V4HI (match_operand:V8HI 1 "register_operand" "0") - (parallel [(const_int 0) - (const_int 2) - (const_int 4) - (const_int 6)]))) - (sign_extend:V4SI (vec_select:V4HI (match_operand:V8HI 2 "nonimmediate_operand" "xm") - (parallel [(const_int 0) - (const_int 2) - (const_int 4) - (const_int 6)])))) - (mult:V4SI - (sign_extend:V4SI (vec_select:V4HI (match_dup 1) - (parallel [(const_int 1) - (const_int 3) - (const_int 5) - (const_int 7)]))) - (sign_extend:V4SI (vec_select:V4HI (match_dup 2) - (parallel [(const_int 1) - (const_int 3) - (const_int 5) - (const_int 7)]))))))] - "TARGET_SSE2" - "pmaddwd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -;; Same as pxor, but don't show input operands so that we don't think -;; they are live. -(define_insn "sse2_clrti" - [(set (match_operand:TI 0 "register_operand" "=x") (const_int 0))] - "TARGET_SSE2" +(define_expand "stack_protect_test" + [(match_operand 0 "memory_operand" "") + (match_operand 1 "memory_operand" "") + (match_operand 2 "" "")] + "" { - if (get_attr_mode (insn) == MODE_TI) - return "pxor\t%0, %0"; - else - return "xorps\t%0, %0"; -} - [(set_attr "type" "ssemov") - (set_attr "memory" "none") - (set (attr "mode") - (if_then_else - (ne (symbol_ref "optimize_size") - (const_int 0)) - (const_string "V4SF") - (const_string "TI")))]) - -;; MMX unsigned averages/sum of absolute differences - -(define_insn "sse2_uavgv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (ashiftrt:V16QI - (plus:V16QI (plus:V16QI - (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")) - (const_vector:V16QI [(const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1)])) - (const_int 1)))] - "TARGET_SSE2" - "pavgb\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "sse2_uavgv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ashiftrt:V8HI - (plus:V8HI (plus:V8HI - (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")) - (const_vector:V8HI [(const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1) - (const_int 1) (const_int 1)])) - (const_int 1)))] - "TARGET_SSE2" - "pavgw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -;; @@@ this isn't the right representation. -(define_insn "sse2_psadbw" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (unspec:V2DI [(match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")] - UNSPEC_PSADBW))] - "TARGET_SSE2" - "psadbw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - - -;; MMX insert/extract/shuffle - -(define_insn "sse2_pinsrw" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (vec_merge:V8HI (match_operand:V8HI 1 "register_operand" "0") - (vec_duplicate:V8HI - (truncate:HI - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (match_operand:SI 3 "const_0_to_255_operand" "N")))] - "TARGET_SSE2" - "pinsrw\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_pextrw" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI - (vec_select:HI (match_operand:V8HI 1 "register_operand" "x") - (parallel - [(match_operand:SI 2 "const_0_to_7_operand" "N")]))))] - "TARGET_SSE2" - "pextrw\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_pshufd" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")] - UNSPEC_SHUFFLE))] - "TARGET_SSE2" - "pshufd\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_pshuflw" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")] - UNSPEC_PSHUFLW))] - "TARGET_SSE2" - "pshuflw\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_pshufhw" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")] - UNSPEC_PSHUFHW))] - "TARGET_SSE2" - "pshufhw\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -;; MMX mask-generating comparisons - -(define_insn "eqv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (eq:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pcmpeqb\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "TI")]) - -(define_insn "eqv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (eq:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pcmpeqw\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "TI")]) - -(define_insn "eqv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (eq:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:V4SI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pcmpeqd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "TI")]) - -(define_insn "gtv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (gt:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pcmpgtb\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "TI")]) - -(define_insn "gtv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (gt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pcmpgtw\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "TI")]) - -(define_insn "gtv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (gt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:V4SI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pcmpgtd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecmp") - (set_attr "mode" "TI")]) - - -;; MMX max/min insns - -(define_insn "umaxv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (umax:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pmaxub\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "smaxv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (smax:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pmaxsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "uminv16qi3" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (umin:V16QI (match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pminub\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - -(define_insn "sminv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (smin:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:V8HI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2" - "pminsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") - (set_attr "mode" "TI")]) - - -;; MMX shifts - -(define_insn "ashrv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psraw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashrv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psrad\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "lshrv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psrlw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "lshrv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psrld\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "lshrv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psrlq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashlv8hi3" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psllw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashlv4si3" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "pslld\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashlv2di3" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "xi")))] - "TARGET_SSE2" - "psllq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashrv8hi3_ti" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psraw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashrv4si3_ti" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psrad\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "lshrv8hi3_ti" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psrlw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "lshrv4si3_ti" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psrld\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "lshrv2di3_ti" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psrlq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashlv8hi3_ti" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psllw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashlv4si3_ti" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "pslld\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "ashlv2di3_ti" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0") - (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] - "TARGET_SSE2" - "psllq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -;; See logical MMX insns for the reason for the unspec. Strictly speaking -;; we wouldn't need here it since we never generate TImode arithmetic. - -;; There has to be some kind of prize for the weirdest new instruction... -(define_insn "sse2_ashlti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (unspec:TI - [(ashift:TI (match_operand:TI 1 "register_operand" "0") - (mult:SI (match_operand:SI 2 "immediate_operand" "i") - (const_int 8)))] UNSPEC_NOP))] - "TARGET_SSE2" - "pslldq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -(define_insn "sse2_lshrti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (unspec:TI - [(lshiftrt:TI (match_operand:TI 1 "register_operand" "0") - (mult:SI (match_operand:SI 2 "immediate_operand" "i") - (const_int 8)))] UNSPEC_NOP))] - "TARGET_SSE2" - "psrldq\t{%2, %0|%0, %2}" - [(set_attr "type" "sseishft") - (set_attr "mode" "TI")]) - -;; SSE unpack - -(define_insn "sse2_unpckhpd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_concat:V2DF - (vec_select:DF (match_operand:V2DF 1 "register_operand" "0") - (parallel [(const_int 1)])) - (vec_select:DF (match_operand:V2DF 2 "register_operand" "x") - (parallel [(const_int 1)]))))] - "TARGET_SSE2" - "unpckhpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_unpcklpd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_concat:V2DF - (vec_select:DF (match_operand:V2DF 1 "register_operand" "0") - (parallel [(const_int 0)])) - (vec_select:DF (match_operand:V2DF 2 "register_operand" "x") - (parallel [(const_int 0)]))))] - "TARGET_SSE2" - "unpcklpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -;; MMX pack/unpack insns. - -(define_insn "sse2_packsswb" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (vec_concat:V16QI - (ss_truncate:V8QI (match_operand:V8HI 1 "register_operand" "0")) - (ss_truncate:V8QI (match_operand:V8HI 2 "register_operand" "x"))))] - "TARGET_SSE2" - "packsswb\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_packssdw" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (vec_concat:V8HI - (ss_truncate:V4HI (match_operand:V4SI 1 "register_operand" "0")) - (ss_truncate:V4HI (match_operand:V4SI 2 "register_operand" "x"))))] - "TARGET_SSE2" - "packssdw\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_packuswb" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (vec_concat:V16QI - (us_truncate:V8QI (match_operand:V8HI 1 "register_operand" "0")) - (us_truncate:V8QI (match_operand:V8HI 2 "register_operand" "x"))))] - "TARGET_SSE2" - "packuswb\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpckhbw" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (vec_merge:V16QI - (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "0") - (parallel [(const_int 8) (const_int 0) - (const_int 9) (const_int 1) - (const_int 10) (const_int 2) - (const_int 11) (const_int 3) - (const_int 12) (const_int 4) - (const_int 13) (const_int 5) - (const_int 14) (const_int 6) - (const_int 15) (const_int 7)])) - (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "x") - (parallel [(const_int 0) (const_int 8) - (const_int 1) (const_int 9) - (const_int 2) (const_int 10) - (const_int 3) (const_int 11) - (const_int 4) (const_int 12) - (const_int 5) (const_int 13) - (const_int 6) (const_int 14) - (const_int 7) (const_int 15)])) - (const_int 21845)))] - "TARGET_SSE2" - "punpckhbw\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpckhwd" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (vec_merge:V8HI - (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "0") - (parallel [(const_int 4) (const_int 0) - (const_int 5) (const_int 1) - (const_int 6) (const_int 2) - (const_int 7) (const_int 3)])) - (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "x") - (parallel [(const_int 0) (const_int 4) - (const_int 1) (const_int 5) - (const_int 2) (const_int 6) - (const_int 3) (const_int 7)])) - (const_int 85)))] - "TARGET_SSE2" - "punpckhwd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpckhdq" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_merge:V4SI - (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "0") - (parallel [(const_int 2) (const_int 0) - (const_int 3) (const_int 1)])) - (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "x") - (parallel [(const_int 0) (const_int 2) - (const_int 1) (const_int 3)])) - (const_int 5)))] - "TARGET_SSE2" - "punpckhdq\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpcklbw" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (vec_merge:V16QI - (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "0") - (parallel [(const_int 0) (const_int 8) - (const_int 1) (const_int 9) - (const_int 2) (const_int 10) - (const_int 3) (const_int 11) - (const_int 4) (const_int 12) - (const_int 5) (const_int 13) - (const_int 6) (const_int 14) - (const_int 7) (const_int 15)])) - (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "x") - (parallel [(const_int 8) (const_int 0) - (const_int 9) (const_int 1) - (const_int 10) (const_int 2) - (const_int 11) (const_int 3) - (const_int 12) (const_int 4) - (const_int 13) (const_int 5) - (const_int 14) (const_int 6) - (const_int 15) (const_int 7)])) - (const_int 21845)))] - "TARGET_SSE2" - "punpcklbw\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpcklwd" - [(set (match_operand:V8HI 0 "register_operand" "=x") - (vec_merge:V8HI - (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "0") - (parallel [(const_int 0) (const_int 4) - (const_int 1) (const_int 5) - (const_int 2) (const_int 6) - (const_int 3) (const_int 7)])) - (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "x") - (parallel [(const_int 4) (const_int 0) - (const_int 5) (const_int 1) - (const_int 6) (const_int 2) - (const_int 7) (const_int 3)])) - (const_int 85)))] - "TARGET_SSE2" - "punpcklwd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpckldq" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_merge:V4SI - (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "0") - (parallel [(const_int 0) (const_int 2) - (const_int 1) (const_int 3)])) - (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "x") - (parallel [(const_int 2) (const_int 0) - (const_int 3) (const_int 1)])) - (const_int 5)))] - "TARGET_SSE2" - "punpckldq\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpcklqdq" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (vec_merge:V2DI - (vec_select:V2DI (match_operand:V2DI 2 "register_operand" "x") - (parallel [(const_int 1) - (const_int 0)])) - (match_operand:V2DI 1 "register_operand" "0") - (const_int 1)))] - "TARGET_SSE2" - "punpcklqdq\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_punpckhqdq" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (vec_merge:V2DI - (match_operand:V2DI 1 "register_operand" "0") - (vec_select:V2DI (match_operand:V2DI 2 "register_operand" "x") - (parallel [(const_int 1) - (const_int 0)])) - (const_int 1)))] - "TARGET_SSE2" - "punpckhqdq\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -;; SSE2 moves - -(define_insn "sse2_movapd" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m") - (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")] - UNSPEC_MOVA))] - "TARGET_SSE2 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "movapd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_movupd" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m") - (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")] - UNSPEC_MOVU))] - "TARGET_SSE2 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "movupd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_movdqa" - [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m") - (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")] - UNSPEC_MOVA))] - "TARGET_SSE2 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "movdqa\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movdqu" - [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m") - (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")] - UNSPEC_MOVU))] - "TARGET_SSE2 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "movdqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movdq2q" - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,y") - (vec_select:DI (match_operand:V2DI 1 "register_operand" "x,x") - (parallel [(const_int 0)])))] - "TARGET_SSE2 && !TARGET_64BIT" - "@ - movq\t{%1, %0|%0, %1} - movdq2q\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movdq2q_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,y,r") - (vec_select:DI (match_operand:V2DI 1 "register_operand" "x,x,x") - (parallel [(const_int 0)])))] - "TARGET_SSE2 && TARGET_64BIT" - "@ - movq\t{%1, %0|%0, %1} - movdq2q\t{%1, %0|%0, %1} - movd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movq2dq" - [(set (match_operand:V2DI 0 "register_operand" "=x,?x") - (vec_concat:V2DI (match_operand:DI 1 "nonimmediate_operand" "m,y") - (const_int 0)))] - "TARGET_SSE2 && !TARGET_64BIT" - "@ - movq\t{%1, %0|%0, %1} - movq2dq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt,ssemov") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movq2dq_rex64" - [(set (match_operand:V2DI 0 "register_operand" "=x,?x,?x") - (vec_concat:V2DI (match_operand:DI 1 "nonimmediate_operand" "m,y,r") - (const_int 0)))] - "TARGET_SSE2 && TARGET_64BIT" - "@ - movq\t{%1, %0|%0, %1} - movq2dq\t{%1, %0|%0, %1} - movd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt,ssemov,ssecvt") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movq" - [(set (match_operand:V2DI 0 "register_operand" "=x") - (vec_concat:V2DI (vec_select:DI - (match_operand:V2DI 1 "nonimmediate_operand" "xm") - (parallel [(const_int 0)])) - (const_int 0)))] - "TARGET_SSE2" - "movq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "TI")]) - -(define_insn "sse2_loadd" - [(set (match_operand:V4SI 0 "register_operand" "=x") - (vec_merge:V4SI - (vec_duplicate:V4SI (match_operand:SI 1 "nonimmediate_operand" "mr")) - (const_vector:V4SI [(const_int 0) - (const_int 0) - (const_int 0) - (const_int 0)]) - (const_int 1)))] - "TARGET_SSE2" - "movd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "TI")]) - -(define_insn "sse2_stored" - [(set (match_operand:SI 0 "nonimmediate_operand" "=mr") - (vec_select:SI - (match_operand:V4SI 1 "register_operand" "x") - (parallel [(const_int 0)])))] - "TARGET_SSE2" - "movd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") - (set_attr "mode" "TI")]) - -(define_insn "sse2_movhpd" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m") - (vec_merge:V2DF - (match_operand:V2DF 1 "nonimmediate_operand" "0,0") - (match_operand:V2DF 2 "nonimmediate_operand" "m,x") - (const_int 2)))] - "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" - "movhpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) + rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG); + ix86_compare_op0 = operands[0]; + ix86_compare_op1 = operands[1]; + ix86_compare_emitted = flags; -(define_expand "sse2_loadsd" - [(match_operand:V2DF 0 "register_operand" "") - (match_operand:DF 1 "memory_operand" "")] - "TARGET_SSE2" -{ - emit_insn (gen_sse2_loadsd_1 (operands[0], operands[1], - CONST0_RTX (V2DFmode))); +#ifdef TARGET_THREAD_SSP_OFFSET + if (TARGET_64BIT) + emit_insn (gen_stack_tls_protect_test_di (flags, operands[0], + GEN_INT (TARGET_THREAD_SSP_OFFSET))); + else + emit_insn (gen_stack_tls_protect_test_si (flags, operands[0], + GEN_INT (TARGET_THREAD_SSP_OFFSET))); +#else + if (TARGET_64BIT) + emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1])); + else + emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1])); +#endif + emit_jump_insn (gen_beq (operands[2])); DONE; }) -(define_insn "sse2_loadsd_1" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF - (vec_duplicate:V2DF (match_operand:DF 1 "memory_operand" "m")) - (match_operand:V2DF 2 "const0_operand" "X") - (const_int 1)))] - "TARGET_SSE2" - "movsd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) - -(define_insn "sse2_movsd" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m") - (vec_merge:V2DF - (match_operand:V2DF 1 "nonimmediate_operand" "0,0,0") - (match_operand:V2DF 2 "nonimmediate_operand" "x,m,x") - (const_int 1)))] - "TARGET_SSE2 && ix86_binary_operator_ok (UNKNOWN, V2DFmode, operands)" - "@movsd\t{%2, %0|%0, %2} - movlpd\t{%2, %0|%0, %2} - movlpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF,V2DF,V2DF")]) - -(define_insn "sse2_storesd" - [(set (match_operand:DF 0 "memory_operand" "=m") - (vec_select:DF - (match_operand:V2DF 1 "register_operand" "x") - (parallel [(const_int 0)])))] - "TARGET_SSE2" - "movsd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) - -(define_insn "sse2_shufpd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm") - (match_operand:SI 3 "immediate_operand" "i")] - UNSPEC_SHUFFLE))] - "TARGET_SSE2" - ;; @@@ check operand order for intel/nonintel syntax - "shufpd\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - -(define_insn "sse2_clflush" - [(unspec_volatile [(match_operand 0 "address_operand" "p")] - UNSPECV_CLFLUSH)] - "TARGET_SSE2" - "clflush %0" - [(set_attr "type" "sse") - (set_attr "memory" "unknown")]) - -(define_expand "sse2_mfence" - [(set (match_dup 0) - (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))] - "TARGET_SSE2" -{ - operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); - MEM_VOLATILE_P (operands[0]) = 1; -}) - -(define_insn "*mfence_insn" - [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))] - "TARGET_SSE2" - "mfence" - [(set_attr "type" "sse") - (set_attr "memory" "unknown")]) +(define_insn "stack_protect_test_si" + [(set (match_operand:CCZ 0 "flags_reg_operand" "") + (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m") + (match_operand:SI 2 "memory_operand" "m")] + UNSPEC_SP_TEST)) + (clobber (match_scratch:SI 3 "=&r"))] + "" + "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}" + [(set_attr "type" "multi")]) -(define_expand "sse2_lfence" - [(set (match_dup 0) - (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))] - "TARGET_SSE2" -{ - operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); - MEM_VOLATILE_P (operands[0]) = 1; -}) +(define_insn "stack_protect_test_di" + [(set (match_operand:CCZ 0 "flags_reg_operand" "") + (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "memory_operand" "m")] + UNSPEC_SP_TEST)) + (clobber (match_scratch:DI 3 "=&r"))] + "TARGET_64BIT" + "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}" + [(set_attr "type" "multi")]) -(define_insn "*lfence_insn" - [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))] - "TARGET_SSE2" - "lfence" - [(set_attr "type" "sse") - (set_attr "memory" "unknown")]) - -;; SSE3 - -(define_insn "mwait" - [(unspec_volatile [(match_operand:SI 0 "register_operand" "a") - (match_operand:SI 1 "register_operand" "c")] - UNSPECV_MWAIT)] - "TARGET_SSE3" - "mwait\t%0, %1" - [(set_attr "length" "3")]) - -(define_insn "monitor" - [(unspec_volatile [(match_operand:SI 0 "register_operand" "a") - (match_operand:SI 1 "register_operand" "c") - (match_operand:SI 2 "register_operand" "d")] - UNSPECV_MONITOR)] - "TARGET_SSE3" - "monitor\t%0, %1, %2" - [(set_attr "length" "3")]) - -;; SSE3 arithmetic - -(define_insn "addsubv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")] - UNSPEC_ADDSUB))] - "TARGET_SSE3" - "addsubps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V4SF")]) - -(define_insn "addsubv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")] - UNSPEC_ADDSUB))] - "TARGET_SSE3" - "addsubpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "haddv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")] - UNSPEC_HADD))] - "TARGET_SSE3" - "haddps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V4SF")]) - -(define_insn "haddv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")] - UNSPEC_HADD))] - "TARGET_SSE3" - "haddpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "hsubv4sf3" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") - (match_operand:V4SF 2 "nonimmediate_operand" "xm")] - UNSPEC_HSUB))] - "TARGET_SSE3" - "hsubps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V4SF")]) - -(define_insn "hsubv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "nonimmediate_operand" "xm")] - UNSPEC_HSUB))] - "TARGET_SSE3" - "hsubpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") - (set_attr "mode" "V2DF")]) - -(define_insn "movshdup" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_MOVSHDUP))] - "TARGET_SSE3" - "movshdup\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "movsldup" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_MOVSLDUP))] - "TARGET_SSE3" - "movsldup\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") - (set_attr "mode" "V4SF")]) - -(define_insn "lddqu" - [(set (match_operand:V16QI 0 "register_operand" "=x") - (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "m")] - UNSPEC_LDQQU))] - "TARGET_SSE3" - "lddqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) +(define_insn "stack_tls_protect_test_si" + [(set (match_operand:CCZ 0 "flags_reg_operand" "") + (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m") + (match_operand:SI 2 "const_int_operand" "i")] + UNSPEC_SP_TLS_TEST)) + (clobber (match_scratch:SI 3 "=r"))] + "" + "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}" + [(set_attr "type" "multi")]) -(define_insn "loadddup" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_duplicate:V2DF (match_operand:DF 1 "memory_operand" "m")))] - "TARGET_SSE3" - "movddup\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) +(define_insn "stack_tls_protect_test_di" + [(set (match_operand:CCZ 0 "flags_reg_operand" "") + (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "const_int_operand" "i")] + UNSPEC_SP_TLS_TEST)) + (clobber (match_scratch:DI 3 "=r"))] + "TARGET_64BIT" + { + /* The kernel uses a different segment register for performance reasons; a + system call would not have to trash the userspace segment register, + which would be expensive */ + if (ix86_cmodel != CM_KERNEL) + return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}"; + else + return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}"; + } + [(set_attr "type" "multi")]) -(define_insn "movddup" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_duplicate:V2DF - (vec_select:DF (match_operand:V2DF 1 "register_operand" "x") - (parallel [(const_int 0)]))))] - "TARGET_SSE3" - "movddup\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) +(include "sse.md") +(include "mmx.md") +(include "sync.md") |