;; UNSPEC usage:
-(define_constants
- [; Relocation specifiers
- (UNSPEC_GOT 0)
- (UNSPEC_GOTOFF 1)
- (UNSPEC_GOTPCREL 2)
- (UNSPEC_GOTTPOFF 3)
- (UNSPEC_TPOFF 4)
- (UNSPEC_NTPOFF 5)
- (UNSPEC_DTPOFF 6)
- (UNSPEC_GOTNTPOFF 7)
- (UNSPEC_INDNTPOFF 8)
- (UNSPEC_PLTOFF 9)
- (UNSPEC_MACHOPIC_OFFSET 10)
-
- ; Prologue support
- (UNSPEC_STACK_ALLOC 11)
- (UNSPEC_SET_GOT 12)
- (UNSPEC_SSE_PROLOGUE_SAVE 13)
- (UNSPEC_REG_SAVE 14)
- (UNSPEC_DEF_CFA 15)
- (UNSPEC_SET_RIP 16)
- (UNSPEC_SET_GOT_OFFSET 17)
- (UNSPEC_MEMORY_BLOCKAGE 18)
- (UNSPEC_SSE_PROLOGUE_SAVE_LOW 19)
-
- ; TLS support
- (UNSPEC_TP 20)
- (UNSPEC_TLS_GD 21)
- (UNSPEC_TLS_LD_BASE 22)
- (UNSPEC_TLSDESC 23)
-
- ; Other random patterns
- (UNSPEC_SCAS 30)
- (UNSPEC_FNSTSW 31)
- (UNSPEC_SAHF 32)
- (UNSPEC_FSTCW 33)
- (UNSPEC_ADD_CARRY 34)
- (UNSPEC_FLDCW 35)
- (UNSPEC_REP 36)
- (UNSPEC_LD_MPIC 38) ; load_macho_picbase
- (UNSPEC_TRUNC_NOOP 39)
-
- ; For SSE/MMX support:
- (UNSPEC_FIX_NOTRUNC 40)
- (UNSPEC_MASKMOV 41)
- (UNSPEC_MOVMSK 42)
- (UNSPEC_MOVNT 43)
- (UNSPEC_MOVU 44)
- (UNSPEC_RCP 45)
- (UNSPEC_RSQRT 46)
- (UNSPEC_SFENCE 47)
- (UNSPEC_PFRCP 49)
- (UNSPEC_PFRCPIT1 40)
- (UNSPEC_PFRCPIT2 41)
- (UNSPEC_PFRSQRT 42)
- (UNSPEC_PFRSQIT1 43)
- (UNSPEC_MFENCE 44)
- (UNSPEC_LFENCE 45)
- (UNSPEC_PSADBW 46)
- (UNSPEC_LDDQU 47)
- (UNSPEC_MS_TO_SYSV_CALL 48)
-
- ; Generic math support
- (UNSPEC_COPYSIGN 50)
- (UNSPEC_IEEE_MIN 51) ; not commutative
- (UNSPEC_IEEE_MAX 52) ; not commutative
-
- ; x87 Floating point
- (UNSPEC_SIN 60)
- (UNSPEC_COS 61)
- (UNSPEC_FPATAN 62)
- (UNSPEC_FYL2X 63)
- (UNSPEC_FYL2XP1 64)
- (UNSPEC_FRNDINT 65)
- (UNSPEC_FIST 66)
- (UNSPEC_F2XM1 67)
- (UNSPEC_TAN 68)
- (UNSPEC_FXAM 69)
-
- ; 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_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)
-
- (UNSPEC_C2_FLAG 95)
- (UNSPEC_FXAM_MEM 96)
-
- ; SSP patterns
- (UNSPEC_SP_SET 100)
- (UNSPEC_SP_TEST 101)
- (UNSPEC_SP_TLS_SET 102)
- (UNSPEC_SP_TLS_TEST 103)
-
- ; SSSE3
- (UNSPEC_PSHUFB 120)
- (UNSPEC_PSIGN 121)
- (UNSPEC_PALIGNR 122)
-
- ; For SSE4A support
- (UNSPEC_EXTRQI 130)
- (UNSPEC_EXTRQ 131)
- (UNSPEC_INSERTQI 132)
- (UNSPEC_INSERTQ 133)
-
- ; For SSE4.1 support
- (UNSPEC_BLENDV 134)
- (UNSPEC_INSERTPS 135)
- (UNSPEC_DP 136)
- (UNSPEC_MOVNTDQA 137)
- (UNSPEC_MPSADBW 138)
- (UNSPEC_PHMINPOSUW 139)
- (UNSPEC_PTEST 140)
- (UNSPEC_ROUND 141)
-
- ; For SSE4.2 support
- (UNSPEC_CRC32 143)
- (UNSPEC_PCMPESTR 144)
- (UNSPEC_PCMPISTR 145)
-
- ; For FMA4 support
- (UNSPEC_FMA4_INTRINSIC 150)
- (UNSPEC_FMA4_FMADDSUB 151)
- (UNSPEC_FMA4_FMSUBADD 152)
- (UNSPEC_XOP_UNSIGNED_CMP 151)
- (UNSPEC_XOP_TRUEFALSE 152)
- (UNSPEC_XOP_PERMUTE 153)
- (UNSPEC_FRCZ 154)
-
- ; For AES support
- (UNSPEC_AESENC 159)
- (UNSPEC_AESENCLAST 160)
- (UNSPEC_AESDEC 161)
- (UNSPEC_AESDECLAST 162)
- (UNSPEC_AESIMC 163)
- (UNSPEC_AESKEYGENASSIST 164)
-
- ; For PCLMUL support
- (UNSPEC_PCLMUL 165)
-
- ; For AVX support
- (UNSPEC_PCMP 166)
- (UNSPEC_VPERMIL 167)
- (UNSPEC_VPERMIL2 168)
- (UNSPEC_VPERMIL2F128 169)
- (UNSPEC_MASKLOAD 170)
- (UNSPEC_MASKSTORE 171)
- (UNSPEC_CAST 172)
- (UNSPEC_VTESTP 173)
- ])
-
-(define_constants
- [(UNSPECV_BLOCKAGE 0)
- (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 10)
- (UNSPECV_XCHG 12)
- (UNSPECV_LOCK 13)
- (UNSPECV_PROLOGUE_USE 14)
- (UNSPECV_CLD 15)
- (UNSPECV_VZEROALL 16)
- (UNSPECV_VZEROUPPER 17)
- (UNSPECV_RDTSC 18)
- (UNSPECV_RDTSCP 19)
- (UNSPECV_RDPMC 20)
- (UNSPECV_VSWAPMOV 21)
- (UNSPECV_LLWP_INTRINSIC 22)
- (UNSPECV_SLWP_INTRINSIC 23)
- (UNSPECV_LWPVAL_INTRINSIC 24)
- (UNSPECV_LWPINS_INTRINSIC 25)
- ])
+(define_c_enum "unspec" [
+ ;; Relocation specifiers
+ UNSPEC_GOT
+ UNSPEC_GOTOFF
+ UNSPEC_GOTPCREL
+ UNSPEC_GOTTPOFF
+ UNSPEC_TPOFF
+ UNSPEC_NTPOFF
+ UNSPEC_DTPOFF
+ UNSPEC_GOTNTPOFF
+ UNSPEC_INDNTPOFF
+ UNSPEC_PLTOFF
+ UNSPEC_MACHOPIC_OFFSET
+
+ ;; Prologue support
+ UNSPEC_STACK_ALLOC
+ UNSPEC_SET_GOT
+ UNSPEC_REG_SAVE
+ UNSPEC_DEF_CFA
+ UNSPEC_SET_RIP
+ UNSPEC_SET_GOT_OFFSET
+ UNSPEC_MEMORY_BLOCKAGE
+
+ ;; TLS support
+ UNSPEC_TP
+ UNSPEC_TLS_GD
+ UNSPEC_TLS_LD_BASE
+ UNSPEC_TLSDESC
+
+ ;; Other random patterns
+ UNSPEC_SCAS
+ UNSPEC_FNSTSW
+ UNSPEC_SAHF
+ UNSPEC_PARITY
+ UNSPEC_FSTCW
+ UNSPEC_ADD_CARRY
+ UNSPEC_FLDCW
+ UNSPEC_REP
+ UNSPEC_LD_MPIC ; load_macho_picbase
+ UNSPEC_TRUNC_NOOP
+
+ ;; For SSE/MMX support:
+ UNSPEC_FIX_NOTRUNC
+ UNSPEC_MASKMOV
+ UNSPEC_MOVMSK
+ UNSPEC_MOVNT
+ UNSPEC_MOVU
+ UNSPEC_RCP
+ UNSPEC_RSQRT
+ UNSPEC_SFENCE
+ UNSPEC_PFRCP
+ UNSPEC_PFRCPIT1
+ UNSPEC_PFRCPIT2
+ UNSPEC_PFRSQRT
+ UNSPEC_PFRSQIT1
+ UNSPEC_MFENCE
+ UNSPEC_LFENCE
+ UNSPEC_PSADBW
+ UNSPEC_LDDQU
+ UNSPEC_MS_TO_SYSV_CALL
+
+ ;; Generic math support
+ UNSPEC_COPYSIGN
+ UNSPEC_IEEE_MIN ; not commutative
+ UNSPEC_IEEE_MAX ; not commutative
+
+ ;; x87 Floating point
+ UNSPEC_SIN
+ UNSPEC_COS
+ UNSPEC_FPATAN
+ UNSPEC_FYL2X
+ UNSPEC_FYL2XP1
+ UNSPEC_FRNDINT
+ UNSPEC_FIST
+ UNSPEC_F2XM1
+ UNSPEC_TAN
+ UNSPEC_FXAM
+
+ ;; x87 Rounding
+ UNSPEC_FRNDINT_FLOOR
+ UNSPEC_FRNDINT_CEIL
+ UNSPEC_FRNDINT_TRUNC
+ UNSPEC_FRNDINT_MASK_PM
+ UNSPEC_FIST_FLOOR
+ UNSPEC_FIST_CEIL
+
+ ;; x87 Double output FP
+ UNSPEC_SINCOS_COS
+ UNSPEC_SINCOS_SIN
+ UNSPEC_XTRACT_FRACT
+ UNSPEC_XTRACT_EXP
+ UNSPEC_FSCALE_FRACT
+ UNSPEC_FSCALE_EXP
+ UNSPEC_FPREM_F
+ UNSPEC_FPREM_U
+ UNSPEC_FPREM1_F
+ UNSPEC_FPREM1_U
+
+ UNSPEC_C2_FLAG
+ UNSPEC_FXAM_MEM
+
+ ;; SSP patterns
+ UNSPEC_SP_SET
+ UNSPEC_SP_TEST
+ UNSPEC_SP_TLS_SET
+ UNSPEC_SP_TLS_TEST
+
+ ;; SSSE3
+ UNSPEC_PSHUFB
+ UNSPEC_PSIGN
+ UNSPEC_PALIGNR
+
+ ;; For SSE4A support
+ UNSPEC_EXTRQI
+ UNSPEC_EXTRQ
+ UNSPEC_INSERTQI
+ UNSPEC_INSERTQ
+
+ ;; For SSE4.1 support
+ UNSPEC_BLENDV
+ UNSPEC_INSERTPS
+ UNSPEC_DP
+ UNSPEC_MOVNTDQA
+ UNSPEC_MPSADBW
+ UNSPEC_PHMINPOSUW
+ UNSPEC_PTEST
+ UNSPEC_ROUND
+
+ ;; For SSE4.2 support
+ UNSPEC_CRC32
+ UNSPEC_PCMPESTR
+ UNSPEC_PCMPISTR
+
+ ;; For FMA4 support
+ UNSPEC_FMA4_INTRINSIC
+ UNSPEC_FMA4_FMADDSUB
+ UNSPEC_FMA4_FMSUBADD
+ UNSPEC_XOP_UNSIGNED_CMP
+ UNSPEC_XOP_TRUEFALSE
+ UNSPEC_XOP_PERMUTE
+ UNSPEC_FRCZ
+
+ ;; For AES support
+ UNSPEC_AESENC
+ UNSPEC_AESENCLAST
+ UNSPEC_AESDEC
+ UNSPEC_AESDECLAST
+ UNSPEC_AESIMC
+ UNSPEC_AESKEYGENASSIST
+
+ ;; For PCLMUL support
+ UNSPEC_PCLMUL
+
+ ;; For AVX support
+ UNSPEC_PCMP
+ UNSPEC_VPERMIL
+ UNSPEC_VPERMIL2
+ UNSPEC_VPERMIL2F128
+ UNSPEC_MASKLOAD
+ UNSPEC_MASKSTORE
+ UNSPEC_CAST
+ UNSPEC_VTESTP
+ UNSPEC_VCVTPH2PS
+ UNSPEC_VCVTPS2PH
+])
+
+(define_c_enum "unspecv" [
+ UNSPECV_BLOCKAGE
+ UNSPECV_STACK_PROBE
+ UNSPECV_PROBE_STACK_RANGE
+ UNSPECV_EMMS
+ UNSPECV_LDMXCSR
+ UNSPECV_STMXCSR
+ UNSPECV_FEMMS
+ UNSPECV_CLFLUSH
+ UNSPECV_ALIGN
+ UNSPECV_MONITOR
+ UNSPECV_MWAIT
+ UNSPECV_CMPXCHG
+ UNSPECV_XCHG
+ UNSPECV_LOCK
+ UNSPECV_PROLOGUE_USE
+ UNSPECV_CLD
+ UNSPECV_VZEROALL
+ UNSPECV_VZEROUPPER
+ UNSPECV_RDTSC
+ UNSPECV_RDTSCP
+ UNSPECV_RDPMC
+ UNSPECV_VSWAPMOV
+ UNSPECV_LLWP_INTRINSIC
+ UNSPECV_SLWP_INTRINSIC
+ UNSPECV_LWPVAL_INTRINSIC
+ UNSPECV_LWPINS_INTRINSIC
+ UNSPECV_RDFSBASE
+ UNSPECV_RDGSBASE
+ UNSPECV_WRFSBASE
+ UNSPECV_WRGSBASE
+ UNSPECV_RDRAND
+])
;; Constants to represent pcomtrue/pcomfalse variants
(define_constants
push,pop,call,callv,leave,
str,bitmanip,
fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
- sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+ sselog,sselog1,sseiadd,sseiadd1,sseishft,sseishft1,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,ssediv,sseins,
ssemuladd,sse4arg,lwp,
mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
(define_attr "unit" "integer,i387,sse,mmx,unknown"
(cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
(const_string "i387")
- (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+ (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseishft1,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,
ssecvt1,sseicvt,ssediv,sseins,ssemuladd,sse4arg")
(const_string "sse")
(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")
(div "i") (udiv "")])
-;; All single word integer modes.
+;; 64bit single word integer modes.
+(define_mode_iterator SWI1248x [QI HI SI DI])
+
+;; 64bit single word integer modes without QImode and HImode.
+(define_mode_iterator SWI48x [SI DI])
+
+;; Single word integer modes.
(define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")])
+;; Single word integer modes without SImode and DImode.
+(define_mode_iterator SWI12 [QI HI])
+
;; Single word integer modes without DImode.
(define_mode_iterator SWI124 [QI HI SI])
+;; Single word integer modes without QImode and DImode.
+(define_mode_iterator SWI24 [HI SI])
+
;; Single word integer modes without QImode.
(define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")])
(SI "general_operand")
(DI "x86_64_szext_general_operand")])
+;; Immediate operand predicate for integer modes.
+(define_mode_attr immediate_operand
+ [(QI "immediate_operand")
+ (HI "immediate_operand")
+ (SI "immediate_operand")
+ (DI "x86_64_immediate_operand")])
+
;; Operand predicate for shifts.
(define_mode_attr shift_operand
[(QI "nonimmediate_operand")
\f
;; Move instructions.
-;; General case of fullword move.
+(define_expand "movoi"
+ [(set (match_operand:OI 0 "nonimmediate_operand" "")
+ (match_operand:OI 1 "general_operand" ""))]
+ "TARGET_AVX"
+ "ix86_expand_move (OImode, operands); DONE;")
-(define_expand "movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
+(define_expand "movti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "nonimmediate_operand" ""))]
+ "TARGET_64BIT || TARGET_SSE"
+{
+ if (TARGET_64BIT)
+ ix86_expand_move (TImode, operands);
+ else if (push_operand (operands[0], TImode))
+ ix86_expand_push (TImode, operands[1]);
+ else
+ ix86_expand_vector_move (TImode, operands);
+ DONE;
+})
+
+;; This expands to what emit_move_complex would generate if we didn't
+;; have a movti pattern. Having this avoids problems with reload on
+;; 32-bit targets when SSE is present, but doesn't seem to be harmful
+;; to have around all the time.
+(define_expand "movcdi"
+ [(set (match_operand:CDI 0 "nonimmediate_operand" "")
+ (match_operand:CDI 1 "general_operand" ""))]
+ ""
+{
+ if (push_operand (operands[0], CDImode))
+ emit_move_complex_push (CDImode, operands[0], operands[1]);
+ else
+ emit_move_complex_parts (operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "mov<mode>"
+ [(set (match_operand:SWI1248x 0 "nonimmediate_operand" "")
+ (match_operand:SWI1248x 1 "general_operand" ""))]
""
- "ix86_expand_move (SImode, operands); DONE;")
+ "ix86_expand_move (<MODE>mode, operands); DONE;")
;; Push/pop instructions. They are separate since autoinc/dec is not a
;; general_operand.
;; targets without our curiosities, and it is just as easy to represent
;; this differently.
+(define_insn "*pushdi2_rex64"
+ [(set (match_operand:DI 0 "push_operand" "=<,!<")
+ (match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
+ "TARGET_64BIT"
+ "@
+ push{q}\t%1
+ #"
+ [(set_attr "type" "push,multi")
+ (set_attr "mode" "DI")])
+
+;; Convert impossible pushes of immediate to existing instructions.
+;; First try to get scratch register and go through it. In case this
+;; fails, push sign extended lower part first and then overwrite
+;; upper part by 32bit move.
+(define_peephole2
+ [(match_scratch:DI 2 "r")
+ (set (match_operand:DI 0 "push_operand" "")
+ (match_operand:DI 1 "immediate_operand" ""))]
+ "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
+ && !x86_64_immediate_operand (operands[1], DImode)"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (match_dup 2))]
+ "")
+
+;; 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" ""))]
+ "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
+ && !x86_64_immediate_operand (operands[1], DImode) && 1"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+{
+ split_di (&operands[1], 1, &operands[2], &operands[3]);
+
+ operands[1] = gen_lowpart (DImode, operands[2]);
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ GEN_INT (4)));
+})
+
+(define_split
+ [(set (match_operand:DI 0 "push_operand" "")
+ (match_operand:DI 1 "immediate_operand" ""))]
+ "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
+ ? epilogue_completed : reload_completed)
+ && !symbolic_operand (operands[1], DImode)
+ && !x86_64_immediate_operand (operands[1], DImode)"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+{
+ split_di (&operands[1], 1, &operands[2], &operands[3]);
+
+ operands[1] = gen_lowpart (DImode, operands[2]);
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ GEN_INT (4)));
+})
+
+(define_insn "*pushdi2"
+ [(set (match_operand:DI 0 "push_operand" "=<")
+ (match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
+ "!TARGET_64BIT"
+ "#")
+
+(define_split
+ [(set (match_operand:DI 0 "push_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && !(MMX_REG_P (operands[1]) || SSE_REG_P (operands[1]))"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
+
(define_insn "*pushsi2"
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
[(set_attr "type" "push")
(set_attr "mode" "SI")])
+;; emit_push_insn when it calls move_by_pieces requires an insn to
+;; "push a byte/word". But actually we use pushl, which has the effect
+;; of rounding the amount pushed up to a word.
+
;; For 64BIT abi we always round up to 8 bytes.
-(define_insn "*pushsi2_rex64"
- [(set (match_operand:SI 0 "push_operand" "=X")
- (match_operand:SI 1 "nonmemory_no_elim_operand" "ri"))]
+(define_insn "*push<mode>2_rex64"
+ [(set (match_operand:SWI124 0 "push_operand" "=X")
+ (match_operand:SWI124 1 "nonmemory_no_elim_operand" "r<i>"))]
"TARGET_64BIT"
"push{q}\t%q1"
[(set_attr "type" "push")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "DI")])
-(define_insn "*pushsi2_prologue"
- [(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_no_elim_operand" "ri*m"))
- (clobber (mem:BLK (scratch)))]
+(define_insn "*push<mode>2"
+ [(set (match_operand:SWI12 0 "push_operand" "=X")
+ (match_operand:SWI12 1 "nonmemory_no_elim_operand" "rn"))]
"!TARGET_64BIT"
- "push{l}\t%1"
+ "push{l}\t%k1"
[(set_attr "type" "push")
(set_attr "mode" "SI")])
-(define_insn "*popsi1_epilogue"
+(define_insn "*push<mode>2_prologue"
+ [(set (match_operand:P 0 "push_operand" "=<")
+ (match_operand:P 1 "general_no_elim_operand" "r<i>*m"))
+ (clobber (mem:BLK (scratch)))]
+ ""
+ "push{<imodesuffix>}\t%1"
+ [(set_attr "type" "push")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "popdi1"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
+ (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")
+ (set_attr "mode" "DI")])
+
+(define_insn "popsi1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
(mem:SI (reg:SI SP_REG)))
(set (reg:SI SP_REG)
- (plus:SI (reg:SI SP_REG) (const_int 4)))
- (clobber (mem:BLK (scratch)))]
+ (plus:SI (reg:SI SP_REG) (const_int 4)))]
"!TARGET_64BIT"
"pop{l}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "SI")])
-(define_insn "popsi1"
+(define_insn "*popdi1_epilogue"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
+ (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"
+ [(set_attr "type" "pop")
+ (set_attr "mode" "DI")])
+
+(define_insn "*popsi1_epilogue"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
(mem:SI (reg:SI SP_REG)))
(set (reg:SI SP_REG)
- (plus:SI (reg:SI SP_REG) (const_int 4)))]
+ (plus:SI (reg:SI SP_REG) (const_int 4)))
+ (clobber (mem:BLK (scratch)))]
"!TARGET_64BIT"
"pop{l}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "SI")])
-(define_insn "*movsi_xor"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "const0_operand" ""))
+(define_insn "*mov<mode>_xor"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (match_operand:SWI48 1 "const0_operand" ""))
(clobber (reg:CC FLAGS_REG))]
"reload_completed"
- "xor{l}\t%0, %0"
+ "xor{l}\t%k0, %k0"
[(set_attr "type" "alu1")
(set_attr "mode" "SI")
(set_attr "length_immediate" "0")])
-(define_insn "*movsi_or"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "immediate_operand" "i"))
+(define_insn "*mov<mode>_or"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (match_operand:SWI48 1 "const_int_operand" ""))
(clobber (reg:CC FLAGS_REG))]
"reload_completed
&& operands[1] == constm1_rtx"
-{
- operands[1] = constm1_rtx;
- return "or{l}\t{%1, %0|%0, %1}";
-}
+ "or{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
- (set_attr "mode" "SI")
+ (set_attr "mode" "<MODE>")
(set_attr "length_immediate" "1")])
-(define_insn "*movsi_1"
- [(set (match_operand:SI 0 "nonimmediate_operand"
- "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
- (match_operand:SI 1 "general_operand"
- "g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+(define_insn "*movoi_internal_avx"
+ [(set (match_operand:OI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:OI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
- switch (get_attr_type (insn))
+ switch (which_alternative)
{
- case TYPE_SSELOG1:
- if (get_attr_mode (insn) == MODE_TI)
- return "%vpxor\t%0, %d0";
- return "%vxorps\t%0, %d0";
+ case 0:
+ return "vxorps\t%0, %0, %0";
+ case 1:
+ case 2:
+ if (misaligned_operand (operands[0], OImode)
+ || misaligned_operand (operands[1], OImode))
+ return "vmovdqu\t{%1, %0|%0, %1}";
+ else
+ return "vmovdqa\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sselog1,ssemov,ssemov")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
- case TYPE_SSEMOV:
- switch (get_attr_mode (insn))
+(define_insn "*movti_internal_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 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return "#";
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vxorps\t%0, %d0";
+ else
+ return "%vpxor\t%0, %d0";
+ case 3:
+ case 4:
+ /* TDmode values are passed as TImode on the stack. Moving them
+ to stack may result in unaligned memory access. */
+ if (misaligned_operand (operands[0], TImode)
+ || misaligned_operand (operands[1], TImode))
{
- case MODE_TI:
- return "%vmovdqa\t{%1, %0|%0, %1}";
- case MODE_V4SF:
- return "%vmovaps\t{%1, %0|%0, %1}";
- case MODE_SI:
- return "%vmovd\t{%1, %0|%0, %1}";
- case MODE_SF:
- return "%vmovss\t{%1, %0|%0, %1}";
- default:
- gcc_unreachable ();
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vmovups\t{%1, %0|%0, %1}";
+ else
+ return "%vmovdqu\t{%1, %0|%0, %1}";
+ }
+ else
+ {
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ else
+ return "%vmovdqa\t{%1, %0|%0, %1}";
}
-
- case TYPE_MMX:
- return "pxor\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:
- gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
- return "mov{l}\t{%1, %0|%0, %1}";
+ gcc_unreachable ();
}
}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "2")
- (const_string "mmx")
- (eq_attr "alternative" "3,4,5")
- (const_string "mmxmov")
- (eq_attr "alternative" "6")
- (const_string "sselog1")
- (eq_attr "alternative" "7,8,9,10,11")
- (const_string "ssemov")
- (match_operand:DI 1 "pic_32bit_operand" "")
- (const_string "lea")
- ]
- (const_string "imov")))
- (set (attr "prefix")
- (if_then_else (eq_attr "alternative" "0,1,2,3,4,5")
- (const_string "orig")
- (const_string "maybe_vex")))
- (set (attr "prefix_data16")
- (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
- (const_string "1")
- (const_string "*")))
+ [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
+ (set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex")
(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
-;; into register when rax is not available
-(define_insn "*movabssi_1_rex64"
- [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
- (match_operand:SI 1 "nonmemory_operand" "a,er"))]
- "TARGET_64BIT && ix86_check_movabs (insn, 0)"
- "@
- movabs{l}\t{%1, %P0|%P0, %1}
- mov{l}\t{%1, %a0|%a0, %1}"
- [(set_attr "type" "imov")
- (set_attr "modrm" "0,*")
- (set_attr "length_address" "8,0")
- (set_attr "length_immediate" "0,*")
- (set_attr "memory" "store")
- (set_attr "mode" "SI")])
-
-(define_insn "*movabssi_2_rex64"
- [(set (match_operand:SI 0 "register_operand" "=a,r")
- (mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT && ix86_check_movabs (insn, 1)"
- "@
- movabs{l}\t{%P1, %0|%0, %P1}
- mov{l}\t{%a1, %0|%0, %a1}"
- [(set_attr "type" "imov")
- (set_attr "modrm" "0,*")
- (set_attr "length_address" "8,0")
- (set_attr "length_immediate" "0")
- (set_attr "memory" "load")
- (set_attr "mode" "SI")])
-
-(define_insn "*swapsi"
- [(set (match_operand:SI 0 "register_operand" "+r")
- (match_operand:SI 1 "register_operand" "+r"))
- (set (match_dup 1)
- (match_dup 0))]
- ""
- "xchg{l}\t%1, %0"
- [(set_attr "type" "imov")
- (set_attr "mode" "SI")
- (set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "double")])
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "ix86_expand_move (HImode, operands); DONE;")
-
-(define_insn "*pushhi2"
- [(set (match_operand:HI 0 "push_operand" "=X")
- (match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
- "!TARGET_64BIT"
- "push{l}\t%k1"
- [(set_attr "type" "push")
- (set_attr "mode" "SI")])
-
-;; For 64BIT abi we always round up to 8 bytes.
-(define_insn "*pushhi2_rex64"
- [(set (match_operand:HI 0 "push_operand" "=X")
- (match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
- "TARGET_64BIT"
- "push{q}\t%q1"
- [(set_attr "type" "push")
- (set_attr "mode" "DI")])
-
-(define_insn "*movhi_1"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
- (match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOVX:
- /* movzwl is faster than movw on p2 due to partial word stalls,
- though not as fast as an aligned movl. */
- return "movz{wl|x}\t{%1, %k0|%k0, %1}";
- default:
- if (get_attr_mode (insn) == MODE_SI)
- return "mov{l}\t{%k1, %k0|%k0, %k1}";
- else
- return "mov{w}\t{%1, %0|%0, %1}";
- }
-}
- [(set (attr "type")
- (cond [(ne (symbol_ref "optimize_function_for_size_p (cfun)") (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")
- (const_int 0))))
- (const_string "imov")
- (and (eq_attr "alternative" "1,2")
- (match_operand:HI 1 "aligned_operand" ""))
- (const_string "imov")
- (and (ne (symbol_ref "TARGET_MOVX")
- (const_int 0))
- (eq_attr "alternative" "0,2"))
- (const_string "imovx")
- ]
- (const_string "imov")))
- (set (attr "mode")
- (cond [(eq_attr "type" "imovx")
- (const_string "SI")
- (and (eq_attr "alternative" "1,2")
- (match_operand:HI 1 "aligned_operand" ""))
- (const_string "SI")
- (and (eq_attr "alternative" "0")
- (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
- (const_int 0))
- (eq (symbol_ref "TARGET_HIMODE_MATH")
- (const_int 0))))
- (const_string "SI")
- ]
- (const_string "HI")))])
-
-;; Stores and loads of ax to arbitrary constant address.
-;; We fake an second form of instruction to force reload to load address
-;; into register when rax is not available
-(define_insn "*movabshi_1_rex64"
- [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
- (match_operand:HI 1 "nonmemory_operand" "a,er"))]
- "TARGET_64BIT && ix86_check_movabs (insn, 0)"
- "@
- movabs{w}\t{%1, %P0|%P0, %1}
- mov{w}\t{%1, %a0|%a0, %1}"
- [(set_attr "type" "imov")
- (set_attr "modrm" "0,*")
- (set_attr "length_address" "8,0")
- (set_attr "length_immediate" "0,*")
- (set_attr "memory" "store")
- (set_attr "mode" "HI")])
-
-(define_insn "*movabshi_2_rex64"
- [(set (match_operand:HI 0 "register_operand" "=a,r")
- (mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT && ix86_check_movabs (insn, 1)"
- "@
- movabs{w}\t{%P1, %0|%0, %P1}
- mov{w}\t{%a1, %0|%0, %a1}"
- [(set_attr "type" "imov")
- (set_attr "modrm" "0,*")
- (set_attr "length_address" "8,0")
- (set_attr "length_immediate" "0")
- (set_attr "memory" "load")
- (set_attr "mode" "HI")])
-
-(define_insn "*swaphi_1"
- [(set (match_operand:HI 0 "register_operand" "+r")
- (match_operand:HI 1 "register_operand" "+r"))
- (set (match_dup 1)
- (match_dup 0))]
- "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
- "xchg{l}\t%k1, %k0"
- [(set_attr "type" "imov")
- (set_attr "mode" "SI")
- (set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "double")])
-
-;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
-(define_insn "*swaphi_2"
- [(set (match_operand:HI 0 "register_operand" "+r")
- (match_operand:HI 1 "register_operand" "+r"))
- (set (match_dup 1)
- (match_dup 0))]
- "TARGET_PARTIAL_REG_STALL"
- "xchg{w}\t%1, %0"
- [(set_attr "type" "imov")
- (set_attr "mode" "HI")
- (set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")])
+ (cond [(eq_attr "alternative" "2,3")
+ (if_then_else
+ (ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (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_function_for_size_p (cfun)")
+ (const_int 0)))
+ (const_string "V4SF")
+ (const_string "TI"))]
+ (const_string "DI")))])
-(define_expand "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
- (match_operand:HI 1 "general_operand" ""))]
- ""
-{
- if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun))
- FAIL;
- /* Don't generate memory->memory moves, go through a register */
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[1] = force_reg (HImode, operands[1]);
-})
+(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_insn "*movstricthi_1"
- [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+rm,r"))
- (match_operand:HI 1 "general_operand" "rn,m"))]
- "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+(define_insn "*movti_internal_sse"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE && !TARGET_64BIT
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "mov{w}\t{%1, %0|%0, %1}"
- [(set_attr "type" "imov")
- (set_attr "mode" "HI")])
-
-(define_insn "*movstricthi_xor"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
- (match_operand:HI 1 "const0_operand" ""))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- "xor{w}\t%0, %0"
- [(set_attr "type" "alu1")
- (set_attr "mode" "HI")
- (set_attr "length_immediate" "0")])
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "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 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")
- (match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
- "!TARGET_64BIT"
- "push{l}\t%k1"
- [(set_attr "type" "push")
- (set_attr "mode" "SI")])
-
-;; For 64BIT abi we always round up to 8 bytes.
-(define_insn "*pushqi2_rex64"
- [(set (match_operand:QI 0 "push_operand" "=X")
- (match_operand:QI 1 "nonmemory_no_elim_operand" "qn"))]
- "TARGET_64BIT"
- "push{q}\t%q1"
- [(set_attr "type" "push")
- (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
-;; partial register dependency machines (such as AMD Athlon), where QImode
-;; moves issue extra dependency and for partial register stalls machines
-;; that don't use QImode patterns (and QImode move cause stall on the next
-;; instruction).
-;;
-;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
-;; register stall machines with, where we use QImode instructions, since
-;; partial register stall can be caused there. Then we use movzx.
-(define_insn "*movqi_1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
- (match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,qm,qn"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
- switch (get_attr_type (insn))
+ switch (which_alternative)
{
- case TYPE_IMOVX:
- gcc_assert (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1]));
- return "movz{bl|x}\t{%1, %k0|%k0, %1}";
- default:
- if (get_attr_mode (insn) == MODE_SI)
- return "mov{l}\t{%k1, %k0|%k0, %k1}";
+ case 0:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vxorps\t%0, %d0";
else
- return "mov{b}\t{%1, %0|%0, %1}";
- }
-}
- [(set (attr "type")
- (cond [(and (eq_attr "alternative" "5")
- (not (match_operand:QI 1 "aligned_operand" "")))
- (const_string "imovx")
- (ne (symbol_ref "optimize_function_for_size_p (cfun)") (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")
- (const_int 0))))
- (const_string "imov")
- (eq_attr "alternative" "3,5")
- (const_string "imovx")
- (and (ne (symbol_ref "TARGET_MOVX")
- (const_int 0))
- (eq_attr "alternative" "2"))
- (const_string "imovx")
- ]
- (const_string "imov")))
- (set (attr "mode")
- (cond [(eq_attr "alternative" "3,4,5")
- (const_string "SI")
- (eq_attr "alternative" "6")
- (const_string "QI")
- (eq_attr "type" "imovx")
- (const_string "SI")
- (and (eq_attr "type" "imov")
- (and (eq_attr "alternative" "0,1")
- (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
- (const_int 0))
- (and (eq (symbol_ref "optimize_function_for_size_p (cfun)")
- (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")
- (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
- (const_int 0))
- (eq (symbol_ref "TARGET_QIMODE_MATH")
- (const_int 0)))))
- (const_string "SI")
- ]
- (const_string "QI")))])
-
-(define_insn "*swapqi_1"
- [(set (match_operand:QI 0 "register_operand" "+r")
- (match_operand:QI 1 "register_operand" "+r"))
- (set (match_dup 1)
- (match_dup 0))]
- "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
- "xchg{l}\t%k1, %k0"
- [(set_attr "type" "imov")
- (set_attr "mode" "SI")
- (set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "vector")])
-
-;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
-(define_insn "*swapqi_2"
- [(set (match_operand:QI 0 "register_operand" "+q")
- (match_operand:QI 1 "register_operand" "+q"))
- (set (match_dup 1)
- (match_dup 0))]
- "TARGET_PARTIAL_REG_STALL"
- "xchg{b}\t%1, %0"
- [(set_attr "type" "imov")
- (set_attr "mode" "QI")
- (set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")])
-
-(define_expand "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
- (match_operand:QI 1 "general_operand" ""))]
- ""
-{
- if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun))
- FAIL;
- /* Don't generate memory->memory moves, go through a register. */
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[1] = force_reg (QImode, operands[1]);
-})
-
-(define_insn "*movstrictqi_1"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
- (match_operand:QI 1 "general_operand" "*qn,m"))]
- "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "mov{b}\t{%1, %0|%0, %1}"
- [(set_attr "type" "imov")
- (set_attr "mode" "QI")])
-
-(define_insn "*movstrictqi_xor"
- [(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
- (match_operand:QI 1 "const0_operand" ""))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- "xor{b}\t%0, %0"
- [(set_attr "type" "alu1")
- (set_attr "mode" "QI")
- (set_attr "length_immediate" "0")])
-
-(define_insn "*movsi_extv_1"
- [(set (match_operand:SI 0 "register_operand" "=R")
- (sign_extract:SI (match_operand 1 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8)))]
- ""
- "movs{bl|x}\t{%h1, %0|%0, %h1}"
- [(set_attr "type" "imovx")
- (set_attr "mode" "SI")])
-
-(define_insn "*movhi_extv_1"
- [(set (match_operand:HI 0 "register_operand" "=R")
- (sign_extract:HI (match_operand 1 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8)))]
- ""
- "movs{bl|x}\t{%h1, %k0|%k0, %h1}"
- [(set_attr "type" "imovx")
- (set_attr "mode" "SI")])
-
-(define_insn "*movqi_extv_1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
- (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)))]
- "!TARGET_64BIT"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOVX:
- return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
- default:
- return "mov{b}\t{%h1, %0|%0, %h1}";
- }
-}
- [(set (attr "type")
- (if_then_else (and (match_operand:QI 0 "register_operand" "")
- (ior (not (match_operand:QI 0 "q_regs_operand" ""))
- (ne (symbol_ref "TARGET_MOVX")
- (const_int 0))))
- (const_string "imovx")
- (const_string "imov")))
- (set (attr "mode")
- (if_then_else (eq_attr "type" "imovx")
- (const_string "SI")
- (const_string "QI")))])
-
-(define_insn "*movqi_extv_1_rex64"
- [(set (match_operand:QI 0 "register_operand" "=Q,?R")
- (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)))]
- "TARGET_64BIT"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOVX:
- return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
- default:
- return "mov{b}\t{%h1, %0|%0, %h1}";
- }
-}
- [(set (attr "type")
- (if_then_else (and (match_operand:QI 0 "register_operand" "")
- (ior (not (match_operand:QI 0 "q_regs_operand" ""))
- (ne (symbol_ref "TARGET_MOVX")
- (const_int 0))))
- (const_string "imovx")
- (const_string "imov")))
- (set (attr "mode")
- (if_then_else (eq_attr "type" "imovx")
- (const_string "SI")
- (const_string "QI")))])
-
-;; Stores and loads of ax to arbitrary constant address.
-;; We fake an second form of instruction to force reload to load address
-;; into register when rax is not available
-(define_insn "*movabsqi_1_rex64"
- [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
- (match_operand:QI 1 "nonmemory_operand" "a,er"))]
- "TARGET_64BIT && ix86_check_movabs (insn, 0)"
- "@
- movabs{b}\t{%1, %P0|%P0, %1}
- mov{b}\t{%1, %a0|%a0, %1}"
- [(set_attr "type" "imov")
- (set_attr "modrm" "0,*")
- (set_attr "length_address" "8,0")
- (set_attr "length_immediate" "0,*")
- (set_attr "memory" "store")
- (set_attr "mode" "QI")])
-
-(define_insn "*movabsqi_2_rex64"
- [(set (match_operand:QI 0 "register_operand" "=a,r")
- (mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT && ix86_check_movabs (insn, 1)"
- "@
- movabs{b}\t{%P1, %0|%0, %P1}
- mov{b}\t{%a1, %0|%0, %a1}"
- [(set_attr "type" "imov")
- (set_attr "modrm" "0,*")
- (set_attr "length_address" "8,0")
- (set_attr "length_immediate" "0")
- (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" "SI")])
-
-(define_insn "*movsi_extzv_1"
- [(set (match_operand:SI 0 "register_operand" "=R")
- (zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8)))]
- ""
- "movz{bl|x}\t{%h1, %0|%0, %h1}"
- [(set_attr "type" "imovx")
- (set_attr "mode" "SI")])
-
-(define_insn "*movqi_extzv_2"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
- (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)) 0))]
- "!TARGET_64BIT"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOVX:
- return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
+ return "%vpxor\t%0, %d0";
+ case 1:
+ case 2:
+ /* TDmode values are passed as TImode on the stack. Moving them
+ to stack may result in unaligned memory access. */
+ if (misaligned_operand (operands[0], TImode)
+ || misaligned_operand (operands[1], TImode))
+ {
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vmovups\t{%1, %0|%0, %1}";
+ else
+ return "%vmovdqu\t{%1, %0|%0, %1}";
+ }
+ else
+ {
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ else
+ return "%vmovdqa\t{%1, %0|%0, %1}";
+ }
default:
- return "mov{b}\t{%h1, %0|%0, %h1}";
+ gcc_unreachable ();
}
}
- [(set (attr "type")
- (if_then_else (and (match_operand:QI 0 "register_operand" "")
- (ior (not (match_operand:QI 0 "q_regs_operand" ""))
- (ne (symbol_ref "TARGET_MOVX")
- (const_int 0))))
- (const_string "imovx")
- (const_string "imov")))
+ [(set_attr "type" "sselog1,ssemov,ssemov")
+ (set_attr "prefix" "maybe_vex")
(set (attr "mode")
- (if_then_else (eq_attr "type" "imovx")
- (const_string "SI")
- (const_string "QI")))])
+ (cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
+ (ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (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 "*movqi_extzv_2_rex64"
- [(set (match_operand:QI 0 "register_operand" "=Q,?R")
- (subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)) 0))]
- "TARGET_64BIT"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOVX:
- return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
- default:
- return "mov{b}\t{%h1, %0|%0, %h1}";
- }
-}
- [(set (attr "type")
- (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
- (ne (symbol_ref "TARGET_MOVX")
- (const_int 0)))
- (const_string "imovx")
- (const_string "imov")))
- (set (attr "mode")
- (if_then_else (eq_attr "type" "imovx")
- (const_string "SI")
- (const_string "QI")))])
+(define_insn "*movdi_internal_rex64"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=r,r ,r,m ,!m,*y,*y,?r ,m ,?*Ym,?*y,*x,*x,?r ,m,?*Yi,*x,?*x,?*Ym")
+ (match_operand:DI 1 "general_operand"
+ "Z ,rem,i,re,n ,C ,*y,*Ym,*y,r ,m ,C ,*x,*Yi,*x,r ,m ,*Ym,*x"))]
+ "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_SSECVT:
+ if (SSE_REG_P (operands[0]))
+ return "movq2dq\t{%1, %0|%0, %1}";
+ else
+ return "movdq2q\t{%1, %0|%0, %1}";
-(define_insn "movsi_insv_1"
- [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
- (const_int 8)
- (const_int 8))
- (match_operand:SI 1 "general_operand" "Qmn"))]
- "!TARGET_64BIT"
- "mov{b}\t{%b1, %h0|%h0, %b1}"
- [(set_attr "type" "imov")
- (set_attr "mode" "QI")])
+ case TYPE_SSEMOV:
+ if (TARGET_AVX)
+ {
+ if (get_attr_mode (insn) == MODE_TI)
+ return "vmovdqa\t{%1, %0|%0, %1}";
+ else
+ return "vmovq\t{%1, %0|%0, %1}";
+ }
-(define_insn "*movsi_insv_1_rex64"
- [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
- (const_int 8)
- (const_int 8))
- (match_operand:SI 1 "nonmemory_operand" "Qn"))]
- "TARGET_64BIT"
- "mov{b}\t{%b1, %h0|%h0, %b1}"
- [(set_attr "type" "imov")
- (set_attr "mode" "QI")])
+ if (get_attr_mode (insn) == MODE_TI)
+ return "movdqa\t{%1, %0|%0, %1}";
+ /* FALLTHRU */
-(define_insn "movdi_insv_1_rex64"
- [(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q")
- (const_int 8)
- (const_int 8))
- (match_operand:DI 1 "nonmemory_operand" "Qn"))]
- "TARGET_64BIT"
- "mov{b}\t{%b1, %h0|%h0, %b1}"
- [(set_attr "type" "imov")
- (set_attr "mode" "QI")])
+ case TYPE_MMXMOV:
+ /* Moves from and into integer register is done using movd
+ opcode with REX prefix. */
+ 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}";
-(define_insn "*movqi_insv_2"
- [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
- (const_int 8)
- (const_int 8))
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
- (const_int 8)))]
- ""
- "mov{b}\t{%h1, %h0|%h0, %h1}"
- [(set_attr "type" "imov")
- (set_attr "mode" "QI")])
+ case TYPE_SSELOG1:
+ return "%vpxor\t%0, %d0";
-(define_expand "movdi"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "ix86_expand_move (DImode, operands); DONE;")
+ case TYPE_MMX:
+ return "pxor\t%0, %0";
-(define_insn "*pushdi"
- [(set (match_operand:DI 0 "push_operand" "=<")
- (match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
- "!TARGET_64BIT"
- "#")
+ case TYPE_MULTI:
+ return "#";
-(define_insn "*pushdi2_rex64"
- [(set (match_operand:DI 0 "push_operand" "=<,!<")
- (match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
- "TARGET_64BIT"
- "@
- push{q}\t%1
- #"
- [(set_attr "type" "push,multi")
- (set_attr "mode" "DI")])
+ case TYPE_LEA:
+ return "lea{q}\t{%a1, %0|%0, %a1}";
-;; Convert impossible pushes of immediate to existing instructions.
+ default:
+ 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)
+ 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")
+ (const_string "mmx")
+ (eq_attr "alternative" "6,7,8,9,10")
+ (const_string "mmxmov")
+ (eq_attr "alternative" "11")
+ (const_string "sselog1")
+ (eq_attr "alternative" "12,13,14,15,16")
+ (const_string "ssemov")
+ (eq_attr "alternative" "17,18")
+ (const_string "ssecvt")
+ (eq_attr "alternative" "4")
+ (const_string "multi")
+ (match_operand:DI 1 "pic_32bit_operand" "")
+ (const_string "lea")
+ ]
+ (const_string "imov")))
+ (set (attr "modrm")
+ (if_then_else
+ (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
+ (const_string "0")
+ (const_string "*")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
+ (const_string "8")
+ (const_string "*")))
+ (set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*")
+ (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "11,12,13,14,15,16")
+ (const_string "maybe_vex")
+ (const_string "orig")))
+ (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI,DI,DI")])
+
+;; Convert impossible stores of immediate to existing instructions.
;; First try to get scratch register and go through it. In case this
-;; fails, push sign extended lower part first and then overwrite
-;; upper part by 32bit move.
+;; fails, move by 32bit parts.
(define_peephole2
[(match_scratch:DI 2 "r")
- (set (match_operand:DI 0 "push_operand" "")
+ (set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
;; 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" "")
+ [(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode) && 1"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
-{
- split_di (&operands[1], 1, &operands[2], &operands[3]);
-
- operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
- GEN_INT (4)));
-})
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 5))]
+ "split_di (&operands[0], 2, &operands[2], &operands[4]);")
(define_split
- [(set (match_operand:DI 0 "push_operand" "")
+ [(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
? epilogue_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
-{
- split_di (&operands[1], 1, &operands[2], &operands[3]);
-
- operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
- GEN_INT (4)));
-})
-
-(define_insn "*pushdi2_prologue_rex64"
- [(set (match_operand:DI 0 "push_operand" "=<")
- (match_operand:DI 1 "general_no_elim_operand" "re*m"))
- (clobber (mem:BLK (scratch)))]
- "TARGET_64BIT"
- "push{q}\t%1"
- [(set_attr "type" "push")
- (set_attr "mode" "DI")])
-
-(define_insn "*popdi1_epilogue_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
- (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"
- [(set_attr "type" "pop")
- (set_attr "mode" "DI")])
-
-(define_insn "popdi1"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
- (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")
- (set_attr "mode" "DI")])
-
-(define_insn "*movdi_xor_rex64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "const0_operand" ""))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
- && reload_completed"
- "xor{l}\t%k0, %k0";
- [(set_attr "type" "alu1")
- (set_attr "mode" "SI")
- (set_attr "length_immediate" "0")])
-
-(define_insn "*movdi_or_rex64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "const_int_operand" "i"))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
- && reload_completed
- && operands[1] == constm1_rtx"
-{
- operands[1] = constm1_rtx;
- return "or{q}\t{%1, %0|%0, %1}";
-}
- [(set_attr "type" "alu1")
- (set_attr "mode" "DI")
- (set_attr "length_immediate" "1")])
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 5))]
+ "split_di (&operands[0], 2, &operands[2], &operands[4]);")
-(define_insn "*movdi_2"
+(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand"
"=r ,o ,*y,m*y,*y,*Y2,m ,*Y2,*Y2,*x,m ,*x,*x")
(match_operand:DI 1 "general_operand"
(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" "")
- (match_operand:DI 1 "general_operand" ""))]
- "!TARGET_64BIT && reload_completed
- && (! MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
-
-;; %%% This multiword shite has got to go.
-(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed
- && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
- && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
+ && !(MMX_REG_P (operands[0]) || SSE_REG_P (operands[0]))
+ && !(MMX_REG_P (operands[1]) || SSE_REG_P (operands[1]))"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
-(define_insn "*movdi_1_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=r,r ,r,m ,!m,*y,*y,?r ,m ,?*Ym,?*y,*x,*x,?r ,m,?*Yi,*x,?*x,?*Ym")
- (match_operand:DI 1 "general_operand"
- "Z ,rem,i,re,n ,C ,*y,*Ym,*y,r ,m ,C ,*x,*Yi,*x,r ,m ,*Ym,*x"))]
- "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+(define_insn "*movsi_internal"
+ [(set (match_operand:SI 0 "nonimmediate_operand"
+ "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
+ (match_operand:SI 1 "general_operand"
+ "g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
- case TYPE_SSECVT:
- if (SSE_REG_P (operands[0]))
- return "movq2dq\t{%1, %0|%0, %1}";
- else
- return "movdq2q\t{%1, %0|%0, %1}";
+ case TYPE_SSELOG1:
+ if (get_attr_mode (insn) == MODE_TI)
+ return "%vpxor\t%0, %d0";
+ return "%vxorps\t%0, %d0";
case TYPE_SSEMOV:
- if (TARGET_AVX)
+ switch (get_attr_mode (insn))
{
- if (get_attr_mode (insn) == MODE_TI)
- return "vmovdqa\t{%1, %0|%0, %1}";
- else
- return "vmovq\t{%1, %0|%0, %1}";
- }
-
- if (get_attr_mode (insn) == MODE_TI)
- return "movdqa\t{%1, %0|%0, %1}";
- /* FALLTHRU */
-
- case TYPE_MMXMOV:
- /* Moves from and into integer register is done using movd
- opcode with REX prefix. */
- 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:
- return "%vpxor\t%0, %d0";
+ case MODE_TI:
+ return "%vmovdqa\t{%1, %0|%0, %1}";
+ case MODE_V4SF:
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ case MODE_SI:
+ return "%vmovd\t{%1, %0|%0, %1}";
+ case MODE_SF:
+ return "%vmovss\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
case TYPE_MMX:
return "pxor\t%0, %0";
- case TYPE_MULTI:
- return "#";
+ 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{q}\t{%a1, %0|%0, %a1}";
+ return "lea{l}\t{%a1, %0|%0, %a1}";
default:
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)
- return "movabs{q}\t{%1, %0|%0, %1}";
- else
- return "mov{q}\t{%1, %0|%0, %1}";
+ return "mov{l}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "5")
+ (cond [(eq_attr "alternative" "2")
(const_string "mmx")
- (eq_attr "alternative" "6,7,8,9,10")
+ (eq_attr "alternative" "3,4,5")
(const_string "mmxmov")
- (eq_attr "alternative" "11")
+ (eq_attr "alternative" "6")
(const_string "sselog1")
- (eq_attr "alternative" "12,13,14,15,16")
+ (eq_attr "alternative" "7,8,9,10,11")
(const_string "ssemov")
- (eq_attr "alternative" "17,18")
- (const_string "ssecvt")
- (eq_attr "alternative" "4")
- (const_string "multi")
(match_operand:DI 1 "pic_32bit_operand" "")
(const_string "lea")
]
(const_string "imov")))
- (set (attr "modrm")
- (if_then_else
- (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
- (const_string "0")
- (const_string "*")))
- (set (attr "length_immediate")
- (if_then_else
- (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
- (const_string "8")
- (const_string "*")))
- (set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*")
- (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*")
(set (attr "prefix")
- (if_then_else (eq_attr "alternative" "11,12,13,14,15,16")
- (const_string "maybe_vex")
- (const_string "orig")))
- (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI,DI,DI")])
+ (if_then_else (eq_attr "alternative" "0,1,2,3,4,5")
+ (const_string "orig")
+ (const_string "maybe_vex")))
+ (set (attr "prefix_data16")
+ (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
+ (const_string "1")
+ (const_string "*")))
+ (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")))])
+
+(define_insn "*movhi_internal"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
+ (match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_IMOVX:
+ /* movzwl is faster than movw on p2 due to partial word stalls,
+ though not as fast as an aligned movl. */
+ return "movz{wl|x}\t{%1, %k0|%k0, %1}";
+ default:
+ if (get_attr_mode (insn) == MODE_SI)
+ return "mov{l}\t{%k1, %k0|%k0, %k1}";
+ else
+ return "mov{w}\t{%1, %0|%0, %1}";
+ }
+}
+ [(set (attr "type")
+ (cond [(ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (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")
+ (const_int 0))))
+ (const_string "imov")
+ (and (eq_attr "alternative" "1,2")
+ (match_operand:HI 1 "aligned_operand" ""))
+ (const_string "imov")
+ (and (ne (symbol_ref "TARGET_MOVX")
+ (const_int 0))
+ (eq_attr "alternative" "0,2"))
+ (const_string "imovx")
+ ]
+ (const_string "imov")))
+ (set (attr "mode")
+ (cond [(eq_attr "type" "imovx")
+ (const_string "SI")
+ (and (eq_attr "alternative" "1,2")
+ (match_operand:HI 1 "aligned_operand" ""))
+ (const_string "SI")
+ (and (eq_attr "alternative" "0")
+ (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
+ (const_int 0))
+ (eq (symbol_ref "TARGET_HIMODE_MATH")
+ (const_int 0))))
+ (const_string "SI")
+ ]
+ (const_string "HI")))])
+
+;; 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
+;; partial register dependency machines (such as AMD Athlon), where QImode
+;; moves issue extra dependency and for partial register stalls machines
+;; that don't use QImode patterns (and QImode move cause stall on the next
+;; instruction).
+;;
+;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
+;; register stall machines with, where we use QImode instructions, since
+;; partial register stall can be caused there. Then we use movzx.
+(define_insn "*movqi_internal"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
+ (match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,qm,qn"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_IMOVX:
+ gcc_assert (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1]));
+ return "movz{bl|x}\t{%1, %k0|%k0, %1}";
+ default:
+ if (get_attr_mode (insn) == MODE_SI)
+ return "mov{l}\t{%k1, %k0|%k0, %k1}";
+ else
+ return "mov{b}\t{%1, %0|%0, %1}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (eq_attr "alternative" "5")
+ (not (match_operand:QI 1 "aligned_operand" "")))
+ (const_string "imovx")
+ (ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (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")
+ (const_int 0))))
+ (const_string "imov")
+ (eq_attr "alternative" "3,5")
+ (const_string "imovx")
+ (and (ne (symbol_ref "TARGET_MOVX")
+ (const_int 0))
+ (eq_attr "alternative" "2"))
+ (const_string "imovx")
+ ]
+ (const_string "imov")))
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "3,4,5")
+ (const_string "SI")
+ (eq_attr "alternative" "6")
+ (const_string "QI")
+ (eq_attr "type" "imovx")
+ (const_string "SI")
+ (and (eq_attr "type" "imov")
+ (and (eq_attr "alternative" "0,1")
+ (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
+ (const_int 0))
+ (and (eq (symbol_ref "optimize_function_for_size_p (cfun)")
+ (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")
+ (and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
+ (const_int 0))
+ (eq (symbol_ref "TARGET_QIMODE_MATH")
+ (const_int 0)))))
+ (const_string "SI")
+ ]
+ (const_string "QI")))])
;; Stores and loads of ax to arbitrary constant address.
;; We fake an second form of instruction to force reload to load address
;; into register when rax is not available
-(define_insn "*movabsdi_1_rex64"
- [(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
- (match_operand:DI 1 "nonmemory_operand" "a,er"))]
+(define_insn "*movabs<mode>_1"
+ [(set (mem:SWI1248x (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
+ (match_operand:SWI1248x 1 "nonmemory_operand" "a,er"))]
"TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
- movabs{q}\t{%1, %P0|%P0, %1}
- mov{q}\t{%1, %a0|%a0, %1}"
+ movabs{<imodesuffix>}\t{%1, %P0|%P0, %1}
+ mov{<imodesuffix>}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*movabsdi_2_rex64"
- [(set (match_operand:DI 0 "register_operand" "=a,r")
- (mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
+(define_insn "*movabs<mode>_2"
+ [(set (match_operand:SWI1248x 0 "register_operand" "=a,r")
+ (mem:SWI1248x (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
"TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
- movabs{q}\t{%P1, %0|%0, %P1}
- mov{q}\t{%a1, %0|%0, %a1}"
+ movabs{<imodesuffix>}\t{%P1, %0|%0, %P1}
+ mov{<imodesuffix>}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0")
(set_attr "memory" "load")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "<MODE>")])
-;; Convert impossible stores of immediate to existing instructions.
-;; First try to get scratch register and go through it. In case this
-;; fails, move by 32bit parts.
-(define_peephole2
- [(match_scratch:DI 2 "r")
- (set (match_operand:DI 0 "memory_operand" "")
- (match_operand:DI 1 "immediate_operand" ""))]
- "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
- && !x86_64_immediate_operand (operands[1], DImode)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (match_dup 2))]
- "")
+(define_insn "*swap<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "+r")
+ (match_operand:SWI48 1 "register_operand" "+r"))
+ (set (match_dup 1)
+ (match_dup 0))]
+ ""
+ "xchg{<imodesuffix>}\t%1, %0"
+ [(set_attr "type" "imov")
+ (set_attr "mode" "<MODE>")
+ (set_attr "pent_pair" "np")
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "double")])
-;; 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" ""))]
- "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
- && !x86_64_immediate_operand (operands[1], DImode) && 1"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
- "split_di (&operands[0], 2, &operands[2], &operands[4]);")
+(define_insn "*swap<mode>_1"
+ [(set (match_operand:SWI12 0 "register_operand" "+r")
+ (match_operand:SWI12 1 "register_operand" "+r"))
+ (set (match_dup 1)
+ (match_dup 0))]
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
+ "xchg{l}\t%k1, %k0"
+ [(set_attr "type" "imov")
+ (set_attr "mode" "SI")
+ (set_attr "pent_pair" "np")
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "double")])
-(define_split
- [(set (match_operand:DI 0 "memory_operand" "")
- (match_operand:DI 1 "immediate_operand" ""))]
- "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? epilogue_completed : reload_completed)
- && !symbolic_operand (operands[1], DImode)
- && !x86_64_immediate_operand (operands[1], DImode)"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
- "split_di (&operands[0], 2, &operands[2], &operands[4]);")
+;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL
+;; is disabled for AMDFAM10
+(define_insn "*swap<mode>_2"
+ [(set (match_operand:SWI12 0 "register_operand" "+<r>")
+ (match_operand:SWI12 1 "register_operand" "+<r>"))
+ (set (match_dup 1)
+ (match_dup 0))]
+ "TARGET_PARTIAL_REG_STALL"
+ "xchg{<imodesuffix>}\t%1, %0"
+ [(set_attr "type" "imov")
+ (set_attr "mode" "<MODE>")
+ (set_attr "pent_pair" "np")
+ (set_attr "athlon_decode" "vector")])
+
+(define_expand "movstrict<mode>"
+ [(set (strict_low_part (match_operand:SWI12 0 "nonimmediate_operand" ""))
+ (match_operand:SWI12 1 "general_operand" ""))]
+ ""
+{
+ if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun))
+ FAIL;
+ /* Don't generate memory->memory moves, go through a register */
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
-(define_insn "*swapdi_rex64"
- [(set (match_operand:DI 0 "register_operand" "+r")
- (match_operand:DI 1 "register_operand" "+r"))
- (set (match_dup 1)
- (match_dup 0))]
- "TARGET_64BIT"
- "xchg{q}\t%1, %0"
+(define_insn "*movstrict<mode>_1"
+ [(set (strict_low_part
+ (match_operand:SWI12 0 "nonimmediate_operand" "+<r>m,<r>"))
+ (match_operand:SWI12 1 "general_operand" "<r>n,m"))]
+ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "mov{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "type" "imov")
- (set_attr "mode" "DI")
- (set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "double")])
+ (set_attr "mode" "<MODE>")])
-(define_expand "movoi"
- [(set (match_operand:OI 0 "nonimmediate_operand" "")
- (match_operand:OI 1 "general_operand" ""))]
- "TARGET_AVX"
- "ix86_expand_move (OImode, operands); DONE;")
+(define_insn "*movstrict<mode>_xor"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (match_operand:SWI12 1 "const0_operand" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ "xor{<imodesuffix>}\t%0, %0"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length_immediate" "0")])
-(define_insn "*movoi_internal"
- [(set (match_operand:OI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:OI 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_AVX
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+(define_insn "*mov<mode>_extv_1"
+ [(set (match_operand:SWI24 0 "register_operand" "=R")
+ (sign_extract:SWI24 (match_operand 1 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)))]
+ ""
+ "movs{bl|x}\t{%h1, %k0|%k0, %h1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "SI")])
+
+(define_insn "*movqi_extv_1_rex64"
+ [(set (match_operand:QI 0 "register_operand" "=Q,?R")
+ (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)))]
+ "TARGET_64BIT"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- return "vxorps\t%0, %0, %0";
- case 1:
- case 2:
- if (misaligned_operand (operands[0], OImode)
- || misaligned_operand (operands[1], OImode))
- return "vmovdqu\t{%1, %0|%0, %1}";
- else
- return "vmovdqa\t{%1, %0|%0, %1}";
+ case TYPE_IMOVX:
+ return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
default:
- gcc_unreachable ();
+ return "mov{b}\t{%h1, %0|%0, %h1}";
}
}
- [(set_attr "type" "sselog1,ssemov,ssemov")
- (set_attr "prefix" "vex")
- (set_attr "mode" "OI")])
+ [(set (attr "type")
+ (if_then_else (and (match_operand:QI 0 "register_operand" "")
+ (ior (not (match_operand:QI 0 "q_regs_operand" ""))
+ (ne (symbol_ref "TARGET_MOVX")
+ (const_int 0))))
+ (const_string "imovx")
+ (const_string "imov")))
+ (set (attr "mode")
+ (if_then_else (eq_attr "type" "imovx")
+ (const_string "SI")
+ (const_string "QI")))])
-(define_expand "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE || TARGET_64BIT"
+(define_insn "*movqi_extv_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
+ (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)))]
+ "!TARGET_64BIT"
{
- if (TARGET_64BIT)
- ix86_expand_move (TImode, operands);
- else if (push_operand (operands[0], TImode))
- ix86_expand_push (TImode, operands[1]);
- else
- ix86_expand_vector_move (TImode, operands);
- DONE;
-})
+ switch (get_attr_type (insn))
+ {
+ case TYPE_IMOVX:
+ return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
+ default:
+ return "mov{b}\t{%h1, %0|%0, %h1}";
+ }
+}
+ [(set (attr "type")
+ (if_then_else (and (match_operand:QI 0 "register_operand" "")
+ (ior (not (match_operand:QI 0 "q_regs_operand" ""))
+ (ne (symbol_ref "TARGET_MOVX")
+ (const_int 0))))
+ (const_string "imovx")
+ (const_string "imov")))
+ (set (attr "mode")
+ (if_then_else (eq_attr "type" "imovx")
+ (const_string "SI")
+ (const_string "QI")))])
-(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
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+(define_insn "*mov<mode>_extzv_1"
+ [(set (match_operand:SWI48 0 "register_operand" "=R")
+ (zero_extract:SWI48 (match_operand 1 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)))]
+ ""
+ "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "SI")])
+
+(define_insn "*movqi_extzv_2_rex64"
+ [(set (match_operand:QI 0 "register_operand" "=Q,?R")
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0))]
+ "TARGET_64BIT"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vxorps\t%0, %d0";
- else
- return "%vpxor\t%0, %d0";
- case 1:
- case 2:
- /* TDmode values are passed as TImode on the stack. Moving them
- to stack may result in unaligned memory access. */
- if (misaligned_operand (operands[0], TImode)
- || misaligned_operand (operands[1], TImode))
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovups\t{%1, %0|%0, %1}";
- else
- return "%vmovdqu\t{%1, %0|%0, %1}";
- }
- else
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovdqa\t{%1, %0|%0, %1}";
- }
+ case TYPE_IMOVX:
+ return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
default:
- gcc_unreachable ();
+ return "mov{b}\t{%h1, %0|%0, %h1}";
}
}
- [(set_attr "type" "sselog1,ssemov,ssemov")
- (set_attr "prefix" "maybe_vex")
+ [(set (attr "type")
+ (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
+ (ne (symbol_ref "TARGET_MOVX")
+ (const_int 0)))
+ (const_string "imovx")
+ (const_string "imov")))
(set (attr "mode")
- (cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
- (ne (symbol_ref "optimize_function_for_size_p (cfun)") (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")))])
+ (if_then_else (eq_attr "type" "imovx")
+ (const_string "SI")
+ (const_string "QI")))])
-(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
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+(define_insn "*movqi_extzv_2"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0))]
+ "!TARGET_64BIT"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- case 1:
- return "#";
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vxorps\t%0, %d0";
- else
- return "%vpxor\t%0, %d0";
- case 3:
- case 4:
- /* TDmode values are passed as TImode on the stack. Moving them
- to stack may result in unaligned memory access. */
- if (misaligned_operand (operands[0], TImode)
- || misaligned_operand (operands[1], TImode))
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovups\t{%1, %0|%0, %1}";
- else
- return "%vmovdqu\t{%1, %0|%0, %1}";
- }
- else
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovdqa\t{%1, %0|%0, %1}";
- }
+ case TYPE_IMOVX:
+ return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
default:
- gcc_unreachable ();
+ return "mov{b}\t{%h1, %0|%0, %h1}";
}
}
- [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
- (set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex")
+ [(set (attr "type")
+ (if_then_else (and (match_operand:QI 0 "register_operand" "")
+ (ior (not (match_operand:QI 0 "q_regs_operand" ""))
+ (ne (symbol_ref "TARGET_MOVX")
+ (const_int 0))))
+ (const_string "imovx")
+ (const_string "imov")))
(set (attr "mode")
- (cond [(eq_attr "alternative" "2,3")
- (if_then_else
- (ne (symbol_ref "optimize_function_for_size_p (cfun)")
- (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_function_for_size_p (cfun)")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "DI")))])
+ (if_then_else (eq_attr "type" "imovx")
+ (const_string "SI")
+ (const_string "QI")))])
-(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 "mov<mode>_insv_1"
+ [(set (zero_extract:SWI48 (match_operand 0 "ext_register_operand" "")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:SWI48 1 "nonmemory_operand" ""))]
+ ""
+ "")
-;; This expands to what emit_move_complex would generate if we didn't
-;; have a movti pattern. Having this avoids problems with reload on
-;; 32-bit targets when SSE is present, but doesn't seem to be harmful
-;; to have around all the time.
-(define_expand "movcdi"
- [(set (match_operand:CDI 0 "nonimmediate_operand" "")
- (match_operand:CDI 1 "general_operand" ""))]
+(define_insn "*mov<mode>_insv_1_rex64"
+ [(set (zero_extract:SWI48x (match_operand 0 "ext_register_operand" "+Q")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:SWI48x 1 "nonmemory_operand" "Qn"))]
+ "TARGET_64BIT"
+ "mov{b}\t{%b1, %h0|%h0, %b1}"
+ [(set_attr "type" "imov")
+ (set_attr "mode" "QI")])
+
+(define_insn "*movsi_insv_1"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:SI 1 "general_operand" "Qmn"))]
+ "!TARGET_64BIT"
+ "mov{b}\t{%b1, %h0|%h0, %b1}"
+ [(set_attr "type" "imov")
+ (set_attr "mode" "QI")])
+
+(define_insn "*movqi_insv_2"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
+ (const_int 8)
+ (const_int 8))
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
+ (const_int 8)))]
""
+ "mov{b}\t{%h1, %h0|%h0, %h1}"
+ [(set_attr "type" "imov")
+ (set_attr "mode" "QI")])
+\f
+;; Floating point move instructions.
+
+(define_expand "movtf"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE2"
{
- if (push_operand (operands[0], CDImode))
- emit_move_complex_push (CDImode, operands[0], operands[1]);
- else
- emit_move_complex_parts (operands[0], operands[1]);
+ ix86_expand_move (TFmode, operands);
DONE;
})
-(define_expand "movsf"
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
+(define_expand "mov<mode>"
+ [(set (match_operand:X87MODEF 0 "nonimmediate_operand" "")
+ (match_operand:X87MODEF 1 "general_operand" ""))]
""
- "ix86_expand_move (SFmode, operands); DONE;")
-
-(define_insn "*pushsf"
- [(set (match_operand:SF 0 "push_operand" "=<,<,<")
- (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
- "!TARGET_64BIT"
-{
- /* 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")])
+ "ix86_expand_move (<MODE>mode, operands); DONE;")
-(define_insn "*pushsf_rex64"
- [(set (match_operand:SF 0 "push_operand" "=X,X,X")
- (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
- "TARGET_64BIT"
+(define_insn "*pushtf"
+ [(set (match_operand:TF 0 "push_operand" "=<,<,<")
+ (match_operand:TF 1 "general_no_elim_operand" "x,Fo,*r"))]
+ "TARGET_SSE2"
{
- /* Anything else should be already split before reg-stack. */
- gcc_assert (which_alternative == 1);
- return "push{q}\t%q1";
+ /* This insn should be already split before reg-stack. */
+ gcc_unreachable ();
}
- [(set_attr "type" "multi,push,multi")
- (set_attr "unit" "i387,*,*")
- (set_attr "mode" "SF,DI,SF")])
-
-(define_split
- [(set (match_operand:SF 0 "push_operand" "")
- (match_operand:SF 1 "memory_operand" ""))]
- "reload_completed
- && MEM_P (operands[1])
- && (operands[2] = find_constant_src (insn))"
- [(set (match_dup 0)
- (match_dup 2))])
+ [(set_attr "type" "multi")
+ (set_attr "unit" "sse,*,*")
+ (set_attr "mode" "TF,SI,SI")])
-;; %%% Kill this when call knows how to work this out.
(define_split
- [(set (match_operand:SF 0 "push_operand" "")
- (match_operand:SF 1 "any_fp_register_operand" ""))]
- "!TARGET_64BIT"
- [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
- (set (mem:SF (reg:SI SP_REG)) (match_dup 1))])
+ [(set (match_operand:TF 0 "push_operand" "")
+ (match_operand:TF 1 "general_operand" ""))]
+ "TARGET_SSE2 && reload_completed
+ && !SSE_REG_P (operands[1])"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
(define_split
- [(set (match_operand:SF 0 "push_operand" "")
- (match_operand:SF 1 "any_fp_register_operand" ""))]
- "TARGET_64BIT"
- [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
- (set (mem:SF (reg:DI SP_REG)) (match_dup 1))])
+ [(set (match_operand:TF 0 "push_operand" "")
+ (match_operand:TF 1 "any_fp_register_operand" ""))]
+ "TARGET_SSE2"
+ [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -16)))
+ (set (mem:TF (reg:P SP_REG)) (match_dup 1))]
+ "")
-(define_insn "*movsf_1"
- [(set (match_operand:SF 0 "nonimmediate_operand"
- "=f,m,f,r ,m ,x,x,x ,m,!*y,!m,!*y,?Yi,?r,!*Ym,!r")
- (match_operand:SF 1 "general_operand"
- "fm,f,G,rmF,Fr,C,x,xm,x,m ,*y,*y ,r ,Yi,r ,*Ym"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))
- && (reload_in_progress || reload_completed
- || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
- || (!TARGET_SSE_MATH && optimize_function_for_size_p (cfun)
- && standard_80387_constant_p (operands[1]))
- || GET_CODE (operands[1]) != CONST_DOUBLE
- || memory_operand (operands[0], SFmode))"
+(define_insn "*pushxf"
+ [(set (match_operand:XF 0 "push_operand" "=<,<")
+ (match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
+ "optimize_function_for_speed_p (cfun)"
{
- switch (which_alternative)
- {
- case 0:
- case 1:
- return output_387_reg_move (insn, operands);
-
- 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 "%vpxor\t%0, %d0";
- else
- return "%vxorps\t%0, %d0";
- case 6:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovss\t{%1, %d0|%d0, %1}";
- case 7:
- if (TARGET_AVX)
- return REG_P (operands[1]) ? "vmovss\t{%1, %0, %0|%0, %0, %1}"
- : "vmovss\t{%1, %0|%0, %1}";
- else
- return "movss\t{%1, %0|%0, %1}";
- case 8:
- return "%vmovss\t{%1, %0|%0, %1}";
-
- case 9: case 10: case 14: case 15:
- return "movd\t{%1, %0|%0, %1}";
- case 12: case 13:
- return "%vmovd\t{%1, %0|%0, %1}";
+ /* This insn should be already split before reg-stack. */
+ gcc_unreachable ();
+}
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387,*")
+ (set_attr "mode" "XF,SI")])
- case 11:
- return "movq\t{%1, %0|%0, %1}";
+;; Size of pushxf is 3 (for sub) + 2 (for fstp) + memory operand size.
+;; Size of pushxf using integer instructions is 3+3*memory operand size
+;; Pushing using integer instructions is longer except for constants
+;; and direct memory references (assuming that any given constant is pushed
+;; only once, but this ought to be handled elsewhere).
- default:
- gcc_unreachable ();
- }
+(define_insn "*pushxf_nointeger"
+ [(set (match_operand:XF 0 "push_operand" "=X,X,X")
+ (match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
+ "optimize_function_for_size_p (cfun)"
+{
+ /* This insn should be already split before reg-stack. */
+ gcc_unreachable ();
}
- [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov,ssemov,ssemov,mmxmov,mmxmov")
- (set (attr "prefix")
- (if_then_else (eq_attr "alternative" "5,6,7,8,12,13")
- (const_string "maybe_vex")
- (const_string "orig")))
- (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_function_for_size_p (cfun)")
- (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.
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387,*,*")
+ (set_attr "mode" "XF,SI,SI")])
- 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_SPLIT_REGS")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "SF"))
- (eq_attr "alternative" "11")
- (const_string "DI")]
- (const_string "SF")))])
+(define_split
+ [(set (match_operand:XF 0 "push_operand" "")
+ (match_operand:XF 1 "any_fp_register_operand" ""))]
+ "reload_completed"
+ [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2)))
+ (set (mem:XF (reg:P SP_REG)) (match_dup 1))]
+ "operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));")
-(define_insn "*swapsf"
- [(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_80387"
+(define_split
+ [(set (match_operand:XF 0 "push_operand" "")
+ (match_operand:XF 1 "general_operand" ""))]
+ "reload_completed
+ && !ANY_FP_REG_P (operands[1])"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
+
+(define_insn "*pushdf"
+ [(set (match_operand:DF 0 "push_operand" "=<,<,<")
+ (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y2"))]
+ "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
{
- if (STACK_TOP_P (operands[0]))
- return "fxch\t%1";
- else
- return "fxch\t%0";
+ /* This insn should be already split before reg-stack. */
+ gcc_unreachable ();
}
- [(set_attr "type" "fxch")
- (set_attr "mode" "SF")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "ix86_expand_move (DFmode, operands); DONE;")
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387,*,*")
+ (set_attr "mode" "DF,SI,DF")])
;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
;; Size of pushdf using integer instructions is 2+2*memory operand size
(define_insn "*pushdf_nointeger"
[(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
(match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y2"))]
- "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
+ "!(TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES)"
{
/* This insn should be already split before reg-stack. */
gcc_unreachable ();
(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,rFo,Y2"))]
- "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
+;; %%% Kill this when call knows how to work this out.
+(define_split
+ [(set (match_operand:DF 0 "push_operand" "")
+ (match_operand:DF 1 "any_fp_register_operand" ""))]
+ "reload_completed"
+ [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -8)))
+ (set (mem:DF (reg:P SP_REG)) (match_dup 1))]
+ "")
+
+(define_split
+ [(set (match_operand:DF 0 "push_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ "reload_completed
+ && !ANY_FP_REG_P (operands[1])"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
+
+(define_insn "*pushsf_rex64"
+ [(set (match_operand:SF 0 "push_operand" "=X,X,X")
+ (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
+ "TARGET_64BIT"
+{
+ /* 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_insn "*pushsf"
+ [(set (match_operand:SF 0 "push_operand" "=<,<,<")
+ (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
+ "!TARGET_64BIT"
{
- /* This insn should be already split before reg-stack. */
- gcc_unreachable ();
+ /* Anything else should be already split before reg-stack. */
+ gcc_assert (which_alternative == 1);
+ return "push{l}\t%1";
}
- [(set_attr "type" "multi")
+ [(set_attr "type" "multi,push,multi")
(set_attr "unit" "i387,*,*")
- (set_attr "mode" "DF,SI,DF")])
+ (set_attr "mode" "SF,SI,SF")])
+
+(define_split
+ [(set (match_operand:SF 0 "push_operand" "")
+ (match_operand:SF 1 "memory_operand" ""))]
+ "reload_completed
+ && MEM_P (operands[1])
+ && (operands[2] = find_constant_src (insn))"
+ [(set (match_dup 0)
+ (match_dup 2))])
;; %%% Kill this when call knows how to work this out.
(define_split
- [(set (match_operand:DF 0 "push_operand" "")
- (match_operand:DF 1 "any_fp_register_operand" ""))]
+ [(set (match_operand:SF 0 "push_operand" "")
+ (match_operand:SF 1 "any_fp_register_operand" ""))]
"reload_completed"
- [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -8)))
- (set (mem:DF (reg:P SP_REG)) (match_dup 1))]
- "")
+ [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2)))
+ (set (mem:SF (reg:P SP_REG)) (match_dup 1))]
+ "operands[2] = GEN_INT (-GET_MODE_SIZE (<MODE>mode));")
+
+(define_insn "*movtf_internal"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=x,m,x,?r,?o")
+ (match_operand:TF 1 "general_operand" "xm,x,C,roF,Fr"))]
+ "TARGET_SSE2
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ else
+ return "%vmovdqa\t{%1, %0|%0, %1}";
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "%vxorps\t%0, %d0";
+ else
+ return "%vpxor\t%0, %d0";
+ case 3:
+ case 4:
+ return "#";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "ssemov,ssemov,sselog1,*,*")
+ (set_attr "prefix" "maybe_vex,maybe_vex,maybe_vex,*,*")
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "0,2")
+ (if_then_else
+ (ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (const_int 0))
+ (const_string "V4SF")
+ (const_string "TI"))
+ (eq_attr "alternative" "1")
+ (if_then_else
+ (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
+ (const_int 0))
+ (ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (const_int 0)))
+ (const_string "V4SF")
+ (const_string "TI"))]
+ (const_string "DI")))])
(define_split
- [(set (match_operand:DF 0 "push_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- "reload_completed"
+ [(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;")
-;; Moving is usually shorter when only FP registers are used. This separate
-;; movdf pattern avoids the use of integer registers for FP operations
-;; when optimizing for size.
-
-(define_insn "*movdf_nointeger"
- [(set (match_operand:DF 0 "nonimmediate_operand"
- "=f,m,f,*r ,o ,Y2*x,Y2*x,Y2*x ,m ")
- (match_operand:DF 1 "general_operand"
- "fm,f,G,*roF,*Fr,C ,Y2*x,mY2*x,Y2*x"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))
- && ((optimize_function_for_size_p (cfun)
- || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
+(define_insn "*movxf_internal"
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
+ (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
+ "optimize_function_for_speed_p (cfun)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (reload_in_progress || reload_completed
- || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
- || (!(TARGET_SSE2 && TARGET_SSE_MATH)
- && optimize_function_for_size_p (cfun)
- && !memory_operand (operands[0], DFmode)
- && standard_80387_constant_p (operands[1]))
|| GET_CODE (operands[1]) != CONST_DOUBLE
- || ((optimize_function_for_size_p (cfun)
- || !TARGET_MEMORY_MISMATCH_STALL
- || reload_in_progress || reload_completed)
- && memory_operand (operands[0], DFmode)))"
+ || memory_operand (operands[0], XFmode))"
{
switch (which_alternative)
{
case 2:
return standard_80387_constant_opcode (operands[1]);
- case 3:
- case 4:
+ case 3: case 4:
return "#";
- case 5:
- switch (get_attr_mode (insn))
- {
- case MODE_V4SF:
- return "%vxorps\t%0, %d0";
- case MODE_V2DF:
- if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
- return "%vxorps\t%0, %d0";
- else
- return "%vxorpd\t%0, %d0";
- case MODE_TI:
- if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
- return "%vxorps\t%0, %d0";
- else
- return "%vpxor\t%0, %d0";
- default:
- gcc_unreachable ();
- }
- case 6:
- case 7:
- case 8:
- switch (get_attr_mode (insn))
- {
- case MODE_V4SF:
- return "%vmovaps\t{%1, %0|%0, %1}";
- case MODE_V2DF:
- if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovapd\t{%1, %0|%0, %1}";
- case MODE_TI:
- if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovdqa\t{%1, %0|%0, %1}";
- case MODE_DI:
- return "%vmovq\t{%1, %0|%0, %1}";
- case MODE_DF:
- if (TARGET_AVX)
- {
- if (REG_P (operands[0]) && REG_P (operands[1]))
- return "vmovsd\t{%1, %0, %0|%0, %0, %1}";
- else
- return "vmovsd\t{%1, %0|%0, %1}";
- }
- else
- return "movsd\t{%1, %0|%0, %1}";
- case MODE_V1DF:
- if (TARGET_AVX)
- {
- if (REG_P (operands[0]))
- return "vmovlpd\t{%1, %0, %0|%0, %0, %1}";
- else
- return "vmovlpd\t{%1, %0|%0, %1}";
- }
- else
- return "movlpd\t{%1, %0|%0, %1}";
- case MODE_V2SF:
- if (TARGET_AVX)
- {
- if (REG_P (operands[0]))
- return "vmovlps\t{%1, %0, %0|%0, %0, %1}";
- else
- return "vmovlps\t{%1, %0|%0, %1}";
- }
- else
- return "movlps\t{%1, %0|%0, %1}";
- default:
- gcc_unreachable ();
- }
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
- (set (attr "prefix")
- (if_then_else (eq_attr "alternative" "0,1,2,3,4")
- (const_string "orig")
- (const_string "maybe_vex")))
- (set (attr "prefix_data16")
- (if_then_else (eq_attr "mode" "V1DF")
- (const_string "1")
- (const_string "*")))
- (set (attr "mode")
- (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_function_for_size_p (cfun)")
- (const_int 0))
- (const_string "V4SF")
- (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
- (const_int 0))
- (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.
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi")
+ (set_attr "mode" "XF,XF,XF,SI,SI")])
- movaps encodes one byte shorter. */
- (eq_attr "alternative" "6")
- (cond
- [(ne (symbol_ref "optimize_function_for_size_p (cfun)")
- (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_SPLIT_REGS")
- (const_int 0))
- (const_string "V1DF")
- (const_string "DF"))
- ]
- (const_string "DF")))])
+;; Do not use integer registers when optimizing for size
+(define_insn "*movxf_internal_nointeger"
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
+ (match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
+ "optimize_function_for_size_p (cfun)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && (reload_in_progress || reload_completed
+ || standard_80387_constant_p (operands[1])
+ || GET_CODE (operands[1]) != CONST_DOUBLE
+ || memory_operand (operands[0], XFmode))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return output_387_reg_move (insn, operands);
+
+ case 2:
+ return standard_80387_constant_opcode (operands[1]);
+
+ case 3: case 4:
+ return "#";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi")
+ (set_attr "mode" "XF,XF,XF,SI,SI")])
+
+(define_split
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (match_operand:XF 1 "general_operand" ""))]
+ "reload_completed
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ! (ANY_FP_REG_P (operands[0]) ||
+ (GET_CODE (operands[0]) == SUBREG
+ && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
+ && ! (ANY_FP_REG_P (operands[1]) ||
+ (GET_CODE (operands[1]) == SUBREG
+ && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
-(define_insn "*movdf_integer_rex64"
+(define_insn "*movdf_internal_rex64"
[(set (match_operand:DF 0 "nonimmediate_operand"
"=f,m,f,r ,m ,Y2*x,Y2*x,Y2*x,m ,Yi,r ")
(match_operand:DF 1 "general_operand"
]
(const_string "DF")))])
-(define_insn "*movdf_integer"
+(define_insn "*movdf_internal"
[(set (match_operand:DF 0 "nonimmediate_operand"
"=f,m,f,r ,o ,Y2*x,Y2*x,Y2*x,m ")
(match_operand:DF 1 "general_operand"
]
(const_string "DF")))])
-(define_split
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- "reload_completed
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))
- && ! (ANY_FP_REG_P (operands[0]) ||
- (GET_CODE (operands[0]) == SUBREG
- && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
- && ! (ANY_FP_REG_P (operands[1]) ||
- (GET_CODE (operands[1]) == SUBREG
- && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
-
-(define_insn "*swapdf"
- [(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_80387"
-{
- if (STACK_TOP_P (operands[0]))
- return "fxch\t%1";
- else
- return "fxch\t%0";
-}
- [(set_attr "type" "fxch")
- (set_attr "mode" "DF")])
-
-(define_expand "movxf"
- [(set (match_operand:XF 0 "nonimmediate_operand" "")
- (match_operand:XF 1 "general_operand" ""))]
- ""
- "ix86_expand_move (XFmode, operands); DONE;")
-
-;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
-;; Size of pushdf using integer instructions is 3+3*memory operand size
-;; Pushing using integer instructions is longer except for constants
-;; and direct memory references.
-;; (assuming that any given constant is pushed only once, but this ought to be
-;; handled elsewhere).
-
-(define_insn "*pushxf_nointeger"
- [(set (match_operand:XF 0 "push_operand" "=X,X,X")
- (match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
- "optimize_function_for_size_p (cfun)"
-{
- /* This insn should be already split before reg-stack. */
- 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,ro"))]
- "optimize_function_for_speed_p (cfun)"
-{
- /* This insn should be already split before reg-stack. */
- gcc_unreachable ();
-}
- [(set_attr "type" "multi")
- (set_attr "unit" "i387,*")
- (set_attr "mode" "XF,SI")])
-
-(define_split
- [(set (match_operand 0 "push_operand" "")
- (match_operand 1 "general_operand" ""))]
- "reload_completed
- && (GET_MODE (operands[0]) == XFmode
- || GET_MODE (operands[0]) == DFmode)
- && !ANY_FP_REG_P (operands[1])"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
-
-(define_split
- [(set (match_operand:XF 0 "push_operand" "")
- (match_operand:XF 1 "any_fp_register_operand" ""))]
- ""
- [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2)))
- (set (mem:XF (reg:P SP_REG)) (match_dup 1))]
- "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
+;; Moving is usually shorter when only FP registers are used. This separate
+;; movdf pattern avoids the use of integer registers for FP operations
+;; when optimizing for size.
-;; Do not use integer registers when optimizing for size
-(define_insn "*movxf_nointeger"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
- (match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
- "optimize_function_for_size_p (cfun)
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+(define_insn "*movdf_internal_nointeger"
+ [(set (match_operand:DF 0 "nonimmediate_operand"
+ "=f,m,f,*r ,o ,Y2*x,Y2*x,Y2*x ,m ")
+ (match_operand:DF 1 "general_operand"
+ "fm,f,G,*roF,*Fr,C ,Y2*x,mY2*x,Y2*x"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ((optimize_function_for_size_p (cfun)
+ || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
&& (reload_in_progress || reload_completed
- || standard_80387_constant_p (operands[1])
+ || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
+ || (!(TARGET_SSE2 && TARGET_SSE_MATH)
+ && optimize_function_for_size_p (cfun)
+ && !memory_operand (operands[0], DFmode)
+ && standard_80387_constant_p (operands[1]))
|| GET_CODE (operands[1]) != CONST_DOUBLE
- || memory_operand (operands[0], XFmode))"
+ || ((optimize_function_for_size_p (cfun)
+ || !TARGET_MEMORY_MISMATCH_STALL
+ || reload_in_progress || reload_completed)
+ && memory_operand (operands[0], DFmode)))"
{
switch (which_alternative)
{
case 2:
return standard_80387_constant_opcode (operands[1]);
- case 3: case 4:
+ case 3:
+ case 4:
return "#";
+ case 5:
+ switch (get_attr_mode (insn))
+ {
+ case MODE_V4SF:
+ return "%vxorps\t%0, %d0";
+ case MODE_V2DF:
+ if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+ return "%vxorps\t%0, %d0";
+ else
+ return "%vxorpd\t%0, %d0";
+ case MODE_TI:
+ if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+ return "%vxorps\t%0, %d0";
+ else
+ return "%vpxor\t%0, %d0";
+ default:
+ gcc_unreachable ();
+ }
+ case 6:
+ case 7:
+ case 8:
+ switch (get_attr_mode (insn))
+ {
+ case MODE_V4SF:
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ case MODE_V2DF:
+ if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ else
+ return "%vmovapd\t{%1, %0|%0, %1}";
+ case MODE_TI:
+ if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ else
+ return "%vmovdqa\t{%1, %0|%0, %1}";
+ case MODE_DI:
+ return "%vmovq\t{%1, %0|%0, %1}";
+ case MODE_DF:
+ if (TARGET_AVX)
+ {
+ if (REG_P (operands[0]) && REG_P (operands[1]))
+ return "vmovsd\t{%1, %0, %0|%0, %0, %1}";
+ else
+ return "vmovsd\t{%1, %0|%0, %1}";
+ }
+ else
+ return "movsd\t{%1, %0|%0, %1}";
+ case MODE_V1DF:
+ if (TARGET_AVX)
+ {
+ if (REG_P (operands[0]))
+ return "vmovlpd\t{%1, %0, %0|%0, %0, %1}";
+ else
+ return "vmovlpd\t{%1, %0|%0, %1}";
+ }
+ else
+ return "movlpd\t{%1, %0|%0, %1}";
+ case MODE_V2SF:
+ if (TARGET_AVX)
+ {
+ if (REG_P (operands[0]))
+ return "vmovlps\t{%1, %0, %0|%0, %0, %1}";
+ else
+ return "vmovlps\t{%1, %0|%0, %1}";
+ }
+ else
+ return "movlps\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi")
- (set_attr "mode" "XF,XF,XF,SI,SI")])
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "0,1,2,3,4")
+ (const_string "orig")
+ (const_string "maybe_vex")))
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "V1DF")
+ (const_string "1")
+ (const_string "*")))
+ (set (attr "mode")
+ (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_function_for_size_p (cfun)")
+ (const_int 0))
+ (const_string "V4SF")
+ (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
+ (const_int 0))
+ (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.
+
+ movaps encodes one byte shorter. */
+ (eq_attr "alternative" "6")
+ (cond
+ [(ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (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_SPLIT_REGS")
+ (const_int 0))
+ (const_string "V1DF")
+ (const_string "DF"))
+ ]
+ (const_string "DF")))])
-(define_insn "*movxf_integer"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
- (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
- "optimize_function_for_speed_p (cfun)
+(define_split
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ "reload_completed
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ! (ANY_FP_REG_P (operands[0]) ||
+ (GET_CODE (operands[0]) == SUBREG
+ && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
+ && ! (ANY_FP_REG_P (operands[1]) ||
+ (GET_CODE (operands[1]) == SUBREG
+ && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
+
+(define_insn "*movsf_internal"
+ [(set (match_operand:SF 0 "nonimmediate_operand"
+ "=f,m,f,r ,m ,x,x,x ,m,!*y,!m,!*y,?Yi,?r,!*Ym,!r")
+ (match_operand:SF 1 "general_operand"
+ "fm,f,G,rmF,Fr,C,x,xm,x,m ,*y,*y ,r ,Yi,r ,*Ym"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (reload_in_progress || reload_completed
+ || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
+ || (!TARGET_SSE_MATH && optimize_function_for_size_p (cfun)
+ && standard_80387_constant_p (operands[1]))
|| GET_CODE (operands[1]) != CONST_DOUBLE
- || memory_operand (operands[0], XFmode))"
+ || memory_operand (operands[0], SFmode))"
{
switch (which_alternative)
{
case 2:
return standard_80387_constant_opcode (operands[1]);
- case 3: case 4:
- return "#";
-
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi")
- (set_attr "mode" "XF,XF,XF,SI,SI")])
-
-(define_expand "movtf"
- [(set (match_operand:TF 0 "nonimmediate_operand" "")
- (match_operand:TF 1 "nonimmediate_operand" ""))]
- "TARGET_SSE2"
-{
- ix86_expand_move (TFmode, operands);
- DONE;
-})
-
-(define_insn "*movtf_internal"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=x,m,x,?r,?o")
- (match_operand:TF 1 "general_operand" "xm,x,C,roF,Fr"))]
- "TARGET_SSE2
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
+ case 3:
+ case 4:
+ return "mov{l}\t{%1, %0|%0, %1}";
+ case 5:
+ if (get_attr_mode (insn) == MODE_TI)
+ return "%vpxor\t%0, %d0";
+ else
+ return "%vxorps\t%0, %d0";
+ case 6:
if (get_attr_mode (insn) == MODE_V4SF)
return "%vmovaps\t{%1, %0|%0, %1}";
else
- return "%vmovdqa\t{%1, %0|%0, %1}";
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vxorps\t%0, %d0";
+ return "%vmovss\t{%1, %d0|%d0, %1}";
+ case 7:
+ if (TARGET_AVX)
+ return REG_P (operands[1]) ? "vmovss\t{%1, %0, %0|%0, %0, %1}"
+ : "vmovss\t{%1, %0|%0, %1}";
else
- return "%vpxor\t%0, %d0";
- case 3:
- case 4:
- return "#";
+ return "movss\t{%1, %0|%0, %1}";
+ case 8:
+ return "%vmovss\t{%1, %0|%0, %1}";
+
+ case 9: case 10: case 14: case 15:
+ return "movd\t{%1, %0|%0, %1}";
+ case 12: case 13:
+ return "%vmovd\t{%1, %0|%0, %1}";
+
+ case 11:
+ return "movq\t{%1, %0|%0, %1}";
+
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "ssemov,ssemov,sselog1,*,*")
- (set_attr "prefix" "maybe_vex,maybe_vex,maybe_vex,*,*")
+ [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov,ssemov,ssemov,mmxmov,mmxmov")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "5,6,7,8,12,13")
+ (const_string "maybe_vex")
+ (const_string "orig")))
(set (attr "mode")
- (cond [(eq_attr "alternative" "0,2")
+ (cond [(eq_attr "alternative" "3,4,9,10")
+ (const_string "SI")
+ (eq_attr "alternative" "5")
(if_then_else
- (ne (symbol_ref "optimize_function_for_size_p (cfun)")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "1")
+ (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_function_for_size_p (cfun)")
+ (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_TYPELESS_STORES")
+ (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
(const_int 0))
- (ne (symbol_ref "optimize_function_for_size_p (cfun)")
+ (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
(const_int 0)))
(const_string "V4SF")
- (const_string "TI"))]
- (const_string "DI")))])
-
-(define_insn "*pushtf_sse"
- [(set (match_operand:TF 0 "push_operand" "=<,<,<")
- (match_operand:TF 1 "general_no_elim_operand" "x,Fo,*r"))]
- "TARGET_SSE2"
-{
- /* This insn should be already split before reg-stack. */
- gcc_unreachable ();
-}
- [(set_attr "type" "multi")
- (set_attr "unit" "sse,*,*")
- (set_attr "mode" "TF,SI,SI")])
-
-(define_split
- [(set (match_operand:TF 0 "push_operand" "")
- (match_operand:TF 1 "general_operand" ""))]
- "TARGET_SSE2 && reload_completed
- && !SSE_REG_P (operands[1])"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
-
-(define_split
- [(set (match_operand:TF 0 "push_operand" "")
- (match_operand:TF 1 "any_fp_register_operand" ""))]
- "TARGET_SSE2"
- [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -16)))
- (set (mem:TF (reg:P SP_REG)) (match_dup 1))]
- "")
-
-(define_split
- [(set (match_operand 0 "nonimmediate_operand" "")
- (match_operand 1 "general_operand" ""))]
- "reload_completed
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))
- && GET_MODE (operands[0]) == XFmode
- && ! (ANY_FP_REG_P (operands[0]) ||
- (GET_CODE (operands[0]) == SUBREG
- && ANY_FP_REG_P (SUBREG_REG (operands[0]))))
- && ! (ANY_FP_REG_P (operands[1]) ||
- (GET_CODE (operands[1]) == SUBREG
- && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
+ (const_string "SF"))
+ (eq_attr "alternative" "11")
+ (const_string "DI")]
+ (const_string "SF")))])
(define_split
[(set (match_operand 0 "register_operand" "")
&& MEM_P (operands[1])
&& (GET_MODE (operands[0]) == TFmode
|| GET_MODE (operands[0]) == XFmode
- || GET_MODE (operands[0]) == SFmode
- || GET_MODE (operands[0]) == DFmode)
+ || GET_MODE (operands[0]) == DFmode
+ || GET_MODE (operands[0]) == SFmode)
&& (operands[2] = find_constant_src (insn))"
[(set (match_dup 0) (match_dup 2))]
{
&& MEM_P (operands[1])
&& (GET_MODE (operands[0]) == TFmode
|| GET_MODE (operands[0]) == XFmode
- || GET_MODE (operands[0]) == SFmode
- || GET_MODE (operands[0]) == DFmode)
+ || GET_MODE (operands[0]) == DFmode
+ || GET_MODE (operands[0]) == SFmode)
&& (operands[2] = find_constant_src (insn))"
[(set (match_dup 0) (match_dup 2))]
{
FAIL;
})
-(define_insn "swapxf"
- [(set (match_operand:XF 0 "register_operand" "+f")
- (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";
- else
- return "fxch\t%0";
-}
- [(set_attr "type" "fxch")
- (set_attr "mode" "XF")])
-
;; Split the load of -0.0 or -1.0 into fldz;fchs or fld1;fchs sequence
(define_split
[(set (match_operand:X87MODEF 0 "register_operand" "")
operands[1] = CONST1_RTX (<MODE>mode);
})
-(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;")
+(define_insn "swapxf"
+ [(set (match_operand:XF 0 "register_operand" "+f")
+ (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";
+ else
+ return "fxch\t%0";
+}
+ [(set_attr "type" "fxch")
+ (set_attr "mode" "XF")])
+
+(define_insn "*swap<mode>"
+ [(set (match_operand:MODEF 0 "fp_register_operand" "+f")
+ (match_operand:MODEF 1 "fp_register_operand" "+f"))
+ (set (match_dup 1)
+ (match_dup 0))]
+ "TARGET_80387 || reload_completed"
+{
+ if (STACK_TOP_P (operands[0]))
+ return "fxch\t%1";
+ else
+ return "fxch\t%0";
+}
+ [(set_attr "type" "fxch")
+ (set_attr "mode" "<MODE>")])
\f
;; Zero extension instructions
(zero_extend:DI (match_operand:SI 1 "general_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed
- && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])"
+ && !(MMX_REG_P (operands[0]) || SSE_REG_P (operands[0]))"
[(set (match_dup 3) (match_dup 1))
(set (match_dup 4) (const_int 0))]
"split_di (&operands[0], 1, &operands[3], &operands[4]);")
""
[(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2)))
(set (mem:XF (reg:P SP_REG)) (float_extend:XF (match_dup 1)))]
- "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
+ "operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
""
[(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2)))
(set (mem:DF (reg:P SP_REG)) (float_extend:XF (match_dup 1)))]
- "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
+ "operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));")
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(set (match_operand:SSEMODEI24 2 "register_operand" "")
(fix:SSEMODEI24 (match_dup 0)))]
"TARGET_SHORTEN_X87_SSE
+ && !(TARGET_AVOID_VECTOR_DECODE && optimize_insn_for_speed_p ())
&& peep2_reg_dead_p (2, operands[0])"
[(set (match_dup 2) (fix:SSEMODEI24 (match_dup 1)))]
"")
(compare:CCC
(plus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "%0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>m"))
+ (match_operand:SWI 2 "<general_operand>" "<g>"))
(match_dup 1)))
(clobber (match_scratch:SWI 0 "=<r>"))]
"ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
\f
;; Divide instructions
-(define_insn "<u>divqi3"
- [(set (match_operand:QI 0 "register_operand" "=a")
- (any_div:QI
- (match_operand:HI 1 "register_operand" "0")
- (match_operand:QI 2 "nonimmediate_operand" "qm")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_QIMODE_MATH"
- "<sgnprefix>div{b}\t%2"
- [(set_attr "type" "idiv")
- (set_attr "mode" "QI")])
-
;; The patterns that match these are at the end of this file.
(define_expand "divxf3"
"(TARGET_80387 && X87_ENABLE_ARITH (SFmode))
|| TARGET_SSE_MATH"
{
- if (TARGET_SSE_MATH && TARGET_RECIP && optimize_insn_for_speed_p ()
- && flag_finite_math_only && !flag_trapping_math
- && flag_unsafe_math_optimizations)
- {
- ix86_emit_swdivsf (operands[0], operands[1],
- operands[2], SFmode);
- DONE;
- }
+ if (TARGET_SSE_MATH && TARGET_RECIP && optimize_insn_for_speed_p ()
+ && flag_finite_math_only && !flag_trapping_math
+ && flag_unsafe_math_optimizations)
+ {
+ ix86_emit_swdivsf (operands[0], operands[1],
+ operands[2], SFmode);
+ DONE;
+ }
+})
+\f
+;; Divmod instructions.
+
+(define_expand "divmodqi4"
+ [(parallel [(set (match_operand:QI 0 "register_operand" "")
+ (div:QI
+ (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nonimmediate_operand" "")))
+ (set (match_operand:QI 3 "register_operand" "")
+ (mod:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_QIMODE_MATH"
+{
+ rtx div, mod, insn;
+ rtx tmp0, tmp1;
+
+ tmp0 = gen_reg_rtx (HImode);
+ tmp1 = gen_reg_rtx (HImode);
+
+ /* Extend operands[1] to HImode. Generate 8bit divide. Result is
+ in AX. */
+ emit_insn (gen_extendqihi2 (tmp1, operands[1]));
+ emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2]));
+
+ /* Extract remainder from AH. */
+ tmp1 = gen_rtx_SIGN_EXTRACT (QImode, tmp0, GEN_INT (8), GEN_INT (8));
+ insn = emit_move_insn (operands[3], tmp1);
+
+ mod = gen_rtx_MOD (QImode, operands[1], operands[2]);
+ set_unique_reg_note (insn, REG_EQUAL, mod);
+
+ /* Extract quotient from AL. */
+ insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0));
+
+ div = gen_rtx_DIV (QImode, operands[1], operands[2]);
+ set_unique_reg_note (insn, REG_EQUAL, div);
+
+ DONE;
+})
+
+(define_expand "udivmodqi4"
+ [(parallel [(set (match_operand:QI 0 "register_operand" "")
+ (udiv:QI
+ (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nonimmediate_operand" "")))
+ (set (match_operand:QI 3 "register_operand" "")
+ (umod:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_QIMODE_MATH"
+{
+ rtx div, mod, insn;
+ rtx tmp0, tmp1;
+
+ tmp0 = gen_reg_rtx (HImode);
+ tmp1 = gen_reg_rtx (HImode);
+
+ /* Extend operands[1] to HImode. Generate 8bit divide. Result is
+ in AX. */
+ emit_insn (gen_zero_extendqihi2 (tmp1, operands[1]));
+ emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, operands[2]));
+
+ /* Extract remainder from AH. */
+ tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
+ tmp1 = simplify_gen_subreg (QImode, tmp1, SImode, 0);
+ insn = emit_move_insn (operands[3], tmp1);
+
+ mod = gen_rtx_UMOD (QImode, operands[1], operands[2]);
+ set_unique_reg_note (insn, REG_EQUAL, mod);
+
+ /* Extract quotient from AL. */
+ insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0));
+
+ div = gen_rtx_UDIV (QImode, operands[1], operands[2]);
+ set_unique_reg_note (insn, REG_EQUAL, div);
+
+ DONE;
})
-\f
-;; Divmod instructions.
+
+;; Divide AX by r/m8, with result stored in
+;; AL <- Quotient
+;; AH <- Remainder
+;; Change div/mod to HImode and extend the second argument to HImode
+;; so that mode of div/mod matches with mode of arguments. Otherwise
+;; combine may fail.
+(define_insn "divmodhiqi3"
+ [(set (match_operand:HI 0 "register_operand" "=a")
+ (ior:HI
+ (ashift:HI
+ (zero_extend:HI
+ (truncate:QI
+ (mod:HI (match_operand:HI 1 "register_operand" "0")
+ (sign_extend:HI
+ (match_operand:QI 2 "nonimmediate_operand" "qm")))))
+ (const_int 8))
+ (zero_extend:HI
+ (truncate:QI
+ (div:HI (match_dup 1) (sign_extend:HI (match_dup 2)))))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_QIMODE_MATH"
+ "idiv{b}\t%2"
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "QI")])
+
+(define_insn "udivmodhiqi3"
+ [(set (match_operand:HI 0 "register_operand" "=a")
+ (ior:HI
+ (ashift:HI
+ (zero_extend:HI
+ (truncate:QI
+ (mod:HI (match_operand:HI 1 "register_operand" "0")
+ (zero_extend:HI
+ (match_operand:QI 2 "nonimmediate_operand" "qm")))))
+ (const_int 8))
+ (zero_extend:HI
+ (truncate:QI
+ (div:HI (match_dup 1) (zero_extend:HI (match_dup 2)))))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_QIMODE_MATH"
+ "div{b}\t%2"
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "QI")])
(define_expand "divmod<mode>4"
[(parallel [(set (match_operand:SWIM248 0 "register_operand" "")
"TARGET_64BIT && reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(set (match_dup 0)
- (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))]
+ (zero_extend:DI (subreg:SI (mult:DI (match_dup 1) (match_dup 2)) 0)))]
{
operands[1] = gen_lowpart (Pmode, operands[1]);
operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
(match_operand 3 "register_operand" ""))]
""
{
+ rtx (*gen_mov_insv_1) (rtx, rtx);
+
/* Handle insertions to %ah et al. */
if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
FAIL;
if (! ext_register_operand (operands[0], VOIDmode))
FAIL;
- if (TARGET_64BIT)
- emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3]));
- else
- emit_insn (gen_movsi_insv_1 (operands[0], operands[3]));
+ gen_mov_insv_1 = (TARGET_64BIT
+ ? gen_movdi_insv_1 : gen_movsi_insv_1);
+ emit_insn (gen_mov_insv_1 (operands[0], operands[3]));
DONE;
})
;; Define combination compare-and-branch fp compare instructions to help
;; combine.
-(define_insn "*fp_jcc_3_387"
+(define_insn "*fp_jcc_1_387"
[(set (pc)
(if_then_else (match_operator 0 "ix86_fp_comparison_operator"
[(match_operand 1 "register_operand" "f")
&& !TARGET_CMOVE"
"#")
-(define_insn "*fp_jcc_4_387"
+(define_insn "*fp_jcc_1r_387"
[(set (pc)
(if_then_else (match_operator 0 "ix86_fp_comparison_operator"
[(match_operand 1 "register_operand" "f")
&& !TARGET_CMOVE"
"#")
-(define_insn "*fp_jcc_5_387"
+(define_insn "*fp_jcc_2_387"
[(set (pc)
(if_then_else (match_operator 0 "ix86_fp_comparison_operator"
[(match_operand 1 "register_operand" "f")
&& !TARGET_CMOVE"
"#")
-(define_insn "*fp_jcc_6_387"
+(define_insn "*fp_jcc_2r_387"
[(set (pc)
(if_then_else (match_operator 0 "ix86_fp_comparison_operator"
[(match_operand 1 "register_operand" "f")
&& !TARGET_CMOVE"
"#")
-(define_insn "*fp_jcc_7_387"
+(define_insn "*fp_jcc_3_387"
[(set (pc)
(if_then_else (match_operator 0 "ix86_fp_comparison_operator"
[(match_operand 1 "register_operand" "f")
&& !TARGET_CMOVE"
"#")
-;; 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 "ix86_fp_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"))]
- "X87_FLOAT_MODE_P (GET_MODE (operands[3]))
- && (TARGET_USE_<MODE>MODE_FIOP || optimize_function_for_size_p (cfun))
- && GET_MODE (operands[1]) == GET_MODE (operands[3])
- && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
- && !TARGET_CMOVE"
- "#")
-
(define_split
[(set (pc)
(if_then_else (match_operator 0 "ix86_fp_comparison_operator"
DONE;
})
+;; The order of operands in *fp_jcc_4_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_4_<mode>_387"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "ix86_swapped_fp_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"))]
+ "X87_FLOAT_MODE_P (GET_MODE (operands[3]))
+ && (TARGET_USE_<MODE>MODE_FIOP || optimize_function_for_size_p (cfun))
+ && GET_MODE (operands[1]) == GET_MODE (operands[3])
+ && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
+ && !TARGET_CMOVE"
+ "#")
+
(define_split
[(set (pc)
- (if_then_else (match_operator 0 "ix86_fp_comparison_operator"
- [(match_operator 1 "float_operator"
- [(match_operand:X87MODEI12 2 "memory_operand" "")])
- (match_operand 3 "register_operand" "")])
+ (if_then_else
+ (match_operator 0 "ix86_swapped_fp_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))
;; %%% Kill this when reload knows how to do it.
(define_split
[(set (pc)
- (if_then_else (match_operator 0 "ix86_fp_comparison_operator"
- [(match_operator 1 "float_operator"
- [(match_operand:X87MODEI12 2 "register_operand" "")])
- (match_operand 3 "register_operand" "")])
+ (if_then_else
+ (match_operator 0 "ix86_swapped_fp_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))
(define_insn_and_split "paritydi2_cmp"
[(set (reg:CC FLAGS_REG)
- (parity:CC (match_operand:DI 3 "register_operand" "0")))
+ (unspec:CC [(match_operand:DI 3 "register_operand" "0")]
+ UNSPEC_PARITY))
(clobber (match_scratch:DI 0 "=r"))
(clobber (match_scratch:SI 1 "=&r"))
(clobber (match_scratch:HI 2 "=Q"))]
(clobber (reg:CC FLAGS_REG))])
(parallel
[(set (reg:CC FLAGS_REG)
- (parity:CC (match_dup 1)))
+ (unspec:CC [(match_dup 1)] UNSPEC_PARITY))
(clobber (match_dup 1))
(clobber (match_dup 2))])]
{
(define_insn_and_split "paritysi2_cmp"
[(set (reg:CC FLAGS_REG)
- (parity:CC (match_operand:SI 2 "register_operand" "0")))
+ (unspec:CC [(match_operand:SI 2 "register_operand" "0")]
+ UNSPEC_PARITY))
(clobber (match_scratch:SI 0 "=r"))
(clobber (match_scratch:HI 1 "=&Q"))]
"! TARGET_POPCNT"
(clobber (reg:CC FLAGS_REG))])
(parallel
[(set (reg:CC FLAGS_REG)
- (parity:CC (match_dup 1)))
+ (unspec:CC [(match_dup 1)] UNSPEC_PARITY))
(clobber (match_dup 1))])]
{
operands[3] = gen_lowpart (HImode, operands[2]);
(define_insn "*parityhi2_cmp"
[(set (reg:CC FLAGS_REG)
- (parity:CC (match_operand:HI 1 "register_operand" "0")))
+ (unspec:CC [(match_operand:HI 1 "register_operand" "0")]
+ UNSPEC_PARITY))
(clobber (match_scratch:HI 0 "=Q"))]
"! TARGET_POPCNT"
"xor{b}\t{%h0, %b0|%b0, %h0}"
[(set_attr "length" "2")
(set_attr "mode" "HI")])
-
-(define_insn "*parityqi2_cmp"
- [(set (reg:CC FLAGS_REG)
- (parity:CC (match_operand:QI 0 "register_operand" "q")))]
- "! TARGET_POPCNT"
- "test{b}\t%0, %0"
- [(set_attr "length" "2")
- (set_attr "mode" "QI")])
\f
;; Thread-local storage patterns for ELF.
;;
(use (match_operand:MODEF 2 "general_operand" ""))]
"TARGET_USE_FANCY_MATH_387"
{
+ rtx (*gen_truncxf) (rtx, rtx);
+
rtx label = gen_label_rtx ();
rtx op1 = gen_reg_rtx (XFmode);
/* Truncate the result properly for strict SSE math. */
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
&& !TARGET_MIX_SSE_I387)
- emit_insn (gen_truncxf<mode>2 (operands[0], op1));
+ gen_truncxf = gen_truncxf<mode>2;
else
- emit_insn (gen_truncxf<mode>2_i387_noop_unspec (operands[0], op1));
+ gen_truncxf = gen_truncxf<mode>2_i387_noop_unspec;
+ emit_insn (gen_truncxf (operands[0], op1));
DONE;
})
(use (match_operand:MODEF 2 "general_operand" ""))]
"TARGET_USE_FANCY_MATH_387"
{
+ rtx (*gen_truncxf) (rtx, rtx);
+
rtx label = gen_label_rtx ();
rtx op1 = gen_reg_rtx (XFmode);
/* Truncate the result properly for strict SSE math. */
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
&& !TARGET_MIX_SSE_I387)
- emit_insn (gen_truncxf<mode>2 (operands[0], op1));
+ gen_truncxf = gen_truncxf<mode>2;
else
- emit_insn (gen_truncxf<mode>2_i387_noop_unspec (operands[0], op1));
+ gen_truncxf = gen_truncxf<mode>2_i387_noop_unspec;
+ emit_insn (gen_truncxf (operands[0], op1));
DONE;
})
}
else
{
- rtx (*cmp_insn)(rtx, rtx);
+ rtx (*gen_cmp) (rtx, rtx);
- if (TARGET_64BIT)
- cmp_insn = gen_cmpdi_1;
- else
- cmp_insn = gen_cmpsi_1;
- emit_insn (cmp_insn (countreg, countreg));
+ gen_cmp = (TARGET_64BIT
+ ? gen_cmpdi_1 : gen_cmpsi_1);
+
+ emit_insn (gen_cmp (countreg, countreg));
emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
operands[1], operands[2]));
}
;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
;;
;; in proper program order.
-(define_insn "pro_epilogue_adjust_stack_1"
- [(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 FLAGS_REG))
- (clobber (mem:BLK (scratch)))]
- "!TARGET_64BIT"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_IMOV:
- return "mov{l}\t{%1, %0|%0, %1}";
- case TYPE_ALU:
- if (CONST_INT_P (operands[2])
- && (INTVAL (operands[2]) == 128
- || (INTVAL (operands[2]) < 0
- && INTVAL (operands[2]) != -128)))
- {
- operands[2] = GEN_INT (-INTVAL (operands[2]));
- return "sub{l}\t{%2, %0|%0, %2}";
- }
- return "add{l}\t{%2, %0|%0, %2}";
-
- case TYPE_LEA:
- operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
- return "lea{l}\t{%a2, %0|%0, %a2}";
-
- default:
- gcc_unreachable ();
- }
-}
- [(set (attr "type")
- (cond [(and (eq_attr "alternative" "0")
- (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
- (const_string "alu")
- (match_operand:SI 2 "const0_operand" "")
- (const_string "imov")
- ]
- (const_string "lea")))
- (set (attr "length_immediate")
- (cond [(eq_attr "type" "imov")
- (const_string "0")
- (and (eq_attr "type" "alu")
- (match_operand 2 "const128_operand" ""))
- (const_string "1")
- ]
- (const_string "*")))
- (set_attr "mode" "SI")])
-
-(define_insn "pro_epilogue_adjust_stack_rex64"
- [(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")))
+(define_insn "pro_epilogue_adjust_stack_<mode>_1"
+ [(set (match_operand:P 0 "register_operand" "=r,r")
+ (plus:P (match_operand:P 1 "register_operand" "0,r")
+ (match_operand:P 2 "<immediate_operand>" "<i>,<i>")))
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))]
- "TARGET_64BIT"
+ ""
{
switch (get_attr_type (insn))
{
case TYPE_IMOV:
- return "mov{q}\t{%1, %0|%0, %1}";
+ return "mov{<imodesuffix>}\t{%1, %0|%0, %1}";
case TYPE_ALU:
- if (CONST_INT_P (operands[2])
- /* Avoid overflows. */
- && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))
- && (INTVAL (operands[2]) == 128
- || (INTVAL (operands[2]) < 0
- && INTVAL (operands[2]) != -128)))
- {
- operands[2] = GEN_INT (-INTVAL (operands[2]));
- return "sub{q}\t{%2, %0|%0, %2}";
- }
- return "add{q}\t{%2, %0|%0, %2}";
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
+ if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
+ return "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
- case TYPE_LEA:
- operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
- return "lea{q}\t{%a2, %0|%0, %a2}";
+ return "add{<imodesuffix>}\t{%2, %0|%0, %2}";
default:
- gcc_unreachable ();
+ operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+ return "lea{<imodesuffix>}\t{%a2, %0|%0, %a2}";
}
}
[(set (attr "type")
(cond [(and (eq_attr "alternative" "0")
- (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
(const_string "alu")
- (match_operand:DI 2 "const0_operand" "")
+ (match_operand:<MODE> 2 "const0_operand" "")
(const_string "imov")
]
(const_string "lea")))
(const_string "1")
]
(const_string "*")))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "pro_epilogue_adjust_stack_rex64_2"
+(define_insn "pro_epilogue_adjust_stack_di_2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(plus:DI (match_operand:DI 1 "register_operand" "0,r")
(match_operand:DI 3 "immediate_operand" "i,i")))
UNSPECV_STACK_PROBE))
(set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 1)))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT && TARGET_STACK_PROBE"
+ "!TARGET_64BIT && ix86_target_stack_probe ()"
"call\t___chkstk"
[(set_attr "type" "multi")
(set_attr "length" "5")])
(clobber (reg:DI R10_REG))
(clobber (reg:DI R11_REG))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && TARGET_STACK_PROBE"
+ "TARGET_64BIT && ix86_target_stack_probe ()"
"call\t___chkstk"
[(set_attr "type" "multi")
(set_attr "length" "5")])
(define_expand "allocate_stack"
[(match_operand 0 "register_operand" "")
(match_operand 1 "general_operand" "")]
- "TARGET_STACK_PROBE"
+ "ix86_target_stack_probe ()"
{
rtx x;
}
else
{
- x = copy_to_mode_reg (Pmode, operands[1]);
+ rtx (*gen_allocate_stack_worker) (rtx, rtx);
+
if (TARGET_64BIT)
- x = gen_allocate_stack_worker_64 (x, x);
+ gen_allocate_stack_worker = gen_allocate_stack_worker_64;
else
- x = gen_allocate_stack_worker_32 (x, x);
- emit_insn (x);
+ gen_allocate_stack_worker = gen_allocate_stack_worker_32;
+
+ x = copy_to_mode_reg (Pmode, operands[1]);
+ emit_insn (gen_allocate_stack_worker (x, x));
}
emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
[(match_operand 0 "memory_operand" "")]
""
{
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_iordi3 (operands[0], operands[0], const0_rtx));
- else
- emit_insn (gen_iorsi3 (operands[0], operands[0], const0_rtx));
+ rtx (*gen_ior3) (rtx, rtx, rtx);
+
+ gen_ior3 = (GET_MODE (operands[0]) == DImode
+ ? gen_iordi3 : gen_iorsi3);
+
+ emit_insn (gen_ior3 (operands[0], operands[0], const0_rtx));
DONE;
})
+(define_insn "adjust_stack_and_probe<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")]
+ UNSPECV_PROBE_STACK_RANGE))
+ (set (reg:P SP_REG)
+ (minus:P (reg:P SP_REG) (match_operand:P 2 "const_int_operand" "n")))
+ (clobber (reg:CC FLAGS_REG))
+ (clobber (mem:BLK (scratch)))]
+ ""
+ "* return output_adjust_stack_and_probe (operands[0]);"
+ [(set_attr "type" "multi")])
+
+(define_insn "probe_stack_range<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
+ (match_operand:P 2 "const_int_operand" "n")]
+ UNSPECV_PROBE_STACK_RANGE))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "* return output_probe_stack_range (operands[0], operands[2]);"
+ [(set_attr "type" "multi")])
+
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"!TARGET_64BIT && flag_pic"
[(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); })
+ "operands[2] = GEN_INT (INTVAL (operands[2]) - 1);")
(define_peephole2
[(parallel
(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); })
+ "operands[2] = GEN_INT (INTVAL (operands[2]) - 1);")
(define_peephole2
[(parallel
[(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); })
+ "operands[2] = GEN_INT (INTVAL (operands[2]) - 1);")
(define_peephole2
[(parallel
(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); })
+ "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.
[(set (match_dup 3) (match_dup 1))
(parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
-"")
+ "")
(define_peephole2
[(match_scratch:SI 3 "r")
[(set (match_dup 3) (match_dup 1))
(parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
-"")
+ "")
(define_peephole2
[(match_scratch:SI 3 "r")
"TARGET_SLOW_IMUL_IMM32_MEM && optimize_insn_for_speed_p ()
&& !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))))
+ (parallel [(set (match_dup 0)
+ (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
(clobber (reg:CC FLAGS_REG))])]
-"")
+ "")
;; imul $8/16bit_imm, regmem, reg is vector decoded.
;; Convert it into imul reg, reg
;; leal (%edx,%eax,4), %eax
(define_peephole2
- [(parallel [(set (match_operand 0 "register_operand" "")
+ [(match_scratch:P 5 "r")
+ (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" "")))
+ (parallel [(set (match_operand 3 "register_operand" "")
+ (plus (match_dup 0)
+ (match_operand 4 "x86_64_general_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
/* Validate MODE for lea. */
|| GET_MODE (operands[0]) == HImode))
|| GET_MODE (operands[0]) == SImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
+ && (rtx_equal_p (operands[0], operands[3])
+ || peep2_reg_dead_p (2, operands[0]))
/* 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))
+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
+ [(set (match_dup 5) (match_dup 4))
(set (match_dup 0) (match_dup 1))]
{
- enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
+ enum machine_mode mode = GET_MODE (operands[1]) == 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]);
+ rtx base = gen_lowpart (Pmode, operands[5]);
+ rtx dest = gen_lowpart (mode, operands[3]);
operands[1] = gen_rtx_PLUS (Pmode, base,
gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
+ operands[5] = base;
if (mode != Pmode)
- operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
+ {
+ operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
+ operands[5] = gen_rtx_SUBREG (mode, operands[5], 0);
+ }
operands[0] = dest;
})
\f
{ return ASM_SHORT "0x0b0f"; }
[(set_attr "length" "2")])
-(define_expand "sse_prologue_save"
- [(parallel [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(reg:DI XMM0_REG)
- (reg:DI XMM1_REG)
- (reg:DI XMM2_REG)
- (reg:DI XMM3_REG)
- (reg:DI XMM4_REG)
- (reg:DI XMM5_REG)
- (reg:DI XMM6_REG)
- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE))
- (clobber (reg:CC FLAGS_REG))
- (clobber (match_operand:DI 1 "register_operand" ""))
- (use (match_operand:DI 2 "immediate_operand" ""))
- (use (label_ref:DI (match_operand 3 "" "")))
- (clobber (match_operand:DI 4 "register_operand" ""))
- (use (match_dup 1))])]
- "TARGET_64BIT"
- "")
-
-;; Pre-reload version of prologue save. Until after prologue generation we don't know
-;; what the size of save instruction will be.
-;; Operand 0+operand 6 is the memory save area
-;; Operand 1 is number of registers to save (will get overwritten to operand 5)
-;; Operand 2 is number of non-vaargs SSE arguments
-;; Operand 3 is label starting the save block
-;; Operand 4 is used for temporary computation of jump address
-(define_insn "*sse_prologue_save_insn1"
- [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
- (match_operand:DI 6 "const_int_operand" "n")))
- (unspec:BLK [(reg:DI XMM0_REG)
- (reg:DI XMM1_REG)
- (reg:DI XMM2_REG)
- (reg:DI XMM3_REG)
- (reg:DI XMM4_REG)
- (reg:DI XMM5_REG)
- (reg:DI XMM6_REG)
- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE))
- (clobber (reg:CC FLAGS_REG))
- (clobber (match_operand:DI 1 "register_operand" "=r"))
- (use (match_operand:DI 2 "const_int_operand" "i"))
- (use (label_ref:DI (match_operand 3 "" "X")))
- (clobber (match_operand:DI 4 "register_operand" "=&r"))
- (use (match_operand:DI 5 "register_operand" "1"))]
- "TARGET_64BIT
- && INTVAL (operands[6]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128
- && INTVAL (operands[6]) + INTVAL (operands[2]) * 16 >= -128"
- "#"
- [(set_attr "type" "other")
- (set_attr "memory" "store")
- (set_attr "mode" "DI")])
-
-;; We know size of save instruction; expand the computation of jump address
-;; in the jumptable.
-(define_split
- [(parallel [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(reg:DI XMM0_REG)
- (reg:DI XMM1_REG)
- (reg:DI XMM2_REG)
- (reg:DI XMM3_REG)
- (reg:DI XMM4_REG)
- (reg:DI XMM5_REG)
- (reg:DI XMM6_REG)
- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE))
- (clobber (reg:CC FLAGS_REG))
- (clobber (match_operand:DI 1 "register_operand" ""))
- (use (match_operand:DI 2 "const_int_operand" ""))
- (use (match_operand 3 "" ""))
- (clobber (match_operand:DI 4 "register_operand" ""))
- (use (match_operand:DI 5 "register_operand" ""))])]
- "reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:BLK [(reg:DI XMM0_REG)
- (reg:DI XMM1_REG)
- (reg:DI XMM2_REG)
- (reg:DI XMM3_REG)
- (reg:DI XMM4_REG)
- (reg:DI XMM5_REG)
- (reg:DI XMM6_REG)
- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE_LOW))
- (use (match_dup 1))
- (use (match_dup 2))
- (use (match_dup 3))
- (use (match_dup 5))])]
-{
- /* Movaps is 4 bytes, AVX and movsd is 5 bytes. */
- int size = 4 + (TARGET_AVX || crtl->stack_alignment_needed < 128);
-
- /* Compute address to jump to:
- label - eax*size + nnamed_sse_arguments*size. */
- if (size == 5)
- emit_insn (gen_rtx_SET (VOIDmode, operands[4],
- gen_rtx_PLUS
- (Pmode,
- gen_rtx_MULT (Pmode, operands[1],
- GEN_INT (4)),
- operands[1])));
- else if (size == 4)
- emit_insn (gen_rtx_SET (VOIDmode, operands[4],
- gen_rtx_MULT (Pmode, operands[1],
- GEN_INT (4))));
- else
- gcc_unreachable ();
- if (INTVAL (operands[2]))
- emit_move_insn
- (operands[1],
- gen_rtx_CONST (DImode,
- gen_rtx_PLUS (DImode,
- operands[3],
- GEN_INT (INTVAL (operands[2])
- * size))));
- else
- emit_move_insn (operands[1], operands[3]);
- emit_insn (gen_subdi3 (operands[1], operands[1], operands[4]));
- operands[5] = GEN_INT (size);
-})
-
-(define_insn "sse_prologue_save_insn"
- [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
- (match_operand:DI 4 "const_int_operand" "n")))
- (unspec:BLK [(reg:DI XMM0_REG)
- (reg:DI XMM1_REG)
- (reg:DI XMM2_REG)
- (reg:DI XMM3_REG)
- (reg:DI XMM4_REG)
- (reg:DI XMM5_REG)
- (reg:DI XMM6_REG)
- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE_LOW))
- (use (match_operand:DI 1 "register_operand" "r"))
- (use (match_operand:DI 2 "const_int_operand" "i"))
- (use (label_ref:DI (match_operand 3 "" "X")))
- (use (match_operand:DI 5 "const_int_operand" "i"))]
- "TARGET_64BIT
- && INTVAL (operands[4]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128
- && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128"
-{
- int i;
- operands[0] = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, operands[0], operands[4]));
- /* VEX instruction with a REX prefix will #UD. */
- if (TARGET_AVX && GET_CODE (XEXP (operands[0], 0)) != PLUS)
- gcc_unreachable ();
-
- output_asm_insn ("jmp\t%A1", operands);
- for (i = X86_64_SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--)
- {
- operands[4] = adjust_address (operands[0], DImode, i*16);
- operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i));
- PUT_MODE (operands[4], TImode);
- if (GET_CODE (XEXP (operands[0], 0)) != PLUS)
- output_asm_insn ("rex", operands);
- if (crtl->stack_alignment_needed < 128)
- output_asm_insn ("%vmovsd\t{%5, %4|%4, %5}", operands);
- else
- output_asm_insn ("%vmovaps\t{%5, %4|%4, %5}", operands);
- }
- (*targetm.asm_out.internal_label) (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[3]));
- return "";
-}
- [(set_attr "type" "other")
- (set_attr "length_immediate" "0")
- (set_attr "length_address" "0")
- ;; 2 bytes for jump and opernds[4] bytes for each save.
- (set (attr "length")
- (plus (const_int 2)
- (mult (symbol_ref ("INTVAL (operands[5])"))
- (symbol_ref ("X86_64_SSE_REGPARM_MAX - INTVAL (operands[2])")))))
- (set_attr "memory" "store")
- (set_attr "modrm" "0")
- (set_attr "prefix" "maybe_vex")
- (set_attr "mode" "DI")])
-
(define_expand "prefetch"
[(prefetch (match_operand 0 "address_operand" "")
(match_operand:SI 1 "const_int_operand" "")
operands[1] = const0_rtx;
})
-(define_insn "*prefetch_sse"
- [(prefetch (match_operand:SI 0 "address_operand" "p")
- (const_int 0)
- (match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_PREFETCH_SSE && !TARGET_64BIT"
-{
- static const char * const patterns[4] = {
- "prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
- };
-
- int locality = INTVAL (operands[1]);
- gcc_assert (locality >= 0 && locality <= 3);
-
- return patterns[locality];
-}
- [(set_attr "type" "sse")
- (set_attr "atom_sse_attr" "prefetch")
- (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
- (set_attr "memory" "none")])
-
-(define_insn "*prefetch_sse_rex"
- [(prefetch (match_operand:DI 0 "address_operand" "p")
+(define_insn "*prefetch_sse_<mode>"
+ [(prefetch (match_operand:P 0 "address_operand" "p")
(const_int 0)
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_PREFETCH_SSE && TARGET_64BIT"
+ "TARGET_PREFETCH_SSE"
{
static const char * const patterns[4] = {
"prefetchnta\t%a0", "prefetcht2\t%a0", "prefetcht1\t%a0", "prefetcht0\t%a0"
}
[(set_attr "type" "sse")
(set_attr "atom_sse_attr" "prefetch")
- (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
- (set_attr "memory" "none")])
-
-(define_insn "*prefetch_3dnow"
- [(prefetch (match_operand:SI 0 "address_operand" "p")
- (match_operand:SI 1 "const_int_operand" "n")
- (const_int 3))]
- "TARGET_3DNOW && !TARGET_64BIT"
-{
- if (INTVAL (operands[1]) == 0)
- return "prefetch\t%a0";
- else
- return "prefetchw\t%a0";
-}
- [(set_attr "type" "mmx")
- (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
+ (set (attr "length_address")
+ (symbol_ref "memory_address_length (operands[0])"))
(set_attr "memory" "none")])
-(define_insn "*prefetch_3dnow_rex"
- [(prefetch (match_operand:DI 0 "address_operand" "p")
+(define_insn "*prefetch_3dnow_<mode>"
+ [(prefetch (match_operand:P 0 "address_operand" "p")
(match_operand:SI 1 "const_int_operand" "n")
(const_int 3))]
- "TARGET_3DNOW && TARGET_64BIT"
+ "TARGET_3DNOW"
{
if (INTVAL (operands[1]) == 0)
return "prefetch\t%a0";
return "prefetchw\t%a0";
}
[(set_attr "type" "mmx")
- (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
+ (set (attr "length_address")
+ (symbol_ref "memory_address_length (operands[0])"))
(set_attr "memory" "none")])
(define_expand "stack_protect_set"
(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))
+ (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))]
""
(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))
+ (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"
(set (attr "length")
(symbol_ref "ix86_attr_length_address_default (insn) + 9"))])
+(define_insn "rdfsbase<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec_volatile:SWI48 [(const_int 0)] UNSPECV_RDFSBASE))]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "rdfsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "rdgsbase<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec_volatile:SWI48 [(const_int 0)] UNSPECV_RDGSBASE))]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "rdgsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "wrfsbase<mode>"
+ [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
+ UNSPECV_WRFSBASE)]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "wrfsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "wrgsbase<mode>"
+ [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
+ UNSPECV_WRGSBASE)]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "wrgsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_expand "rdrand<mode>"
+ [(set (match_operand:SWI248 0 "register_operand" "=r")
+ (unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))]
+ "TARGET_RDRND"
+{
+ rtx retry_label, insn, ccc;
+
+ retry_label = gen_label_rtx ();
+
+ emit_label (retry_label);
+
+ /* Generate rdrand. */
+ emit_insn (gen_rdrand<mode>_1 (operands[0]));
+
+ /* Retry if the carry flag isn't valid. */
+ ccc = gen_rtx_REG (CCCmode, FLAGS_REG);
+ ccc = gen_rtx_EQ (VOIDmode, ccc, const0_rtx);
+ ccc = gen_rtx_IF_THEN_ELSE (VOIDmode, ccc, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, retry_label));
+ insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, ccc));
+ JUMP_LABEL (insn) = retry_label;
+
+ DONE;
+})
+
+(define_insn "rdrand<mode>_1"
+ [(set (match_operand:SWI248 0 "register_operand" "=r")
+ (unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))]
+ "TARGET_RDRND"
+ "rdrand %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "1")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")