OSDN Git Service

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