X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fconfig%2Fi386%2Fi386.md;h=c245a49fd3f4ee40bb09818e58f0ab310202ef59;hp=849ca830ebafd0b3a0bda2b084714e851a0f9384;hb=6c24dca6125225d09ddbb06bbf31a49e4ff5c88c;hpb=79959616093d981c7c71a6ab16493a0b3c707257
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 849ca830eba..c245a49fd3f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1,6 +1,6 @@
;; GCC machine description for IA-32 and x86-64.
;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
@@ -9,7 +9,7 @@
;;
;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; GCC is distributed in the hope that it will be useful,
@@ -18,9 +18,8 @@
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA. */
+;; along with GCC; see the file COPYING3. If not see
+;; . */
;;
;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
@@ -96,7 +95,6 @@
(UNSPEC_RCP 45)
(UNSPEC_RSQRT 46)
(UNSPEC_SFENCE 47)
- (UNSPEC_NOP 48) ; prevents combiner cleverness
(UNSPEC_PFRCP 49)
(UNSPEC_PFRCPIT1 40)
(UNSPEC_PFRCPIT2 41)
@@ -159,9 +157,44 @@
; For SSE4A support
(UNSPEC_EXTRQI 130)
- (UNSPEC_EXTRQ 131)
+ (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 SSE5
+ (UNSPEC_SSE5_INTRINSIC 150)
+ (UNSPEC_SSE5_UNSIGNED_CMP 151)
+ (UNSPEC_SSE5_TRUEFALSE 152)
+ (UNSPEC_SSE5_PERMUTE 153)
+ (UNSPEC_FRCZ 154)
+ (UNSPEC_CVTPH2PS 155)
+ (UNSPEC_CVTPS2PH 156)
+
+ ; 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)
])
(define_constants
@@ -179,11 +212,42 @@
(UNSPECV_CMPXCHG_2 11)
(UNSPECV_XCHG 12)
(UNSPECV_LOCK 13)
+ (UNSPECV_PROLOGUE_USE 14)
+ (UNSPECV_CLD 15)
+ ])
+
+;; Constants to represent pcomtrue/pcomfalse variants
+(define_constants
+ [(PCOM_FALSE 0)
+ (PCOM_TRUE 1)
+ (COM_FALSE_S 2)
+ (COM_FALSE_P 3)
+ (COM_TRUE_S 4)
+ (COM_TRUE_P 5)
])
+;; Constants used in the SSE5 pperm instruction
+(define_constants
+ [(PPERM_SRC 0x00) /* copy source */
+ (PPERM_INVERT 0x20) /* invert source */
+ (PPERM_REVERSE 0x40) /* bit reverse source */
+ (PPERM_REV_INV 0x60) /* bit reverse & invert src */
+ (PPERM_ZERO 0x80) /* all 0's */
+ (PPERM_ONES 0xa0) /* all 1's */
+ (PPERM_SIGN 0xc0) /* propagate sign bit */
+ (PPERM_INV_SIGN 0xe0) /* invert & propagate sign */
+ (PPERM_SRC1 0x00) /* use first source byte */
+ (PPERM_SRC2 0x10) /* use second source byte */
+ ])
+
;; Registers by name.
(define_constants
- [(BP_REG 6)
+ [(AX_REG 0)
+ (DX_REG 1)
+ (CX_REG 2)
+ (SI_REG 4)
+ (DI_REG 5)
+ (BP_REG 6)
(SP_REG 7)
(FLAGS_REG 17)
(FPSR_REG 18)
@@ -217,8 +281,9 @@
push,pop,call,callv,leave,
str,bitmanip,
fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
- sselog,sselog1,sseiadd,sseishft,sseimul,
- sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins,
+ sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+ sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,ssediv,sseins,
+ ssemuladd,sse4arg,
mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
(const_string "other"))
@@ -231,8 +296,9 @@
(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,sseishft,sseimul,
- sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins")
+ (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+ sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,
+ ssecvt1,sseicvt,ssediv,sseins,ssemuladd,sse4arg")
(const_string "sse")
(eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
(const_string "mmx")
@@ -317,6 +383,9 @@
]
(const_int 0)))
+;; There are also additional prefixes in SSSE3.
+(define_attr "prefix_extra" "" (const_int 0))
+
;; Set when modrm byte is used.
(define_attr "modrm" ""
(cond [(eq_attr "type" "str,leave")
@@ -366,7 +435,8 @@
(plus (plus (attr "modrm")
(plus (attr "prefix_0f")
(plus (attr "prefix_rex")
- (const_int 1))))
+ (plus (attr "prefix_extra")
+ (const_int 1)))))
(plus (attr "prefix_rep")
(plus (attr "prefix_data16")
(plus (attr "length_immediate")
@@ -428,11 +498,11 @@
"!alu1,negnot,ishift1,
imov,imovx,icmp,test,bitmanip,
fmov,fcmp,fsgn,
- sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
- mmx,mmxmov,mmxcmp,mmxcvt")
+ sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,sselog1,
+ sseiadd1,mmx,mmxmov,mmxcmp,mmxcvt")
(match_operand 2 "memory_operand" ""))
(const_string "load")
- (and (eq_attr "type" "icmov")
+ (and (eq_attr "type" "icmov,ssemuladd,sse4arg")
(match_operand 3 "memory_operand" ""))
(const_string "load")
]
@@ -469,23 +539,87 @@
[(set_attr "length" "128")
(set_attr "type" "multi")])
-;; All x87 floating point modes
-(define_mode_macro X87MODEF [SF DF XF])
+;; All integer comparison codes.
+(define_code_iterator int_cond [ne eq ge gt le lt geu gtu leu ltu ])
+
+;; All floating-point comparison codes.
+(define_code_iterator fp_cond [unordered ordered
+ uneq unge ungt unle unlt ltgt ])
+
+(define_code_iterator plusminus [plus minus])
+
+(define_code_iterator sat_plusminus [ss_plus us_plus ss_minus us_minus])
+
+;; Base name for define_insn
+(define_code_attr plusminus_insn
+ [(plus "add") (ss_plus "ssadd") (us_plus "usadd")
+ (minus "sub") (ss_minus "sssub") (us_minus "ussub")])
+
+;; Base name for insn mnemonic.
+(define_code_attr plusminus_mnemonic
+ [(plus "add") (ss_plus "adds") (us_plus "addus")
+ (minus "sub") (ss_minus "subs") (us_minus "subus")])
+
+;; Mark commutative operators as such in constraints.
+(define_code_attr comm [(plus "%") (ss_plus "%") (us_plus "%")
+ (minus "") (ss_minus "") (us_minus "")])
+
+;; Mapping of signed max and min
+(define_code_iterator smaxmin [smax smin])
+
+;; Mapping of unsigned max and min
+(define_code_iterator umaxmin [umax umin])
-;; x87 SFmode and DFMode floating point modes
-(define_mode_macro X87MODEF12 [SF DF])
+;; Base name for integer and FP insn mnemonic
+(define_code_attr maxminiprefix [(smax "maxs") (smin "mins")
+ (umax "maxu") (umin "minu")])
+(define_code_attr maxminfprefix [(smax "max") (smin "min")])
+
+;; Mapping of parallel logic operators
+(define_code_iterator plogic [and ior xor])
+
+;; Base name for insn mnemonic.
+(define_code_attr plogicprefix [(and "and") (ior "or") (xor "xor")])
+
+;; Mapping of abs neg operators
+(define_code_iterator absneg [abs neg])
+
+;; Base name for x87 insn mnemonic.
+(define_code_attr absnegprefix [(abs "abs") (neg "chs")])
+
+;; All single word integer modes.
+(define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")])
+
+;; Instruction suffix for integer modes.
+(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
+
+;; Register class for integer modes.
+(define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")])
+
+;; Immediate operand constraint for integer modes.
+(define_mode_attr i [(QI "i") (HI "i") (SI "i") (DI "e")])
+
+;; General operand predicate for integer modes.
+(define_mode_attr general_operand
+ [(QI "general_operand")
+ (HI "general_operand")
+ (SI "general_operand")
+ (DI "x86_64_general_operand")])
+
+;; SSE and x87 SFmode and DFmode floating point modes
+(define_mode_iterator MODEF [SF DF])
+
+;; All x87 floating point modes
+(define_mode_iterator X87MODEF [SF DF XF])
;; All integer modes handled by x87 fisttp operator.
-(define_mode_macro X87MODEI [HI SI DI])
+(define_mode_iterator X87MODEI [HI SI DI])
;; All integer modes handled by integer x87 operators.
-(define_mode_macro X87MODEI12 [HI SI])
-
-;; All SSE floating point modes
-(define_mode_macro SSEMODEF [SF DF])
+(define_mode_iterator X87MODEI12 [HI SI])
;; All integer modes handled by SSE cvtts?2si* operators.
-(define_mode_macro SSEMODEI24 [SI DI])
+(define_mode_iterator SSEMODEI24 [SI DI])
;; SSE asm suffix for floating point modes
(define_mode_attr ssemodefsuffix [(SF "s") (DF "d")])
@@ -493,6 +627,9 @@
;; SSE vector mode corresponding to a scalar mode
(define_mode_attr ssevecmode
[(QI "V16QI") (HI "V8HI") (SI "V4SI") (DI "V2DI") (SF "V4SF") (DF "V2DF")])
+
+;; Instruction suffix for REX 64bit operators.
+(define_mode_attr rex64suffix [(SI "") (DI "{q}")])
;; Scheduling descriptions
@@ -643,8 +780,8 @@
(define_expand "cmpsi_1"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
- (match_operand:SI 1 "general_operand" "ri,mr")))]
+ (compare:CC (match_operand:SI 0 "nonimmediate_operand" "")
+ (match_operand:SI 1 "general_operand" "")))]
""
"")
@@ -841,8 +978,8 @@
(define_expand "cmp"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:SSEMODEF 0 "cmp_fp_expander_operand" "")
- (match_operand:SSEMODEF 1 "cmp_fp_expander_operand" "")))]
+ (compare:CC (match_operand:MODEF 0 "cmp_fp_expander_operand" "")
+ (match_operand:MODEF 1 "cmp_fp_expander_operand" "")))]
"TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
{
ix86_compare_op0 = operands[0];
@@ -866,8 +1003,7 @@
(match_operand 1 "register_operand" "f")
(match_operand 2 "const0_operand" "X"))]
UNSPEC_FNSTSW))]
- "TARGET_80387
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
@@ -880,6 +1016,34 @@
]
(const_string "XF")))])
+(define_insn_and_split "*cmpfp_0_cc"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (match_operand 1 "register_operand" "f")
+ (match_operand 2 "const0_operand" "X")))
+ (clobber (match_operand:HI 0 "register_operand" "=a"))]
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_SAHF && !TARGET_CMOVE
+ && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:HI
+ [(compare:CCFP (match_dup 1)(match_dup 2))]
+ UNSPEC_FNSTSW))
+ (set (reg:CC FLAGS_REG)
+ (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set (attr "mode")
+ (cond [(match_operand:SF 1 "" "")
+ (const_string "SF")
+ (match_operand:DF 1 "" "")
+ (const_string "DF")
+ ]
+ (const_string "XF")))])
+
(define_insn "*cmpfp_xf"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
@@ -893,12 +1057,33 @@
(set_attr "unit" "i387")
(set_attr "mode" "XF")])
+(define_insn_and_split "*cmpfp_xf_cc"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (match_operand:XF 1 "register_operand" "f")
+ (match_operand:XF 2 "register_operand" "f")))
+ (clobber (match_operand:HI 0 "register_operand" "=a"))]
+ "TARGET_80387
+ && TARGET_SAHF && !TARGET_CMOVE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:HI
+ [(compare:CCFP (match_dup 1)(match_dup 2))]
+ UNSPEC_FNSTSW))
+ (set (reg:CC FLAGS_REG)
+ (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set_attr "mode" "XF")])
+
(define_insn "*cmpfp_"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
- (match_operand:X87MODEF12 1 "register_operand" "f")
- (match_operand:X87MODEF12 2 "nonimmediate_operand" "fm"))]
+ (match_operand:MODEF 1 "register_operand" "f")
+ (match_operand:MODEF 2 "nonimmediate_operand" "fm"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
"* return output_fp_compare (insn, operands, 0, 0);"
@@ -906,6 +1091,27 @@
(set_attr "unit" "i387")
(set_attr "mode" "")])
+(define_insn_and_split "*cmpfp__cc"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (match_operand:MODEF 1 "register_operand" "f")
+ (match_operand:MODEF 2 "nonimmediate_operand" "fm")))
+ (clobber (match_operand:HI 0 "register_operand" "=a"))]
+ "TARGET_80387
+ && TARGET_SAHF && !TARGET_CMOVE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:HI
+ [(compare:CCFP (match_dup 1)(match_dup 2))]
+ UNSPEC_FNSTSW))
+ (set (reg:CC FLAGS_REG)
+ (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set_attr "mode" "")])
+
(define_insn "*cmpfp_u"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
@@ -913,8 +1119,7 @@
(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f"))]
UNSPEC_FNSTSW))]
- "TARGET_80387
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"* return output_fp_compare (insn, operands, 0, 1);"
[(set_attr "type" "multi")
@@ -927,6 +1132,34 @@
]
(const_string "XF")))])
+(define_insn_and_split "*cmpfp_u_cc"
+ [(set (reg:CCFPU FLAGS_REG)
+ (compare:CCFPU
+ (match_operand 1 "register_operand" "f")
+ (match_operand 2 "register_operand" "f")))
+ (clobber (match_operand:HI 0 "register_operand" "=a"))]
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_SAHF && !TARGET_CMOVE
+ && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:HI
+ [(compare:CCFPU (match_dup 1)(match_dup 2))]
+ UNSPEC_FNSTSW))
+ (set (reg:CC FLAGS_REG)
+ (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set (attr "mode")
+ (cond [(match_operand:SF 1 "" "")
+ (const_string "SF")
+ (match_operand:DF 1 "" "")
+ (const_string "DF")
+ ]
+ (const_string "XF")))])
+
(define_insn "*cmpfp_"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
@@ -935,8 +1168,8 @@
(match_operator 3 "float_operator"
[(match_operand:X87MODEI12 2 "memory_operand" "m")]))]
UNSPEC_FNSTSW))]
- "TARGET_80387 && TARGET_USE_MODE_FIOP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_USE_MODE_FIOP
&& (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
"* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
@@ -944,6 +1177,33 @@
(set_attr "fp_int_src" "true")
(set_attr "mode" "")])
+(define_insn_and_split "*cmpfp__cc"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (match_operand 1 "register_operand" "f")
+ (match_operator 3 "float_operator"
+ [(match_operand:X87MODEI12 2 "memory_operand" "m")])))
+ (clobber (match_operand:HI 0 "register_operand" "=a"))]
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_SAHF && !TARGET_CMOVE
+ && TARGET_USE_MODE_FIOP
+ && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:HI
+ [(compare:CCFP
+ (match_dup 1)
+ (match_op_dup 3 [(match_dup 2)]))]
+ UNSPEC_FNSTSW))
+ (set (reg:CC FLAGS_REG)
+ (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set_attr "fp_int_src" "true")
+ (set_attr "mode" "")])
+
;; FP compares, step 2
;; Move the fpsw to ax.
@@ -977,7 +1237,7 @@
(set_attr "mode" "SI")])
;; Pentium Pro can do steps 1 through 3 in one go.
-;; comi*, ucomi*, fcomi*, ficomi*,fucomi* (i387 instructions set condition codes)
+;; comi*, ucomi*, fcomi*, ficomi*,fucomi* (i387 instructions set condition codes)
(define_insn "*cmpfp_i_mixed"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "f,x")
@@ -1014,9 +1274,9 @@
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "f")
(match_operand 1 "register_operand" "f")))]
- "TARGET_80387 && TARGET_CMOVE
- && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
- && FLOAT_MODE_P (GET_MODE (operands[0]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[0]))
+ && TARGET_CMOVE
+ && !(SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && TARGET_SSE_MATH)
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "fcmp")
@@ -1066,9 +1326,9 @@
[(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "f")
(match_operand 1 "register_operand" "f")))]
- "TARGET_80387 && TARGET_CMOVE
- && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
- && FLOAT_MODE_P (GET_MODE (operands[0]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[0]))
+ && TARGET_CMOVE
+ && !(SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && TARGET_SSE_MATH)
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
[(set_attr "type" "fcmp")
@@ -1287,7 +1547,7 @@
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "double")])
+ (set_attr "amdfam10_decode" "double")])
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
@@ -1405,7 +1665,7 @@
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "double")])
+ (set_attr "amdfam10_decode" "double")])
;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
(define_insn "*swaphi_2"
@@ -1551,25 +1811,6 @@
]
(const_string "QI")))])
-(define_expand "reload_outqi"
- [(parallel [(match_operand:QI 0 "" "=m")
- (match_operand:QI 1 "register_operand" "r")
- (match_operand:QI 2 "register_operand" "=&q")])]
- ""
-{
- rtx op0, op1, op2;
- op0 = operands[0]; op1 = operands[1]; op2 = operands[2];
-
- gcc_assert (!reg_overlap_mentioned_p (op2, op0));
- if (! q_regs_operand (op1, QImode))
- {
- emit_insn (gen_movqi (op2, op1));
- op1 = op2;
- }
- emit_insn (gen_movqi (op0, op1));
- DONE;
-})
-
(define_insn "*swapqi_1"
[(set (match_operand:QI 0 "register_operand" "+r")
(match_operand:QI 1 "register_operand" "+r"))
@@ -1581,7 +1822,7 @@
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "vector")])
+ (set_attr "amdfam10_decode" "vector")])
;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
(define_insn "*swapqi_2"
@@ -1890,7 +2131,7 @@
&& !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);
+ "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)));
@@ -1900,12 +2141,12 @@
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)
+ ? 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);
+ "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)));
@@ -2130,18 +2371,18 @@
&& !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, 2, operands + 2, operands + 4);")
+ "split_di (&operands[0], 2, &operands[2], &operands[4]);")
(define_split
[(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)
+ ? 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, 2, operands + 2, operands + 4);")
+ "split_di (&operands[0], 2, &operands[2], &operands[4]);")
(define_insn "*swapdi_rex64"
[(set (match_operand:DI 0 "register_operand" "+r")
@@ -2154,7 +2395,7 @@
(set_attr "mode" "DI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "double")])
+ (set_attr "amdfam10_decode" "double")])
(define_expand "movti"
[(set (match_operand:TI 0 "nonimmediate_operand" "")
@@ -2163,6 +2404,8 @@
{
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;
@@ -2183,10 +2426,23 @@
return "pxor\t%0, %0";
case 1:
case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
+ /* 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 "movups\t{%1, %0|%0, %1}";
+ else
+ return "movdqu\t{%1, %0|%0, %1}";
+ }
else
- return "movdqa\t{%1, %0|%0, %1}";
+ {
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ }
default:
gcc_unreachable ();
}
@@ -2220,10 +2476,23 @@
return "pxor\t%0, %0";
case 3:
case 4:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
+ /* 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 "movups\t{%1, %0|%0, %1}";
+ else
+ return "movdqu\t{%1, %0|%0, %1}";
+ }
else
- return "movdqa\t{%1, %0|%0, %1}";
+ {
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ }
default:
gcc_unreachable ();
}
@@ -2290,7 +2559,7 @@
(set_attr "mode" "SF,SI,SF")])
(define_insn "*pushsf_rex64"
- [(set (match_operand:SF 0 "push_operand" "=<,<,<")
+ [(set (match_operand:SF 0 "push_operand" "=X,X,X")
(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
"TARGET_64BIT"
{
@@ -2343,13 +2612,8 @@
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return standard_80387_constant_opcode (operands[1]);
@@ -2499,26 +2763,25 @@
[(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,F*r,C ,Y2*x,mY2*x,Y2*x"))]
+ "fm,f,G,*roF,*Fr,C ,Y2*x,mY2*x,Y2*x"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
&& (reload_in_progress || reload_completed
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
|| (!(TARGET_SSE2 && TARGET_SSE_MATH) && optimize_size
+ && !memory_operand (operands[0], DFmode)
&& standard_80387_constant_p (operands[1]))
|| GET_CODE (operands[1]) != CONST_DOUBLE
- || memory_operand (operands[0], DFmode))"
+ || ((optimize_size
+ || !TARGET_MEMORY_MISMATCH_STALL
+ || reload_in_progress || reload_completed)
+ && memory_operand (operands[0], DFmode)))"
{
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return standard_80387_constant_opcode (operands[1]);
@@ -2633,13 +2896,8 @@
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return standard_80387_constant_opcode (operands[1]);
@@ -2760,13 +3018,8 @@
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return standard_80387_constant_opcode (operands[1]);
@@ -2972,15 +3225,8 @@
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- /* There is no non-popping store to memory for XFmode. So if
- we need one, follow the store with a load. */
- if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0\;fld%z0\t%y0";
- else
- return "fstp%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return standard_80387_constant_opcode (operands[1]);
@@ -3007,15 +3253,8 @@
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- /* There is no non-popping store to memory for XFmode. So if
- we need one, follow the store with a load. */
- if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0\;fld%z0\t%y0";
- else
- return "fstp%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return standard_80387_constant_opcode (operands[1]);
@@ -3030,6 +3269,59 @@
[(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_64BIT"
+{
+ 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_64BIT
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "xorps\t%0, %0";
+ else
+ return "pxor\t%0, %0";
+ case 3:
+ case 4:
+ return "#";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "ssemov,ssemov,sselog1,*,*")
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "0,2")
+ (if_then_else
+ (ne (symbol_ref "optimize_size")
+ (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_size")
+ (const_int 0)))
+ (const_string "V4SF")
+ (const_string "TI"))]
+ (const_string "DI")))])
+
(define_split
[(set (match_operand 0 "nonimmediate_operand" "")
(match_operand 1 "general_operand" ""))]
@@ -3050,7 +3342,8 @@
(match_operand 1 "memory_operand" ""))]
"reload_completed
&& MEM_P (operands[1])
- && (GET_MODE (operands[0]) == XFmode
+ && (GET_MODE (operands[0]) == TFmode
+ || GET_MODE (operands[0]) == XFmode
|| GET_MODE (operands[0]) == SFmode
|| GET_MODE (operands[0]) == DFmode)
&& (operands[2] = find_constant_src (insn))"
@@ -3081,7 +3374,8 @@
(float_extend (match_operand 1 "memory_operand" "")))]
"reload_completed
&& MEM_P (operands[1])
- && (GET_MODE (operands[0]) == XFmode
+ && (GET_MODE (operands[0]) == TFmode
+ || GET_MODE (operands[0]) == XFmode
|| GET_MODE (operands[0]) == SFmode
|| GET_MODE (operands[0]) == DFmode)
&& (operands[2] = find_constant_src (insn))"
@@ -3142,64 +3436,11 @@
operands[1] = CONST1_RTX (mode);
})
-(define_expand "movtf"
- [(set (match_operand:TF 0 "nonimmediate_operand" "")
- (match_operand:TF 1 "nonimmediate_operand" ""))]
- "TARGET_64BIT"
-{
- ix86_expand_move (TFmode, operands);
- DONE;
-})
-
-(define_insn "*movtf_internal"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
- (match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
- "TARGET_64BIT
- && !(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 "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 3:
- case 4:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "2,3")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "4")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "DI")))])
-
(define_split
[(set (match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:TF 1 "general_operand" ""))]
- "reload_completed && !SSE_REG_P (operands[0])
- && !SSE_REG_P (operands[1])"
+ "reload_completed
+ && !(SSE_REG_P (operands[0]) || SSE_REG_P (operands[1]))"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
@@ -3275,7 +3516,7 @@
[(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
"(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
- "movz{bl|x}\t{%1, %k0|%k0, %k1}"
+ "movz{bl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
@@ -3388,8 +3629,8 @@
;; %%% Kill me once multi-word ops are sane.
(define_expand "zero_extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
""
{
if (!TARGET_64BIT)
@@ -3554,9 +3795,9 @@
emit_move_insn (operands[3], operands[1]);
/* Generate a cltd if possible and doing so it profitable. */
- if (true_regnum (operands[1]) == 0
- && true_regnum (operands[2]) == 1
- && (optimize_size || TARGET_USE_CLTD))
+ if ((optimize_size || TARGET_USE_CLTD)
+ && true_regnum (operands[1]) == AX_REG
+ && true_regnum (operands[2]) == DX_REG)
{
emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31)));
}
@@ -3585,8 +3826,8 @@
emit_move_insn (operands[3], operands[1]);
/* Generate a cltd if possible and doing so it profitable. */
- if (true_regnum (operands[3]) == 0
- && (optimize_size || TARGET_USE_CLTD))
+ if ((optimize_size || TARGET_USE_CLTD)
+ && true_regnum (operands[3]) == AX_REG)
{
emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31)));
DONE;
@@ -3703,7 +3944,7 @@
;; %%% Kill these when call knows how to work out a DFmode push earlier.
(define_insn "*dummy_extendsfdf2"
[(set (match_operand:DF 0 "push_operand" "=<")
- (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY2")))]
"0"
"#")
@@ -3780,7 +4021,50 @@
}
})
-(define_insn "*extendsfdf2_mixed"
+/* For converting SF(xmm2) to DF(xmm1), use the following code instead of
+ cvtss2sd:
+ unpcklps xmm2,xmm2 ; packed conversion might crash on signaling NaNs
+ cvtps2pd xmm2,xmm1
+ We do the conversion post reload to avoid producing of 128bit spills
+ that might lead to ICE on 32bit target. The sequence unlikely combine
+ anyway. */
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float_extend:DF
+ (match_operand:SF 1 "nonimmediate_operand" "")))]
+ "(TARGET_USE_VECTOR_CONVERTS || TARGET_GENERIC) && !optimize_size
+ && reload_completed && SSE_REG_P (operands[0])"
+ [(set (match_dup 2)
+ (float_extend:V2DF
+ (vec_select:V2SF
+ (match_dup 3)
+ (parallel [(const_int 0) (const_int 1)]))))]
+{
+ operands[2] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
+ operands[3] = simplify_gen_subreg (V4SFmode, operands[0], DFmode, 0);
+ /* Use movss for loading from memory, unpcklps reg, reg for registers.
+ Try to avoid move when unpacking can be done in source. */
+ if (REG_P (operands[1]))
+ {
+ /* If it is unsafe to overwrite upper half of source, we need
+ to move to destination and unpack there. */
+ if ((ORIGINAL_REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+ || PSEUDO_REGNO_BYTES (ORIGINAL_REGNO (operands[1])) > 4)
+ && true_regnum (operands[0]) != true_regnum (operands[1]))
+ {
+ rtx tmp = gen_rtx_REG (SFmode, true_regnum (operands[0]));
+ emit_move_insn (tmp, operands[1]);
+ }
+ else
+ operands[3] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+ emit_insn (gen_sse_unpcklps (operands[3], operands[3], operands[3]));
+ }
+ else
+ emit_insn (gen_vec_setv4sf_0 (operands[3],
+ CONST0_RTX (V4SFmode), operands[1]));
+})
+
+(define_insn "*extendsfdf2_mixed"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,x")
(float_extend:DF
(match_operand:SF 1 "nonimmediate_operand" "fm,f,xm")))]
@@ -3789,13 +4073,8 @@
switch (which_alternative)
{
case 0:
- return output_387_reg_move (insn, operands);
-
case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
case 2:
return "cvtss2sd\t{%1, %0|%0, %1}";
@@ -3819,73 +4098,13 @@
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
"TARGET_80387"
-{
- switch (which_alternative)
- {
- case 0:
- return output_387_reg_move (insn, operands);
-
- case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
-
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF,XF")])
-
-(define_expand "extendsfxf2"
- [(set (match_operand:XF 0 "nonimmediate_operand" "")
- (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
- "TARGET_80387"
-{
- /* ??? Needed for compress_float_constant since all fp constants
- are LEGITIMATE_CONSTANT_P. */
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- if (standard_80387_constant_p (operands[1]) > 0)
- {
- operands[1] = simplify_const_unary_operation
- (FLOAT_EXTEND, XFmode, operands[1], SFmode);
- emit_move_insn_1 (operands[0], operands[1]);
- DONE;
- }
- operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
- }
-})
-
-(define_insn "*extendsfxf2_i387"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
- (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
- "TARGET_80387"
-{
- switch (which_alternative)
- {
- case 0:
- return output_387_reg_move (insn, operands);
-
- case 1:
- /* There is no non-popping store to memory for XFmode. So if
- we need one, follow the store with a load. */
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fstp%z0\t%y0\n\tfld%z0\t%y0";
-
- default:
- gcc_unreachable ();
- }
-}
+ "* return output_387_reg_move (insn, operands);"
[(set_attr "type" "fmov")
(set_attr "mode" "SF,XF")])
-(define_expand "extenddfxf2"
+(define_expand "extendxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
- (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
+ (float_extend:XF (match_operand:MODEF 1 "general_operand" "")))]
"TARGET_80387"
{
/* ??? Needed for compress_float_constant since all fp constants
@@ -3895,38 +4114,22 @@
if (standard_80387_constant_p (operands[1]) > 0)
{
operands[1] = simplify_const_unary_operation
- (FLOAT_EXTEND, XFmode, operands[1], DFmode);
+ (FLOAT_EXTEND, XFmode, operands[1], mode);
emit_move_insn_1 (operands[0], operands[1]);
DONE;
}
- operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
+ operands[1] = validize_mem (force_const_mem (mode, operands[1]));
}
})
-(define_insn "*extenddfxf2_i387"
+(define_insn "*extendxf2_i387"
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
- (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
+ (float_extend:XF
+ (match_operand:MODEF 1 "nonimmediate_operand" "fm,f")))]
"TARGET_80387"
-{
- switch (which_alternative)
- {
- case 0:
- return output_387_reg_move (insn, operands);
-
- case 1:
- /* There is no non-popping store to memory for XFmode. So if
- we need one, follow the store with a load. */
- if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0\n\tfld%z0\t%y0";
- else
- return "fstp%z0\t%y0";
-
- default:
- gcc_unreachable ();
- }
-}
+ "* return output_387_reg_move (insn, operands);"
[(set_attr "type" "fmov")
- (set_attr "mode" "DF,XF")])
+ (set_attr "mode" ",XF")])
;; %%% This seems bad bad news.
;; This cannot output into an f-reg because there is no way to be sure
@@ -3948,12 +4151,58 @@
;
else
{
- rtx temp = assign_386_stack_local (SFmode, SLOT_TEMP);
+ int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+ rtx temp = assign_386_stack_local (SFmode, slot);
emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
DONE;
}
})
+/* For converting DF(xmm2) to SF(xmm1), use the following code instead of
+ cvtsd2ss:
+ unpcklpd xmm2,xmm2 ; packed conversion might crash on signaling NaNs
+ cvtpd2ps xmm2,xmm1
+ We do the conversion post reload to avoid producing of 128bit spills
+ that might lead to ICE on 32bit target. The sequence unlikely combine
+ anyway. */
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "(TARGET_USE_VECTOR_CONVERTS || TARGET_GENERIC) && !optimize_size
+ && reload_completed && SSE_REG_P (operands[0])"
+ [(set (match_dup 2)
+ (vec_concat:V4SF
+ (float_truncate:V2SF
+ (match_dup 4))
+ (match_dup 3)))]
+{
+ operands[2] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
+ operands[3] = CONST0_RTX (V2SFmode);
+ operands[4] = simplify_gen_subreg (V2DFmode, operands[0], SFmode, 0);
+ /* Use movsd for loading from memory, unpcklpd for registers.
+ Try to avoid move when unpacking can be done in source, or SSE3
+ movddup is available. */
+ if (REG_P (operands[1]))
+ {
+ if (!TARGET_SSE3
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && (ORIGINAL_REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+ || PSEUDO_REGNO_BYTES (ORIGINAL_REGNO (operands[1])) > 8))
+ {
+ rtx tmp = simplify_gen_subreg (DFmode, operands[0], SFmode, 0);
+ emit_move_insn (tmp, operands[1]);
+ operands[1] = tmp;
+ }
+ else if (!TARGET_SSE3)
+ operands[4] = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
+ emit_insn (gen_vec_dupv2df (operands[4], operands[1]));
+ }
+ else
+ emit_insn (gen_sse2_loadlpd (operands[4],
+ CONST0_RTX (V2DFmode), operands[1]));
+})
+
(define_expand "truncdfsf2_with_temp"
[(parallel [(set (match_operand:SF 0 "" "")
(float_truncate:SF (match_operand:DF 1 "" "")))
@@ -3961,27 +4210,22 @@
"")
(define_insn "*truncdfsf_fast_mixed"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f,x")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=fm,x")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f ,f,xm")))]
+ (match_operand:DF 1 "nonimmediate_operand" "f ,xm")))]
"TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
{
switch (which_alternative)
{
case 0:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
- case 1:
return output_387_reg_move (insn, operands);
- case 2:
+ case 1:
return "cvtsd2ss\t{%1, %0|%0, %1}";
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,fmov,ssecvt")
+ [(set_attr "type" "fmov,ssecvt")
(set_attr "mode" "SF")])
;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
@@ -4014,10 +4258,8 @@
switch (which_alternative)
{
case 0:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
+
case 1:
return "#";
case 2:
@@ -4040,10 +4282,8 @@
switch (which_alternative)
{
case 0:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
+
case 1:
return "#";
default:
@@ -4061,12 +4301,7 @@
"TARGET_80387
&& !(TARGET_SSE2 && TARGET_SSE_MATH)
&& !TARGET_MIX_SSE_I387"
-{
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
-}
+ "* return output_387_reg_move (insn, operands);"
[(set_attr "type" "fmov")
(set_attr "mode" "SF")])
@@ -4082,162 +4317,93 @@
operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
})
-;; Conversion from XFmode to SFmode.
+;; Conversion from XFmode to {SF,DF}mode
-(define_expand "truncxfsf2"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (float_truncate:SF
- (match_operand:XF 1 "register_operand" "")))
+(define_expand "truncxf2"
+ [(parallel [(set (match_operand:MODEF 0 "nonimmediate_operand" "")
+ (float_truncate:MODEF
+ (match_operand:XF 1 "register_operand" "")))
(clobber (match_dup 2))])]
"TARGET_80387"
{
if (flag_unsafe_math_optimizations)
{
- rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
- emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
+ rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (mode);
+ emit_insn (gen_truncxf2_i387_noop (reg, operands[1]));
if (reg != operands[0])
emit_move_insn (operands[0], reg);
DONE;
}
else
- operands[2] = assign_386_stack_local (SFmode, SLOT_TEMP);
+ {
+ int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+ operands[2] = assign_386_stack_local (mode, slot);
+ }
})
(define_insn "*truncxfsf2_mixed"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
(float_truncate:SF
- (match_operand:XF 1 "register_operand" "f,f,f,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
+ (match_operand:XF 1 "register_operand" "f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
"TARGET_80387"
{
gcc_assert (!which_alternative);
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
}
- [(set_attr "type" "fmov,multi,multi,multi")
- (set_attr "unit" "*,i387,i387,i387")
- (set_attr "mode" "SF")])
-
-(define_insn "truncxfsf2_i387_noop"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
- "TARGET_80387 && flag_unsafe_math_optimizations"
- "* return output_387_reg_move (insn, operands);"
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF")])
-
-(define_insn "*truncxfsf2_i387"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (float_truncate:SF
- (match_operand:XF 1 "register_operand" "f")))]
- "TARGET_80387"
-{
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
-}
- [(set_attr "type" "fmov")
+ [(set_attr "type" "fmov,multi")
+ (set_attr "unit" "*,i387")
(set_attr "mode" "SF")])
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (float_truncate:SF
- (match_operand:XF 1 "register_operand" "")))
- (clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
- "")
-
-(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
- (float_truncate:SF
- (match_operand:XF 1 "register_operand" "")))
- (clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
- "")
-
-;; Conversion from XFmode to DFmode.
-
-(define_expand "truncxfdf2"
- [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (float_truncate:DF
- (match_operand:XF 1 "register_operand" "")))
- (clobber (match_dup 2))])]
- "TARGET_80387"
-{
- if (flag_unsafe_math_optimizations)
- {
- rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
- emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
- if (reg != operands[0])
- emit_move_insn (operands[0], reg);
- DONE;
- }
- else
- operands[2] = assign_386_stack_local (DFmode, SLOT_TEMP);
-})
-
(define_insn "*truncxfdf2_mixed"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y2*x")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?fY2*r")
(float_truncate:DF
- (match_operand:XF 1 "register_operand" "f,f,f,f")))
- (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
+ (match_operand:XF 1 "register_operand" "f,f")))
+ (clobber (match_operand:DF 2 "memory_operand" "=X,m"))]
"TARGET_80387"
{
gcc_assert (!which_alternative);
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return output_387_reg_move (insn, operands);
}
- [(set_attr "type" "fmov,multi,multi,multi")
- (set_attr "unit" "*,i387,i387,i387")
+ [(set_attr "type" "fmov,multi")
+ (set_attr "unit" "*,i387")
(set_attr "mode" "DF")])
-(define_insn "truncxfdf2_i387_noop"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
+(define_insn "truncxf2_i387_noop"
+ [(set (match_operand:MODEF 0 "register_operand" "=f")
+ (float_truncate:MODEF
+ (match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387 && flag_unsafe_math_optimizations"
"* return output_387_reg_move (insn, operands);"
[(set_attr "type" "fmov")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "")])
-(define_insn "*truncxfdf2_i387"
- [(set (match_operand:DF 0 "memory_operand" "=m")
- (float_truncate:DF
+(define_insn "*truncxf2_i387"
+ [(set (match_operand:MODEF 0 "memory_operand" "=m")
+ (float_truncate:MODEF
(match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387"
-{
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
-}
+ "* return output_387_reg_move (insn, operands);"
[(set_attr "type" "fmov")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "")])
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (float_truncate:DF
- (match_operand:XF 1 "register_operand" "")))
- (clobber (match_operand:DF 2 "memory_operand" ""))]
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float_truncate:MODEF
+ (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_operand:MODEF 2 "memory_operand" ""))]
"TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
+ [(set (match_dup 2) (float_truncate:MODEF (match_dup 1)))
(set (match_dup 0) (match_dup 2))]
"")
(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
- (float_truncate:DF
- (match_operand:XF 1 "register_operand" "")))
- (clobber (match_operand:DF 2 "memory_operand" ""))]
+ [(set (match_operand:MODEF 0 "memory_operand" "")
+ (float_truncate:MODEF
+ (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_operand:MODEF 2 "memory_operand" ""))]
"TARGET_80387"
- [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
+ [(set (match_dup 0) (float_truncate:MODEF (match_dup 1)))]
"")
;; Signed conversion to DImode.
@@ -4257,7 +4423,7 @@
(define_expand "fix_truncdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
+ (fix:DI (match_operand:MODEF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (mode))"
{
@@ -4294,7 +4460,7 @@
(define_expand "fix_truncsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
+ (fix:SI (match_operand:MODEF 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_80387 || SSE_FLOAT_MODE_P (mode)"
{
@@ -4336,7 +4502,7 @@
[(parallel
[(set (match_operand:SI 0 "register_operand" "")
(unsigned_fix:SI
- (match_operand:SSEMODEF 1 "nonimmediate_operand" "")))
+ (match_operand:MODEF 1 "nonimmediate_operand" "")))
(use (match_dup 2))
(clobber (match_scratch: 3 ""))
(clobber (match_scratch: 4 ""))])]
@@ -4356,7 +4522,7 @@
(define_insn_and_split "*fixuns_trunc_1"
[(set (match_operand:SI 0 "register_operand" "=&x,&x")
(unsigned_fix:SI
- (match_operand:SSEMODEF 3 "nonimmediate_operand" "xm,xm")))
+ (match_operand:MODEF 3 "nonimmediate_operand" "xm,xm")))
(use (match_operand: 4 "nonimmediate_operand" "m,x"))
(clobber (match_scratch: 1 "=x,&x"))
(clobber (match_scratch: 2 "=x,x"))]
@@ -4375,7 +4541,7 @@
(define_expand "fixuns_trunchi2"
[(set (match_dup 2)
- (fix:SI (match_operand:SSEMODEF 1 "nonimmediate_operand" "")))
+ (fix:SI (match_operand:MODEF 1 "nonimmediate_operand" "")))
(set (match_operand:HI 0 "nonimmediate_operand" "")
(subreg:HI (match_dup 2) 0))]
"SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH"
@@ -4384,7 +4550,7 @@
;; When SSE is available, it is always faster to use it!
(define_insn "fix_truncdi_sse"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (fix:DI (match_operand:SSEMODEF 1 "nonimmediate_operand" "x,xm")))]
+ (fix:DI (match_operand:MODEF 1 "nonimmediate_operand" "x,m")))]
"TARGET_64BIT && SSE_FLOAT_MODE_P (mode)
&& (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvtts2si{q}\t{%1, %0|%0, %1}"
@@ -4395,7 +4561,7 @@
(define_insn "fix_truncsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (fix:SI (match_operand:SSEMODEF 1 "nonimmediate_operand" "x,xm")))]
+ (fix:SI (match_operand:MODEF 1 "nonimmediate_operand" "x,m")))]
"SSE_FLOAT_MODE_P (mode)
&& (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvtts2si\t{%1, %0|%0, %1}"
@@ -4406,8 +4572,8 @@
;; Shorten x87->SSE reload sequences of fix_trunc?f?i_sse patterns.
(define_peephole2
- [(set (match_operand:SSEMODEF 0 "register_operand" "")
- (match_operand:SSEMODEF 1 "memory_operand" ""))
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (match_operand:MODEF 1 "memory_operand" ""))
(set (match_operand:SSEMODEI24 2 "register_operand" "")
(fix:SSEMODEI24 (match_dup 0)))]
"TARGET_SHORTEN_X87_SSE
@@ -4435,10 +4601,10 @@
"")
(define_insn_and_split "fix_trunc_fisttp_i387_1"
- [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
- (fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
- "TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
+ (fix:X87MODEI (match_operand 1 "register_operand" "")))]
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_FISTTP
&& !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || mode != DImode))
&& TARGET_SSE_MATH)
@@ -4465,8 +4631,8 @@
[(set (match_operand:X87MODEI 0 "memory_operand" "=m")
(fix:X87MODEI (match_operand 1 "register_operand" "f")))
(clobber (match_scratch:XF 2 "=&1f"))]
- "TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_FISTTP
&& !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || mode != DImode))
&& TARGET_SSE_MATH)"
@@ -4477,10 +4643,10 @@
(define_insn "fix_trunc_i387_fisttp_with_temp"
[(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
(fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
- (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
+ (clobber (match_operand:X87MODEI 2 "memory_operand" "=X,m"))
(clobber (match_scratch:XF 3 "=&1f,&1f"))]
- "TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && TARGET_FISTTP
&& !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || mode != DImode))
&& TARGET_SSE_MATH)"
@@ -4515,11 +4681,11 @@
;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
;; function in i386.c.
(define_insn_and_split "*fix_trunc_i387_1"
- [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
- (fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
+ (fix:X87MODEI (match_operand 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_80387 && !TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !TARGET_FISTTP
&& !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& (TARGET_64BIT || mode != DImode))
&& !(reload_completed || reload_in_progress)"
@@ -4553,8 +4719,8 @@
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))
(clobber (match_scratch:XF 4 "=&1f"))]
- "TARGET_80387 && !TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !TARGET_FISTTP
&& !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fistp")
@@ -4566,10 +4732,10 @@
(fix:DI (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
+ (clobber (match_operand:DI 4 "memory_operand" "=X,m"))
(clobber (match_scratch:XF 5 "=&1f,&1f"))]
- "TARGET_80387 && !TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !TARGET_FISTTP
&& !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"#"
[(set_attr "type" "fistp")
@@ -4610,8 +4776,8 @@
(fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
- "TARGET_80387 && !TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !TARGET_FISTTP
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fistp")
@@ -4623,9 +4789,9 @@
(fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
- "TARGET_80387 && !TARGET_FISTTP
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" "=X,m"))]
+ "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !TARGET_FISTTP
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
"#"
[(set_attr "type" "fistp")
@@ -4675,318 +4841,634 @@
(set_attr "mode" "HI")
(set_attr "unit" "i387")
(set_attr "athlon_decode" "vector")
- (set_attr "amdfam10_decode" "vector")])
+ (set_attr "amdfam10_decode" "vector")])
;; Conversion between fixed point and floating point.
;; Even though we only accept memory inputs, the backend _really_
;; wants to be able to do this between registers.
-(define_expand "floathisf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:HI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
+(define_expand "floathi2"
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:HI 1 "nonimmediate_operand" "")))]
+ "TARGET_80387
+ && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)"
+ "")
+
+;; Pre-reload splitter to add memory clobber to the pattern.
+(define_insn_and_split "*floathi2_1"
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:HI 1 "register_operand" "")))]
+ "TARGET_80387
+ && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (float:X87MODEF (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "operands[2] = assign_386_stack_local (HImode, SLOT_TEMP);")
+
+(define_insn "*floathi2_i387_with_temp"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
+ (float:X87MODEF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))
+ (clobber (match_operand:HI 2 "memory_operand" "=m,m"))]
+ "TARGET_80387
+ && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)"
+ "#"
+ [(set_attr "type" "fmov,multi")
+ (set_attr "mode" "")
+ (set_attr "unit" "*,i387")
+ (set_attr "fp_int_src" "true")])
+
+(define_insn "*floathi2_i387"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f")
+ (float:X87MODEF (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_80387
+ && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)"
+ "fild%z1\t%1"
+ [(set_attr "type" "fmov")
+ (set_attr "mode" "")
+ (set_attr "fp_int_src" "true")])
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:HI 1 "register_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387
+ && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)
+ && reload_completed"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (float:X87MODEF (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:HI 1 "memory_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387
+ && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)
+ && reload_completed"
+ [(set (match_dup 0) (float:X87MODEF (match_dup 1)))]
+ "")
+
+(define_expand "float2"
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF
+ (match_operand:SSEMODEI24 1 "nonimmediate_operand" "")))]
+ "TARGET_80387
+ || ((mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
+ "")
+
+;; Pre-reload splitter to add memory clobber to the pattern.
+(define_insn_and_split "*float2_1"
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))]
+ "((TARGET_80387
+ && (!((mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387))
+ || ((mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
+ && ((mode == SImode
+ && TARGET_SSE2 && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+ && flag_trapping_math)
+ || !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size))))
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0) (float:X87MODEF (match_dup 1)))
+ (clobber (match_dup 2))])]
{
- if (TARGET_SSE_MATH)
+ operands[2] = assign_386_stack_local (mode, SLOT_TEMP);
+
+ /* Avoid store forwarding (partial memory) stall penalty
+ by passing DImode value through XMM registers. */
+ if (mode == DImode && !TARGET_64BIT
+ && TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES
+ && !optimize_size)
{
- emit_insn (gen_floatsisf2 (operands[0],
- convert_to_mode (SImode, operands[1], 0)));
+ emit_insn (gen_floatdi2_i387_with_xmm (operands[0],
+ operands[1],
+ operands[2]));
DONE;
}
})
-(define_insn "*floathisf2_i387"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
+(define_insn "*floatsi2_vector_mixed_with_temp"
+ [(set (match_operand:MODEF 0 "register_operand" "=f,f,x,x,x")
+ (float:MODEF
+ (match_operand:SI 1 "nonimmediate_operand" "m,?r,r,m,!x")))
+ (clobber (match_operand:SI 2 "memory_operand" "=X,m,m,X,m"))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+ "#"
+ [(set_attr "type" "fmov,multi,sseicvt,sseicvt,sseicvt")
+ (set_attr "mode" ",,,,")
+ (set_attr "unit" "*,i387,*,*,*")
+ (set_attr "athlon_decode" "*,*,double,direct,double")
+ (set_attr "amdfam10_decode" "*,*,vector,double,double")
+ (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsi2_vector_mixed"
+ [(set (match_operand:MODEF 0 "register_operand" "=f,x")
+ (float:MODEF (match_operand:SI 1 "memory_operand" "m,m")))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
"@
fild%z1\t%1
#"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "SF")
- (set_attr "unit" "*,i387")
+ [(set_attr "type" "fmov,sseicvt")
+ (set_attr "mode" ",")
+ (set_attr "unit" "i387,*")
+ (set_attr "athlon_decode" "*,direct")
+ (set_attr "amdfam10_decode" "*,double")
(set_attr "fp_int_src" "true")])
-(define_expand "floatsisf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
- "")
-
-(define_insn "*floatsisf2_mixed"
- [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_MIX_SSE_I387"
- "@
- fild%z1\t%1
- #
- cvtsi2ss\t{%1, %0|%0, %1}
- cvtsi2ss\t{%1, %0|%0, %1}"
+(define_insn "*float2_mixed_with_temp"
+ [(set (match_operand:MODEF 0 "register_operand" "=f,f,x,x")
+ (float:MODEF
+ (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,?r,r,m")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=X,m,m,X"))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387"
+ "#"
[(set_attr "type" "fmov,multi,sseicvt,sseicvt")
- (set_attr "mode" "SF")
+ (set_attr "mode" "")
(set_attr "unit" "*,i387,*,*")
- (set_attr "athlon_decode" "*,*,vector,double")
+ (set_attr "athlon_decode" "*,*,double,direct")
(set_attr "amdfam10_decode" "*,*,vector,double")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatsisf2_sse"
- [(set (match_operand:SF 0 "register_operand" "=x,x")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_SSE_MATH"
- "cvtsi2ss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "SF")
- (set_attr "athlon_decode" "vector,double")
- (set_attr "amdfam10_decode" "vector,double")
- (set_attr "fp_int_src" "true")])
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387
+ && TARGET_INTER_UNIT_CONVERSIONS
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(set (match_dup 0) (float:MODEF (match_dup 1)))]
+ "")
-(define_insn "*floatsisf2_i387"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387"
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387
+ && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (float:MODEF (match_dup 2)))]
+ "")
+
+(define_insn "*float2_mixed_interunit"
+ [(set (match_operand:MODEF 0 "register_operand" "=f,x,x")
+ (float:MODEF
+ (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,r,m")))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387
+ && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
"@
fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "SF")
- (set_attr "unit" "*,i387")
+ cvtsi2s\t{%1, %0|%0, %1}
+ cvtsi2s\t{%1, %0|%0, %1}"
+ [(set_attr "type" "fmov,sseicvt,sseicvt")
+ (set_attr "mode" "")
+ (set_attr "unit" "i387,*,*")
+ (set_attr "athlon_decode" "*,double,direct")
+ (set_attr "amdfam10_decode" "*,vector,double")
(set_attr "fp_int_src" "true")])
-(define_expand "floatdisf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
- "")
-
-(define_insn "*floatdisf2_mixed"
- [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_64BIT && TARGET_MIX_SSE_I387"
+(define_insn "*float2_mixed_nointerunit"
+ [(set (match_operand:MODEF 0 "register_operand" "=f,x")
+ (float:MODEF
+ (match_operand:SSEMODEI24 1 "memory_operand" "m,m")))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_MIX_SSE_I387
+ && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
"@
fild%z1\t%1
- #
- cvtsi2ss{q}\t{%1, %0|%0, %1}
- cvtsi2ss{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
- (set_attr "mode" "SF")
- (set_attr "unit" "*,i387,*,*")
- (set_attr "athlon_decode" "*,*,vector,double")
- (set_attr "amdfam10_decode" "*,*,vector,double")
+ cvtsi2s\t{%1, %0|%0, %1}"
+ [(set_attr "type" "fmov,sseicvt")
+ (set_attr "mode" "")
+ (set_attr "athlon_decode" "*,direct")
+ (set_attr "amdfam10_decode" "*,double")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatdisf2_sse"
- [(set (match_operand:SF 0 "register_operand" "=x,x")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_64BIT && TARGET_SSE_MATH"
- "cvtsi2ss{q}\t{%1, %0|%0, %1}"
+(define_insn "*floatsi2_vector_sse_with_temp"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x,x")
+ (float:MODEF
+ (match_operand:SI 1 "nonimmediate_operand" "r,m,!x")))
+ (clobber (match_operand:SI 2 "memory_operand" "=m,X,m"))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+ "#"
[(set_attr "type" "sseicvt")
- (set_attr "mode" "SF")
- (set_attr "athlon_decode" "vector,double")
- (set_attr "amdfam10_decode" "vector,double")
+ (set_attr "mode" ",,")
+ (set_attr "athlon_decode" "double,direct,double")
+ (set_attr "amdfam10_decode" "vector,double,double")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatdisf2_i387"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387"
- "@
- fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "SF")
- (set_attr "unit" "*,i387")
+(define_insn "*floatsi2_vector_sse"
+ [(set (match_operand:MODEF 0 "register_operand" "=x")
+ (float:MODEF (match_operand:SI 1 "memory_operand" "m")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+ "#"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "")
+ (set_attr "athlon_decode" "direct")
+ (set_attr "amdfam10_decode" "double")
(set_attr "fp_int_src" "true")])
-(define_expand "floathidf2"
- [(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:HI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(const_int 0)]
{
- if (TARGET_SSE2 && TARGET_SSE_MATH)
+ rtx op1 = operands[1];
+
+ operands[3] = simplify_gen_subreg (mode, operands[0],
+ mode, 0);
+ if (GET_CODE (op1) == SUBREG)
+ op1 = SUBREG_REG (op1);
+
+ if (GENERAL_REG_P (op1) && TARGET_INTER_UNIT_MOVES)
{
- emit_insn (gen_floatsidf2 (operands[0],
- convert_to_mode (SImode, operands[1], 0)));
- DONE;
+ operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0);
+ emit_insn (gen_sse2_loadld (operands[4],
+ CONST0_RTX (V4SImode), operands[1]));
}
+ /* We can ignore possible trapping value in the
+ high part of SSE register for non-trapping math. */
+ else if (SSE_REG_P (op1) && !flag_trapping_math)
+ operands[4] = simplify_gen_subreg (V4SImode, operands[1], SImode, 0);
+ else
+ {
+ operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0);
+ emit_move_insn (operands[2], operands[1]);
+ emit_insn (gen_sse2_loadld (operands[4],
+ CONST0_RTX (V4SImode), operands[2]));
+ }
+ emit_insn
+ (gen_sse2_cvtdq2p (operands[3], operands[4]));
+ DONE;
})
-(define_insn "*floathidf2_i387"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
- "@
- fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "DF")
- (set_attr "unit" "*,i387")
- (set_attr "fp_int_src" "true")])
-
-(define_expand "floatsidf2"
- [(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "")
-
-(define_insn "*floatsidf2_mixed"
- [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_SSE2 && TARGET_MIX_SSE_I387"
- "@
- fild%z1\t%1
- #
- cvtsi2sd\t{%1, %0|%0, %1}
- cvtsi2sd\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
- (set_attr "mode" "DF")
- (set_attr "unit" "*,i387,*,*")
- (set_attr "athlon_decode" "*,*,double,direct")
- (set_attr "amdfam10_decode" "*,*,vector,double")
- (set_attr "fp_int_src" "true")])
-
-(define_insn "*floatsidf2_sse"
- [(set (match_operand:DF 0 "register_operand" "=x,x")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_SSE2 && TARGET_SSE_MATH"
- "cvtsi2sd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "DF")
- (set_attr "athlon_decode" "double,direct")
- (set_attr "amdfam10_decode" "vector,double")
- (set_attr "fp_int_src" "true")])
-
-(define_insn "*floatsidf2_i387"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387"
- "@
- fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "DF")
- (set_attr "unit" "*,i387")
- (set_attr "fp_int_src" "true")])
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SI 1 "memory_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(const_int 0)]
+{
+ operands[3] = simplify_gen_subreg (mode, operands[0],
+ mode, 0);
+ operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0);
-(define_expand "floatdidf2"
- [(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
+ emit_insn (gen_sse2_loadld (operands[4],
+ CONST0_RTX (V4SImode), operands[1]));
+ emit_insn
+ (gen_sse2_cvtdq2p (operands[3], operands[4]));
+ DONE;
+})
+
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SI 1 "register_operand" "")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(const_int 0)]
{
- if (!TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)
+ rtx op1 = operands[1];
+
+ operands[3] = simplify_gen_subreg (mode, operands[0],
+ mode, 0);
+ if (GET_CODE (op1) == SUBREG)
+ op1 = SUBREG_REG (op1);
+
+ if (GENERAL_REG_P (op1) && TARGET_INTER_UNIT_MOVES)
{
- ix86_expand_convert_sign_didf_sse (operands[0], operands[1]);
- DONE;
+ operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0);
+ emit_insn (gen_sse2_loadld (operands[4],
+ CONST0_RTX (V4SImode), operands[1]));
}
+ /* We can ignore possible trapping value in the
+ high part of SSE register for non-trapping math. */
+ else if (SSE_REG_P (op1) && !flag_trapping_math)
+ operands[4] = simplify_gen_subreg (V4SImode, operands[1], SImode, 0);
+ else
+ gcc_unreachable ();
})
-(define_insn "*floatdidf2_mixed"
- [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
- "@
- fild%z1\t%1
- #
- cvtsi2sd{q}\t{%1, %0|%0, %1}
- cvtsi2sd{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
- (set_attr "mode" "DF")
- (set_attr "unit" "*,i387,*,*")
- (set_attr "athlon_decode" "*,*,double,direct")
- (set_attr "amdfam10_decode" "*,*,vector,double")
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SI 1 "memory_operand" "")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(const_int 0)]
+{
+ operands[3] = simplify_gen_subreg (mode, operands[0],
+ mode, 0);
+ operands[4] = simplify_gen_subreg (V4SImode, operands[0], mode, 0);
+
+ emit_insn (gen_sse2_loadld (operands[4],
+ CONST0_RTX (V4SImode), operands[1]));
+ emit_insn
+ (gen_sse2_cvtdq2p (operands[3], operands[4]));
+ DONE;
+})
+
+(define_insn "*float2_sse_with_temp"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x")
+ (float:MODEF
+ (match_operand:SSEMODEI24 1 "nonimmediate_operand" "r,m")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=m,X"))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH"
+ "#"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "")
+ (set_attr "athlon_decode" "double,direct")
+ (set_attr "amdfam10_decode" "vector,double")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatdidf2_sse"
- [(set (match_operand:DF 0 "register_operand" "=x,x")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
- "cvtsi2sd{q}\t{%1, %0|%0, %1}"
+(define_insn "*float2_sse_interunit"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x")
+ (float:MODEF
+ (match_operand:SSEMODEI24 1 "nonimmediate_operand" "r,m")))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
+ && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
+ "cvtsi2s\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
- (set_attr "mode" "DF")
+ (set_attr "mode" "")
(set_attr "athlon_decode" "double,direct")
(set_attr "amdfam10_decode" "vector,double")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatdidf2_i387"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387"
- "@
- fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "DF")
- (set_attr "unit" "*,i387")
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SSEMODEI24 1 "nonimmediate_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
+ && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(set (match_dup 0) (float:MODEF (match_dup 1)))]
+ "")
+
+(define_insn "*float2_sse_nointerunit"
+ [(set (match_operand:MODEF 0 "register_operand" "=x")
+ (float:MODEF
+ (match_operand:SSEMODEI24 1 "memory_operand" "m")))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
+ && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
+ "cvtsi2s\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "")
+ (set_attr "athlon_decode" "direct")
+ (set_attr "amdfam10_decode" "double")
(set_attr "fp_int_src" "true")])
-(define_insn "floathixf2"
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
+ && !(TARGET_INTER_UNIT_CONVERSIONS || optimize_size)
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (float:MODEF (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (float:MODEF (match_operand:SSEMODEI24 1 "memory_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "(mode != DImode || TARGET_64BIT)
+ && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
+ && reload_completed
+ && (SSE_REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && SSE_REG_P (operands[0])))"
+ [(set (match_dup 0) (float:MODEF (match_dup 1)))]
+ "")
+
+(define_insn "*float2_i387_with_temp"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
+ (float:X87MODEF
+ (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,?r")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=X,m"))]
"TARGET_80387"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
- (set_attr "mode" "XF")
+ (set_attr "mode" "")
(set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
-(define_insn "floatsixf2"
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
+(define_insn "*float2_i387"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f")
+ (float:X87MODEF
+ (match_operand:SSEMODEI24 1 "memory_operand" "m")))]
"TARGET_80387"
- "@
- fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "XF")
- (set_attr "unit" "*,i387")
+ "fild%z1\t%1"
+ [(set_attr "type" "fmov")
+ (set_attr "mode" "")
(set_attr "fp_int_src" "true")])
-(define_insn "floatdixf2"
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
- "TARGET_80387"
- "@
- fild%z1\t%1
- #"
- [(set_attr "type" "fmov,multi")
- (set_attr "mode" "XF")
- (set_attr "unit" "*,i387")
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "TARGET_80387
+ && reload_completed
+ && FP_REG_P (operands[0])"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (float:X87MODEF (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:SSEMODEI24 1 "memory_operand" "")))
+ (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))]
+ "TARGET_80387
+ && reload_completed
+ && FP_REG_P (operands[0])"
+ [(set (match_dup 0) (float:X87MODEF (match_dup 1)))]
+ "")
+
+;; Avoid store forwarding (partial memory) stall penalty
+;; by passing DImode value through XMM registers. */
+
+(define_insn "floatdi2_i387_with_xmm"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
+ (float:X87MODEF
+ (match_operand:DI 1 "nonimmediate_operand" "m,?r")))
+ (clobber (match_scratch:V4SI 3 "=X,x"))
+ (clobber (match_scratch:V4SI 4 "=X,x"))
+ (clobber (match_operand:DI 2 "memory_operand" "=X,m"))]
+ "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES
+ && !TARGET_64BIT && !optimize_size"
+ "#"
+ [(set_attr "type" "multi")
+ (set_attr "mode" "")
+ (set_attr "unit" "i387")
(set_attr "fp_int_src" "true")])
-;; %%% Kill these when reload knows how to do it.
(define_split
- [(set (match_operand 0 "fp_register_operand" "")
- (float (match_operand 1 "register_operand" "")))]
- "reload_completed
- && TARGET_80387
- && FLOAT_MODE_P (GET_MODE (operands[0]))"
- [(const_int 0)]
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:DI 1 "register_operand" "")))
+ (clobber (match_scratch:V4SI 3 ""))
+ (clobber (match_scratch:V4SI 4 ""))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES
+ && !TARGET_64BIT && !optimize_size
+ && reload_completed
+ && FP_REG_P (operands[0])"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (float:X87MODEF (match_dup 2)))]
{
- operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
- operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[2]));
- ix86_free_from_memory (GET_MODE (operands[1]));
- DONE;
+ /* The DImode arrived in a pair of integral registers (e.g. %edx:%eax).
+ Assemble the 64-bit DImode value in an xmm register. */
+ emit_insn (gen_sse2_loadld (operands[3], CONST0_RTX (V4SImode),
+ gen_rtx_SUBREG (SImode, operands[1], 0)));
+ emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode),
+ gen_rtx_SUBREG (SImode, operands[1], 4)));
+ emit_insn (gen_sse2_punpckldq (operands[3], operands[3], operands[4]));
+
+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
})
-(define_expand "floatunssisf2"
- [(use (match_operand:SF 0 "register_operand" ""))
- (use (match_operand:SI 1 "nonimmediate_operand" ""))]
- "!TARGET_64BIT"
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (float:X87MODEF (match_operand:DI 1 "memory_operand" "")))
+ (clobber (match_scratch:V4SI 3 ""))
+ (clobber (match_scratch:V4SI 4 ""))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES
+ && !TARGET_64BIT && !optimize_size
+ && reload_completed
+ && FP_REG_P (operands[0])"
+ [(set (match_dup 0) (float:X87MODEF (match_dup 1)))]
+ "")
+
+;; Avoid store forwarding (partial memory) stall penalty by extending
+;; SImode value to DImode through XMM register instead of pushing two
+;; SImode values to stack. Note that even !TARGET_INTER_UNIT_MOVES
+;; targets benefit from this optimization. Also note that fild
+;; loads from memory only.
+
+(define_insn "*floatunssi2_1"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
+ (unsigned_float:X87MODEF
+ (match_operand:SI 1 "nonimmediate_operand" "x,m")))
+ (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
+ (clobber (match_scratch:SI 3 "=X,x"))]
+ "!TARGET_64BIT
+ && TARGET_80387 && TARGET_SSE"
+ "#"
+ [(set_attr "type" "multi")
+ (set_attr "mode" "")])
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (unsigned_float:X87MODEF
+ (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))
+ (clobber (match_scratch:SI 3 ""))]
+ "!TARGET_64BIT
+ && TARGET_80387 && TARGET_SSE
+ && reload_completed"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0)
+ (float:X87MODEF (match_dup 2)))]
+ "operands[1] = simplify_gen_subreg (DImode, operands[1], SImode, 0);")
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (unsigned_float:X87MODEF
+ (match_operand:SI 1 "memory_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))
+ (clobber (match_scratch:SI 3 ""))]
+ "!TARGET_64BIT
+ && TARGET_80387 && TARGET_SSE
+ && reload_completed"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0)
+ (float:X87MODEF (match_dup 2)))]
{
- if (TARGET_SSE_MATH && TARGET_SSE2)
- ix86_expand_convert_uns_sisf_sse (operands[0], operands[1]);
- else
- x86_emit_floatuns (operands);
- DONE;
+ emit_move_insn (operands[3], operands[1]);
+ operands[3] = simplify_gen_subreg (DImode, operands[3], SImode, 0);
})
-(define_expand "floatunssidf2"
- [(use (match_operand:DF 0 "register_operand" ""))
- (use (match_operand:SI 1 "nonimmediate_operand" ""))]
- "!TARGET_64BIT && TARGET_SSE_MATH && TARGET_SSE2"
- "ix86_expand_convert_uns_sidf_sse (operands[0], operands[1]); DONE;")
+(define_expand "floatunssi2"
+ [(parallel
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (unsigned_float:X87MODEF
+ (match_operand:SI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))
+ (clobber (match_scratch:SI 3 ""))])]
+ "!TARGET_64BIT
+ && ((TARGET_80387 && TARGET_SSE)
+ || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))"
+{
+ if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ {
+ ix86_expand_convert_uns_si_sse (operands[0], operands[1]);
+ DONE;
+ }
+ else
+ {
+ int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+ operands[2] = assign_386_stack_local (DImode, slot);
+ }
+})
(define_expand "floatunsdisf2"
[(use (match_operand:SF 0 "register_operand" ""))
@@ -4997,8 +5479,8 @@
(define_expand "floatunsdidf2"
[(use (match_operand:DF 0 "register_operand" ""))
(use (match_operand:DI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE_MATH && TARGET_SSE2
- && (TARGET_64BIT || TARGET_KEEPS_VECTOR_ALIGNED_STACK)"
+ "(TARGET_64BIT || TARGET_KEEPS_VECTOR_ALIGNED_STACK)
+ && TARGET_SSE2 && TARGET_SSE_MATH"
{
if (TARGET_64BIT)
x86_emit_floatuns (operands);
@@ -5007,9 +5489,6 @@
DONE;
})
-;; SSE extract/set expanders
-
-
;; Add instructions
;; %%% splits for addditi3
@@ -5044,9 +5523,7 @@
(match_dup 4))
(match_dup 5)))
(clobber (reg:CC FLAGS_REG))])]
- "split_ti (operands+0, 1, operands+0, operands+3);
- split_ti (operands+1, 1, operands+1, operands+4);
- split_ti (operands+2, 1, operands+2, operands+5);")
+ "split_ti (&operands[0], 3, &operands[0], &operands[3]);")
;; %%% splits for addsidi3
; [(set (match_operand:DI 0 "nonimmediate_operand" "")
@@ -5083,9 +5560,7 @@
(match_dup 4))
(match_dup 5)))
(clobber (reg:CC FLAGS_REG))])]
- "split_di (operands+0, 1, operands+0, operands+3);
- split_di (operands+1, 1, operands+1, operands+4);
- split_di (operands+2, 1, operands+2, operands+5);")
+ "split_di (&operands[0], 3, &operands[0], &operands[3]);")
(define_insn "adddi3_carry_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
@@ -5111,6 +5586,56 @@
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
+(define_insn "*3_cc_overflow"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plusminus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "0,0")
+ (match_operand:SWI 2 "" ",m"))
+ (match_dup 1)))
+ (set (match_operand:SWI 0 "nonimmediate_operand" "=m,")
+ (plusminus:SWI (match_dup 1) (match_dup 2)))]
+ "ix86_binary_operator_ok (, mode, operands)"
+ "{}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "")])
+
+(define_insn "*add3_cconly_overflow"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0")
+ (match_operand:SWI 2 "" "m"))
+ (match_dup 1)))
+ (clobber (match_scratch:SWI 0 "="))]
+ "ix86_binary_operator_ok (PLUS, mode, operands)"
+ "add{}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "")])
+
+(define_insn "*sub3_cconly_overflow"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "m,")
+ (match_operand:SWI 1 "" ",m"))
+ (match_dup 0)))]
+ ""
+ "cmp{}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "icmp")
+ (set_attr "mode" "")])
+
+(define_insn "*si3_zext_cc_overflow"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plusminus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_dup 1)))
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)"
+ "{l}\t{%2, %k0|%k0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "SI")])
+
(define_insn "addqi3_carry"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
(plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
@@ -5152,7 +5677,7 @@
(zero_extend:DI
(plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
(match_operand:SI 1 "nonimmediate_operand" "%0"))
- (match_operand:SI 2 "general_operand" "rim"))))
+ (match_operand:SI 2 "general_operand" "g"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %k0|%k0, %2}"
@@ -6730,18 +7255,11 @@
"TARGET_80387"
"")
-(define_expand "adddf3"
- [(set (match_operand:DF 0 "register_operand" "")
- (plus:DF (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "")
-
-(define_expand "addsf3"
- [(set (match_operand:SF 0 "register_operand" "")
- (plus:SF (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
+(define_expand "add3"
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (plus:MODEF (match_operand:MODEF 1 "register_operand" "")
+ (match_operand:MODEF 2 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
"")
;; Subtract instructions
@@ -6777,9 +7295,7 @@
(plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 5))))
(clobber (reg:CC FLAGS_REG))])]
- "split_ti (operands+0, 1, operands+0, operands+3);
- split_ti (operands+1, 1, operands+1, operands+4);
- split_ti (operands+2, 1, operands+2, operands+5);")
+ "split_ti (&operands[0], 3, &operands[0], &operands[3]);")
;; %%% splits for subsidi3
@@ -6812,9 +7328,7 @@
(plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 5))))
(clobber (reg:CC FLAGS_REG))])]
- "split_di (operands+0, 1, operands+0, operands+3);
- split_di (operands+1, 1, operands+1, operands+4);
- split_di (operands+2, 1, operands+2, operands+5);")
+ "split_di (&operands[0], 3, &operands[0], &operands[3]);")
(define_insn "subdi3_carry_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
@@ -6901,11 +7415,11 @@
(set_attr "mode" "SI")])
(define_insn "subsi3_carry_zext"
- [(set (match_operand:DI 0 "register_operand" "=rm,r")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (minus:SI (match_operand:SI 1 "register_operand" "0")
(plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
- (match_operand:SI 2 "general_operand" "ri,rm")))))
+ (match_operand:SI 2 "general_operand" "g")))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sbb{l}\t{%2, %k0|%k0, %2}"
@@ -6935,7 +7449,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "rim"))))
+ (match_operand:SI 2 "general_operand" "g"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\t{%2, %k0|%k0, %2}"
@@ -6960,7 +7474,7 @@
[(set (reg FLAGS_REG)
(compare
(minus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "rim"))
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
@@ -6987,7 +7501,7 @@
(define_insn "*subsi_3_zext"
[(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "rim")))
+ (match_operand:SI 2 "general_operand" "g")))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_dup 1)
@@ -7106,18 +7620,11 @@
"TARGET_80387"
"")
-(define_expand "subdf3"
- [(set (match_operand:DF 0 "register_operand" "")
- (minus:DF (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "")
-
-(define_expand "subsf3"
- [(set (match_operand:SF 0 "register_operand" "")
- (minus:SF (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
+(define_expand "sub3"
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (minus:MODEF (match_operand:MODEF 1 "register_operand" "")
+ (match_operand:MODEF 2 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
"")
;; Multiply instructions
@@ -7130,11 +7637,11 @@
"TARGET_64BIT"
"")
-;; On AMDFAM10
+;; On AMDFAM10
;; IMUL reg64, reg64, imm8 Direct
;; IMUL reg64, mem64, imm8 VectorPath
;; IMUL reg64, reg64, imm32 Direct
-;; IMUL reg64, mem64, imm32 VectorPath
+;; IMUL reg64, mem64, imm32 VectorPath
;; IMUL reg64, reg64 Direct
;; IMUL reg64, mem64 Direct
@@ -7164,7 +7671,7 @@
(cond [(and (eq_attr "alternative" "0,1")
(match_operand 1 "memory_operand" ""))
(const_string "vector")]
- (const_string "direct")))
+ (const_string "direct")))
(set_attr "mode" "DI")])
(define_expand "mulsi3"
@@ -7175,7 +7682,7 @@
""
"")
-;; On AMDFAM10
+;; On AMDFAM10
;; IMUL reg32, reg32, imm8 Direct
;; IMUL reg32, mem32, imm8 VectorPath
;; IMUL reg32, reg32, imm32 Direct
@@ -7208,7 +7715,7 @@
(cond [(and (eq_attr "alternative" "0,1")
(match_operand 1 "memory_operand" ""))
(const_string "vector")]
- (const_string "direct")))
+ (const_string "direct")))
(set_attr "mode" "SI")])
(define_insn "*mulsi3_1_zext"
@@ -7238,7 +7745,7 @@
(cond [(and (eq_attr "alternative" "0,1")
(match_operand 1 "memory_operand" ""))
(const_string "vector")]
- (const_string "direct")))
+ (const_string "direct")))
(set_attr "mode" "SI")])
(define_expand "mulhi3"
@@ -7306,7 +7813,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "direct")))
- (set_attr "amdfam10_decode" "direct")
+ (set_attr "amdfam10_decode" "direct")
(set_attr "mode" "QI")])
(define_expand "umulqihi3"
@@ -7333,7 +7840,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "direct")))
- (set_attr "amdfam10_decode" "direct")
+ (set_attr "amdfam10_decode" "direct")
(set_attr "mode" "QI")])
(define_expand "mulqihi3"
@@ -7358,7 +7865,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "direct")))
- (set_attr "amdfam10_decode" "direct")
+ (set_attr "amdfam10_decode" "direct")
(set_attr "mode" "QI")])
(define_expand "umulditi3"
@@ -7385,7 +7892,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "double")))
- (set_attr "amdfam10_decode" "double")
+ (set_attr "amdfam10_decode" "double")
(set_attr "mode" "DI")])
;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
@@ -7413,7 +7920,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "double")))
- (set_attr "amdfam10_decode" "double")
+ (set_attr "amdfam10_decode" "double")
(set_attr "mode" "SI")])
(define_expand "mulditi3"
@@ -7467,7 +7974,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "double")))
- (set_attr "amdfam10_decode" "double")
+ (set_attr "amdfam10_decode" "double")
(set_attr "mode" "SI")])
(define_expand "umuldi3_highpart"
@@ -7504,7 +8011,7 @@
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
(const_string "double")))
- (set_attr "amdfam10_decode" "double")
+ (set_attr "amdfam10_decode" "double")
(set_attr "mode" "DI")])
(define_expand "umulsi3_highpart"
@@ -7567,7 +8074,7 @@
(set_attr "mode" "SI")])
(define_expand "smuldi3_highpart"
- [(parallel [(set (match_operand:DI 0 "register_operand" "=d")
+ [(parallel [(set (match_operand:DI 0 "register_operand" "")
(truncate:DI
(lshiftrt:TI
(mult:TI (sign_extend:TI
@@ -7668,19 +8175,15 @@
"TARGET_80387"
"")
-(define_expand "muldf3"
- [(set (match_operand:DF 0 "register_operand" "")
- (mult:DF (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
+(define_expand "mul3"
+ [(set (match_operand:MODEF 0 "register_operand" "")
+ (mult:MODEF (match_operand:MODEF 1 "register_operand" "")
+ (match_operand:MODEF 2 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
"")
-(define_expand "mulsf3"
- [(set (match_operand:SF 0 "register_operand" "")
- (mult:SF (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
- "")
+;; SSE5 scalar multiply/add instructions are defined in sse.md.
+
;; Divide instructions
@@ -7725,7 +8228,16 @@
(div:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
"TARGET_80387 || TARGET_SSE_MATH"
- "")
+{
+ if (TARGET_SSE_MATH && TARGET_RECIP && !optimize_size
+ && flag_finite_math_only && !flag_trapping_math
+ && flag_unsafe_math_optimizations)
+ {
+ ix86_emit_swdivsf (operands[0], operands[1],
+ operands[2], SFmode);
+ DONE;
+ }
+})
;; Remainder instructions.
@@ -8521,7 +9033,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))))
+ (match_operand:SI 2 "general_operand" "g"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
"and{l}\t{%2, %k0|%k0, %2}"
@@ -8531,7 +9043,7 @@
(define_insn "*andsi_2"
[(set (reg FLAGS_REG)
(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "rim,ri"))
+ (match_operand:SI 2 "general_operand" "g,ri"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
(and:SI (match_dup 1) (match_dup 2)))]
@@ -8545,7 +9057,7 @@
(define_insn "*andsi_2_zext"
[(set (reg FLAGS_REG)
(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
@@ -8590,7 +9102,7 @@
(define_insn "*andhi_2"
[(set (reg FLAGS_REG)
(compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rim,ri"))
+ (match_operand:HI 2 "general_operand" "g,ri"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
(and:HI (match_dup 1) (match_dup 2)))]
@@ -8899,7 +9411,7 @@
(define_insn "*iorsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "ri,rmi")))
+ (match_operand:SI 2 "general_operand" "ri,g")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (IOR, SImode, operands)"
"or{l}\t{%2, %0|%0, %2}"
@@ -8908,10 +9420,10 @@
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*iorsi_1_zext"
- [(set (match_operand:DI 0 "register_operand" "=rm")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))))
+ (match_operand:SI 2 "general_operand" "g"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
"or{l}\t{%2, %k0|%k0, %2}"
@@ -8919,7 +9431,7 @@
(set_attr "mode" "SI")])
(define_insn "*iorsi_1_zext_imm"
- [(set (match_operand:DI 0 "register_operand" "=rm")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
(clobber (reg:CC FLAGS_REG))]
@@ -8931,7 +9443,7 @@
(define_insn "*iorsi_2"
[(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "rim,ri"))
+ (match_operand:SI 2 "general_operand" "g,ri"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
(ior:SI (match_dup 1) (match_dup 2)))]
@@ -8946,7 +9458,7 @@
(define_insn "*iorsi_2_zext"
[(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))]
@@ -8972,7 +9484,7 @@
(define_insn "*iorsi_3"
[(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"ix86_match_ccmode (insn, CCNOmode)
@@ -8992,7 +9504,7 @@
(define_insn "*iorhi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rmi,ri")))
+ (match_operand:HI 2 "general_operand" "g,ri")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (IOR, HImode, operands)"
"or{w}\t{%2, %0|%0, %2}"
@@ -9002,7 +9514,7 @@
(define_insn "*iorhi_2"
[(set (reg FLAGS_REG)
(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rim,ri"))
+ (match_operand:HI 2 "general_operand" "g,ri"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
(ior:HI (match_dup 1) (match_dup 2)))]
@@ -9015,7 +9527,7 @@
(define_insn "*iorhi_3"
[(set (reg FLAGS_REG)
(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
- (match_operand:HI 2 "general_operand" "rim"))
+ (match_operand:HI 2 "general_operand" "g"))
(const_int 0)))
(clobber (match_scratch:HI 0 "=r"))]
"ix86_match_ccmode (insn, CCNOmode)
@@ -9229,11 +9741,9 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& ix86_binary_operator_ok (XOR, DImode, operands)"
- "@
- xor{q}\t{%2, %0|%0, %2}
- xor{q}\t{%2, %0|%0, %2}"
+ "xor{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
- (set_attr "mode" "DI,DI")])
+ (set_attr "mode" "DI")])
(define_insn "*xordi_2_rex64"
[(set (reg FLAGS_REG)
@@ -9245,11 +9755,9 @@
"TARGET_64BIT
&& ix86_match_ccmode (insn, CCNOmode)
&& ix86_binary_operator_ok (XOR, DImode, operands)"
- "@
- xor{q}\t{%2, %0|%0, %2}
- xor{q}\t{%2, %0|%0, %2}"
+ "xor{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
- (set_attr "mode" "DI,DI")])
+ (set_attr "mode" "DI")])
(define_insn "*xordi_3_rex64"
[(set (reg FLAGS_REG)
@@ -9288,7 +9796,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))))
+ (match_operand:SI 2 "general_operand" "g"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\t{%2, %k0|%k0, %2}"
@@ -9308,7 +9816,7 @@
(define_insn "*xorsi_2"
[(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "rim,ri"))
+ (match_operand:SI 2 "general_operand" "g,ri"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
(xor:SI (match_dup 1) (match_dup 2)))]
@@ -9323,7 +9831,7 @@
(define_insn "*xorsi_2_zext"
[(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
@@ -9349,7 +9857,7 @@
(define_insn "*xorsi_3"
[(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "rim"))
+ (match_operand:SI 2 "general_operand" "g"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"ix86_match_ccmode (insn, CCNOmode)
@@ -9369,7 +9877,7 @@
(define_insn "*xorhi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rmi,ri")))
+ (match_operand:HI 2 "general_operand" "g,ri")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (XOR, HImode, operands)"
"xor{w}\t{%2, %0|%0, %2}"
@@ -9379,7 +9887,7 @@
(define_insn "*xorhi_2"
[(set (reg FLAGS_REG)
(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rim,ri"))
+ (match_operand:HI 2 "general_operand" "g,ri"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
(xor:HI (match_dup 1) (match_dup 2)))]
@@ -9392,7 +9900,7 @@
(define_insn "*xorhi_3"
[(set (reg FLAGS_REG)
(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
- (match_operand:HI 2 "general_operand" "rim"))
+ (match_operand:HI 2 "general_operand" "g"))
(const_int 0)))
(clobber (match_scratch:HI 0 "=r"))]
"ix86_match_ccmode (insn, CCNOmode)
@@ -9674,20 +10182,19 @@
"TARGET_64BIT && reload_completed"
[(parallel
[(set (reg:CCZ FLAGS_REG)
- (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
- (set (match_dup 0) (neg:DI (match_dup 2)))])
+ (compare:CCZ (neg:DI (match_dup 1)) (const_int 0)))
+ (set (match_dup 0) (neg:DI (match_dup 1)))])
(parallel
- [(set (match_dup 1)
+ [(set (match_dup 2)
(plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 3))
(const_int 0)))
(clobber (reg:CC FLAGS_REG))])
(parallel
- [(set (match_dup 1)
- (neg:DI (match_dup 1)))
+ [(set (match_dup 2)
+ (neg:DI (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
- "split_ti (operands+1, 1, operands+2, operands+3);
- split_ti (operands+0, 1, operands+0, operands+1);")
+ "split_ti (&operands[0], 2, &operands[0], &operands[2]);")
(define_expand "negdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
@@ -9711,20 +10218,19 @@
"!TARGET_64BIT && reload_completed"
[(parallel
[(set (reg:CCZ FLAGS_REG)
- (compare:CCZ (neg:SI (match_dup 2)) (const_int 0)))
- (set (match_dup 0) (neg:SI (match_dup 2)))])
+ (compare:CCZ (neg:SI (match_dup 1)) (const_int 0)))
+ (set (match_dup 0) (neg:SI (match_dup 1)))])
(parallel
- [(set (match_dup 1)
+ [(set (match_dup 2)
(plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 3))
(const_int 0)))
(clobber (reg:CC FLAGS_REG))])
(parallel
- [(set (match_dup 1)
- (neg:SI (match_dup 1)))
+ [(set (match_dup 2)
+ (neg:SI (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
- "split_di (operands+1, 1, operands+2, operands+3);
- split_di (operands+0, 1, operands+0, operands+1);")
+ "split_di (&operands[0], 2, &operands[0], &operands[2]);");
(define_insn "*negdi2_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
@@ -9852,233 +10358,67 @@
"ix86_unary_operator_ok (NEG, QImode, operands)"
"neg{b}\t%0"
[(set_attr "type" "negnot")
- (set_attr "mode" "QI")])
-
-(define_insn "*negqi2_cmpz"
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
- (const_int 0)))
- (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
- (neg:QI (match_dup 1)))]
- "ix86_unary_operator_ok (NEG, QImode, operands)"
- "neg{b}\t%0"
- [(set_attr "type" "negnot")
- (set_attr "mode" "QI")])
-
-;; Changing of sign for FP values is doable using integer unit too.
-
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
- "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;")
-
-(define_expand "abssf2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE_MATH"
- "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
-
-(define_insn "*absnegsf2_mixed"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=x ,x,f,rm")
- (match_operator:SF 3 "absneg_operator"
- [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0,0 ")]))
- (use (match_operand:V4SF 2 "nonimmediate_operand" "xm ,0,X,X "))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
- && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
- "#")
-
-(define_insn "*absnegsf2_sse"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=x,x,rm")
- (match_operator:SF 3 "absneg_operator"
- [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")]))
- (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,X"))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_SSE_MATH
- && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
- "#")
-
-(define_insn "*absnegsf2_i387"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm")
- (match_operator:SF 3 "absneg_operator"
- [(match_operand:SF 1 "nonimmediate_operand" "0,0")]))
- (use (match_operand 2 "" ""))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_80387 && !TARGET_SSE_MATH
- && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
- "#")
-
-(define_expand "copysignsf3"
- [(match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "nonmemory_operand" "")
- (match_operand:SF 2 "register_operand" "")]
- "TARGET_SSE_MATH"
-{
- ix86_expand_copysign (operands);
- DONE;
-})
-
-(define_insn_and_split "copysignsf3_const"
- [(set (match_operand:SF 0 "register_operand" "=x")
- (unspec:SF
- [(match_operand:V4SF 1 "vector_move_operand" "xmC")
- (match_operand:SF 2 "register_operand" "0")
- (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
- UNSPEC_COPYSIGN))]
- "TARGET_SSE_MATH"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- ix86_split_copysign_const (operands);
- DONE;
-})
-
-(define_insn "copysignsf3_var"
- [(set (match_operand:SF 0 "register_operand" "=x, x, x, x,x")
- (unspec:SF
- [(match_operand:SF 2 "register_operand" " x, 0, 0, x,x")
- (match_operand:SF 3 "register_operand" " 1, 1, x, 1,x")
- (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
- (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:V4SF 1 "=x, x, x, x,x"))]
- "TARGET_SSE_MATH"
- "#")
+ (set_attr "mode" "QI")])
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (unspec:SF
- [(match_operand:SF 2 "register_operand" "")
- (match_operand:SF 3 "register_operand" "")
- (match_operand:V4SF 4 "" "")
- (match_operand:V4SF 5 "" "")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:V4SF 1 ""))]
- "TARGET_SSE_MATH && reload_completed"
- [(const_int 0)]
-{
- ix86_split_copysign_var (operands);
- DONE;
-})
+(define_insn "*negqi2_cmpz"
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (neg:QI (match_dup 1)))]
+ "ix86_unary_operator_ok (NEG, QImode, operands)"
+ "neg{b}\t%0"
+ [(set_attr "type" "negnot")
+ (set_attr "mode" "QI")])
-(define_expand "negdf2"
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;")
+;; Changing of sign for FP values is doable using integer unit too.
-(define_expand "absdf2"
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
+(define_expand "2"
+ [(set (match_operand:X87MODEF 0 "register_operand" "")
+ (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "")))]
+ "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
+ "ix86_expand_fp_absneg_operator (, mode, operands); DONE;")
-(define_insn "*absnegdf2_mixed"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=x,x,f,rm")
- (match_operator:DF 3 "absneg_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "0 ,x,0,0")]))
- (use (match_operand:V2DF 2 "nonimmediate_operand" "xm,0,X,X"))
+(define_insn "*absneg2_mixed"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x,f,!r")
+ (match_operator:MODEF 3 "absneg_operator"
+ [(match_operand:MODEF 1 "register_operand" "0,x,0,0")]))
+ (use (match_operand: 2 "nonimmediate_operand" "xm,0,X,X"))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
- && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
+ "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (mode)"
"#")
-(define_insn "*absnegdf2_sse"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=x,x,rm")
- (match_operator:DF 3 "absneg_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "0 ,x,0 ")]))
- (use (match_operand:V2DF 2 "nonimmediate_operand" "xm,0,X "))
+(define_insn "*absneg2_sse"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x,!r")
+ (match_operator:MODEF 3 "absneg_operator"
+ [(match_operand:MODEF 1 "register_operand" "0 ,x,0")]))
+ (use (match_operand: 2 "register_operand" "xm,0,X"))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_SSE2 && TARGET_SSE_MATH
- && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
+ "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH"
"#")
-(define_insn "*absnegdf2_i387"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm")
- (match_operator:DF 3 "absneg_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "0,0")]))
+(define_insn "*absneg2_i387"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,!r")
+ (match_operator:X87MODEF 3 "absneg_operator"
+ [(match_operand:X87MODEF 1 "register_operand" "0,0")]))
(use (match_operand 2 "" ""))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
- && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
- "#")
-
-(define_expand "copysigndf3"
- [(match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "nonmemory_operand" "")
- (match_operand:DF 2 "register_operand" "")]
- "TARGET_SSE2 && TARGET_SSE_MATH"
-{
- ix86_expand_copysign (operands);
- DONE;
-})
-
-(define_insn_and_split "copysigndf3_const"
- [(set (match_operand:DF 0 "register_operand" "=x")
- (unspec:DF
- [(match_operand:V2DF 1 "vector_move_operand" "xmC")
- (match_operand:DF 2 "register_operand" "0")
- (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
- UNSPEC_COPYSIGN))]
- "TARGET_SSE2 && TARGET_SSE_MATH"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- ix86_split_copysign_const (operands);
- DONE;
-})
-
-(define_insn "copysigndf3_var"
- [(set (match_operand:DF 0 "register_operand" "=x, x, x, x,x")
- (unspec:DF
- [(match_operand:DF 2 "register_operand" " x, 0, 0, x,x")
- (match_operand:DF 3 "register_operand" " 1, 1, x, 1,x")
- (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
- (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:V2DF 1 "=x, x, x, x,x"))]
- "TARGET_SSE2 && TARGET_SSE_MATH"
+ "TARGET_80387 && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)"
"#")
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (unspec:DF
- [(match_operand:DF 2 "register_operand" "")
- (match_operand:DF 3 "register_operand" "")
- (match_operand:V2DF 4 "" "")
- (match_operand:V2DF 5 "" "")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:V2DF 1 ""))]
- "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
- [(const_int 0)]
-{
- ix86_split_copysign_var (operands);
- DONE;
-})
-
-(define_expand "negxf2"
- [(set (match_operand:XF 0 "nonimmediate_operand" "")
- (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;")
-
-(define_expand "absxf2"
- [(set (match_operand:XF 0 "nonimmediate_operand" "")
- (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;")
+(define_expand "tf2"
+ [(set (match_operand:TF 0 "register_operand" "")
+ (absneg:TF (match_operand:TF 1 "register_operand" "")))]
+ "TARGET_64BIT"
+ "ix86_expand_fp_absneg_operator (, TFmode, operands); DONE;")
-(define_insn "*absnegxf2_i387"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm")
- (match_operator:XF 3 "absneg_operator"
- [(match_operand:XF 1 "nonimmediate_operand" "0,0")]))
- (use (match_operand 2 "" ""))
+(define_insn "*absnegtf2_sse"
+ [(set (match_operand:TF 0 "register_operand" "=x,x")
+ (match_operator:TF 3 "absneg_operator"
+ [(match_operand:TF 1 "register_operand" "0,x")]))
+ (use (match_operand:TF 2 "nonimmediate_operand" "xm,0"))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_80387
- && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)"
+ "TARGET_64BIT"
"#")
;; Splitters for fp abs and neg.
@@ -10207,137 +10547,109 @@
operands[1] = tmp;
})
-(define_split
- [(set (match_operand 0 "memory_operand" "")
- (match_operator 1 "absneg_operator" [(match_dup 0)]))
- (use (match_operand 2 "" ""))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (match_dup 1))
- (clobber (reg:CC FLAGS_REG))])]
-{
- enum machine_mode mode = GET_MODE (operands[0]);
- int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode);
- rtx tmp;
-
- operands[0] = adjust_address (operands[0], QImode, size - 1);
- if (GET_CODE (operands[1]) == ABS)
- {
- tmp = gen_int_mode (0x7f, QImode);
- tmp = gen_rtx_AND (QImode, operands[0], tmp);
- }
- else
- {
- tmp = gen_int_mode (0x80, QImode);
- tmp = gen_rtx_XOR (QImode, operands[0], tmp);
- }
- operands[1] = tmp;
-})
-
;; Conditionalize these after reload. If they match before reload, we
;; lose the clobber and ability to use integer instructions.
-(define_insn "*negsf2_1"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
- "fchs"
+(define_insn "*2_1"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f")
+ (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))]
+ "TARGET_80387
+ && (reload_completed
+ || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))"
+ "f"
[(set_attr "type" "fsgn")
- (set_attr "mode" "SF")])
+ (set_attr "mode" "")])
-(define_insn "*negdf2_1"
+(define_insn "*extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (match_operand:DF 1 "register_operand" "0")))]
- "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
- "fchs"
+ (absneg:DF (float_extend:DF
+ (match_operand:SF 1 "register_operand" "0"))))]
+ "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
+ "f"
[(set_attr "type" "fsgn")
(set_attr "mode" "DF")])
-(define_insn "*negxf2_1"
+(define_insn "*extendsfxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (match_operand:XF 1 "register_operand" "0")))]
+ (absneg:XF (float_extend:XF
+ (match_operand:SF 1 "register_operand" "0"))))]
"TARGET_80387"
- "fchs"
+ "f"
[(set_attr "type" "fsgn")
(set_attr "mode" "XF")])
-(define_insn "*abssf2_1"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
- "fabs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "SF")])
-
-(define_insn "*absdf2_1"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (match_operand:DF 1 "register_operand" "0")))]
- "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
- "fabs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "DF")])
-
-(define_insn "*absxf2_1"
+(define_insn "*extenddfxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
- (abs:XF (match_operand:XF 1 "register_operand" "0")))]
+ (absneg:XF (float_extend:XF
+ (match_operand:DF 1 "register_operand" "0"))))]
"TARGET_80387"
- "fabs"
+ "f"
[(set_attr "type" "fsgn")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "XF")])
-(define_insn "*negextendsfdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "DF")])
+;; Copysign instructions
-(define_insn "*negextenddfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (float_extend:XF
- (match_operand:DF 1 "register_operand" "0"))))]
- "TARGET_80387"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")])
+(define_mode_iterator CSGNMODE [SF DF TF])
+(define_mode_attr CSGNVMODE [(SF "V4SF") (DF "V2DF") (TF "TF")])
-(define_insn "*negextendsfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (float_extend:XF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")])
+(define_expand "copysign3"
+ [(match_operand:CSGNMODE 0 "register_operand" "")
+ (match_operand:CSGNMODE 1 "nonmemory_operand" "")
+ (match_operand:CSGNMODE 2 "register_operand" "")]
+ "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || (TARGET_64BIT && (mode == TFmode))"
+{
+ ix86_expand_copysign (operands);
+ DONE;
+})
-(define_insn "*absextendsfdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
- "fabs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "DF")])
+(define_insn_and_split "copysign3_const"
+ [(set (match_operand:CSGNMODE 0 "register_operand" "=x")
+ (unspec:CSGNMODE
+ [(match_operand: 1 "vector_move_operand" "xmC")
+ (match_operand:CSGNMODE 2 "register_operand" "0")
+ (match_operand: 3 "nonimmediate_operand" "xm")]
+ UNSPEC_COPYSIGN))]
+ "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || (TARGET_64BIT && (mode == TFmode))"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ ix86_split_copysign_const (operands);
+ DONE;
+})
-(define_insn "*absextenddfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (abs:XF (float_extend:XF
- (match_operand:DF 1 "register_operand" "0"))))]
- "TARGET_80387"
- "fabs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")])
+(define_insn "copysign3_var"
+ [(set (match_operand:CSGNMODE 0 "register_operand" "=x,x,x,x,x")
+ (unspec:CSGNMODE
+ [(match_operand:CSGNMODE 2 "register_operand" "x,0,0,x,x")
+ (match_operand:CSGNMODE 3 "register_operand" "1,1,x,1,x")
+ (match_operand: 4 "nonimmediate_operand" "X,xm,xm,0,0")
+ (match_operand: 5 "nonimmediate_operand" "0,xm,1,xm,1")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch: 1 "=x,x,x,x,x"))]
+ "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ || (TARGET_64BIT && (mode == TFmode))"
+ "#")
-(define_insn "*absextendsfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (abs:XF (float_extend:XF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387"
- "fabs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")])
+(define_split
+ [(set (match_operand:CSGNMODE 0 "register_operand" "")
+ (unspec:CSGNMODE
+ [(match_operand:CSGNMODE 2 "register_operand" "")
+ (match_operand:CSGNMODE 3 "register_operand" "")
+ (match_operand: