OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / sse.md
1 ;; GCC machine description for SSE instructions
2 ;; Copyright (C) 2005, 2006, 2007, 2008
3 ;; Free Software Foundation, Inc.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21
22 ;; 16 byte integral modes handled by SSE, minus TImode, which gets
23 ;; special-cased for TARGET_64BIT.
24 (define_mode_iterator SSEMODEI [V16QI V8HI V4SI V2DI])
25
26 ;; All 16-byte vector modes handled by SSE
27 (define_mode_iterator SSEMODE [V16QI V8HI V4SI V2DI V4SF V2DF])
28
29 ;; Mix-n-match
30 (define_mode_iterator SSEMODE12 [V16QI V8HI])
31 (define_mode_iterator SSEMODE24 [V8HI V4SI])
32 (define_mode_iterator SSEMODE14 [V16QI V4SI])
33 (define_mode_iterator SSEMODE124 [V16QI V8HI V4SI])
34 (define_mode_iterator SSEMODE248 [V8HI V4SI V2DI])
35 (define_mode_iterator SSEMODE1248 [V16QI V8HI V4SI V2DI])
36 (define_mode_iterator SSEMODEF4 [SF DF V4SF V2DF])
37 (define_mode_iterator SSEMODEF2P [V4SF V2DF])
38
39 ;; Mapping from float mode to required SSE level
40 (define_mode_attr sse [(SF "sse") (DF "sse2") (V4SF "sse") (V2DF "sse2")])
41
42 ;; Mapping from integer vector mode to mnemonic suffix
43 (define_mode_attr ssevecsize [(V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")])
44
45 ;; Mapping of the sse5 suffix
46 (define_mode_attr ssemodesuffixf4 [(SF "ss") (DF "sd") (V4SF "ps") (V2DF "pd")])
47 (define_mode_attr ssemodesuffixf2s [(SF "ss") (DF "sd") (V4SF "ss") (V2DF "sd")])
48 (define_mode_attr ssemodesuffixf2c [(V4SF "s") (V2DF "d")])
49
50 ;; Mapping of the max integer size for sse5 rotate immediate constraint
51 (define_mode_attr sserotatemax [(V16QI "7") (V8HI "15") (V4SI "31") (V2DI "63")])
52
53 ;; Mapping of vector modes back to the scalar modes
54 (define_mode_attr ssescalarmode [(V4SF "SF") (V2DF "DF")])
55
56 ;; Mapping of immediate bits for blend instructions
57 (define_mode_attr blendbits [(V4SF "15") (V2DF "3")])
58
59 ;; Patterns whose name begins with "sse{,2,3}_" are invoked by intrinsics.
60
61 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62 ;;
63 ;; Move patterns
64 ;;
65 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
66
67 ;; All of these patterns are enabled for SSE1 as well as SSE2.
68 ;; This is essential for maintaining stable calling conventions.
69
70 (define_expand "mov<mode>"
71   [(set (match_operand:SSEMODEI 0 "nonimmediate_operand" "")
72         (match_operand:SSEMODEI 1 "nonimmediate_operand" ""))]
73   "TARGET_SSE"
74 {
75   ix86_expand_vector_move (<MODE>mode, operands);
76   DONE;
77 })
78
79 (define_insn "*mov<mode>_internal"
80   [(set (match_operand:SSEMODEI 0 "nonimmediate_operand" "=x,x ,m")
81         (match_operand:SSEMODEI 1 "nonimmediate_or_sse_const_operand"  "C ,xm,x"))]
82   "TARGET_SSE
83    && (register_operand (operands[0], <MODE>mode)
84        || register_operand (operands[1], <MODE>mode))"
85 {
86   switch (which_alternative)
87     {
88     case 0:
89       return standard_sse_constant_opcode (insn, operands[1]);
90     case 1:
91     case 2:
92       if (get_attr_mode (insn) == MODE_V4SF)
93         return "movaps\t{%1, %0|%0, %1}";
94       else
95         return "movdqa\t{%1, %0|%0, %1}";
96     default:
97       gcc_unreachable ();
98     }
99 }
100   [(set_attr "type" "sselog1,ssemov,ssemov")
101    (set (attr "mode")
102         (if_then_else
103           (ior (ior (ne (symbol_ref "optimize_size") (const_int 0))
104                     (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
105                (and (eq_attr "alternative" "2")
106                     (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
107                         (const_int 0))))
108           (const_string "V4SF")
109           (const_string "TI")))])
110
111 ;; Move a DI from a 32-bit register pair (e.g. %edx:%eax) to an xmm.
112 ;; We'd rather avoid this entirely; if the 32-bit reg pair was loaded
113 ;; from memory, we'd prefer to load the memory directly into the %xmm
114 ;; register.  To facilitate this happy circumstance, this pattern won't
115 ;; split until after register allocation.  If the 64-bit value didn't
116 ;; come from memory, this is the best we can do.  This is much better
117 ;; than storing %edx:%eax into a stack temporary and loading an %xmm
118 ;; from there.
119
120 (define_insn_and_split "movdi_to_sse"
121   [(parallel
122     [(set (match_operand:V4SI 0 "register_operand" "=?x,x")
123           (subreg:V4SI (match_operand:DI 1 "nonimmediate_operand" "r,m") 0))
124      (clobber (match_scratch:V4SI 2 "=&x,X"))])]
125   "!TARGET_64BIT && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES"
126   "#"
127   "&& reload_completed"
128   [(const_int 0)]
129 {
130  if (register_operand (operands[1], DImode))
131    {
132       /* The DImode arrived in a pair of integral registers (e.g. %edx:%eax).
133          Assemble the 64-bit DImode value in an xmm register.  */
134       emit_insn (gen_sse2_loadld (operands[0], CONST0_RTX (V4SImode),
135                                   gen_rtx_SUBREG (SImode, operands[1], 0)));
136       emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode),
137                                   gen_rtx_SUBREG (SImode, operands[1], 4)));
138       emit_insn (gen_sse2_punpckldq (operands[0], operands[0], operands[2]));
139     }
140  else if (memory_operand (operands[1], DImode))
141       emit_insn (gen_vec_concatv2di (gen_lowpart (V2DImode, operands[0]), operands[1], const0_rtx));
142  else
143       gcc_unreachable ();
144 })
145
146 (define_expand "mov<mode>"
147   [(set (match_operand:SSEMODEF2P 0 "nonimmediate_operand" "")
148         (match_operand:SSEMODEF2P 1 "nonimmediate_operand" ""))]
149   "TARGET_SSE"
150 {
151   ix86_expand_vector_move (<MODE>mode, operands);
152   DONE;
153 })
154
155 (define_insn "*movv4sf_internal"
156   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
157         (match_operand:V4SF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
158   "TARGET_SSE
159    && (register_operand (operands[0], V4SFmode)
160        || register_operand (operands[1], V4SFmode))"
161 {
162   switch (which_alternative)
163     {
164     case 0:
165       return standard_sse_constant_opcode (insn, operands[1]);
166     case 1:
167     case 2:
168       return "movaps\t{%1, %0|%0, %1}";
169     default:
170       gcc_unreachable ();
171     }
172 }
173   [(set_attr "type" "sselog1,ssemov,ssemov")
174    (set_attr "mode" "V4SF")])
175
176 (define_split
177   [(set (match_operand:V4SF 0 "register_operand" "")
178         (match_operand:V4SF 1 "zero_extended_scalar_load_operand" ""))]
179   "TARGET_SSE && reload_completed"
180   [(set (match_dup 0)
181         (vec_merge:V4SF
182           (vec_duplicate:V4SF (match_dup 1))
183           (match_dup 2)
184           (const_int 1)))]
185 {
186   operands[1] = simplify_gen_subreg (SFmode, operands[1], V4SFmode, 0);
187   operands[2] = CONST0_RTX (V4SFmode);
188 })
189
190 (define_insn "*movv2df_internal"
191   [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
192         (match_operand:V2DF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
193   "TARGET_SSE
194    && (register_operand (operands[0], V2DFmode)
195        || register_operand (operands[1], V2DFmode))"
196 {
197   switch (which_alternative)
198     {
199     case 0:
200       return standard_sse_constant_opcode (insn, operands[1]);
201     case 1:
202     case 2:
203       if (get_attr_mode (insn) == MODE_V4SF)
204         return "movaps\t{%1, %0|%0, %1}";
205       else
206         return "movapd\t{%1, %0|%0, %1}";
207     default:
208       gcc_unreachable ();
209     }
210 }
211   [(set_attr "type" "sselog1,ssemov,ssemov")
212    (set (attr "mode")
213         (if_then_else
214           (ior (ior (ne (symbol_ref "optimize_size") (const_int 0))
215                     (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
216                (and (eq_attr "alternative" "2")
217                     (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
218                         (const_int 0))))
219           (const_string "V4SF")
220           (const_string "V2DF")))])
221
222 (define_split
223   [(set (match_operand:V2DF 0 "register_operand" "")
224         (match_operand:V2DF 1 "zero_extended_scalar_load_operand" ""))]
225   "TARGET_SSE2 && reload_completed"
226   [(set (match_dup 0) (vec_concat:V2DF (match_dup 1) (match_dup 2)))]
227 {
228   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2DFmode, 0);
229   operands[2] = CONST0_RTX (DFmode);
230 })
231
232 (define_expand "push<mode>1"
233   [(match_operand:SSEMODE 0 "register_operand" "")]
234   "TARGET_SSE"
235 {
236   ix86_expand_push (<MODE>mode, operands[0]);
237   DONE;
238 })
239
240 (define_expand "movmisalign<mode>"
241   [(set (match_operand:SSEMODE 0 "nonimmediate_operand" "")
242         (match_operand:SSEMODE 1 "nonimmediate_operand" ""))]
243   "TARGET_SSE"
244 {
245   ix86_expand_vector_move_misalign (<MODE>mode, operands);
246   DONE;
247 })
248
249 (define_insn "<sse>_movup<ssemodesuffixf2c>"
250   [(set (match_operand:SSEMODEF2P 0 "nonimmediate_operand" "=x,m")
251         (unspec:SSEMODEF2P
252           [(match_operand:SSEMODEF2P 1 "nonimmediate_operand" "xm,x")]
253           UNSPEC_MOVU))]
254   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
255    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
256   "movup<ssemodesuffixf2c>\t{%1, %0|%0, %1}"
257   [(set_attr "type" "ssemov")
258    (set_attr "mode" "<MODE>")])
259
260 (define_insn "sse2_movdqu"
261   [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
262         (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")]
263                       UNSPEC_MOVU))]
264   "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
265   "movdqu\t{%1, %0|%0, %1}"
266   [(set_attr "type" "ssemov")
267    (set_attr "prefix_data16" "1")
268    (set_attr "mode" "TI")])
269
270 (define_insn "<sse>_movnt<mode>"
271   [(set (match_operand:SSEMODEF2P 0 "memory_operand" "=m")
272         (unspec:SSEMODEF2P
273           [(match_operand:SSEMODEF2P 1 "register_operand" "x")]
274           UNSPEC_MOVNT))]
275   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
276   "movntp<ssemodesuffixf2c>\t{%1, %0|%0, %1}"
277   [(set_attr "type" "ssemov")
278    (set_attr "mode" "<MODE>")])
279
280 (define_insn "sse2_movntv2di"
281   [(set (match_operand:V2DI 0 "memory_operand" "=m")
282         (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "x")]
283                      UNSPEC_MOVNT))]
284   "TARGET_SSE2"
285   "movntdq\t{%1, %0|%0, %1}"
286   [(set_attr "type" "ssecvt")
287    (set_attr "prefix_data16" "1")
288    (set_attr "mode" "TI")])
289
290 (define_insn "sse2_movntsi"
291   [(set (match_operand:SI 0 "memory_operand" "=m")
292         (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
293                    UNSPEC_MOVNT))]
294   "TARGET_SSE2"
295   "movnti\t{%1, %0|%0, %1}"
296   [(set_attr "type" "ssecvt")
297    (set_attr "mode" "V2DF")])
298
299 (define_insn "sse3_lddqu"
300   [(set (match_operand:V16QI 0 "register_operand" "=x")
301         (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "m")]
302                       UNSPEC_LDDQU))]
303   "TARGET_SSE3"
304   "lddqu\t{%1, %0|%0, %1}"
305   [(set_attr "type" "ssecvt")
306    (set_attr "prefix_rep" "1")
307    (set_attr "mode" "TI")])
308
309 ; Expand patterns for non-temporal stores.  At the moment, only those
310 ; that directly map to insns are defined; it would be possible to
311 ; define patterns for other modes that would expand to several insns.
312
313 (define_expand "storent<mode>"
314   [(set (match_operand:SSEMODEF2P 0 "memory_operand" "")
315         (unspec:SSEMODEF2P
316           [(match_operand:SSEMODEF2P 1 "register_operand" "")]
317           UNSPEC_MOVNT))]
318   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
319   "")
320
321 (define_expand "storent<mode>"
322   [(set (match_operand:MODEF 0 "memory_operand" "")
323         (unspec:MODEF
324           [(match_operand:MODEF 1 "register_operand" "")]
325           UNSPEC_MOVNT))]
326   "TARGET_SSE4A"
327   "")
328
329 (define_expand "storentv2di"
330   [(set (match_operand:V2DI 0 "memory_operand" "")
331         (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "")]
332                      UNSPEC_MOVNT))]
333   "TARGET_SSE2"
334   "")
335
336 (define_expand "storentsi"
337   [(set (match_operand:SI 0 "memory_operand" "")
338         (unspec:SI [(match_operand:SI 1 "register_operand" "")]
339                    UNSPEC_MOVNT))]
340   "TARGET_SSE2"
341   "")
342
343 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
344 ;;
345 ;; Parallel floating point arithmetic
346 ;;
347 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
348
349 (define_expand "neg<mode>2"
350   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
351         (neg:SSEMODEF2P (match_operand:SSEMODEF2P 1 "register_operand" "")))]
352   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
353   "ix86_expand_fp_absneg_operator (NEG, <MODE>mode, operands); DONE;")
354
355 (define_expand "abs<mode>2"
356   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
357         (abs:SSEMODEF2P (match_operand:SSEMODEF2P 1 "register_operand" "")))]
358   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
359   "ix86_expand_fp_absneg_operator (ABS, <MODE>mode, operands); DONE;")
360
361 (define_expand "add<mode>3"
362   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
363         (plus:SSEMODEF2P
364           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
365           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
366   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
367   "ix86_fixup_binary_operands_no_copy (PLUS, <MODE>mode, operands);")
368
369 (define_insn "*add<mode>3"
370   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
371         (plus:SSEMODEF2P
372           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
373           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
374   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
375    && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
376   "addp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
377   [(set_attr "type" "sseadd")
378    (set_attr "mode" "<MODE>")])
379
380 (define_insn "<sse>_vmadd<mode>3"
381   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
382         (vec_merge:SSEMODEF2P
383           (plus:SSEMODEF2P
384             (match_operand:SSEMODEF2P 1 "register_operand" "0")
385             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm"))
386           (match_dup 1)
387           (const_int 1)))]
388   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
389    && ix86_binary_operator_ok (PLUS, V4SFmode, operands)"
390   "adds<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
391   [(set_attr "type" "sseadd")
392    (set_attr "mode" "<ssescalarmode>")])
393
394 (define_expand "sub<mode>3"
395   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
396         (minus:SSEMODEF2P
397           (match_operand:SSEMODEF2P 1 "register_operand" "")
398           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
399   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
400   "ix86_fixup_binary_operands_no_copy (MINUS, <MODE>mode, operands);")
401
402 (define_insn "*sub<mode>3"
403   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
404         (minus:SSEMODEF2P
405           (match_operand:SSEMODEF2P 1 "register_operand" "0")
406           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
407   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
408   "subp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
409   [(set_attr "type" "sseadd")
410    (set_attr "mode" "<MODE>")])
411
412 (define_insn "<sse>_vmsub<mode>3"
413   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
414         (vec_merge:SSEMODEF2P
415           (minus:SSEMODEF2P
416             (match_operand:SSEMODEF2P 1 "register_operand" "0")
417             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm"))
418           (match_dup 1)
419           (const_int 1)))]
420   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
421   "subs<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
422   [(set_attr "type" "sseadd")
423    (set_attr "mode" "<ssescalarmode>")])
424
425 (define_expand "mul<mode>3"
426   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
427         (mult:SSEMODEF2P
428           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
429           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
430   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
431   "ix86_fixup_binary_operands_no_copy (MULT, <MODE>mode, operands);")
432
433 (define_insn "*mul<mode>3"
434   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
435         (mult:SSEMODEF2P
436           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
437           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
438   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
439    && ix86_binary_operator_ok (MULT, <MODE>mode, operands)"
440   "mulp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
441   [(set_attr "type" "ssemul")
442    (set_attr "mode" "<MODE>")])
443
444 (define_insn "<sse>_vmmul<mode>3"
445   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
446         (vec_merge:SSEMODEF2P
447           (mult:SSEMODEF2P
448             (match_operand:SSEMODEF2P 1 "register_operand" "0")
449             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm"))
450           (match_dup 1)
451           (const_int 1)))]
452   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
453    && ix86_binary_operator_ok (MULT, <MODE>mode, operands)"
454   "muls<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
455   [(set_attr "type" "ssemul")
456    (set_attr "mode" "<ssescalarmode>")])
457
458 (define_expand "divv4sf3"
459   [(set (match_operand:V4SF 0 "register_operand" "")
460         (div:V4SF (match_operand:V4SF 1 "register_operand" "")
461                   (match_operand:V4SF 2 "nonimmediate_operand" "")))]
462   "TARGET_SSE"
463 {
464   ix86_fixup_binary_operands_no_copy (DIV, V4SFmode, operands);
465
466   if (TARGET_SSE_MATH && TARGET_RECIP && !optimize_size
467       && flag_finite_math_only && !flag_trapping_math
468       && flag_unsafe_math_optimizations)
469     {
470       ix86_emit_swdivsf (operands[0], operands[1],
471                          operands[2], V4SFmode);
472       DONE;
473     }
474 })
475
476 (define_expand "divv2df3"
477   [(set (match_operand:V2DF 0 "register_operand" "")
478         (div:V2DF (match_operand:V2DF 1 "register_operand" "")
479                   (match_operand:V2DF 2 "nonimmediate_operand" "")))]
480   "TARGET_SSE2"
481   "ix86_fixup_binary_operands_no_copy (DIV, V2DFmode, operands);")
482
483 (define_insn "<sse>_div<mode>3"
484   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
485         (div:SSEMODEF2P
486           (match_operand:SSEMODEF2P 1 "register_operand" "0")
487           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
488   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
489   "divp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
490   [(set_attr "type" "ssediv")
491    (set_attr "mode" "<MODE>")])
492
493 (define_insn "<sse>_vmdiv<mode>3"
494   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
495         (vec_merge:SSEMODEF2P
496           (div:SSEMODEF2P
497             (match_operand:SSEMODEF2P 1 "register_operand" "0")
498             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm"))
499           (match_dup 1)
500           (const_int 1)))]
501   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
502   "divs<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
503   [(set_attr "type" "ssediv")
504    (set_attr "mode" "<ssescalarmode>")])
505
506 (define_insn "sse_rcpv4sf2"
507   [(set (match_operand:V4SF 0 "register_operand" "=x")
508         (unspec:V4SF
509           [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))]
510   "TARGET_SSE"
511   "rcpps\t{%1, %0|%0, %1}"
512   [(set_attr "type" "sse")
513    (set_attr "mode" "V4SF")])
514
515 (define_insn "sse_vmrcpv4sf2"
516   [(set (match_operand:V4SF 0 "register_operand" "=x")
517         (vec_merge:V4SF
518           (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
519                        UNSPEC_RCP)
520           (match_operand:V4SF 2 "register_operand" "0")
521           (const_int 1)))]
522   "TARGET_SSE"
523   "rcpss\t{%1, %0|%0, %1}"
524   [(set_attr "type" "sse")
525    (set_attr "mode" "SF")])
526
527 (define_expand "sqrtv4sf2"
528   [(set (match_operand:V4SF 0 "register_operand" "")
529         (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")))]
530   "TARGET_SSE"
531 {
532   if (TARGET_SSE_MATH && TARGET_RECIP && !optimize_size
533       && flag_finite_math_only && !flag_trapping_math
534       && flag_unsafe_math_optimizations)
535     {
536       ix86_emit_swsqrtsf (operands[0], operands[1], V4SFmode, 0);
537       DONE;
538     }
539 })
540
541 (define_insn "sse_sqrtv4sf2"
542   [(set (match_operand:V4SF 0 "register_operand" "=x")
543         (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
544   "TARGET_SSE"
545   "sqrtps\t{%1, %0|%0, %1}"
546   [(set_attr "type" "sse")
547    (set_attr "mode" "V4SF")])
548
549 (define_insn "sqrtv2df2"
550   [(set (match_operand:V2DF 0 "register_operand" "=x")
551         (sqrt:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "xm")))]
552   "TARGET_SSE2"
553   "sqrtpd\t{%1, %0|%0, %1}"
554   [(set_attr "type" "sse")
555    (set_attr "mode" "V2DF")])
556
557 (define_insn "<sse>_vmsqrt<mode>2"
558   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
559         (vec_merge:SSEMODEF2P
560           (sqrt:SSEMODEF2P
561             (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "xm"))
562           (match_operand:SSEMODEF2P 2 "register_operand" "0")
563           (const_int 1)))]
564   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
565   "sqrts<ssemodesuffixf2c>\t{%1, %0|%0, %1}"
566   [(set_attr "type" "sse")
567    (set_attr "mode" "<ssescalarmode>")])
568
569 (define_expand "rsqrtv4sf2"
570   [(set (match_operand:V4SF 0 "register_operand" "")
571         (unspec:V4SF
572           [(match_operand:V4SF 1 "nonimmediate_operand" "")] UNSPEC_RSQRT))]
573   "TARGET_SSE_MATH"
574 {
575   ix86_emit_swsqrtsf (operands[0], operands[1], V4SFmode, 1);
576   DONE;
577 })
578
579 (define_insn "sse_rsqrtv4sf2"
580   [(set (match_operand:V4SF 0 "register_operand" "=x")
581         (unspec:V4SF
582           [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))]
583   "TARGET_SSE"
584   "rsqrtps\t{%1, %0|%0, %1}"
585   [(set_attr "type" "sse")
586    (set_attr "mode" "V4SF")])
587
588 (define_insn "sse_vmrsqrtv4sf2"
589   [(set (match_operand:V4SF 0 "register_operand" "=x")
590         (vec_merge:V4SF
591           (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
592                        UNSPEC_RSQRT)
593           (match_operand:V4SF 2 "register_operand" "0")
594           (const_int 1)))]
595   "TARGET_SSE"
596   "rsqrtss\t{%1, %0|%0, %1}"
597   [(set_attr "type" "sse")
598    (set_attr "mode" "SF")])
599
600 ;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
601 ;; isn't really correct, as those rtl operators aren't defined when
602 ;; applied to NaNs.  Hopefully the optimizers won't get too smart on us.
603
604 (define_expand "smin<mode>3"
605   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
606         (smin:SSEMODEF2P
607           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
608           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
609   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
610 {
611   if (!flag_finite_math_only)
612     operands[1] = force_reg (<MODE>mode, operands[1]);
613   ix86_fixup_binary_operands_no_copy (SMIN, <MODE>mode, operands);
614 })
615
616 (define_insn "*smin<mode>3_finite"
617   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
618         (smin:SSEMODEF2P
619           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
620           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
621   "SSE_VEC_FLOAT_MODE_P (<MODE>mode) && flag_finite_math_only
622    && ix86_binary_operator_ok (SMIN, <MODE>mode, operands)"
623   "minp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
624   [(set_attr "type" "sseadd")
625    (set_attr "mode" "<MODE>")])
626
627 (define_insn "*smin<mode>3"
628   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
629         (smin:SSEMODEF2P
630           (match_operand:SSEMODEF2P 1 "register_operand" "0")
631           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
632   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
633   "minp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
634   [(set_attr "type" "sseadd")
635    (set_attr "mode" "<MODE>")])
636
637 (define_insn "<sse>_vmsmin<mode>3"
638   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
639         (vec_merge:SSEMODEF2P
640           (smin:SSEMODEF2P
641             (match_operand:SSEMODEF2P 1 "register_operand" "0")
642             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm"))
643          (match_dup 1)
644          (const_int 1)))]
645   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
646   "mins<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
647   [(set_attr "type" "sse")
648    (set_attr "mode" "<ssescalarmode>")])
649
650 (define_expand "smax<mode>3"
651   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
652         (smax:SSEMODEF2P
653           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
654           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
655   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
656 {
657   if (!flag_finite_math_only)
658     operands[1] = force_reg (<MODE>mode, operands[1]);
659   ix86_fixup_binary_operands_no_copy (SMAX, <MODE>mode, operands);
660 })
661
662 (define_insn "*smax<mode>3_finite"
663   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
664         (smax:SSEMODEF2P
665           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
666           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
667   "SSE_VEC_FLOAT_MODE_P (<MODE>mode) && flag_finite_math_only
668    && ix86_binary_operator_ok (SMAX, <MODE>mode, operands)"
669   "maxp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
670   [(set_attr "type" "sseadd")
671    (set_attr "mode" "<MODE>")])
672
673 (define_insn "*smax<mode>3"
674   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
675         (smax:SSEMODEF2P
676           (match_operand:SSEMODEF2P 1 "register_operand" "0")
677           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
678   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
679   "maxp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
680   [(set_attr "type" "sseadd")
681    (set_attr "mode" "<MODE>")])
682
683 (define_insn "<sse>_vmsmax<mode>3"
684   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
685         (vec_merge:SSEMODEF2P
686           (smax:SSEMODEF2P
687             (match_operand:SSEMODEF2P 1 "register_operand" "0")
688             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm"))
689           (match_dup 1)
690           (const_int 1)))]
691   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
692   "maxs<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
693   [(set_attr "type" "sseadd")
694    (set_attr "mode" "<ssescalarmode>")])
695
696 ;; These versions of the min/max patterns implement exactly the operations
697 ;;   min = (op1 < op2 ? op1 : op2)
698 ;;   max = (!(op1 < op2) ? op1 : op2)
699 ;; Their operands are not commutative, and thus they may be used in the
700 ;; presence of -0.0 and NaN.
701
702 (define_insn "*ieee_smin<mode>3"
703   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
704         (unspec:SSEMODEF2P
705           [(match_operand:SSEMODEF2P 1 "register_operand" "0")
706            (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")]
707          UNSPEC_IEEE_MIN))]
708   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
709   "minp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
710   [(set_attr "type" "sseadd")
711    (set_attr "mode" "<MODE>")])
712
713 (define_insn "*ieee_smax<mode>3"
714   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
715         (unspec:SSEMODEF2P
716           [(match_operand:SSEMODEF2P 1 "register_operand" "0")
717            (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")]
718          UNSPEC_IEEE_MAX))]
719   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
720   "maxp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
721   [(set_attr "type" "sseadd")
722    (set_attr "mode" "<MODE>")])
723
724 (define_insn "sse3_addsubv4sf3"
725   [(set (match_operand:V4SF 0 "register_operand" "=x")
726         (vec_merge:V4SF
727           (plus:V4SF
728             (match_operand:V4SF 1 "register_operand" "0")
729             (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
730           (minus:V4SF (match_dup 1) (match_dup 2))
731           (const_int 5)))]
732   "TARGET_SSE3"
733   "addsubps\t{%2, %0|%0, %2}"
734   [(set_attr "type" "sseadd")
735    (set_attr "prefix_rep" "1")
736    (set_attr "mode" "V4SF")])
737
738 (define_insn "sse3_addsubv2df3"
739   [(set (match_operand:V2DF 0 "register_operand" "=x")
740         (vec_merge:V2DF
741           (plus:V2DF
742             (match_operand:V2DF 1 "register_operand" "0")
743             (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
744           (minus:V2DF (match_dup 1) (match_dup 2))
745           (const_int 1)))]
746   "TARGET_SSE3"
747   "addsubpd\t{%2, %0|%0, %2}"
748   [(set_attr "type" "sseadd")
749    (set_attr "mode" "V2DF")])
750
751 (define_insn "sse3_haddv4sf3"
752   [(set (match_operand:V4SF 0 "register_operand" "=x")
753         (vec_concat:V4SF
754           (vec_concat:V2SF
755             (plus:SF
756               (vec_select:SF
757                 (match_operand:V4SF 1 "register_operand" "0")
758                 (parallel [(const_int 0)]))
759               (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
760             (plus:SF
761               (vec_select:SF (match_dup 1) (parallel [(const_int 2)]))
762               (vec_select:SF (match_dup 1) (parallel [(const_int 3)]))))
763           (vec_concat:V2SF
764             (plus:SF
765               (vec_select:SF
766                 (match_operand:V4SF 2 "nonimmediate_operand" "xm")
767                 (parallel [(const_int 0)]))
768               (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))
769             (plus:SF
770               (vec_select:SF (match_dup 2) (parallel [(const_int 2)]))
771               (vec_select:SF (match_dup 2) (parallel [(const_int 3)]))))))]
772   "TARGET_SSE3"
773   "haddps\t{%2, %0|%0, %2}"
774   [(set_attr "type" "sseadd")
775    (set_attr "prefix_rep" "1")
776    (set_attr "mode" "V4SF")])
777
778 (define_insn "sse3_haddv2df3"
779   [(set (match_operand:V2DF 0 "register_operand" "=x")
780         (vec_concat:V2DF
781           (plus:DF
782             (vec_select:DF
783               (match_operand:V2DF 1 "register_operand" "0")
784               (parallel [(const_int 0)]))
785             (vec_select:DF (match_dup 1) (parallel [(const_int 1)])))
786           (plus:DF
787             (vec_select:DF
788               (match_operand:V2DF 2 "nonimmediate_operand" "xm")
789               (parallel [(const_int 0)]))
790             (vec_select:DF (match_dup 2) (parallel [(const_int 1)])))))]
791   "TARGET_SSE3"
792   "haddpd\t{%2, %0|%0, %2}"
793   [(set_attr "type" "sseadd")
794    (set_attr "mode" "V2DF")])
795
796 (define_insn "sse3_hsubv4sf3"
797   [(set (match_operand:V4SF 0 "register_operand" "=x")
798         (vec_concat:V4SF
799           (vec_concat:V2SF
800             (minus:SF
801               (vec_select:SF
802                 (match_operand:V4SF 1 "register_operand" "0")
803                 (parallel [(const_int 0)]))
804               (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
805             (minus:SF
806               (vec_select:SF (match_dup 1) (parallel [(const_int 2)]))
807               (vec_select:SF (match_dup 1) (parallel [(const_int 3)]))))
808           (vec_concat:V2SF
809             (minus:SF
810               (vec_select:SF
811                 (match_operand:V4SF 2 "nonimmediate_operand" "xm")
812                 (parallel [(const_int 0)]))
813               (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))
814             (minus:SF
815               (vec_select:SF (match_dup 2) (parallel [(const_int 2)]))
816               (vec_select:SF (match_dup 2) (parallel [(const_int 3)]))))))]
817   "TARGET_SSE3"
818   "hsubps\t{%2, %0|%0, %2}"
819   [(set_attr "type" "sseadd")
820    (set_attr "prefix_rep" "1")
821    (set_attr "mode" "V4SF")])
822
823 (define_insn "sse3_hsubv2df3"
824   [(set (match_operand:V2DF 0 "register_operand" "=x")
825         (vec_concat:V2DF
826           (minus:DF
827             (vec_select:DF
828               (match_operand:V2DF 1 "register_operand" "0")
829               (parallel [(const_int 0)]))
830             (vec_select:DF (match_dup 1) (parallel [(const_int 1)])))
831           (minus:DF
832             (vec_select:DF
833               (match_operand:V2DF 2 "nonimmediate_operand" "xm")
834               (parallel [(const_int 0)]))
835             (vec_select:DF (match_dup 2) (parallel [(const_int 1)])))))]
836   "TARGET_SSE3"
837   "hsubpd\t{%2, %0|%0, %2}"
838   [(set_attr "type" "sseadd")
839    (set_attr "mode" "V2DF")])
840
841 (define_expand "reduc_splus_v4sf"
842   [(match_operand:V4SF 0 "register_operand" "")
843    (match_operand:V4SF 1 "register_operand" "")]
844   "TARGET_SSE"
845 {
846   if (TARGET_SSE3)
847     {
848       rtx tmp = gen_reg_rtx (V4SFmode);
849       emit_insn (gen_sse3_haddv4sf3 (tmp, operands[1], operands[1]));
850       emit_insn (gen_sse3_haddv4sf3 (operands[0], tmp, tmp));
851     }
852   else
853     ix86_expand_reduc_v4sf (gen_addv4sf3, operands[0], operands[1]);
854   DONE;
855 })
856
857 (define_expand "reduc_splus_v2df"
858   [(match_operand:V2DF 0 "register_operand" "")
859    (match_operand:V2DF 1 "register_operand" "")]
860   "TARGET_SSE3"
861 {
862   emit_insn (gen_sse3_haddv2df3 (operands[0], operands[1], operands[1]));
863   DONE;
864 })
865
866 (define_expand "reduc_smax_v4sf"
867   [(match_operand:V4SF 0 "register_operand" "")
868    (match_operand:V4SF 1 "register_operand" "")]
869   "TARGET_SSE"
870 {
871   ix86_expand_reduc_v4sf (gen_smaxv4sf3, operands[0], operands[1]);
872   DONE;
873 })
874
875 (define_expand "reduc_smin_v4sf"
876   [(match_operand:V4SF 0 "register_operand" "")
877    (match_operand:V4SF 1 "register_operand" "")]
878   "TARGET_SSE"
879 {
880   ix86_expand_reduc_v4sf (gen_sminv4sf3, operands[0], operands[1]);
881   DONE;
882 })
883
884 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
885 ;;
886 ;; Parallel floating point comparisons
887 ;;
888 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
889
890 (define_insn "<sse>_maskcmp<mode>3"
891   [(set (match_operand:SSEMODEF4 0 "register_operand" "=x")
892         (match_operator:SSEMODEF4 3 "sse_comparison_operator"
893                 [(match_operand:SSEMODEF4 1 "register_operand" "0")
894                  (match_operand:SSEMODEF4 2 "nonimmediate_operand" "xm")]))]
895   "(SSE_FLOAT_MODE_P (<MODE>mode) || SSE_VEC_FLOAT_MODE_P (<MODE>mode))
896    && !TARGET_SSE5"
897   "cmp%D3<ssemodesuffixf4>\t{%2, %0|%0, %2}"
898   [(set_attr "type" "ssecmp")
899    (set_attr "mode" "<MODE>")])
900
901 (define_insn "<sse>_vmmaskcmp<mode>3"
902   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
903         (vec_merge:SSEMODEF2P
904          (match_operator:SSEMODEF2P 3 "sse_comparison_operator"
905                 [(match_operand:SSEMODEF2P 1 "register_operand" "0")
906                  (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")])
907          (match_dup 1)
908          (const_int 1)))]
909   "SSE_VEC_FLOAT_MODE_P (<MODE>mode) && !TARGET_SSE5"
910   "cmp%D3s<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
911   [(set_attr "type" "ssecmp")
912    (set_attr "mode" "<ssescalarmode>")])
913
914 (define_insn "<sse>_comi"
915   [(set (reg:CCFP FLAGS_REG)
916         (compare:CCFP
917           (vec_select:MODEF
918             (match_operand:<ssevecmode> 0 "register_operand" "x")
919             (parallel [(const_int 0)]))
920           (vec_select:MODEF
921             (match_operand:<ssevecmode> 1 "nonimmediate_operand" "xm")
922             (parallel [(const_int 0)]))))]
923   "SSE_FLOAT_MODE_P (<MODE>mode)"
924   "comis<ssemodefsuffix>\t{%1, %0|%0, %1}"
925   [(set_attr "type" "ssecomi")
926    (set_attr "mode" "<MODE>")])
927
928 (define_insn "<sse>_ucomi"
929   [(set (reg:CCFPU FLAGS_REG)
930         (compare:CCFPU
931           (vec_select:MODEF
932             (match_operand:<ssevecmode> 0 "register_operand" "x")
933             (parallel [(const_int 0)]))
934           (vec_select:MODEF
935             (match_operand:<ssevecmode> 1 "nonimmediate_operand" "xm")
936             (parallel [(const_int 0)]))))]
937   "SSE_FLOAT_MODE_P (<MODE>mode)"
938   "ucomis<ssemodefsuffix>\t{%1, %0|%0, %1}"
939   [(set_attr "type" "ssecomi")
940    (set_attr "mode" "<MODE>")])
941
942 (define_expand "vcond<mode>"
943   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
944         (if_then_else:SSEMODEF2P
945           (match_operator 3 ""
946             [(match_operand:SSEMODEF2P 4 "nonimmediate_operand" "")
947              (match_operand:SSEMODEF2P 5 "nonimmediate_operand" "")])
948           (match_operand:SSEMODEF2P 1 "general_operand" "")
949           (match_operand:SSEMODEF2P 2 "general_operand" "")))]
950   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
951 {
952   if (ix86_expand_fp_vcond (operands))
953     DONE;
954   else
955     FAIL;
956 })
957
958 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
959 ;;
960 ;; Parallel floating point logical operations
961 ;;
962 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
963
964 (define_expand "and<mode>3"
965   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
966         (and:SSEMODEF2P
967           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
968           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
969   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
970   "ix86_fixup_binary_operands_no_copy (AND, <MODE>mode, operands);")
971
972 (define_insn "*and<mode>3"
973   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
974         (and:SSEMODEF2P
975           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
976           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
977   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
978    && ix86_binary_operator_ok (AND, <MODE>mode, operands)"
979   "andp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
980   [(set_attr "type" "sselog")
981    (set_attr "mode" "<MODE>")])
982
983 (define_insn "<sse>_nand<mode>3"
984   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
985         (and:SSEMODEF2P
986           (not:SSEMODEF2P
987             (match_operand:SSEMODEF2P 1 "register_operand" "0"))
988           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
989   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
990   "andnp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
991   [(set_attr "type" "sselog")
992    (set_attr "mode" "<MODE>")])
993
994 (define_expand "ior<mode>3"
995   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
996         (ior:SSEMODEF2P
997           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
998           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
999   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
1000   "ix86_fixup_binary_operands_no_copy (IOR, <MODE>mode, operands);")
1001
1002 (define_insn "*ior<mode>3"
1003   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
1004         (ior:SSEMODEF2P
1005           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
1006           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
1007   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
1008    && ix86_binary_operator_ok (IOR, <MODE>mode, operands)"
1009   "orp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
1010   [(set_attr "type" "sselog")
1011    (set_attr "mode" "<MODE>")])
1012
1013 (define_expand "xor<mode>3"
1014   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1015         (xor:SSEMODEF2P
1016           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "")
1017           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "")))]
1018   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
1019   "ix86_fixup_binary_operands_no_copy (XOR, <MODE>mode, operands);")
1020
1021 (define_insn "*xor<mode>3"
1022   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
1023         (xor:SSEMODEF2P
1024           (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0")
1025           (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")))]
1026   "SSE_VEC_FLOAT_MODE_P (<MODE>mode)
1027    && ix86_binary_operator_ok (XOR, <MODE>mode, operands)"
1028   "xorp<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
1029   [(set_attr "type" "sselog")
1030    (set_attr "mode" "<MODE>")])
1031
1032 ;; Also define scalar versions.  These are used for abs, neg, and
1033 ;; conditional move.  Using subregs into vector modes causes register
1034 ;; allocation lossage.  These patterns do not allow memory operands
1035 ;; because the native instructions read the full 128-bits.
1036
1037 (define_insn "*and<mode>3"
1038   [(set (match_operand:MODEF 0 "register_operand" "=x")
1039         (and:MODEF
1040           (match_operand:MODEF 1 "register_operand" "0")
1041           (match_operand:MODEF 2 "register_operand" "x")))]
1042   "SSE_FLOAT_MODE_P (<MODE>mode)"
1043   "andp<ssemodefsuffix>\t{%2, %0|%0, %2}"
1044   [(set_attr "type" "sselog")
1045    (set_attr "mode" "<ssevecmode>")])
1046
1047 (define_insn "*nand<mode>3"
1048   [(set (match_operand:MODEF 0 "register_operand" "=x")
1049         (and:MODEF
1050           (not:MODEF
1051             (match_operand:MODEF 1 "register_operand" "0"))
1052             (match_operand:MODEF 2 "register_operand" "x")))]
1053   "SSE_FLOAT_MODE_P (<MODE>mode)"
1054   "andnp<ssemodefsuffix>\t{%2, %0|%0, %2}"
1055   [(set_attr "type" "sselog")
1056    (set_attr "mode" "<ssevecmode>")])
1057
1058 (define_insn "*ior<mode>3"
1059   [(set (match_operand:MODEF 0 "register_operand" "=x")
1060         (ior:MODEF
1061           (match_operand:MODEF 1 "register_operand" "0")
1062           (match_operand:MODEF 2 "register_operand" "x")))]
1063   "SSE_FLOAT_MODE_P (<MODE>mode)"
1064   "orp<ssemodefsuffix>\t{%2, %0|%0, %2}"
1065   [(set_attr "type" "sselog")
1066    (set_attr "mode" "<ssevecmode>")])
1067
1068 (define_insn "*xor<mode>3"
1069   [(set (match_operand:MODEF 0 "register_operand" "=x")
1070         (xor:MODEF
1071           (match_operand:MODEF 1 "register_operand" "0")
1072           (match_operand:MODEF 2 "register_operand" "x")))]
1073   "SSE_FLOAT_MODE_P (<MODE>mode)"
1074   "xorp<ssemodefsuffix>\t{%2, %0|%0, %2}"
1075   [(set_attr "type" "sselog")
1076    (set_attr "mode" "<ssevecmode>")])
1077
1078 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1079 ;;
1080 ;; SSE5 floating point multiply/accumulate instructions This includes the
1081 ;; scalar version of the instructions as well as the vector
1082 ;;
1083 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1084
1085 ;; In order to match (*a * *b) + *c, particularly when vectorizing, allow
1086 ;; combine to generate a multiply/add with two memory references.  We then
1087 ;; split this insn, into loading up the destination register with one of the
1088 ;; memory operations.  If we don't manage to split the insn, reload will
1089 ;; generate the appropriate moves.  The reason this is needed, is that combine
1090 ;; has already folded one of the memory references into both the multiply and
1091 ;; add insns, and it can't generate a new pseudo.  I.e.:
1092 ;;      (set (reg1) (mem (addr1)))
1093 ;;      (set (reg2) (mult (reg1) (mem (addr2))))
1094 ;;      (set (reg3) (plus (reg2) (mem (addr3))))
1095
1096 (define_insn "sse5_fmadd<mode>4"
1097   [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
1098         (plus:SSEMODEF4
1099          (mult:SSEMODEF4
1100           (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
1101           (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))
1102          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")))]
1103   "TARGET_SSE5 && TARGET_FUSED_MADD
1104    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
1105   "fmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1106   [(set_attr "type" "ssemuladd")
1107    (set_attr "mode" "<MODE>")])
1108
1109 ;; Split fmadd with two memory operands into a load and the fmadd.
1110 (define_split
1111   [(set (match_operand:SSEMODEF4 0 "register_operand" "")
1112         (plus:SSEMODEF4
1113          (mult:SSEMODEF4
1114           (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
1115           (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
1116          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
1117   "TARGET_SSE5
1118    && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
1119    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
1120    && !reg_mentioned_p (operands[0], operands[1])
1121    && !reg_mentioned_p (operands[0], operands[2])
1122    && !reg_mentioned_p (operands[0], operands[3])"
1123   [(const_int 0)]
1124 {
1125   ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
1126   emit_insn (gen_sse5_fmadd<mode>4 (operands[0], operands[1],
1127                                     operands[2], operands[3]));
1128   DONE;
1129 })
1130
1131 ;; For the scalar operations, use operand1 for the upper words that aren't
1132 ;; modified, so restrict the forms that are generated.
1133 ;; Scalar version of fmadd
1134 (define_insn "sse5_vmfmadd<mode>4"
1135   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1136         (vec_merge:SSEMODEF2P
1137          (plus:SSEMODEF2P
1138           (mult:SSEMODEF2P
1139            (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
1140            (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
1141           (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
1142          (match_dup 1)
1143          (const_int 1)))]
1144   "TARGET_SSE5 && TARGET_FUSED_MADD
1145    && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1146   "fmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1147   [(set_attr "type" "ssemuladd")
1148    (set_attr "mode" "<MODE>")])
1149
1150 ;; Floating multiply and subtract
1151 ;; Allow two memory operands the same as fmadd
1152 (define_insn "sse5_fmsub<mode>4"
1153   [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
1154         (minus:SSEMODEF4
1155          (mult:SSEMODEF4
1156           (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
1157           (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))
1158          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")))]
1159   "TARGET_SSE5 && TARGET_FUSED_MADD
1160    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
1161   "fmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1162   [(set_attr "type" "ssemuladd")
1163    (set_attr "mode" "<MODE>")])
1164
1165 ;; Split fmsub with two memory operands into a load and the fmsub.
1166 (define_split
1167   [(set (match_operand:SSEMODEF4 0 "register_operand" "")
1168         (minus:SSEMODEF4
1169          (mult:SSEMODEF4
1170           (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
1171           (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
1172          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
1173   "TARGET_SSE5
1174    && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
1175    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
1176    && !reg_mentioned_p (operands[0], operands[1])
1177    && !reg_mentioned_p (operands[0], operands[2])
1178    && !reg_mentioned_p (operands[0], operands[3])"
1179   [(const_int 0)]
1180 {
1181   ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
1182   emit_insn (gen_sse5_fmsub<mode>4 (operands[0], operands[1],
1183                                     operands[2], operands[3]));
1184   DONE;
1185 })
1186
1187 ;; For the scalar operations, use operand1 for the upper words that aren't
1188 ;; modified, so restrict the forms that are generated.
1189 ;; Scalar version of fmsub
1190 (define_insn "sse5_vmfmsub<mode>4"
1191   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1192         (vec_merge:SSEMODEF2P
1193          (minus:SSEMODEF2P
1194           (mult:SSEMODEF2P
1195            (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
1196            (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
1197           (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
1198          (match_dup 1)
1199          (const_int 1)))]
1200   "TARGET_SSE5 && TARGET_FUSED_MADD
1201    && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1202   "fmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1203   [(set_attr "type" "ssemuladd")
1204    (set_attr "mode" "<MODE>")])
1205
1206 ;; Floating point negative multiply and add
1207 ;; Rewrite (- (a * b) + c) into the canonical form: c - (a * b)
1208 ;; Note operands are out of order to simplify call to ix86_sse5_valid_p
1209 ;; Allow two memory operands to help in optimizing.
1210 (define_insn "sse5_fnmadd<mode>4"
1211   [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
1212         (minus:SSEMODEF4
1213          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")
1214          (mult:SSEMODEF4
1215           (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
1216           (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))))]
1217   "TARGET_SSE5 && TARGET_FUSED_MADD
1218    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
1219   "fnmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1220   [(set_attr "type" "ssemuladd")
1221    (set_attr "mode" "<MODE>")])
1222
1223 ;; Split fnmadd with two memory operands into a load and the fnmadd.
1224 (define_split
1225   [(set (match_operand:SSEMODEF4 0 "register_operand" "")
1226         (minus:SSEMODEF4
1227          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")
1228          (mult:SSEMODEF4
1229           (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
1230           (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))))]
1231   "TARGET_SSE5
1232    && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
1233    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
1234    && !reg_mentioned_p (operands[0], operands[1])
1235    && !reg_mentioned_p (operands[0], operands[2])
1236    && !reg_mentioned_p (operands[0], operands[3])"
1237   [(const_int 0)]
1238 {
1239   ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
1240   emit_insn (gen_sse5_fnmadd<mode>4 (operands[0], operands[1],
1241                                      operands[2], operands[3]));
1242   DONE;
1243 })
1244
1245 ;; For the scalar operations, use operand1 for the upper words that aren't
1246 ;; modified, so restrict the forms that are generated.
1247 ;; Scalar version of fnmadd
1248 (define_insn "sse5_vmfnmadd<mode>4"
1249   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1250         (vec_merge:SSEMODEF2P
1251          (minus:SSEMODEF2P
1252           (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x")
1253           (mult:SSEMODEF2P
1254            (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
1255            (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm")))
1256          (match_dup 1)
1257          (const_int 1)))]
1258   "TARGET_SSE5 && TARGET_FUSED_MADD
1259    && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1260   "fnmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1261   [(set_attr "type" "ssemuladd")
1262    (set_attr "mode" "<MODE>")])
1263
1264 ;; Floating point negative multiply and subtract
1265 ;; Rewrite (- (a * b) - c) into the canonical form: ((-a) * b) - c
1266 ;; Allow 2 memory operands to help with optimization
1267 (define_insn "sse5_fnmsub<mode>4"
1268   [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x")
1269         (minus:SSEMODEF4
1270          (mult:SSEMODEF4
1271           (neg:SSEMODEF4
1272            (match_operand:SSEMODEF4 1 "nonimmediate_operand" "0,0"))
1273           (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm"))
1274          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x")))]
1275   "TARGET_SSE5 && TARGET_FUSED_MADD
1276    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
1277   "fnmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1278   [(set_attr "type" "ssemuladd")
1279    (set_attr "mode" "<MODE>")])
1280
1281 ;; Split fnmsub with two memory operands into a load and the fmsub.
1282 (define_split
1283   [(set (match_operand:SSEMODEF4 0 "register_operand" "")
1284         (minus:SSEMODEF4
1285          (mult:SSEMODEF4
1286           (neg:SSEMODEF4
1287            (match_operand:SSEMODEF4 1 "nonimmediate_operand" ""))
1288           (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
1289          (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
1290   "TARGET_SSE5
1291    && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
1292    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
1293    && !reg_mentioned_p (operands[0], operands[1])
1294    && !reg_mentioned_p (operands[0], operands[2])
1295    && !reg_mentioned_p (operands[0], operands[3])"
1296   [(const_int 0)]
1297 {
1298   ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
1299   emit_insn (gen_sse5_fnmsub<mode>4 (operands[0], operands[1],
1300                                      operands[2], operands[3]));
1301   DONE;
1302 })
1303
1304 ;; For the scalar operations, use operand1 for the upper words that aren't
1305 ;; modified, so restrict the forms that are generated.
1306 ;; Scalar version of fnmsub
1307 (define_insn "sse5_vmfnmsub<mode>4"
1308   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1309         (vec_merge:SSEMODEF2P
1310          (minus:SSEMODEF2P
1311           (mult:SSEMODEF2P
1312            (neg:SSEMODEF2P
1313             (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0"))
1314            (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
1315           (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
1316          (match_dup 1)
1317          (const_int 1)))]
1318   "TARGET_SSE5 && TARGET_FUSED_MADD
1319    && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
1320   "fnmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1321   [(set_attr "type" "ssemuladd")
1322    (set_attr "mode" "<MODE>")])
1323
1324 ;; The same instructions using an UNSPEC to allow the intrinsic to be used
1325 ;; even if the user used -mno-fused-madd
1326 ;; Parallel instructions.  During instruction generation, just default
1327 ;; to registers, and let combine later build the appropriate instruction.
1328 (define_expand "sse5i_fmadd<mode>4"
1329   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1330         (unspec:SSEMODEF2P
1331          [(plus:SSEMODEF2P
1332            (mult:SSEMODEF2P
1333             (match_operand:SSEMODEF2P 1 "register_operand" "")
1334             (match_operand:SSEMODEF2P 2 "register_operand" ""))
1335            (match_operand:SSEMODEF2P 3 "register_operand" ""))]
1336          UNSPEC_SSE5_INTRINSIC))]
1337   "TARGET_SSE5"
1338 {
1339   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1340   if (TARGET_FUSED_MADD)
1341     {
1342       emit_insn (gen_sse5_fmadd<mode>4 (operands[0], operands[1],
1343                                         operands[2], operands[3]));
1344       DONE;
1345     }
1346 })
1347
1348 (define_insn "*sse5i_fmadd<mode>4"
1349   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
1350         (unspec:SSEMODEF2P
1351          [(plus:SSEMODEF2P
1352            (mult:SSEMODEF2P
1353             (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0,0,x,xm")
1354             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x"))
1355            (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0"))]
1356          UNSPEC_SSE5_INTRINSIC))]
1357   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1358   "fmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1359   [(set_attr "type" "ssemuladd")
1360    (set_attr "mode" "<MODE>")])
1361
1362 (define_expand "sse5i_fmsub<mode>4"
1363   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1364         (unspec:SSEMODEF2P
1365          [(minus:SSEMODEF2P
1366            (mult:SSEMODEF2P
1367             (match_operand:SSEMODEF2P 1 "register_operand" "")
1368             (match_operand:SSEMODEF2P 2 "register_operand" ""))
1369            (match_operand:SSEMODEF2P 3 "register_operand" ""))]
1370          UNSPEC_SSE5_INTRINSIC))]
1371   "TARGET_SSE5"
1372 {
1373   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1374   if (TARGET_FUSED_MADD)
1375     {
1376       emit_insn (gen_sse5_fmsub<mode>4 (operands[0], operands[1],
1377                                         operands[2], operands[3]));
1378       DONE;
1379     }
1380 })
1381
1382 (define_insn "*sse5i_fmsub<mode>4"
1383   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
1384         (unspec:SSEMODEF2P
1385          [(minus:SSEMODEF2P
1386            (mult:SSEMODEF2P
1387             (match_operand:SSEMODEF2P 1 "register_operand" "%0,0,x,xm")
1388             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x"))
1389            (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0"))]
1390          UNSPEC_SSE5_INTRINSIC))]
1391   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1392   "fmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1393   [(set_attr "type" "ssemuladd")
1394    (set_attr "mode" "<MODE>")])
1395
1396 ;; Rewrite (- (a * b) + c) into the canonical form: c - (a * b)
1397 ;; Note operands are out of order to simplify call to ix86_sse5_valid_p
1398 (define_expand "sse5i_fnmadd<mode>4"
1399   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1400         (unspec:SSEMODEF2P
1401          [(minus:SSEMODEF2P
1402            (match_operand:SSEMODEF2P 3 "register_operand" "")
1403            (mult:SSEMODEF2P
1404             (match_operand:SSEMODEF2P 1 "register_operand" "")
1405             (match_operand:SSEMODEF2P 2 "register_operand" "")))]
1406          UNSPEC_SSE5_INTRINSIC))]
1407   "TARGET_SSE5"
1408 {
1409   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1410   if (TARGET_FUSED_MADD)
1411     {
1412       emit_insn (gen_sse5_fnmadd<mode>4 (operands[0], operands[1],
1413                                          operands[2], operands[3]));
1414       DONE;
1415     }
1416 })
1417
1418 (define_insn "*sse5i_fnmadd<mode>4"
1419   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
1420         (unspec:SSEMODEF2P
1421          [(minus:SSEMODEF2P
1422            (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0")
1423            (mult:SSEMODEF2P
1424             (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0,0,x,xm")
1425             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x")))]
1426          UNSPEC_SSE5_INTRINSIC))]
1427   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1428   "fnmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1429   [(set_attr "type" "ssemuladd")
1430    (set_attr "mode" "<MODE>")])
1431
1432 ;; Rewrite (- (a * b) - c) into the canonical form: ((-a) * b) - c
1433 (define_expand "sse5i_fnmsub<mode>4"
1434   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1435         (unspec:SSEMODEF2P
1436          [(minus:SSEMODEF2P
1437            (mult:SSEMODEF2P
1438             (neg:SSEMODEF2P
1439              (match_operand:SSEMODEF2P 1 "register_operand" ""))
1440             (match_operand:SSEMODEF2P 2 "register_operand" ""))
1441            (match_operand:SSEMODEF2P 3 "register_operand" ""))]
1442          UNSPEC_SSE5_INTRINSIC))]
1443   "TARGET_SSE5"
1444 {
1445   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1446   if (TARGET_FUSED_MADD)
1447     {
1448       emit_insn (gen_sse5_fnmsub<mode>4 (operands[0], operands[1],
1449                                          operands[2], operands[3]));
1450       DONE;
1451     }
1452 })
1453
1454 (define_insn "*sse5i_fnmsub<mode>4"
1455   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
1456         (unspec:SSEMODEF2P
1457          [(minus:SSEMODEF2P
1458            (mult:SSEMODEF2P
1459             (neg:SSEMODEF2P
1460              (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0,0,x,xm"))
1461             (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x"))
1462            (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0"))]
1463          UNSPEC_SSE5_INTRINSIC))]
1464   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1465   "fnmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1466   [(set_attr "type" "ssemuladd")
1467    (set_attr "mode" "<MODE>")])
1468
1469 ;; Scalar instructions
1470 (define_expand "sse5i_vmfmadd<mode>4"
1471   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1472         (unspec:SSEMODEF2P
1473          [(vec_merge:SSEMODEF2P
1474            (plus:SSEMODEF2P
1475             (mult:SSEMODEF2P
1476              (match_operand:SSEMODEF2P 1 "register_operand" "")
1477              (match_operand:SSEMODEF2P 2 "register_operand" ""))
1478             (match_operand:SSEMODEF2P 3 "register_operand" ""))
1479            (match_dup 1)
1480            (const_int 0))]
1481          UNSPEC_SSE5_INTRINSIC))]
1482   "TARGET_SSE5"
1483 {
1484   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1485   if (TARGET_FUSED_MADD)
1486     {
1487       emit_insn (gen_sse5_vmfmadd<mode>4 (operands[0], operands[1],
1488                                           operands[2], operands[3]));
1489       DONE;
1490     }
1491 })
1492
1493 ;; For the scalar operations, use operand1 for the upper words that aren't
1494 ;; modified, so restrict the forms that are accepted.
1495 (define_insn "*sse5i_vmfmadd<mode>4"
1496   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1497         (unspec:SSEMODEF2P
1498          [(vec_merge:SSEMODEF2P
1499            (plus:SSEMODEF2P
1500             (mult:SSEMODEF2P
1501              (match_operand:SSEMODEF2P 1 "register_operand" "0,0")
1502              (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
1503             (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
1504            (match_dup 0)
1505            (const_int 0))]
1506          UNSPEC_SSE5_INTRINSIC))]
1507   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1508   "fmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1509   [(set_attr "type" "ssemuladd")
1510    (set_attr "mode" "<ssescalarmode>")])
1511
1512 (define_expand "sse5i_vmfmsub<mode>4"
1513   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1514         (unspec:SSEMODEF2P
1515          [(vec_merge:SSEMODEF2P
1516            (minus:SSEMODEF2P
1517             (mult:SSEMODEF2P
1518              (match_operand:SSEMODEF2P 1 "register_operand" "")
1519              (match_operand:SSEMODEF2P 2 "register_operand" ""))
1520             (match_operand:SSEMODEF2P 3 "register_operand" ""))
1521            (match_dup 0)
1522            (const_int 1))]
1523          UNSPEC_SSE5_INTRINSIC))]
1524   "TARGET_SSE5"
1525 {
1526   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1527   if (TARGET_FUSED_MADD)
1528     {
1529       emit_insn (gen_sse5_vmfmsub<mode>4 (operands[0], operands[1],
1530                                           operands[2], operands[3]));
1531       DONE;
1532     }
1533 })
1534
1535 (define_insn "*sse5i_vmfmsub<mode>4"
1536   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1537         (unspec:SSEMODEF2P
1538          [(vec_merge:SSEMODEF2P
1539            (minus:SSEMODEF2P
1540             (mult:SSEMODEF2P
1541              (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
1542              (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
1543             (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
1544            (match_dup 1)
1545            (const_int 1))]
1546          UNSPEC_SSE5_INTRINSIC))]
1547   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1548   "fmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1549   [(set_attr "type" "ssemuladd")
1550    (set_attr "mode" "<ssescalarmode>")])
1551
1552 ;; Note operands are out of order to simplify call to ix86_sse5_valid_p
1553 (define_expand "sse5i_vmfnmadd<mode>4"
1554   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1555         (unspec:SSEMODEF2P
1556          [(vec_merge:SSEMODEF2P
1557            (minus:SSEMODEF2P
1558             (match_operand:SSEMODEF2P 3 "register_operand" "")
1559             (mult:SSEMODEF2P
1560              (match_operand:SSEMODEF2P 1 "register_operand" "")
1561              (match_operand:SSEMODEF2P 2 "register_operand" "")))
1562            (match_dup 1)
1563            (const_int 1))]
1564          UNSPEC_SSE5_INTRINSIC))]
1565   "TARGET_SSE5"
1566 {
1567   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1568   if (TARGET_FUSED_MADD)
1569     {
1570       emit_insn (gen_sse5_vmfnmadd<mode>4 (operands[0], operands[1],
1571                                            operands[2], operands[3]));
1572       DONE;
1573     }
1574 })
1575
1576 (define_insn "*sse5i_vmfnmadd<mode>4"
1577   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1578         (unspec:SSEMODEF2P
1579          [(vec_merge:SSEMODEF2P
1580            (minus:SSEMODEF2P
1581             (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x")
1582             (mult:SSEMODEF2P
1583              (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
1584              (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm")))
1585            (match_dup 1)
1586            (const_int 1))]
1587          UNSPEC_SSE5_INTRINSIC))]
1588   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1589   "fnmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1590   [(set_attr "type" "ssemuladd")
1591    (set_attr "mode" "<ssescalarmode>")])
1592
1593 (define_expand "sse5i_vmfnmsub<mode>4"
1594   [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
1595         (unspec:SSEMODEF2P
1596          [(vec_merge:SSEMODEF2P
1597            (minus:SSEMODEF2P
1598             (mult:SSEMODEF2P
1599              (neg:SSEMODEF2P
1600               (match_operand:SSEMODEF2P 1 "register_operand" ""))
1601              (match_operand:SSEMODEF2P 2 "register_operand" ""))
1602             (match_operand:SSEMODEF2P 3 "register_operand" ""))
1603            (match_dup 1)
1604            (const_int 1))]
1605          UNSPEC_SSE5_INTRINSIC))]
1606   "TARGET_SSE5"
1607 {
1608   /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
1609   if (TARGET_FUSED_MADD)
1610     {
1611       emit_insn (gen_sse5_vmfnmsub<mode>4 (operands[0], operands[1],
1612                                            operands[2], operands[3]));
1613       DONE;
1614     }
1615 })
1616
1617 (define_insn "*sse5i_vmfnmsub<mode>4"
1618   [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
1619         (unspec:SSEMODEF2P
1620          [(vec_merge:SSEMODEF2P
1621            (minus:SSEMODEF2P
1622             (mult:SSEMODEF2P
1623              (neg:SSEMODEF2P
1624               (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0"))
1625              (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
1626             (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
1627            (match_dup 1)
1628            (const_int 1))]
1629          UNSPEC_SSE5_INTRINSIC))]
1630   "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
1631   "fnmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
1632   [(set_attr "type" "ssemuladd")
1633    (set_attr "mode" "<ssescalarmode>")])
1634
1635 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1636 ;;
1637 ;; Parallel single-precision floating point conversion operations
1638 ;;
1639 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1640
1641 (define_insn "sse_cvtpi2ps"
1642   [(set (match_operand:V4SF 0 "register_operand" "=x")
1643         (vec_merge:V4SF
1644           (vec_duplicate:V4SF
1645             (float:V2SF (match_operand:V2SI 2 "nonimmediate_operand" "ym")))
1646           (match_operand:V4SF 1 "register_operand" "0")
1647           (const_int 3)))]
1648   "TARGET_SSE"
1649   "cvtpi2ps\t{%2, %0|%0, %2}"
1650   [(set_attr "type" "ssecvt")
1651    (set_attr "mode" "V4SF")])
1652
1653 (define_insn "sse_cvtps2pi"
1654   [(set (match_operand:V2SI 0 "register_operand" "=y")
1655         (vec_select:V2SI
1656           (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
1657                        UNSPEC_FIX_NOTRUNC)
1658           (parallel [(const_int 0) (const_int 1)])))]
1659   "TARGET_SSE"
1660   "cvtps2pi\t{%1, %0|%0, %1}"
1661   [(set_attr "type" "ssecvt")
1662    (set_attr "unit" "mmx")
1663    (set_attr "mode" "DI")])
1664
1665 (define_insn "sse_cvttps2pi"
1666   [(set (match_operand:V2SI 0 "register_operand" "=y")
1667         (vec_select:V2SI
1668           (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm"))
1669           (parallel [(const_int 0) (const_int 1)])))]
1670   "TARGET_SSE"
1671   "cvttps2pi\t{%1, %0|%0, %1}"
1672   [(set_attr "type" "ssecvt")
1673    (set_attr "unit" "mmx")
1674    (set_attr "mode" "SF")])
1675
1676 (define_insn "sse_cvtsi2ss"
1677   [(set (match_operand:V4SF 0 "register_operand" "=x,x")
1678         (vec_merge:V4SF
1679           (vec_duplicate:V4SF
1680             (float:SF (match_operand:SI 2 "nonimmediate_operand" "r,m")))
1681           (match_operand:V4SF 1 "register_operand" "0,0")
1682           (const_int 1)))]
1683   "TARGET_SSE"
1684   "cvtsi2ss\t{%2, %0|%0, %2}"
1685   [(set_attr "type" "sseicvt")
1686    (set_attr "athlon_decode" "vector,double")
1687    (set_attr "amdfam10_decode" "vector,double")
1688    (set_attr "mode" "SF")])
1689
1690 (define_insn "sse_cvtsi2ssq"
1691   [(set (match_operand:V4SF 0 "register_operand" "=x,x")
1692         (vec_merge:V4SF
1693           (vec_duplicate:V4SF
1694             (float:SF (match_operand:DI 2 "nonimmediate_operand" "r,rm")))
1695           (match_operand:V4SF 1 "register_operand" "0,0")
1696           (const_int 1)))]
1697   "TARGET_SSE && TARGET_64BIT"
1698   "cvtsi2ssq\t{%2, %0|%0, %2}"
1699   [(set_attr "type" "sseicvt")
1700    (set_attr "athlon_decode" "vector,double")
1701    (set_attr "amdfam10_decode" "vector,double")
1702    (set_attr "mode" "SF")])
1703
1704 (define_insn "sse_cvtss2si"
1705   [(set (match_operand:SI 0 "register_operand" "=r,r")
1706         (unspec:SI
1707           [(vec_select:SF
1708              (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
1709              (parallel [(const_int 0)]))]
1710           UNSPEC_FIX_NOTRUNC))]
1711   "TARGET_SSE"
1712   "cvtss2si\t{%1, %0|%0, %1}"
1713   [(set_attr "type" "sseicvt")
1714    (set_attr "athlon_decode" "double,vector")
1715    (set_attr "prefix_rep" "1")
1716    (set_attr "mode" "SI")])
1717
1718 (define_insn "sse_cvtss2si_2"
1719   [(set (match_operand:SI 0 "register_operand" "=r,r")
1720         (unspec:SI [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
1721                    UNSPEC_FIX_NOTRUNC))]
1722   "TARGET_SSE"
1723   "cvtss2si\t{%1, %0|%0, %1}"
1724   [(set_attr "type" "sseicvt")
1725    (set_attr "athlon_decode" "double,vector")
1726    (set_attr "amdfam10_decode" "double,double")
1727    (set_attr "prefix_rep" "1")
1728    (set_attr "mode" "SI")])
1729
1730 (define_insn "sse_cvtss2siq"
1731   [(set (match_operand:DI 0 "register_operand" "=r,r")
1732         (unspec:DI
1733           [(vec_select:SF
1734              (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
1735              (parallel [(const_int 0)]))]
1736           UNSPEC_FIX_NOTRUNC))]
1737   "TARGET_SSE && TARGET_64BIT"
1738   "cvtss2siq\t{%1, %0|%0, %1}"
1739   [(set_attr "type" "sseicvt")
1740    (set_attr "athlon_decode" "double,vector")
1741    (set_attr "prefix_rep" "1")
1742    (set_attr "mode" "DI")])
1743
1744 (define_insn "sse_cvtss2siq_2"
1745   [(set (match_operand:DI 0 "register_operand" "=r,r")
1746         (unspec:DI [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
1747                    UNSPEC_FIX_NOTRUNC))]
1748   "TARGET_SSE && TARGET_64BIT"
1749   "cvtss2siq\t{%1, %0|%0, %1}"
1750   [(set_attr "type" "sseicvt")
1751    (set_attr "athlon_decode" "double,vector")
1752    (set_attr "amdfam10_decode" "double,double")
1753    (set_attr "prefix_rep" "1")
1754    (set_attr "mode" "DI")])
1755
1756 (define_insn "sse_cvttss2si"
1757   [(set (match_operand:SI 0 "register_operand" "=r,r")
1758         (fix:SI
1759           (vec_select:SF
1760             (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
1761             (parallel [(const_int 0)]))))]
1762   "TARGET_SSE"
1763   "cvttss2si\t{%1, %0|%0, %1}"
1764   [(set_attr "type" "sseicvt")
1765    (set_attr "athlon_decode" "double,vector")
1766    (set_attr "amdfam10_decode" "double,double")
1767    (set_attr "prefix_rep" "1")
1768    (set_attr "mode" "SI")])
1769
1770 (define_insn "sse_cvttss2siq"
1771   [(set (match_operand:DI 0 "register_operand" "=r,r")
1772         (fix:DI
1773           (vec_select:SF
1774             (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
1775             (parallel [(const_int 0)]))))]
1776   "TARGET_SSE && TARGET_64BIT"
1777   "cvttss2siq\t{%1, %0|%0, %1}"
1778   [(set_attr "type" "sseicvt")
1779    (set_attr "athlon_decode" "double,vector")
1780    (set_attr "amdfam10_decode" "double,double")
1781    (set_attr "prefix_rep" "1")
1782    (set_attr "mode" "DI")])
1783
1784 (define_insn "sse2_cvtdq2ps"
1785   [(set (match_operand:V4SF 0 "register_operand" "=x")
1786         (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
1787   "TARGET_SSE2"
1788   "cvtdq2ps\t{%1, %0|%0, %1}"
1789   [(set_attr "type" "ssecvt")
1790    (set_attr "mode" "V4SF")])
1791
1792 (define_insn "sse2_cvtps2dq"
1793   [(set (match_operand:V4SI 0 "register_operand" "=x")
1794         (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
1795                      UNSPEC_FIX_NOTRUNC))]
1796   "TARGET_SSE2"
1797   "cvtps2dq\t{%1, %0|%0, %1}"
1798   [(set_attr "type" "ssecvt")
1799    (set_attr "prefix_data16" "1")
1800    (set_attr "mode" "TI")])
1801
1802 (define_insn "sse2_cvttps2dq"
1803   [(set (match_operand:V4SI 0 "register_operand" "=x")
1804         (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
1805   "TARGET_SSE2"
1806   "cvttps2dq\t{%1, %0|%0, %1}"
1807   [(set_attr "type" "ssecvt")
1808    (set_attr "prefix_rep" "1")
1809    (set_attr "mode" "TI")])
1810
1811 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1812 ;;
1813 ;; Parallel double-precision floating point conversion operations
1814 ;;
1815 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1816
1817 (define_insn "sse2_cvtpi2pd"
1818   [(set (match_operand:V2DF 0 "register_operand" "=x,x")
1819         (float:V2DF (match_operand:V2SI 1 "nonimmediate_operand" "y,m")))]
1820   "TARGET_SSE2"
1821   "cvtpi2pd\t{%1, %0|%0, %1}"
1822   [(set_attr "type" "ssecvt")
1823    (set_attr "unit" "mmx,*")
1824    (set_attr "mode" "V2DF")])
1825
1826 (define_insn "sse2_cvtpd2pi"
1827   [(set (match_operand:V2SI 0 "register_operand" "=y")
1828         (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
1829                      UNSPEC_FIX_NOTRUNC))]
1830   "TARGET_SSE2"
1831   "cvtpd2pi\t{%1, %0|%0, %1}"
1832   [(set_attr "type" "ssecvt")
1833    (set_attr "unit" "mmx")
1834    (set_attr "prefix_data16" "1")
1835    (set_attr "mode" "DI")])
1836
1837 (define_insn "sse2_cvttpd2pi"
1838   [(set (match_operand:V2SI 0 "register_operand" "=y")
1839         (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm")))]
1840   "TARGET_SSE2"
1841   "cvttpd2pi\t{%1, %0|%0, %1}"
1842   [(set_attr "type" "ssecvt")
1843    (set_attr "unit" "mmx")
1844    (set_attr "prefix_data16" "1")
1845    (set_attr "mode" "TI")])
1846
1847 (define_insn "sse2_cvtsi2sd"
1848   [(set (match_operand:V2DF 0 "register_operand" "=x,x")
1849         (vec_merge:V2DF
1850           (vec_duplicate:V2DF
1851             (float:DF (match_operand:SI 2 "nonimmediate_operand" "r,m")))
1852           (match_operand:V2DF 1 "register_operand" "0,0")
1853           (const_int 1)))]
1854   "TARGET_SSE2"
1855   "cvtsi2sd\t{%2, %0|%0, %2}"
1856   [(set_attr "type" "sseicvt")
1857    (set_attr "mode" "DF")
1858    (set_attr "athlon_decode" "double,direct")
1859    (set_attr "amdfam10_decode" "vector,double")])
1860
1861 (define_insn "sse2_cvtsi2sdq"
1862   [(set (match_operand:V2DF 0 "register_operand" "=x,x")
1863         (vec_merge:V2DF
1864           (vec_duplicate:V2DF
1865             (float:DF (match_operand:DI 2 "nonimmediate_operand" "r,m")))
1866           (match_operand:V2DF 1 "register_operand" "0,0")
1867           (const_int 1)))]
1868   "TARGET_SSE2 && TARGET_64BIT"
1869   "cvtsi2sdq\t{%2, %0|%0, %2}"
1870   [(set_attr "type" "sseicvt")
1871    (set_attr "mode" "DF")
1872    (set_attr "athlon_decode" "double,direct")
1873    (set_attr "amdfam10_decode" "vector,double")])
1874
1875 (define_insn "sse2_cvtsd2si"
1876   [(set (match_operand:SI 0 "register_operand" "=r,r")
1877         (unspec:SI
1878           [(vec_select:DF
1879              (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
1880              (parallel [(const_int 0)]))]
1881           UNSPEC_FIX_NOTRUNC))]
1882   "TARGET_SSE2"
1883   "cvtsd2si\t{%1, %0|%0, %1}"
1884   [(set_attr "type" "sseicvt")
1885    (set_attr "athlon_decode" "double,vector")
1886    (set_attr "prefix_rep" "1")
1887    (set_attr "mode" "SI")])
1888
1889 (define_insn "sse2_cvtsd2si_2"
1890   [(set (match_operand:SI 0 "register_operand" "=r,r")
1891         (unspec:SI [(match_operand:DF 1 "nonimmediate_operand" "x,m")]
1892                    UNSPEC_FIX_NOTRUNC))]
1893   "TARGET_SSE2"
1894   "cvtsd2si\t{%1, %0|%0, %1}"
1895   [(set_attr "type" "sseicvt")
1896    (set_attr "athlon_decode" "double,vector")
1897    (set_attr "amdfam10_decode" "double,double")
1898    (set_attr "prefix_rep" "1")
1899    (set_attr "mode" "SI")])
1900
1901 (define_insn "sse2_cvtsd2siq"
1902   [(set (match_operand:DI 0 "register_operand" "=r,r")
1903         (unspec:DI
1904           [(vec_select:DF
1905              (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
1906              (parallel [(const_int 0)]))]
1907           UNSPEC_FIX_NOTRUNC))]
1908   "TARGET_SSE2 && TARGET_64BIT"
1909   "cvtsd2siq\t{%1, %0|%0, %1}"
1910   [(set_attr "type" "sseicvt")
1911    (set_attr "athlon_decode" "double,vector")
1912    (set_attr "prefix_rep" "1")
1913    (set_attr "mode" "DI")])
1914
1915 (define_insn "sse2_cvtsd2siq_2"
1916   [(set (match_operand:DI 0 "register_operand" "=r,r")
1917         (unspec:DI [(match_operand:DF 1 "nonimmediate_operand" "x,m")]
1918                    UNSPEC_FIX_NOTRUNC))]
1919   "TARGET_SSE2 && TARGET_64BIT"
1920   "cvtsd2siq\t{%1, %0|%0, %1}"
1921   [(set_attr "type" "sseicvt")
1922    (set_attr "athlon_decode" "double,vector")
1923    (set_attr "amdfam10_decode" "double,double")
1924    (set_attr "prefix_rep" "1")
1925    (set_attr "mode" "DI")])
1926
1927 (define_insn "sse2_cvttsd2si"
1928   [(set (match_operand:SI 0 "register_operand" "=r,r")
1929         (fix:SI
1930           (vec_select:DF
1931             (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
1932             (parallel [(const_int 0)]))))]
1933   "TARGET_SSE2"
1934   "cvttsd2si\t{%1, %0|%0, %1}"
1935   [(set_attr "type" "sseicvt")
1936    (set_attr "prefix_rep" "1")
1937    (set_attr "mode" "SI")
1938    (set_attr "athlon_decode" "double,vector")
1939    (set_attr "amdfam10_decode" "double,double")])
1940
1941 (define_insn "sse2_cvttsd2siq"
1942   [(set (match_operand:DI 0 "register_operand" "=r,r")
1943         (fix:DI
1944           (vec_select:DF
1945             (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
1946             (parallel [(const_int 0)]))))]
1947   "TARGET_SSE2 && TARGET_64BIT"
1948   "cvttsd2siq\t{%1, %0|%0, %1}"
1949   [(set_attr "type" "sseicvt")
1950    (set_attr "prefix_rep" "1")
1951    (set_attr "mode" "DI")
1952    (set_attr "athlon_decode" "double,vector")
1953    (set_attr "amdfam10_decode" "double,double")])
1954
1955 (define_insn "sse2_cvtdq2pd"
1956   [(set (match_operand:V2DF 0 "register_operand" "=x")
1957         (float:V2DF
1958           (vec_select:V2SI
1959             (match_operand:V4SI 1 "nonimmediate_operand" "xm")
1960             (parallel [(const_int 0) (const_int 1)]))))]
1961   "TARGET_SSE2"
1962   "cvtdq2pd\t{%1, %0|%0, %1}"
1963   [(set_attr "type" "ssecvt")
1964    (set_attr "mode" "V2DF")])
1965
1966 (define_expand "sse2_cvtpd2dq"
1967   [(set (match_operand:V4SI 0 "register_operand" "")
1968         (vec_concat:V4SI
1969           (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "")]
1970                        UNSPEC_FIX_NOTRUNC)
1971           (match_dup 2)))]
1972   "TARGET_SSE2"
1973   "operands[2] = CONST0_RTX (V2SImode);")
1974
1975 (define_insn "*sse2_cvtpd2dq"
1976   [(set (match_operand:V4SI 0 "register_operand" "=x")
1977         (vec_concat:V4SI
1978           (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
1979                        UNSPEC_FIX_NOTRUNC)
1980           (match_operand:V2SI 2 "const0_operand" "")))]
1981   "TARGET_SSE2"
1982   "cvtpd2dq\t{%1, %0|%0, %1}"
1983   [(set_attr "type" "ssecvt")
1984    (set_attr "prefix_rep" "1")
1985    (set_attr "mode" "TI")
1986    (set_attr "amdfam10_decode" "double")])
1987
1988 (define_expand "sse2_cvttpd2dq"
1989   [(set (match_operand:V4SI 0 "register_operand" "")
1990         (vec_concat:V4SI
1991           (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" ""))
1992           (match_dup 2)))]
1993   "TARGET_SSE2"
1994   "operands[2] = CONST0_RTX (V2SImode);")
1995
1996 (define_insn "*sse2_cvttpd2dq"
1997   [(set (match_operand:V4SI 0 "register_operand" "=x")
1998         (vec_concat:V4SI
1999           (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
2000           (match_operand:V2SI 2 "const0_operand" "")))]
2001   "TARGET_SSE2"
2002   "cvttpd2dq\t{%1, %0|%0, %1}"
2003   [(set_attr "type" "ssecvt")
2004    (set_attr "prefix_rep" "1")
2005    (set_attr "mode" "TI")
2006    (set_attr "amdfam10_decode" "double")])
2007
2008 (define_insn "sse2_cvtsd2ss"
2009   [(set (match_operand:V4SF 0 "register_operand" "=x,x")
2010         (vec_merge:V4SF
2011           (vec_duplicate:V4SF
2012             (float_truncate:V2SF
2013               (match_operand:V2DF 2 "nonimmediate_operand" "x,m")))
2014           (match_operand:V4SF 1 "register_operand" "0,0")
2015           (const_int 1)))]
2016   "TARGET_SSE2"
2017   "cvtsd2ss\t{%2, %0|%0, %2}"
2018   [(set_attr "type" "ssecvt")
2019    (set_attr "athlon_decode" "vector,double")
2020    (set_attr "amdfam10_decode" "vector,double")
2021    (set_attr "mode" "SF")])
2022
2023 (define_insn "sse2_cvtss2sd"
2024   [(set (match_operand:V2DF 0 "register_operand" "=x,x")
2025         (vec_merge:V2DF
2026           (float_extend:V2DF
2027             (vec_select:V2SF
2028               (match_operand:V4SF 2 "nonimmediate_operand" "x,m")
2029               (parallel [(const_int 0) (const_int 1)])))
2030           (match_operand:V2DF 1 "register_operand" "0,0")
2031           (const_int 1)))]
2032   "TARGET_SSE2"
2033   "cvtss2sd\t{%2, %0|%0, %2}"
2034   [(set_attr "type" "ssecvt")
2035    (set_attr "amdfam10_decode" "vector,double")
2036    (set_attr "mode" "DF")])
2037
2038 (define_expand "sse2_cvtpd2ps"
2039   [(set (match_operand:V4SF 0 "register_operand" "")
2040         (vec_concat:V4SF
2041           (float_truncate:V2SF
2042             (match_operand:V2DF 1 "nonimmediate_operand" ""))
2043           (match_dup 2)))]
2044   "TARGET_SSE2"
2045   "operands[2] = CONST0_RTX (V2SFmode);")
2046
2047 (define_insn "*sse2_cvtpd2ps"
2048   [(set (match_operand:V4SF 0 "register_operand" "=x")
2049         (vec_concat:V4SF
2050           (float_truncate:V2SF
2051             (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
2052           (match_operand:V2SF 2 "const0_operand" "")))]
2053   "TARGET_SSE2"
2054   "cvtpd2ps\t{%1, %0|%0, %1}"
2055   [(set_attr "type" "ssecvt")
2056    (set_attr "prefix_data16" "1")
2057    (set_attr "mode" "V4SF")
2058    (set_attr "amdfam10_decode" "double")])
2059
2060 (define_insn "sse2_cvtps2pd"
2061   [(set (match_operand:V2DF 0 "register_operand" "=x")
2062         (float_extend:V2DF
2063           (vec_select:V2SF
2064             (match_operand:V4SF 1 "nonimmediate_operand" "xm")
2065             (parallel [(const_int 0) (const_int 1)]))))]
2066   "TARGET_SSE2"
2067   "cvtps2pd\t{%1, %0|%0, %1}"
2068   [(set_attr "type" "ssecvt")
2069    (set_attr "mode" "V2DF")
2070    (set_attr "amdfam10_decode" "direct")])
2071
2072 (define_expand "vec_unpacks_hi_v4sf"
2073   [(set (match_dup 2)
2074    (vec_select:V4SF
2075      (vec_concat:V8SF
2076        (match_dup 2)
2077        (match_operand:V4SF 1 "nonimmediate_operand" ""))
2078      (parallel [(const_int 6)
2079                 (const_int 7)
2080                 (const_int 2)
2081                 (const_int 3)])))
2082   (set (match_operand:V2DF 0 "register_operand" "")
2083    (float_extend:V2DF
2084      (vec_select:V2SF
2085        (match_dup 2)
2086        (parallel [(const_int 0) (const_int 1)]))))]
2087  "TARGET_SSE2"
2088 {
2089  operands[2] = gen_reg_rtx (V4SFmode);
2090 })
2091
2092 (define_expand "vec_unpacks_lo_v4sf"
2093   [(set (match_operand:V2DF 0 "register_operand" "")
2094         (float_extend:V2DF
2095           (vec_select:V2SF
2096             (match_operand:V4SF 1 "nonimmediate_operand" "")
2097             (parallel [(const_int 0) (const_int 1)]))))]
2098   "TARGET_SSE2")
2099
2100 (define_expand "vec_unpacks_float_hi_v8hi"
2101   [(match_operand:V4SF 0 "register_operand" "")
2102    (match_operand:V8HI 1 "register_operand" "")]
2103   "TARGET_SSE2"
2104 {
2105   rtx tmp = gen_reg_rtx (V4SImode);
2106
2107   emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
2108   emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
2109   DONE;
2110 })
2111
2112 (define_expand "vec_unpacks_float_lo_v8hi"
2113   [(match_operand:V4SF 0 "register_operand" "")
2114    (match_operand:V8HI 1 "register_operand" "")]
2115   "TARGET_SSE2"
2116 {
2117   rtx tmp = gen_reg_rtx (V4SImode);
2118
2119   emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
2120   emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
2121   DONE;
2122 })
2123
2124 (define_expand "vec_unpacku_float_hi_v8hi"
2125   [(match_operand:V4SF 0 "register_operand" "")
2126    (match_operand:V8HI 1 "register_operand" "")]
2127   "TARGET_SSE2"
2128 {
2129   rtx tmp = gen_reg_rtx (V4SImode);
2130
2131   emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
2132   emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
2133   DONE;
2134 })
2135
2136 (define_expand "vec_unpacku_float_lo_v8hi"
2137   [(match_operand:V4SF 0 "register_operand" "")
2138    (match_operand:V8HI 1 "register_operand" "")]
2139   "TARGET_SSE2"
2140 {
2141   rtx tmp = gen_reg_rtx (V4SImode);
2142
2143   emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
2144   emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
2145   DONE;
2146 })
2147
2148 (define_expand "vec_unpacks_float_hi_v4si"
2149   [(set (match_dup 2)
2150         (vec_select:V4SI
2151           (match_operand:V4SI 1 "nonimmediate_operand" "")
2152           (parallel [(const_int 2)
2153                      (const_int 3)
2154                      (const_int 2)
2155                      (const_int 3)])))
2156    (set (match_operand:V2DF 0 "register_operand" "")
2157         (float:V2DF
2158           (vec_select:V2SI
2159           (match_dup 2)
2160             (parallel [(const_int 0) (const_int 1)]))))]
2161  "TARGET_SSE2"
2162 {
2163  operands[2] = gen_reg_rtx (V4SImode);
2164 })
2165
2166 (define_expand "vec_unpacks_float_lo_v4si"
2167   [(set (match_operand:V2DF 0 "register_operand" "")
2168         (float:V2DF
2169           (vec_select:V2SI
2170             (match_operand:V4SI 1 "nonimmediate_operand" "")
2171             (parallel [(const_int 0) (const_int 1)]))))]
2172   "TARGET_SSE2")
2173
2174 (define_expand "vec_pack_trunc_v2df"
2175   [(match_operand:V4SF 0 "register_operand" "")
2176    (match_operand:V2DF 1 "nonimmediate_operand" "")
2177    (match_operand:V2DF 2 "nonimmediate_operand" "")]
2178   "TARGET_SSE2"
2179 {
2180   rtx r1, r2;
2181
2182   r1 = gen_reg_rtx (V4SFmode);
2183   r2 = gen_reg_rtx (V4SFmode);
2184
2185   emit_insn (gen_sse2_cvtpd2ps (r1, operands[1]));
2186   emit_insn (gen_sse2_cvtpd2ps (r2, operands[2]));
2187   emit_insn (gen_sse_movlhps (operands[0], r1, r2));
2188   DONE;
2189 })
2190
2191 (define_expand "vec_pack_sfix_trunc_v2df"
2192   [(match_operand:V4SI 0 "register_operand" "")
2193    (match_operand:V2DF 1 "nonimmediate_operand" "")
2194    (match_operand:V2DF 2 "nonimmediate_operand" "")]
2195   "TARGET_SSE2"
2196 {
2197   rtx r1, r2;
2198
2199   r1 = gen_reg_rtx (V4SImode);
2200   r2 = gen_reg_rtx (V4SImode);
2201
2202   emit_insn (gen_sse2_cvttpd2dq (r1, operands[1]));
2203   emit_insn (gen_sse2_cvttpd2dq (r2, operands[2]));
2204   emit_insn (gen_sse2_punpcklqdq (gen_lowpart (V2DImode, operands[0]),
2205                                   gen_lowpart (V2DImode, r1),
2206                                   gen_lowpart (V2DImode, r2)));
2207   DONE;
2208 })
2209
2210 (define_expand "vec_pack_sfix_v2df"
2211   [(match_operand:V4SI 0 "register_operand" "")
2212    (match_operand:V2DF 1 "nonimmediate_operand" "")
2213    (match_operand:V2DF 2 "nonimmediate_operand" "")]
2214   "TARGET_SSE2"
2215 {
2216   rtx r1, r2;
2217
2218   r1 = gen_reg_rtx (V4SImode);
2219   r2 = gen_reg_rtx (V4SImode);
2220
2221   emit_insn (gen_sse2_cvtpd2dq (r1, operands[1]));
2222   emit_insn (gen_sse2_cvtpd2dq (r2, operands[2]));
2223   emit_insn (gen_sse2_punpcklqdq (gen_lowpart (V2DImode, operands[0]),
2224                                   gen_lowpart (V2DImode, r1),
2225                                   gen_lowpart (V2DImode, r2)));
2226   DONE;
2227 })
2228
2229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2230 ;;
2231 ;; Parallel single-precision floating point element swizzling
2232 ;;
2233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2234
2235 (define_insn "sse_movhlps"
2236   [(set (match_operand:V4SF 0 "nonimmediate_operand"     "=x,x,m")
2237         (vec_select:V4SF
2238           (vec_concat:V8SF
2239             (match_operand:V4SF 1 "nonimmediate_operand" " 0,0,0")
2240             (match_operand:V4SF 2 "nonimmediate_operand" " x,o,x"))
2241           (parallel [(const_int 6)
2242                      (const_int 7)
2243                      (const_int 2)
2244                      (const_int 3)])))]
2245   "TARGET_SSE && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
2246   "@
2247    movhlps\t{%2, %0|%0, %2}
2248    movlps\t{%H2, %0|%0, %H2}
2249    movhps\t{%2, %0|%0, %2}"
2250   [(set_attr "type" "ssemov")
2251    (set_attr "mode" "V4SF,V2SF,V2SF")])
2252
2253 (define_insn "sse_movlhps"
2254   [(set (match_operand:V4SF 0 "nonimmediate_operand"     "=x,x,o")
2255         (vec_select:V4SF
2256           (vec_concat:V8SF
2257             (match_operand:V4SF 1 "nonimmediate_operand" " 0,0,0")
2258             (match_operand:V4SF 2 "nonimmediate_operand" " x,m,x"))
2259           (parallel [(const_int 0)
2260                      (const_int 1)
2261                      (const_int 4)
2262                      (const_int 5)])))]
2263   "TARGET_SSE && ix86_binary_operator_ok (UNKNOWN, V4SFmode, operands)"
2264   "@
2265    movlhps\t{%2, %0|%0, %2}
2266    movhps\t{%2, %0|%0, %2}
2267    movlps\t{%2, %H0|%H0, %2}"
2268   [(set_attr "type" "ssemov")
2269    (set_attr "mode" "V4SF,V2SF,V2SF")])
2270
2271 (define_insn "sse_unpckhps"
2272   [(set (match_operand:V4SF 0 "register_operand" "=x")
2273         (vec_select:V4SF
2274           (vec_concat:V8SF
2275             (match_operand:V4SF 1 "register_operand" "0")
2276             (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
2277           (parallel [(const_int 2) (const_int 6)
2278                      (const_int 3) (const_int 7)])))]
2279   "TARGET_SSE"
2280   "unpckhps\t{%2, %0|%0, %2}"
2281   [(set_attr "type" "sselog")
2282    (set_attr "mode" "V4SF")])
2283
2284 (define_insn "sse_unpcklps"
2285   [(set (match_operand:V4SF 0 "register_operand" "=x")
2286         (vec_select:V4SF
2287           (vec_concat:V8SF
2288             (match_operand:V4SF 1 "register_operand" "0")
2289             (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
2290           (parallel [(const_int 0) (const_int 4)
2291                      (const_int 1) (const_int 5)])))]
2292   "TARGET_SSE"
2293   "unpcklps\t{%2, %0|%0, %2}"
2294   [(set_attr "type" "sselog")
2295    (set_attr "mode" "V4SF")])
2296
2297 ;; These are modeled with the same vec_concat as the others so that we
2298 ;; capture users of shufps that can use the new instructions
2299 (define_insn "sse3_movshdup"
2300   [(set (match_operand:V4SF 0 "register_operand" "=x")
2301         (vec_select:V4SF
2302           (vec_concat:V8SF
2303             (match_operand:V4SF 1 "nonimmediate_operand" "xm")
2304             (match_dup 1))
2305           (parallel [(const_int 1)
2306                      (const_int 1)
2307                      (const_int 7)
2308                      (const_int 7)])))]
2309   "TARGET_SSE3"
2310   "movshdup\t{%1, %0|%0, %1}"
2311   [(set_attr "type" "sse")
2312    (set_attr "prefix_rep" "1")
2313    (set_attr "mode" "V4SF")])
2314
2315 (define_insn "sse3_movsldup"
2316   [(set (match_operand:V4SF 0 "register_operand" "=x")
2317         (vec_select:V4SF
2318           (vec_concat:V8SF
2319             (match_operand:V4SF 1 "nonimmediate_operand" "xm")
2320             (match_dup 1))
2321           (parallel [(const_int 0)
2322                      (const_int 0)
2323                      (const_int 6)
2324                      (const_int 6)])))]
2325   "TARGET_SSE3"
2326   "movsldup\t{%1, %0|%0, %1}"
2327   [(set_attr "type" "sse")
2328    (set_attr "prefix_rep" "1")
2329    (set_attr "mode" "V4SF")])
2330
2331 (define_expand "sse_shufps"
2332   [(match_operand:V4SF 0 "register_operand" "")
2333    (match_operand:V4SF 1 "register_operand" "")
2334    (match_operand:V4SF 2 "nonimmediate_operand" "")
2335    (match_operand:SI 3 "const_int_operand" "")]
2336   "TARGET_SSE"
2337 {
2338   int mask = INTVAL (operands[3]);
2339   emit_insn (gen_sse_shufps_1 (operands[0], operands[1], operands[2],
2340                                GEN_INT ((mask >> 0) & 3),
2341                                GEN_INT ((mask >> 2) & 3),
2342                                GEN_INT (((mask >> 4) & 3) + 4),
2343                                GEN_INT (((mask >> 6) & 3) + 4)));
2344   DONE;
2345 })
2346
2347 (define_insn "sse_shufps_1"
2348   [(set (match_operand:V4SF 0 "register_operand" "=x")
2349         (vec_select:V4SF
2350           (vec_concat:V8SF
2351             (match_operand:V4SF 1 "register_operand" "0")
2352             (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
2353           (parallel [(match_operand 3 "const_0_to_3_operand" "")
2354                      (match_operand 4 "const_0_to_3_operand" "")
2355                      (match_operand 5 "const_4_to_7_operand" "")
2356                      (match_operand 6 "const_4_to_7_operand" "")])))]
2357   "TARGET_SSE"
2358 {
2359   int mask = 0;
2360   mask |= INTVAL (operands[3]) << 0;
2361   mask |= INTVAL (operands[4]) << 2;
2362   mask |= (INTVAL (operands[5]) - 4) << 4;
2363   mask |= (INTVAL (operands[6]) - 4) << 6;
2364   operands[3] = GEN_INT (mask);
2365
2366   return "shufps\t{%3, %2, %0|%0, %2, %3}";
2367 }
2368   [(set_attr "type" "sselog")
2369    (set_attr "mode" "V4SF")])
2370
2371 (define_insn "sse_storehps"
2372   [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,x,x")
2373         (vec_select:V2SF
2374           (match_operand:V4SF 1 "nonimmediate_operand" "x,x,o")
2375           (parallel [(const_int 2) (const_int 3)])))]
2376   "TARGET_SSE"
2377   "@
2378    movhps\t{%1, %0|%0, %1}
2379    movhlps\t{%1, %0|%0, %1}
2380    movlps\t{%H1, %0|%0, %H1}"
2381   [(set_attr "type" "ssemov")
2382    (set_attr "mode" "V2SF,V4SF,V2SF")])
2383
2384 (define_insn "sse_loadhps"
2385   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
2386         (vec_concat:V4SF
2387           (vec_select:V2SF
2388             (match_operand:V4SF 1 "nonimmediate_operand" "0,0,0")
2389             (parallel [(const_int 0) (const_int 1)]))
2390           (match_operand:V2SF 2 "nonimmediate_operand" "m,x,x")))]
2391   "TARGET_SSE"
2392   "@
2393    movhps\t{%2, %0|%0, %2}
2394    movlhps\t{%2, %0|%0, %2}
2395    movlps\t{%2, %H0|%H0, %2}"
2396   [(set_attr "type" "ssemov")
2397    (set_attr "mode" "V2SF,V4SF,V2SF")])
2398
2399 (define_insn "sse_storelps"
2400   [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,x,x")
2401         (vec_select:V2SF
2402           (match_operand:V4SF 1 "nonimmediate_operand" "x,x,m")
2403           (parallel [(const_int 0) (const_int 1)])))]
2404   "TARGET_SSE"
2405   "@
2406    movlps\t{%1, %0|%0, %1}
2407    movaps\t{%1, %0|%0, %1}
2408    movlps\t{%1, %0|%0, %1}"
2409   [(set_attr "type" "ssemov")
2410    (set_attr "mode" "V2SF,V4SF,V2SF")])
2411
2412 (define_insn "sse_loadlps"
2413   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
2414         (vec_concat:V4SF
2415           (match_operand:V2SF 2 "nonimmediate_operand" "0,m,x")
2416           (vec_select:V2SF
2417             (match_operand:V4SF 1 "nonimmediate_operand" "x,0,0")
2418             (parallel [(const_int 2) (const_int 3)]))))]
2419   "TARGET_SSE"
2420   "@
2421    shufps\t{$0xe4, %1, %0|%0, %1, 0xe4}
2422    movlps\t{%2, %0|%0, %2}
2423    movlps\t{%2, %0|%0, %2}"
2424   [(set_attr "type" "sselog,ssemov,ssemov")
2425    (set_attr "mode" "V4SF,V2SF,V2SF")])
2426
2427 (define_insn "sse_movss"
2428   [(set (match_operand:V4SF 0 "register_operand" "=x")
2429         (vec_merge:V4SF
2430           (match_operand:V4SF 2 "register_operand" "x")
2431           (match_operand:V4SF 1 "register_operand" "0")
2432           (const_int 1)))]
2433   "TARGET_SSE"
2434   "movss\t{%2, %0|%0, %2}"
2435   [(set_attr "type" "ssemov")
2436    (set_attr "mode" "SF")])
2437
2438 (define_insn "*vec_dupv4sf"
2439   [(set (match_operand:V4SF 0 "register_operand" "=x")
2440         (vec_duplicate:V4SF
2441           (match_operand:SF 1 "register_operand" "0")))]
2442   "TARGET_SSE"
2443   "shufps\t{$0, %0, %0|%0, %0, 0}"
2444   [(set_attr "type" "sselog1")
2445    (set_attr "mode" "V4SF")])
2446
2447 ;; ??? In theory we can match memory for the MMX alternative, but allowing
2448 ;; nonimmediate_operand for operand 2 and *not* allowing memory for the SSE
2449 ;; alternatives pretty much forces the MMX alternative to be chosen.
2450 (define_insn "*sse_concatv2sf"
2451   [(set (match_operand:V2SF 0 "register_operand"     "=x,x,*y,*y")
2452         (vec_concat:V2SF
2453           (match_operand:SF 1 "nonimmediate_operand" " 0,m, 0, m")
2454           (match_operand:SF 2 "reg_or_0_operand"     " x,C,*y, C")))]
2455   "TARGET_SSE"
2456   "@
2457    unpcklps\t{%2, %0|%0, %2}
2458    movss\t{%1, %0|%0, %1}
2459    punpckldq\t{%2, %0|%0, %2}
2460    movd\t{%1, %0|%0, %1}"
2461   [(set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
2462    (set_attr "mode" "V4SF,SF,DI,DI")])
2463
2464 (define_insn "*sse_concatv4sf"
2465   [(set (match_operand:V4SF 0 "register_operand"   "=x,x")
2466         (vec_concat:V4SF
2467           (match_operand:V2SF 1 "register_operand" " 0,0")
2468           (match_operand:V2SF 2 "nonimmediate_operand" " x,m")))]
2469   "TARGET_SSE"
2470   "@
2471    movlhps\t{%2, %0|%0, %2}
2472    movhps\t{%2, %0|%0, %2}"
2473   [(set_attr "type" "ssemov")
2474    (set_attr "mode" "V4SF,V2SF")])
2475
2476 (define_expand "vec_initv4sf"
2477   [(match_operand:V4SF 0 "register_operand" "")
2478    (match_operand 1 "" "")]
2479   "TARGET_SSE"
2480 {
2481   ix86_expand_vector_init (false, operands[0], operands[1]);
2482   DONE;
2483 })
2484
2485 (define_insn "vec_setv4sf_0"
2486   [(set (match_operand:V4SF 0 "nonimmediate_operand"  "=x,x,Y2,m")
2487         (vec_merge:V4SF
2488           (vec_duplicate:V4SF
2489             (match_operand:SF 2 "general_operand"     " x,m,*r,x*rfF"))
2490           (match_operand:V4SF 1 "vector_move_operand" " 0,C,C ,0")
2491           (const_int 1)))]
2492   "TARGET_SSE"
2493   "@
2494    movss\t{%2, %0|%0, %2}
2495    movss\t{%2, %0|%0, %2}
2496    movd\t{%2, %0|%0, %2}
2497    #"
2498   [(set_attr "type" "ssemov")
2499    (set_attr "mode" "SF")])
2500
2501 ;; A subset is vec_setv4sf.
2502 (define_insn "*vec_setv4sf_sse4_1"
2503   [(set (match_operand:V4SF 0 "register_operand" "=x")
2504         (vec_merge:V4SF
2505           (vec_duplicate:V4SF
2506             (match_operand:SF 2 "nonimmediate_operand" "xm"))
2507           (match_operand:V4SF 1 "register_operand" "0")
2508           (match_operand:SI 3 "const_pow2_1_to_8_operand" "n")))]
2509   "TARGET_SSE4_1"
2510 {
2511   operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])) << 4);
2512   return "insertps\t{%3, %2, %0|%0, %2, %3}";
2513 }
2514   [(set_attr "type" "sselog")
2515    (set_attr "prefix_extra" "1")
2516    (set_attr "mode" "V4SF")])
2517
2518 (define_insn "sse4_1_insertps"
2519   [(set (match_operand:V4SF 0 "register_operand" "=x")
2520         (unspec:V4SF [(match_operand:V4SF 2 "register_operand" "x")
2521                       (match_operand:V4SF 1 "register_operand" "0")
2522                       (match_operand:SI 3 "const_0_to_255_operand" "n")]
2523                      UNSPEC_INSERTPS))]
2524   "TARGET_SSE4_1"
2525   "insertps\t{%3, %2, %0|%0, %2, %3}";
2526   [(set_attr "type" "sselog")
2527    (set_attr "prefix_extra" "1")
2528    (set_attr "mode" "V4SF")])
2529
2530 (define_split
2531   [(set (match_operand:V4SF 0 "memory_operand" "")
2532         (vec_merge:V4SF
2533           (vec_duplicate:V4SF
2534             (match_operand:SF 1 "nonmemory_operand" ""))
2535           (match_dup 0)
2536           (const_int 1)))]
2537   "TARGET_SSE && reload_completed"
2538   [(const_int 0)]
2539 {
2540   emit_move_insn (adjust_address (operands[0], SFmode, 0), operands[1]);
2541   DONE;
2542 })
2543
2544 (define_expand "vec_setv4sf"
2545   [(match_operand:V4SF 0 "register_operand" "")
2546    (match_operand:SF 1 "register_operand" "")
2547    (match_operand 2 "const_int_operand" "")]
2548   "TARGET_SSE"
2549 {
2550   ix86_expand_vector_set (false, operands[0], operands[1],
2551                           INTVAL (operands[2]));
2552   DONE;
2553 })
2554
2555 (define_insn_and_split "*vec_extractv4sf_0"
2556   [(set (match_operand:SF 0 "nonimmediate_operand" "=x,m,fr")
2557         (vec_select:SF
2558           (match_operand:V4SF 1 "nonimmediate_operand" "xm,x,m")
2559           (parallel [(const_int 0)])))]
2560   "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
2561   "#"
2562   "&& reload_completed"
2563   [(const_int 0)]
2564 {
2565   rtx op1 = operands[1];
2566   if (REG_P (op1))
2567     op1 = gen_rtx_REG (SFmode, REGNO (op1));
2568   else
2569     op1 = gen_lowpart (SFmode, op1);
2570   emit_move_insn (operands[0], op1);
2571   DONE;
2572 })
2573
2574 (define_insn "*sse4_1_extractps"
2575   [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
2576         (vec_select:SF
2577           (match_operand:V4SF 1 "register_operand" "x")
2578           (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n")])))]
2579   "TARGET_SSE4_1"
2580   "extractps\t{%2, %1, %0|%0, %1, %2}"
2581   [(set_attr "type" "sselog")
2582    (set_attr "prefix_extra" "1")
2583    (set_attr "mode" "V4SF")])
2584
2585 (define_insn_and_split "*vec_extract_v4sf_mem"
2586   [(set (match_operand:SF 0 "register_operand" "=x*rf")
2587        (vec_select:SF
2588          (match_operand:V4SF 1 "memory_operand" "o")
2589          (parallel [(match_operand 2 "const_0_to_3_operand" "n")])))]
2590   ""
2591   "#"
2592   "reload_completed"
2593   [(const_int 0)]
2594 {
2595   int i = INTVAL (operands[2]);
2596
2597   emit_move_insn (operands[0], adjust_address (operands[1], SFmode, i*4));
2598   DONE;
2599 })
2600
2601 (define_expand "vec_extractv4sf"
2602   [(match_operand:SF 0 "register_operand" "")
2603    (match_operand:V4SF 1 "register_operand" "")
2604    (match_operand 2 "const_int_operand" "")]
2605   "TARGET_SSE"
2606 {
2607   ix86_expand_vector_extract (false, operands[0], operands[1],
2608                               INTVAL (operands[2]));
2609   DONE;
2610 })
2611
2612 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2613 ;;
2614 ;; Parallel double-precision floating point element swizzling
2615 ;;
2616 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2617
2618 (define_insn "sse2_unpckhpd"
2619   [(set (match_operand:V2DF 0 "nonimmediate_operand"     "=x,x,m")
2620         (vec_select:V2DF
2621           (vec_concat:V4DF
2622             (match_operand:V2DF 1 "nonimmediate_operand" " 0,o,x")
2623             (match_operand:V2DF 2 "nonimmediate_operand" " x,0,0"))
2624           (parallel [(const_int 1)
2625                      (const_int 3)])))]
2626   "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
2627   "@
2628    unpckhpd\t{%2, %0|%0, %2}
2629    movlpd\t{%H1, %0|%0, %H1}
2630    movhpd\t{%1, %0|%0, %1}"
2631   [(set_attr "type" "sselog,ssemov,ssemov")
2632    (set_attr "mode" "V2DF,V1DF,V1DF")])
2633
2634 (define_insn "*sse3_movddup"
2635   [(set (match_operand:V2DF 0 "nonimmediate_operand"     "=x,o")
2636         (vec_select:V2DF
2637           (vec_concat:V4DF
2638             (match_operand:V2DF 1 "nonimmediate_operand" "xm,x")
2639             (match_dup 1))
2640           (parallel [(const_int 0)
2641                      (const_int 2)])))]
2642   "TARGET_SSE3 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
2643   "@
2644    movddup\t{%1, %0|%0, %1}
2645    #"
2646   [(set_attr "type" "sselog1,ssemov")
2647    (set_attr "mode" "V2DF")])
2648
2649 (define_split
2650   [(set (match_operand:V2DF 0 "memory_operand" "")
2651         (vec_select:V2DF
2652           (vec_concat:V4DF
2653             (match_operand:V2DF 1 "register_operand" "")
2654             (match_dup 1))
2655           (parallel [(const_int 0)
2656                      (const_int 2)])))]
2657   "TARGET_SSE3 && reload_completed"
2658   [(const_int 0)]
2659 {
2660   rtx low = gen_rtx_REG (DFmode, REGNO (operands[1]));
2661   emit_move_insn (adjust_address (operands[0], DFmode, 0), low);
2662   emit_move_insn (adjust_address (operands[0], DFmode, 8), low);
2663   DONE;
2664 })
2665
2666 (define_insn "sse2_unpcklpd"
2667   [(set (match_operand:V2DF 0 "nonimmediate_operand"     "=x,x,o")
2668         (vec_select:V2DF
2669           (vec_concat:V4DF
2670             (match_operand:V2DF 1 "nonimmediate_operand" " 0,0,0")
2671             (match_operand:V2DF 2 "nonimmediate_operand" " x,m,x"))
2672           (parallel [(const_int 0)
2673                      (const_int 2)])))]
2674   "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
2675   "@
2676    unpcklpd\t{%2, %0|%0, %2}
2677    movhpd\t{%2, %0|%0, %2}
2678    movlpd\t{%2, %H0|%H0, %2}"
2679   [(set_attr "type" "sselog,ssemov,ssemov")
2680    (set_attr "mode" "V2DF,V1DF,V1DF")])
2681
2682 (define_expand "sse2_shufpd"
2683   [(match_operand:V2DF 0 "register_operand" "")
2684    (match_operand:V2DF 1 "register_operand" "")
2685    (match_operand:V2DF 2 "nonimmediate_operand" "")
2686    (match_operand:SI 3 "const_int_operand" "")]
2687   "TARGET_SSE2"
2688 {
2689   int mask = INTVAL (operands[3]);
2690   emit_insn (gen_sse2_shufpd_1 (operands[0], operands[1], operands[2],
2691                                 GEN_INT (mask & 1),
2692                                 GEN_INT (mask & 2 ? 3 : 2)));
2693   DONE;
2694 })
2695
2696 (define_insn "sse2_shufpd_1"
2697   [(set (match_operand:V2DF 0 "register_operand" "=x")
2698         (vec_select:V2DF
2699           (vec_concat:V4DF
2700             (match_operand:V2DF 1 "register_operand" "0")
2701             (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
2702           (parallel [(match_operand 3 "const_0_to_1_operand" "")
2703                      (match_operand 4 "const_2_to_3_operand" "")])))]
2704   "TARGET_SSE2"
2705 {
2706   int mask;
2707   mask = INTVAL (operands[3]);
2708   mask |= (INTVAL (operands[4]) - 2) << 1;
2709   operands[3] = GEN_INT (mask);
2710
2711   return "shufpd\t{%3, %2, %0|%0, %2, %3}";
2712 }
2713   [(set_attr "type" "sselog")
2714    (set_attr "mode" "V2DF")])
2715
2716 (define_insn "sse2_storehpd"
2717   [(set (match_operand:DF 0 "nonimmediate_operand"     "=m,x,x*fr")
2718         (vec_select:DF
2719           (match_operand:V2DF 1 "nonimmediate_operand" " x,0,o")
2720           (parallel [(const_int 1)])))]
2721   "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
2722   "@
2723    movhpd\t{%1, %0|%0, %1}
2724    unpckhpd\t%0, %0
2725    #"
2726   [(set_attr "type" "ssemov,sselog1,ssemov")
2727    (set_attr "mode" "V1DF,V2DF,DF")])
2728
2729 (define_split
2730   [(set (match_operand:DF 0 "register_operand" "")
2731         (vec_select:DF
2732           (match_operand:V2DF 1 "memory_operand" "")
2733           (parallel [(const_int 1)])))]
2734   "TARGET_SSE2 && reload_completed"
2735   [(set (match_dup 0) (match_dup 1))]
2736 {
2737   operands[1] = adjust_address (operands[1], DFmode, 8);
2738 })
2739
2740 (define_insn "sse2_storelpd"
2741   [(set (match_operand:DF 0 "nonimmediate_operand"     "=m,x,x*fr")
2742         (vec_select:DF
2743           (match_operand:V2DF 1 "nonimmediate_operand" " x,x,m")
2744           (parallel [(const_int 0)])))]
2745   "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
2746   "@
2747    movlpd\t{%1, %0|%0, %1}
2748    #
2749    #"
2750   [(set_attr "type" "ssemov")
2751    (set_attr "mode" "V1DF,DF,DF")])
2752
2753 (define_split
2754   [(set (match_operand:DF 0 "register_operand" "")
2755         (vec_select:DF
2756           (match_operand:V2DF 1 "nonimmediate_operand" "")
2757           (parallel [(const_int 0)])))]
2758   "TARGET_SSE2 && reload_completed"
2759   [(const_int 0)]
2760 {
2761   rtx op1 = operands[1];
2762   if (REG_P (op1))
2763     op1 = gen_rtx_REG (DFmode, REGNO (op1));
2764   else
2765     op1 = gen_lowpart (DFmode, op1);
2766   emit_move_insn (operands[0], op1);
2767   DONE;
2768 })
2769
2770 (define_insn "sse2_loadhpd"
2771   [(set (match_operand:V2DF 0 "nonimmediate_operand"     "=x,x,x,o")
2772         (vec_concat:V2DF
2773           (vec_select:DF
2774             (match_operand:V2DF 1 "nonimmediate_operand" " 0,0,x,0")
2775             (parallel [(const_int 0)]))
2776           (match_operand:DF 2 "nonimmediate_operand"     " m,x,0,x*fr")))]
2777   "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
2778   "@
2779    movhpd\t{%2, %0|%0, %2}
2780    unpcklpd\t{%2, %0|%0, %2}
2781    shufpd\t{$1, %1, %0|%0, %1, 1}
2782    #"
2783   [(set_attr "type" "ssemov,sselog,sselog,other")
2784    (set_attr "mode" "V1DF,V2DF,V2DF,DF")])
2785
2786 (define_split
2787   [(set (match_operand:V2DF 0 "memory_operand" "")
2788         (vec_concat:V2DF
2789           (vec_select:DF (match_dup 0) (parallel [(const_int 0)]))
2790           (match_operand:DF 1 "register_operand" "")))]
2791   "TARGET_SSE2 && reload_completed"
2792   [(set (match_dup 0) (match_dup 1))]
2793 {
2794   operands[0] = adjust_address (operands[0], DFmode, 8);
2795 })
2796
2797 (define_insn "sse2_loadlpd"
2798   [(set (match_operand:V2DF 0 "nonimmediate_operand"    "=x,x,x,x,x,m")
2799         (vec_concat:V2DF
2800           (match_operand:DF 2 "nonimmediate_operand"    " m,m,x,0,0,x*fr")
2801           (vec_select:DF
2802             (match_operand:V2DF 1 "vector_move_operand" " C,0,0,x,o,0")
2803             (parallel [(const_int 1)]))))]
2804   "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
2805   "@
2806    movsd\t{%2, %0|%0, %2}
2807    movlpd\t{%2, %0|%0, %2}
2808    movsd\t{%2, %0|%0, %2}
2809    shufpd\t{$2, %2, %0|%0, %2, 2}
2810    movhpd\t{%H1, %0|%0, %H1}
2811    #"
2812   [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,other")
2813    (set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,DF")])
2814
2815 (define_split
2816   [(set (match_operand:V2DF 0 "memory_operand" "")
2817         (vec_concat:V2DF
2818           (match_operand:DF 1 "register_operand" "")
2819           (vec_select:DF (match_dup 0) (parallel [(const_int 1)]))))]
2820   "TARGET_SSE2 && reload_completed"
2821   [(set (match_dup 0) (match_dup 1))]
2822 {
2823   operands[0] = adjust_address (operands[0], DFmode, 8);
2824 })
2825
2826 ;; Not sure these two are ever used, but it doesn't hurt to have
2827 ;; them. -aoliva
2828 (define_insn "*vec_extractv2df_1_sse"
2829   [(set (match_operand:DF 0 "nonimmediate_operand" "=m,x,x")
2830         (vec_select:DF
2831           (match_operand:V2DF 1 "nonimmediate_operand" "x,x,o")
2832           (parallel [(const_int 1)])))]
2833   "!TARGET_SSE2 && TARGET_SSE
2834    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
2835   "@
2836    movhps\t{%1, %0|%0, %1}
2837    movhlps\t{%1, %0|%0, %1}
2838    movlps\t{%H1, %0|%0, %H1}"
2839   [(set_attr "type" "ssemov")
2840    (set_attr "mode" "V2SF,V4SF,V2SF")])
2841
2842 (define_insn "*vec_extractv2df_0_sse"
2843   [(set (match_operand:DF 0 "nonimmediate_operand" "=m,x,x")
2844         (vec_select:DF
2845           (match_operand:V2DF 1 "nonimmediate_operand" "x,x,m")
2846           (parallel [(const_int 0)])))]
2847   "!TARGET_SSE2 && TARGET_SSE
2848    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
2849   "@
2850    movlps\t{%1, %0|%0, %1}
2851    movaps\t{%1, %0|%0, %1}
2852    movlps\t{%1, %0|%0, %1}"
2853   [(set_attr "type" "ssemov")
2854    (set_attr "mode" "V2SF,V4SF,V2SF")])
2855
2856 (define_insn "sse2_movsd"
2857   [(set (match_operand:V2DF 0 "nonimmediate_operand"   "=x,x,m,x,x,o")
2858         (vec_merge:V2DF
2859           (match_operand:V2DF 2 "nonimmediate_operand" " x,m,x,0,0,0")
2860           (match_operand:V2DF 1 "nonimmediate_operand" " 0,0,0,x,o,x")
2861           (const_int 1)))]
2862   "TARGET_SSE2"
2863   "@
2864    movsd\t{%2, %0|%0, %2}
2865    movlpd\t{%2, %0|%0, %2}
2866    movlpd\t{%2, %0|%0, %2}
2867    shufpd\t{$2, %2, %0|%0, %2, 2}
2868    movhps\t{%H1, %0|%0, %H1}
2869    movhps\t{%1, %H0|%H0, %1}"
2870   [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
2871    (set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,V1DF")])
2872
2873 (define_insn "*vec_dupv2df_sse3"
2874   [(set (match_operand:V2DF 0 "register_operand" "=x")
2875         (vec_duplicate:V2DF
2876           (match_operand:DF 1 "nonimmediate_operand" "xm")))]
2877   "TARGET_SSE3"
2878   "movddup\t{%1, %0|%0, %1}"
2879   [(set_attr "type" "sselog1")
2880    (set_attr "mode" "DF")])
2881
2882 (define_insn "vec_dupv2df"
2883   [(set (match_operand:V2DF 0 "register_operand" "=x")
2884         (vec_duplicate:V2DF
2885           (match_operand:DF 1 "register_operand" "0")))]
2886   "TARGET_SSE2"
2887   "unpcklpd\t%0, %0"
2888   [(set_attr "type" "sselog1")
2889    (set_attr "mode" "V2DF")])
2890
2891 (define_insn "*vec_concatv2df_sse3"
2892   [(set (match_operand:V2DF 0 "register_operand" "=x")
2893         (vec_concat:V2DF
2894           (match_operand:DF 1 "nonimmediate_operand" "xm")
2895           (match_dup 1)))]
2896   "TARGET_SSE3"
2897   "movddup\t{%1, %0|%0, %1}"
2898   [(set_attr "type" "sselog1")
2899    (set_attr "mode" "DF")])
2900
2901 (define_insn "*vec_concatv2df"
2902   [(set (match_operand:V2DF 0 "register_operand"     "=Y2,Y2,Y2,x,x")
2903         (vec_concat:V2DF
2904           (match_operand:DF 1 "nonimmediate_operand" " 0 ,0 ,m ,0,0")
2905           (match_operand:DF 2 "vector_move_operand"  " Y2,m ,C ,x,m")))]
2906   "TARGET_SSE"
2907   "@
2908    unpcklpd\t{%2, %0|%0, %2}
2909    movhpd\t{%2, %0|%0, %2}
2910    movsd\t{%1, %0|%0, %1}
2911    movlhps\t{%2, %0|%0, %2}
2912    movhps\t{%2, %0|%0, %2}"
2913   [(set_attr "type" "sselog,ssemov,ssemov,ssemov,ssemov")
2914    (set_attr "mode" "V2DF,V1DF,DF,V4SF,V2SF")])
2915
2916 (define_expand "vec_setv2df"
2917   [(match_operand:V2DF 0 "register_operand" "")
2918    (match_operand:DF 1 "register_operand" "")
2919    (match_operand 2 "const_int_operand" "")]
2920   "TARGET_SSE"
2921 {
2922   ix86_expand_vector_set (false, operands[0], operands[1],
2923                           INTVAL (operands[2]));
2924   DONE;
2925 })
2926
2927 (define_expand "vec_extractv2df"
2928   [(match_operand:DF 0 "register_operand" "")
2929    (match_operand:V2DF 1 "register_operand" "")
2930    (match_operand 2 "const_int_operand" "")]
2931   "TARGET_SSE"
2932 {
2933   ix86_expand_vector_extract (false, operands[0], operands[1],
2934                               INTVAL (operands[2]));
2935   DONE;
2936 })
2937
2938 (define_expand "vec_initv2df"
2939   [(match_operand:V2DF 0 "register_operand" "")
2940    (match_operand 1 "" "")]
2941   "TARGET_SSE"
2942 {
2943   ix86_expand_vector_init (false, operands[0], operands[1]);
2944   DONE;
2945 })
2946
2947 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2948 ;;
2949 ;; Parallel integral arithmetic
2950 ;;
2951 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2952
2953 (define_expand "neg<mode>2"
2954   [(set (match_operand:SSEMODEI 0 "register_operand" "")
2955         (minus:SSEMODEI
2956           (match_dup 2)
2957           (match_operand:SSEMODEI 1 "nonimmediate_operand" "")))]
2958   "TARGET_SSE2"
2959   "operands[2] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));")
2960
2961 (define_expand "add<mode>3"
2962   [(set (match_operand:SSEMODEI 0 "register_operand" "")
2963         (plus:SSEMODEI (match_operand:SSEMODEI 1 "nonimmediate_operand" "")
2964                        (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
2965   "TARGET_SSE2"
2966   "ix86_fixup_binary_operands_no_copy (PLUS, <MODE>mode, operands);")
2967
2968 (define_insn "*add<mode>3"
2969   [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
2970         (plus:SSEMODEI
2971           (match_operand:SSEMODEI 1 "nonimmediate_operand" "%0")
2972           (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
2973   "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
2974   "padd<ssevecsize>\t{%2, %0|%0, %2}"
2975   [(set_attr "type" "sseiadd")
2976    (set_attr "prefix_data16" "1")
2977    (set_attr "mode" "TI")])
2978
2979 (define_insn "sse2_ssadd<mode>3"
2980   [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
2981         (ss_plus:SSEMODE12
2982           (match_operand:SSEMODE12 1 "nonimmediate_operand" "%0")
2983           (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
2984   "TARGET_SSE2 && ix86_binary_operator_ok (SS_PLUS, <MODE>mode, operands)"
2985   "padds<ssevecsize>\t{%2, %0|%0, %2}"
2986   [(set_attr "type" "sseiadd")
2987    (set_attr "prefix_data16" "1")
2988    (set_attr "mode" "TI")])
2989
2990 (define_insn "sse2_usadd<mode>3"
2991   [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
2992         (us_plus:SSEMODE12
2993           (match_operand:SSEMODE12 1 "nonimmediate_operand" "%0")
2994           (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
2995   "TARGET_SSE2 && ix86_binary_operator_ok (US_PLUS, <MODE>mode, operands)"
2996   "paddus<ssevecsize>\t{%2, %0|%0, %2}"
2997   [(set_attr "type" "sseiadd")
2998    (set_attr "prefix_data16" "1")
2999    (set_attr "mode" "TI")])
3000
3001 (define_expand "sub<mode>3"
3002   [(set (match_operand:SSEMODEI 0 "register_operand" "")
3003         (minus:SSEMODEI (match_operand:SSEMODEI 1 "register_operand" "")
3004                         (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
3005   "TARGET_SSE2"
3006   "ix86_fixup_binary_operands_no_copy (MINUS, <MODE>mode, operands);")
3007
3008 (define_insn "*sub<mode>3"
3009   [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
3010         (minus:SSEMODEI
3011           (match_operand:SSEMODEI 1 "register_operand" "0")
3012           (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
3013   "TARGET_SSE2"
3014   "psub<ssevecsize>\t{%2, %0|%0, %2}"
3015   [(set_attr "type" "sseiadd")
3016    (set_attr "prefix_data16" "1")
3017    (set_attr "mode" "TI")])
3018
3019 (define_insn "sse2_sssub<mode>3"
3020   [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
3021         (ss_minus:SSEMODE12
3022           (match_operand:SSEMODE12 1 "register_operand" "0")
3023           (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
3024   "TARGET_SSE2"
3025   "psubs<ssevecsize>\t{%2, %0|%0, %2}"
3026   [(set_attr "type" "sseiadd")
3027    (set_attr "prefix_data16" "1")
3028    (set_attr "mode" "TI")])
3029
3030 (define_insn "sse2_ussub<mode>3"
3031   [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
3032         (us_minus:SSEMODE12
3033           (match_operand:SSEMODE12 1 "register_operand" "0")
3034           (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
3035   "TARGET_SSE2"
3036   "psubus<ssevecsize>\t{%2, %0|%0, %2}"
3037   [(set_attr "type" "sseiadd")
3038    (set_attr "prefix_data16" "1")
3039    (set_attr "mode" "TI")])
3040
3041 (define_insn_and_split "mulv16qi3"
3042   [(set (match_operand:V16QI 0 "register_operand" "")
3043         (mult:V16QI (match_operand:V16QI 1 "register_operand" "")
3044                     (match_operand:V16QI 2 "register_operand" "")))]
3045   "TARGET_SSE2
3046    && !(reload_completed || reload_in_progress)"
3047   "#"
3048   "&& 1"
3049   [(const_int 0)]
3050 {
3051   rtx t[12], op0, op[3];
3052   int i;
3053
3054   if (TARGET_SSE5)
3055     {
3056       /* On SSE5, we can take advantage of the pperm instruction to pack and
3057          unpack the bytes.  Unpack data such that we've got a source byte in
3058          each low byte of each word.  We don't care what goes into the high
3059          byte, so put 0 there.  */
3060       for (i = 0; i < 6; ++i)
3061         t[i] = gen_reg_rtx (V8HImode);
3062
3063       for (i = 0; i < 2; i++)
3064         {
3065           op[0] = t[i];
3066           op[1] = operands[i+1];
3067           ix86_expand_sse5_unpack (op, true, true);             /* high bytes */
3068
3069           op[0] = t[i+2];
3070           ix86_expand_sse5_unpack (op, true, false);            /* low bytes */
3071         }
3072
3073       /* Multiply words.  */
3074       emit_insn (gen_mulv8hi3 (t[4], t[0], t[1]));              /* high bytes */
3075       emit_insn (gen_mulv8hi3 (t[5], t[2], t[3]));              /* low  bytes */
3076
3077       /* Pack the low byte of each word back into a single xmm */
3078       op[0] = operands[0];
3079       op[1] = t[5];
3080       op[2] = t[4];
3081       ix86_expand_sse5_pack (op);
3082       DONE;
3083     }
3084
3085   for (i = 0; i < 12; ++i)
3086     t[i] = gen_reg_rtx (V16QImode);
3087
3088   /* Unpack data such that we've got a source byte in each low byte of
3089      each word.  We don't care what goes into the high byte of each word.
3090      Rather than trying to get zero in there, most convenient is to let
3091      it be a copy of the low byte.  */
3092   emit_insn (gen_sse2_punpckhbw (t[0], operands[1], operands[1]));
3093   emit_insn (gen_sse2_punpckhbw (t[1], operands[2], operands[2]));
3094   emit_insn (gen_sse2_punpcklbw (t[2], operands[1], operands[1]));
3095   emit_insn (gen_sse2_punpcklbw (t[3], operands[2], operands[2]));
3096
3097   /* Multiply words.  The end-of-line annotations here give a picture of what
3098      the output of that instruction looks like.  Dot means don't care; the
3099      letters are the bytes of the result with A being the most significant.  */
3100   emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[4]), /* .A.B.C.D.E.F.G.H */
3101                            gen_lowpart (V8HImode, t[0]),
3102                            gen_lowpart (V8HImode, t[1])));
3103   emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[5]), /* .I.J.K.L.M.N.O.P */
3104                            gen_lowpart (V8HImode, t[2]),
3105                            gen_lowpart (V8HImode, t[3])));
3106
3107   /* Extract the relevant bytes and merge them back together.  */
3108   emit_insn (gen_sse2_punpckhbw (t[6], t[5], t[4]));    /* ..AI..BJ..CK..DL */
3109   emit_insn (gen_sse2_punpcklbw (t[7], t[5], t[4]));    /* ..EM..FN..GO..HP */
3110   emit_insn (gen_sse2_punpckhbw (t[8], t[7], t[6]));    /* ....AEIM....BFJN */
3111   emit_insn (gen_sse2_punpcklbw (t[9], t[7], t[6]));    /* ....CGKO....DHLP */
3112   emit_insn (gen_sse2_punpckhbw (t[10], t[9], t[8]));   /* ........ACEGIKMO */
3113   emit_insn (gen_sse2_punpcklbw (t[11], t[9], t[8]));   /* ........BDFHJLNP */
3114
3115   op0 = operands[0];
3116   emit_insn (gen_sse2_punpcklbw (op0, t[11], t[10]));   /* ABCDEFGHIJKLMNOP */
3117   DONE;
3118 })
3119
3120 (define_expand "mulv8hi3"
3121   [(set (match_operand:V8HI 0 "register_operand" "")
3122         (mult:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "")
3123                    (match_operand:V8HI 2 "nonimmediate_operand" "")))]
3124   "TARGET_SSE2"
3125   "ix86_fixup_binary_operands_no_copy (MULT, V8HImode, operands);")
3126
3127 (define_insn "*mulv8hi3"
3128   [(set (match_operand:V8HI 0 "register_operand" "=x")
3129         (mult:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "%0")
3130                    (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
3131   "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
3132   "pmullw\t{%2, %0|%0, %2}"
3133   [(set_attr "type" "sseimul")
3134    (set_attr "prefix_data16" "1")
3135    (set_attr "mode" "TI")])
3136
3137 (define_expand "smulv8hi3_highpart"
3138   [(set (match_operand:V8HI 0 "register_operand" "")
3139         (truncate:V8HI
3140           (lshiftrt:V8SI
3141             (mult:V8SI
3142               (sign_extend:V8SI
3143                 (match_operand:V8HI 1 "nonimmediate_operand" ""))
3144               (sign_extend:V8SI
3145                 (match_operand:V8HI 2 "nonimmediate_operand" "")))
3146             (const_int 16))))]
3147   "TARGET_SSE2"
3148   "ix86_fixup_binary_operands_no_copy (MULT, V8HImode, operands);")
3149
3150 (define_insn "*smulv8hi3_highpart"
3151   [(set (match_operand:V8HI 0 "register_operand" "=x")
3152         (truncate:V8HI
3153           (lshiftrt:V8SI
3154             (mult:V8SI
3155               (sign_extend:V8SI
3156                 (match_operand:V8HI 1 "nonimmediate_operand" "%0"))
3157               (sign_extend:V8SI
3158                 (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
3159             (const_int 16))))]
3160   "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
3161   "pmulhw\t{%2, %0|%0, %2}"
3162   [(set_attr "type" "sseimul")
3163    (set_attr "prefix_data16" "1")
3164    (set_attr "mode" "TI")])
3165
3166 (define_expand "umulv8hi3_highpart"
3167   [(set (match_operand:V8HI 0 "register_operand" "")
3168         (truncate:V8HI
3169           (lshiftrt:V8SI
3170             (mult:V8SI
3171               (zero_extend:V8SI
3172                 (match_operand:V8HI 1 "nonimmediate_operand" ""))
3173               (zero_extend:V8SI
3174                 (match_operand:V8HI 2 "nonimmediate_operand" "")))
3175             (const_int 16))))]
3176   "TARGET_SSE2"
3177   "ix86_fixup_binary_operands_no_copy (MULT, V8HImode, operands);")
3178
3179 (define_insn "*umulv8hi3_highpart"
3180   [(set (match_operand:V8HI 0 "register_operand" "=x")
3181         (truncate:V8HI
3182           (lshiftrt:V8SI
3183             (mult:V8SI
3184               (zero_extend:V8SI
3185                 (match_operand:V8HI 1 "nonimmediate_operand" "%0"))
3186               (zero_extend:V8SI
3187                 (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
3188             (const_int 16))))]
3189   "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
3190   "pmulhuw\t{%2, %0|%0, %2}"
3191   [(set_attr "type" "sseimul")
3192    (set_attr "prefix_data16" "1")
3193    (set_attr "mode" "TI")])
3194
3195 (define_insn "sse2_umulv2siv2di3"
3196   [(set (match_operand:V2DI 0 "register_operand" "=x")
3197         (mult:V2DI
3198           (zero_extend:V2DI
3199             (vec_select:V2SI
3200               (match_operand:V4SI 1 "nonimmediate_operand" "%0")
3201               (parallel [(const_int 0) (const_int 2)])))
3202           (zero_extend:V2DI
3203             (vec_select:V2SI
3204               (match_operand:V4SI 2 "nonimmediate_operand" "xm")
3205               (parallel [(const_int 0) (const_int 2)])))))]
3206   "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V4SImode, operands)"
3207   "pmuludq\t{%2, %0|%0, %2}"
3208   [(set_attr "type" "sseimul")
3209    (set_attr "prefix_data16" "1")
3210    (set_attr "mode" "TI")])
3211
3212 (define_insn "sse4_1_mulv2siv2di3"
3213   [(set (match_operand:V2DI 0 "register_operand" "=x")
3214         (mult:V2DI
3215           (sign_extend:V2DI
3216             (vec_select:V2SI
3217               (match_operand:V4SI 1 "nonimmediate_operand" "%0")
3218               (parallel [(const_int 0) (const_int 2)])))
3219           (sign_extend:V2DI
3220             (vec_select:V2SI
3221               (match_operand:V4SI 2 "nonimmediate_operand" "xm")
3222               (parallel [(const_int 0) (const_int 2)])))))]
3223   "TARGET_SSE4_1 && ix86_binary_operator_ok (MULT, V4SImode, operands)"
3224   "pmuldq\t{%2, %0|%0, %2}"
3225   [(set_attr "type" "sseimul")
3226    (set_attr "prefix_extra" "1")
3227    (set_attr "mode" "TI")])
3228
3229 (define_insn "sse2_pmaddwd"
3230   [(set (match_operand:V4SI 0 "register_operand" "=x")
3231         (plus:V4SI
3232           (mult:V4SI
3233             (sign_extend:V4SI
3234               (vec_select:V4HI
3235                 (match_operand:V8HI 1 "nonimmediate_operand" "%0")
3236                 (parallel [(const_int 0)
3237                            (const_int 2)
3238                            (const_int 4)
3239                            (const_int 6)])))
3240             (sign_extend:V4SI
3241               (vec_select:V4HI
3242                 (match_operand:V8HI 2 "nonimmediate_operand" "xm")
3243                 (parallel [(const_int 0)
3244                            (const_int 2)
3245                            (const_int 4)
3246                            (const_int 6)]))))
3247           (mult:V4SI
3248             (sign_extend:V4SI
3249               (vec_select:V4HI (match_dup 1)
3250                 (parallel [(const_int 1)
3251                            (const_int 3)
3252                            (const_int 5)
3253                            (const_int 7)])))
3254             (sign_extend:V4SI
3255               (vec_select:V4HI (match_dup 2)
3256                 (parallel [(const_int 1)
3257                            (const_int 3)
3258                            (const_int 5)
3259                            (const_int 7)]))))))]
3260   "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
3261   "pmaddwd\t{%2, %0|%0, %2}"
3262   [(set_attr "type" "sseiadd")
3263    (set_attr "prefix_data16" "1")
3264    (set_attr "mode" "TI")])
3265
3266 (define_expand "mulv4si3"
3267   [(set (match_operand:V4SI 0 "register_operand" "")
3268         (mult:V4SI (match_operand:V4SI 1 "register_operand" "")
3269                    (match_operand:V4SI 2 "register_operand" "")))]
3270   "TARGET_SSE2"
3271 {
3272   if (TARGET_SSE4_1 || TARGET_SSE5)
3273     ix86_fixup_binary_operands_no_copy (MULT, V4SImode, operands);
3274 })
3275
3276 (define_insn "*sse4_1_mulv4si3"
3277   [(set (match_operand:V4SI 0 "register_operand" "=x")
3278         (mult:V4SI (match_operand:V4SI 1 "nonimmediate_operand" "%0")
3279                    (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
3280   "TARGET_SSE4_1 && ix86_binary_operator_ok (MULT, V4SImode, operands)"
3281   "pmulld\t{%2, %0|%0, %2}"
3282   [(set_attr "type" "sseimul")
3283    (set_attr "prefix_extra" "1")
3284    (set_attr "mode" "TI")])
3285
3286 ;; We don't have a straight 32-bit parallel multiply on SSE5, so fake it with a
3287 ;; multiply/add.  In general, we expect the define_split to occur before
3288 ;; register allocation, so we have to handle the corner case where the target
3289 ;; is used as the base or index register in operands 1/2.
3290 (define_insn_and_split "*sse5_mulv4si3"
3291   [(set (match_operand:V4SI 0 "register_operand" "=&x")
3292         (mult:V4SI (match_operand:V4SI 1 "register_operand" "%x")
3293                    (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
3294   "TARGET_SSE5"
3295   "#"
3296   "&& (reload_completed
3297        || (!reg_mentioned_p (operands[0], operands[1])
3298            && !reg_mentioned_p (operands[0], operands[2])))"
3299   [(set (match_dup 0)
3300         (match_dup 3))
3301    (set (match_dup 0)
3302         (plus:V4SI (mult:V4SI (match_dup 1)
3303                               (match_dup 2))
3304                    (match_dup 0)))]
3305 {
3306   operands[3] = CONST0_RTX (V4SImode);
3307 }
3308   [(set_attr "type" "ssemuladd")
3309    (set_attr "mode" "TI")])
3310
3311 (define_insn_and_split "*sse2_mulv4si3"
3312   [(set (match_operand:V4SI 0 "register_operand" "")
3313         (mult:V4SI (match_operand:V4SI 1 "register_operand" "")
3314                    (match_operand:V4SI 2 "register_operand" "")))]
3315   "TARGET_SSE2 && !TARGET_SSE4_1 && !TARGET_SSE5
3316    && !(reload_completed || reload_in_progress)"
3317   "#"
3318   "&& 1"
3319   [(const_int 0)]
3320 {
3321   rtx t1, t2, t3, t4, t5, t6, thirtytwo;
3322   rtx op0, op1, op2;
3323
3324   op0 = operands[0];
3325   op1 = operands[1];
3326   op2 = operands[2];
3327   t1 = gen_reg_rtx (V4SImode);
3328   t2 = gen_reg_rtx (V4SImode);
3329   t3 = gen_reg_rtx (V4SImode);
3330   t4 = gen_reg_rtx (V4SImode);
3331   t5 = gen_reg_rtx (V4SImode);
3332   t6 = gen_reg_rtx (V4SImode);
3333   thirtytwo = GEN_INT (32);
3334
3335   /* Multiply elements 2 and 0.  */
3336   emit_insn (gen_sse2_umulv2siv2di3 (gen_lowpart (V2DImode, t1),
3337                                      op1, op2));
3338
3339   /* Shift both input vectors down one element, so that elements 3
3340      and 1 are now in the slots for elements 2 and 0.  For K8, at
3341      least, this is faster than using a shuffle.  */
3342   emit_insn (gen_sse2_lshrti3 (gen_lowpart (TImode, t2),
3343                                gen_lowpart (TImode, op1),
3344                                thirtytwo));
3345   emit_insn (gen_sse2_lshrti3 (gen_lowpart (TImode, t3),
3346                                gen_lowpart (TImode, op2),
3347                                thirtytwo));
3348   /* Multiply elements 3 and 1.  */
3349   emit_insn (gen_sse2_umulv2siv2di3 (gen_lowpart (V2DImode, t4),
3350                                      t2, t3));
3351
3352   /* Move the results in element 2 down to element 1; we don't care
3353      what goes in elements 2 and 3.  */
3354   emit_insn (gen_sse2_pshufd_1 (t5, t1, const0_rtx, const2_rtx,
3355                                 const0_rtx, const0_rtx));
3356   emit_insn (gen_sse2_pshufd_1 (t6, t4, const0_rtx, const2_rtx,
3357                                 const0_rtx, const0_rtx));
3358
3359   /* Merge the parts back together.  */
3360   emit_insn (gen_sse2_punpckldq (op0, t5, t6));
3361   DONE;
3362 })
3363
3364 (define_insn_and_split "mulv2di3"
3365   [(set (match_operand:V2DI 0 "register_operand" "")
3366         (mult:V2DI (match_operand:V2DI 1 "register_operand" "")
3367                    (match_operand:V2DI 2 "register_operand" "")))]
3368   "TARGET_SSE2
3369    && !(reload_completed || reload_in_progress)"
3370   "#"
3371   "&& 1"
3372   [(const_int 0)]
3373 {
3374   rtx t1, t2, t3, t4, t5, t6, thirtytwo;
3375   rtx op0, op1, op2;
3376
3377   op0 = operands[0];
3378   op1 = operands[1];
3379   op2 = operands[2];
3380   t1 = gen_reg_rtx (V2DImode);
3381   t2 = gen_reg_rtx (V2DImode);
3382   t3 = gen_reg_rtx (V2DImode);
3383   t4 = gen_reg_rtx (V2DImode);
3384   t5 = gen_reg_rtx (V2DImode);
3385   t6 = gen_reg_rtx (V2DImode);
3386   thirtytwo = GEN_INT (32);
3387
3388   /* Multiply low parts.  */
3389   emit_insn (gen_sse2_umulv2siv2di3 (t1, gen_lowpart (V4SImode, op1),
3390                                      gen_lowpart (V4SImode, op2)));
3391
3392   /* Shift input vectors left 32 bits so we can multiply high parts.  */
3393   emit_insn (gen_lshrv2di3 (t2, op1, thirtytwo));
3394   emit_insn (gen_lshrv2di3 (t3, op2, thirtytwo));
3395
3396   /* Multiply high parts by low parts.  */
3397   emit_insn (gen_sse2_umulv2siv2di3 (t4, gen_lowpart (V4SImode, op1),
3398                                      gen_lowpart (V4SImode, t3)));
3399   emit_insn (gen_sse2_umulv2siv2di3 (t5, gen_lowpart (V4SImode, op2),
3400                                      gen_lowpart (V4SImode, t2)));
3401
3402   /* Shift them back.  */
3403   emit_insn (gen_ashlv2di3 (t4, t4, thirtytwo));
3404   emit_insn (gen_ashlv2di3 (t5, t5, thirtytwo));
3405
3406   /* Add the three parts together.  */
3407   emit_insn (gen_addv2di3 (t6, t1, t4));
3408   emit_i