* configure: Regenerated.
[official-gcc.git] / gcc / config / rs6000 / vsx.md
blob58db3cfb9bfde95db7294bb0a1d8b97b81e38877
1 ;; VSX patterns.
2 ;; Copyright (C) 2009, 2010, 2011, 2012
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 3, or (at your
11 ;; option) any later version.
13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16 ;; License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3.  If not see
20 ;; <http://www.gnu.org/licenses/>.
22 ;; Iterator for both scalar and vector floating point types supported by VSX
23 (define_mode_iterator VSX_B [DF V4SF V2DF])
25 ;; Iterator for the 2 64-bit vector types
26 (define_mode_iterator VSX_D [V2DF V2DI])
28 ;; Iterator for the 2 32-bit vector types
29 (define_mode_iterator VSX_W [V4SF V4SI])
31 ;; Iterator for the DF types
32 (define_mode_iterator VSX_DF [V2DF DF])
34 ;; Iterator for vector floating point types supported by VSX
35 (define_mode_iterator VSX_F [V4SF V2DF])
37 ;; Iterator for logical types supported by VSX
38 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
40 ;; Iterator for memory move.  Handle TImode specially to allow
41 ;; it to use gprs as well as vsx registers.
42 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
44 ;; Map into the appropriate load/store name based on the type
45 (define_mode_attr VSm  [(V16QI "vw4")
46                         (V8HI  "vw4")
47                         (V4SI  "vw4")
48                         (V4SF  "vw4")
49                         (V2DF  "vd2")
50                         (V2DI  "vd2")
51                         (DF    "d")
52                         (TI    "vw4")])
54 ;; Map into the appropriate suffix based on the type
55 (define_mode_attr VSs   [(V16QI "sp")
56                          (V8HI  "sp")
57                          (V4SI  "sp")
58                          (V4SF  "sp")
59                          (V2DF  "dp")
60                          (V2DI  "dp")
61                          (DF    "dp")
62                          (SF    "sp")
63                          (TI    "sp")])
65 ;; Map the register class used
66 (define_mode_attr VSr   [(V16QI "v")
67                          (V8HI  "v")
68                          (V4SI  "v")
69                          (V4SF  "wf")
70                          (V2DI  "wd")
71                          (V2DF  "wd")
72                          (DF    "ws")
73                          (SF    "d")
74                          (TI    "wd")])
76 ;; Map the register class used for float<->int conversions
77 (define_mode_attr VSr2  [(V2DF  "wd")
78                          (V4SF  "wf")
79                          (DF    "ws")])
81 (define_mode_attr VSr3  [(V2DF  "wa")
82                          (V4SF  "wa")
83                          (DF    "ws")])
85 ;; Map the register class for sp<->dp float conversions, destination
86 (define_mode_attr VSr4  [(SF    "ws")
87                          (DF    "f")
88                          (V2DF  "wd")
89                          (V4SF  "v")])
91 ;; Map the register class for sp<->dp float conversions, destination
92 (define_mode_attr VSr5  [(SF    "ws")
93                          (DF    "f")
94                          (V2DF  "v")
95                          (V4SF  "wd")])
97 ;; Same size integer type for floating point data
98 (define_mode_attr VSi [(V4SF  "v4si")
99                        (V2DF  "v2di")
100                        (DF    "di")])
102 (define_mode_attr VSI [(V4SF  "V4SI")
103                        (V2DF  "V2DI")
104                        (DF    "DI")])
106 ;; Word size for same size conversion
107 (define_mode_attr VSc [(V4SF "w")
108                        (V2DF "d")
109                        (DF   "d")])
111 ;; Map into either s or v, depending on whether this is a scalar or vector
112 ;; operation
113 (define_mode_attr VSv   [(V16QI "v")
114                          (V8HI  "v")
115                          (V4SI  "v")
116                          (V4SF  "v")
117                          (V2DI  "v")
118                          (V2DF  "v")
119                          (TI    "v")
120                          (DF    "s")])
122 ;; Appropriate type for add ops (and other simple FP ops)
123 (define_mode_attr VStype_simple [(V2DF "vecdouble")
124                                  (V4SF "vecfloat")
125                                  (DF   "fp")])
127 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
128                                    (V4SF "fp_addsub_s")
129                                    (DF   "fp_addsub_d")])
131 ;; Appropriate type for multiply ops
132 (define_mode_attr VStype_mul    [(V2DF "vecdouble")
133                                  (V4SF "vecfloat")
134                                  (DF   "dmul")])
136 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
137                                  (V4SF "fp_mul_s")
138                                  (DF   "fp_mul_d")])
140 ;; Appropriate type for divide ops.
141 (define_mode_attr VStype_div    [(V2DF "vecdiv")
142                                  (V4SF "vecfdiv")
143                                  (DF   "ddiv")])
145 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
146                                  (V4SF "fp_div_s")
147                                  (DF   "fp_div_d")])
149 ;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
150 ;; the scalar sqrt
151 (define_mode_attr VStype_sqrt   [(V2DF "dsqrt")
152                                  (V4SF "ssqrt")
153                                  (DF   "dsqrt")])
155 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
156                                  (V4SF "fp_sqrt_s")
157                                  (DF   "fp_sqrt_d")])
159 ;; Iterator and modes for sp<->dp conversions
160 ;; Because scalar SF values are represented internally as double, use the
161 ;; V4SF type to represent this than SF.
162 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
164 (define_mode_attr VS_spdp_res [(DF      "V4SF")
165                                (V4SF    "V2DF")
166                                (V2DF    "V4SF")])
168 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
169                                 (V4SF   "xvcvspdp")
170                                 (V2DF   "xvcvdpsp")])
172 (define_mode_attr VS_spdp_type [(DF     "fp")
173                                 (V4SF   "vecdouble")
174                                 (V2DF   "vecdouble")])
176 ;; Map the scalar mode for a vector type
177 (define_mode_attr VS_scalar [(V2DF      "DF")
178                              (V2DI      "DI")
179                              (V4SF      "SF")
180                              (V4SI      "SI")
181                              (V8HI      "HI")
182                              (V16QI     "QI")])
184 ;; Map to a double-sized vector mode
185 (define_mode_attr VS_double [(V4SI      "V8SI")
186                              (V4SF      "V8SF")
187                              (V2DI      "V4DI")
188                              (V2DF      "V4DF")])
190 ;; Constants for creating unspecs
191 (define_c_enum "unspec"
192   [UNSPEC_VSX_CONCAT
193    UNSPEC_VSX_CVDPSXWS
194    UNSPEC_VSX_CVDPUXWS
195    UNSPEC_VSX_CVSPDP
196    UNSPEC_VSX_CVSXWDP
197    UNSPEC_VSX_CVUXWDP
198    UNSPEC_VSX_CVSXDSP
199    UNSPEC_VSX_CVUXDSP
200    UNSPEC_VSX_CVSPSXDS
201    UNSPEC_VSX_CVSPUXDS
202    UNSPEC_VSX_TDIV
203    UNSPEC_VSX_TSQRT
204    UNSPEC_VSX_SET
205    UNSPEC_VSX_ROUND_I
206    UNSPEC_VSX_ROUND_IC
207    UNSPEC_VSX_SLDWI
208   ])
210 ;; VSX moves
211 (define_insn "*vsx_mov<mode>"
212   [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
213         (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
214   "VECTOR_MEM_VSX_P (<MODE>mode)
215    && (register_operand (operands[0], <MODE>mode) 
216        || register_operand (operands[1], <MODE>mode))"
218   switch (which_alternative)
219     {
220     case 0:
221     case 3:
222       gcc_assert (MEM_P (operands[0])
223                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
224                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
225                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
226       return "stx<VSm>x %x1,%y0";
228     case 1:
229     case 4:
230       gcc_assert (MEM_P (operands[1])
231                   && GET_CODE (XEXP (operands[1], 0)) != PRE_INC
232                   && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
233                   && GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
234       return "lx<VSm>x %x0,%y1";
236     case 2:
237     case 5:
238       return "xxlor %x0,%x1,%x1";
240     case 6:
241     case 7:
242     case 8:
243       return "#";
245     case 9:
246     case 10:
247       return "xxlxor %x0,%x0,%x0";
249     case 11:
250       return output_vec_const_move (operands);
252     case 12:
253       gcc_assert (MEM_P (operands[0])
254                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
255                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
256                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
257       return "stvx %1,%y0";
259     case 13:
260       gcc_assert (MEM_P (operands[0])
261                   && GET_CODE (XEXP (operands[0], 0)) != PRE_INC
262                   && GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
263                   && GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
264       return "lvx %0,%y1";
266     default:
267       gcc_unreachable ();
268     }
270   [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
272 ;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
273 ;; unions.  However for plain data movement, slightly favor the vector loads
274 (define_insn "*vsx_movti"
275   [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
276         (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
277   "VECTOR_MEM_VSX_P (TImode)
278    && (register_operand (operands[0], TImode) 
279        || register_operand (operands[1], TImode))"
281   switch (which_alternative)
282     {
283     case 0:
284       return "stxvd2x %x1,%y0";
286     case 1:
287       return "lxvd2x %x0,%y1";
289     case 2:
290       return "xxlor %x0,%x1,%x1";
292     case 3:
293     case 4:
294     case 5:
295       return "#";
297     case 6:
298       return "xxlxor %x0,%x0,%x0";
300     case 7:
301       return output_vec_const_move (operands);
303     case 8:
304       return "stvx %1,%y0";
306     case 9:
307       return "lvx %0,%y1";
309     default:
310       gcc_unreachable ();
311     }
313   [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
315 ;; Explicit  load/store expanders for the builtin functions
316 (define_expand "vsx_load_<mode>"
317   [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
318         (match_operand:VSX_M 1 "memory_operand" ""))]
319   "VECTOR_MEM_VSX_P (<MODE>mode)"
320   "")
322 (define_expand "vsx_store_<mode>"
323   [(set (match_operand:VEC_M 0 "memory_operand" "")
324         (match_operand:VEC_M 1 "vsx_register_operand" ""))]
325   "VECTOR_MEM_VSX_P (<MODE>mode)"
326   "")
329 ;; VSX scalar and vector floating point arithmetic instructions
330 (define_insn "*vsx_add<mode>3"
331   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
332         (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
333                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
334   "VECTOR_UNIT_VSX_P (<MODE>mode)"
335   "x<VSv>add<VSs> %x0,%x1,%x2"
336   [(set_attr "type" "<VStype_simple>")
337    (set_attr "fp_type" "<VSfptype_simple>")])
339 (define_insn "*vsx_sub<mode>3"
340   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
341         (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
342                      (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
343   "VECTOR_UNIT_VSX_P (<MODE>mode)"
344   "x<VSv>sub<VSs> %x0,%x1,%x2"
345   [(set_attr "type" "<VStype_simple>")
346    (set_attr "fp_type" "<VSfptype_simple>")])
348 (define_insn "*vsx_mul<mode>3"
349   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
350         (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
351                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
352   "VECTOR_UNIT_VSX_P (<MODE>mode)"
353   "x<VSv>mul<VSs> %x0,%x1,%x2"
354   [(set_attr "type" "<VStype_mul>")
355    (set_attr "fp_type" "<VSfptype_mul>")])
357 (define_insn "*vsx_div<mode>3"
358   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
359         (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
360                    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
361   "VECTOR_UNIT_VSX_P (<MODE>mode)"
362   "x<VSv>div<VSs> %x0,%x1,%x2"
363   [(set_attr "type" "<VStype_div>")
364    (set_attr "fp_type" "<VSfptype_div>")])
366 ;; *tdiv* instruction returning the FG flag
367 (define_expand "vsx_tdiv<mode>3_fg"
368   [(set (match_dup 3)
369         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
370                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
371                      UNSPEC_VSX_TDIV))
372    (set (match_operand:SI 0 "gpc_reg_operand" "")
373         (gt:SI (match_dup 3)
374                (const_int 0)))]
375   "VECTOR_UNIT_VSX_P (<MODE>mode)"
377   operands[3] = gen_reg_rtx (CCFPmode);
380 ;; *tdiv* instruction returning the FE flag
381 (define_expand "vsx_tdiv<mode>3_fe"
382   [(set (match_dup 3)
383         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
384                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
385                      UNSPEC_VSX_TDIV))
386    (set (match_operand:SI 0 "gpc_reg_operand" "")
387         (eq:SI (match_dup 3)
388                (const_int 0)))]
389   "VECTOR_UNIT_VSX_P (<MODE>mode)"
391   operands[3] = gen_reg_rtx (CCFPmode);
394 (define_insn "*vsx_tdiv<mode>3_internal"
395   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
396         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
397                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
398                    UNSPEC_VSX_TDIV))]
399   "VECTOR_UNIT_VSX_P (<MODE>mode)"
400   "x<VSv>tdiv<VSs> %0,%x1,%x2"
401   [(set_attr "type" "<VStype_simple>")
402    (set_attr "fp_type" "<VSfptype_simple>")])
404 (define_insn "vsx_fre<mode>2"
405   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
406         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
407                       UNSPEC_FRES))]
408   "VECTOR_UNIT_VSX_P (<MODE>mode)"
409   "x<VSv>re<VSs> %x0,%x1"
410   [(set_attr "type" "<VStype_simple>")
411    (set_attr "fp_type" "<VSfptype_simple>")])
413 (define_insn "*vsx_neg<mode>2"
414   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
415         (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
416   "VECTOR_UNIT_VSX_P (<MODE>mode)"
417   "x<VSv>neg<VSs> %x0,%x1"
418   [(set_attr "type" "<VStype_simple>")
419    (set_attr "fp_type" "<VSfptype_simple>")])
421 (define_insn "*vsx_abs<mode>2"
422   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
423         (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
424   "VECTOR_UNIT_VSX_P (<MODE>mode)"
425   "x<VSv>abs<VSs> %x0,%x1"
426   [(set_attr "type" "<VStype_simple>")
427    (set_attr "fp_type" "<VSfptype_simple>")])
429 (define_insn "vsx_nabs<mode>2"
430   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
431         (neg:VSX_B
432          (abs:VSX_B
433           (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
434   "VECTOR_UNIT_VSX_P (<MODE>mode)"
435   "x<VSv>nabs<VSs> %x0,%x1"
436   [(set_attr "type" "<VStype_simple>")
437    (set_attr "fp_type" "<VSfptype_simple>")])
439 (define_insn "vsx_smax<mode>3"
440   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
441         (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
442                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
443   "VECTOR_UNIT_VSX_P (<MODE>mode)"
444   "x<VSv>max<VSs> %x0,%x1,%x2"
445   [(set_attr "type" "<VStype_simple>")
446    (set_attr "fp_type" "<VSfptype_simple>")])
448 (define_insn "*vsx_smin<mode>3"
449   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
450         (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
451                     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
452   "VECTOR_UNIT_VSX_P (<MODE>mode)"
453   "x<VSv>min<VSs> %x0,%x1,%x2"
454   [(set_attr "type" "<VStype_simple>")
455    (set_attr "fp_type" "<VSfptype_simple>")])
457 ;; Special VSX version of smin/smax for single precision floating point.  Since
458 ;; both numbers are rounded to single precision, we can just use the DP version
459 ;; of the instruction.
461 (define_insn "*vsx_smaxsf3"
462   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
463         (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
464                  (match_operand:SF 2 "vsx_register_operand" "f")))]
465   "VECTOR_UNIT_VSX_P (DFmode)"
466   "xsmaxdp %x0,%x1,%x2"
467   [(set_attr "type" "fp")
468    (set_attr "fp_type" "fp_addsub_d")])
470 (define_insn "*vsx_sminsf3"
471   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
472         (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
473                  (match_operand:SF 2 "vsx_register_operand" "f")))]
474   "VECTOR_UNIT_VSX_P (DFmode)"
475   "xsmindp %x0,%x1,%x2"
476   [(set_attr "type" "fp")
477    (set_attr "fp_type" "fp_addsub_d")])
479 (define_insn "*vsx_sqrt<mode>2"
480   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
481         (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
482   "VECTOR_UNIT_VSX_P (<MODE>mode)"
483   "x<VSv>sqrt<VSs> %x0,%x1"
484   [(set_attr "type" "<VStype_sqrt>")
485    (set_attr "fp_type" "<VSfptype_sqrt>")])
487 (define_insn "*vsx_rsqrte<mode>2"
488   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
489         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
490                       UNSPEC_RSQRT))]
491   "VECTOR_UNIT_VSX_P (<MODE>mode)"
492   "x<VSv>rsqrte<VSs> %x0,%x1"
493   [(set_attr "type" "<VStype_simple>")
494    (set_attr "fp_type" "<VSfptype_simple>")])
496 ;; *tsqrt* returning the fg flag
497 (define_expand "vsx_tsqrt<mode>2_fg"
498   [(set (match_dup 3)
499         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
500                      UNSPEC_VSX_TSQRT))
501    (set (match_operand:SI 0 "gpc_reg_operand" "")
502         (gt:SI (match_dup 3)
503                (const_int 0)))]
504   "VECTOR_UNIT_VSX_P (<MODE>mode)"
506   operands[3] = gen_reg_rtx (CCFPmode);
509 ;; *tsqrt* returning the fe flag
510 (define_expand "vsx_tsqrt<mode>2_fe"
511   [(set (match_dup 3)
512         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
513                      UNSPEC_VSX_TSQRT))
514    (set (match_operand:SI 0 "gpc_reg_operand" "")
515         (eq:SI (match_dup 3)
516                (const_int 0)))]
517   "VECTOR_UNIT_VSX_P (<MODE>mode)"
519   operands[3] = gen_reg_rtx (CCFPmode);
522 (define_insn "*vsx_tsqrt<mode>2_internal"
523   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
524         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
525                      UNSPEC_VSX_TSQRT))]
526   "VECTOR_UNIT_VSX_P (<MODE>mode)"
527   "x<VSv>tsqrt<VSs> %0,%x1"
528   [(set_attr "type" "<VStype_simple>")
529    (set_attr "fp_type" "<VSfptype_simple>")])
531 ;; Fused vector multiply/add instructions Support the classical DF versions of
532 ;; fma, which allows the target to be a separate register from the 3 inputs.
533 ;; Under VSX, the target must be either the addend or the first multiply.
534 ;; Where we can, also do the same for the Altivec V4SF fmas.
536 (define_insn "*vsx_fmadf4"
537   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
538         (fma:DF
539           (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
540           (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
541           (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
542   "VECTOR_UNIT_VSX_P (DFmode)"
543   "@
544    xsmaddadp %x0,%x1,%x2
545    xsmaddmdp %x0,%x1,%x3
546    xsmaddadp %x0,%x1,%x2
547    xsmaddmdp %x0,%x1,%x3
548    fmadd %0,%1,%2,%3"
549   [(set_attr "type" "fp")
550    (set_attr "fp_type" "fp_maddsub_d")])
552 (define_insn "*vsx_fmav4sf4"
553   [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
554         (fma:V4SF
555           (match_operand:V4SF 1 "vsx_register_operand" "%ws,ws,wa,wa,v")
556           (match_operand:V4SF 2 "vsx_register_operand" "ws,0,wa,0,v")
557           (match_operand:V4SF 3 "vsx_register_operand" "0,ws,0,wa,v")))]
558   "VECTOR_UNIT_VSX_P (V4SFmode)"
559   "@
560    xvmaddasp %x0,%x1,%x2
561    xvmaddmsp %x0,%x1,%x3
562    xvmaddasp %x0,%x1,%x2
563    xvmaddmsp %x0,%x1,%x3
564    vmaddfp %0,%1,%2,%3"
565   [(set_attr "type" "vecfloat")])
567 (define_insn "*vsx_fmav2df4"
568   [(set (match_operand:V2DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa")
569         (fma:V2DF
570           (match_operand:V2DF 1 "vsx_register_operand" "%ws,ws,wa,wa")
571           (match_operand:V2DF 2 "vsx_register_operand" "ws,0,wa,0")
572           (match_operand:V2DF 3 "vsx_register_operand" "0,ws,0,wa")))]
573   "VECTOR_UNIT_VSX_P (V2DFmode)"
574   "@
575    xvmaddadp %x0,%x1,%x2
576    xvmaddmdp %x0,%x1,%x3
577    xvmaddadp %x0,%x1,%x2
578    xvmaddmdp %x0,%x1,%x3"
579   [(set_attr "type" "vecdouble")])
581 (define_insn "*vsx_fmsdf4"
582   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
583         (fma:DF
584           (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
585           (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
586           (neg:DF
587             (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
588   "VECTOR_UNIT_VSX_P (DFmode)"
589   "@
590    xsmsubadp %x0,%x1,%x2
591    xsmsubmdp %x0,%x1,%x3
592    xsmsubadp %x0,%x1,%x2
593    xsmsubmdp %x0,%x1,%x3
594    fmsub %0,%1,%2,%3"
595   [(set_attr "type" "fp")
596    (set_attr "fp_type" "fp_maddsub_d")])
598 (define_insn "*vsx_fms<mode>4"
599   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
600         (fma:VSX_F
601           (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
602           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
603           (neg:VSX_F
604             (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
605   "VECTOR_UNIT_VSX_P (<MODE>mode)"
606   "@
607    x<VSv>msuba<VSs> %x0,%x1,%x2
608    x<VSv>msubm<VSs> %x0,%x1,%x3
609    x<VSv>msuba<VSs> %x0,%x1,%x2
610    x<VSv>msubm<VSs> %x0,%x1,%x3"
611   [(set_attr "type" "<VStype_mul>")])
613 (define_insn "*vsx_nfmadf4"
614   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
615         (neg:DF
616          (fma:DF
617           (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
618           (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
619           (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
620   "VECTOR_UNIT_VSX_P (DFmode)"
621   "@
622    xsnmaddadp %x0,%x1,%x2
623    xsnmaddmdp %x0,%x1,%x3
624    xsnmaddadp %x0,%x1,%x2
625    xsnmaddmdp %x0,%x1,%x3
626    fnmadd %0,%1,%2,%3"
627   [(set_attr "type" "fp")
628    (set_attr "fp_type" "fp_maddsub_d")])
630 (define_insn "*vsx_nfma<mode>4"
631   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
632         (neg:VSX_F
633          (fma:VSX_F
634           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
635           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
636           (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
637   "VECTOR_UNIT_VSX_P (<MODE>mode)"
638   "@
639    x<VSv>nmadda<VSs> %x0,%x1,%x2
640    x<VSv>nmaddm<VSs> %x0,%x1,%x3
641    x<VSv>nmadda<VSs> %x0,%x1,%x2
642    x<VSv>nmaddm<VSs> %x0,%x1,%x3"
643   [(set_attr "type" "<VStype_mul>")
644    (set_attr "fp_type" "<VSfptype_mul>")])
646 (define_insn "*vsx_nfmsdf4"
647   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
648         (neg:DF
649          (fma:DF
650            (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
651            (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
652            (neg:DF
653              (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
654   "VECTOR_UNIT_VSX_P (DFmode)"
655   "@
656    xsnmsubadp %x0,%x1,%x2
657    xsnmsubmdp %x0,%x1,%x3
658    xsnmsubadp %x0,%x1,%x2
659    xsnmsubmdp %x0,%x1,%x3
660    fnmsub %0,%1,%2,%3"
661   [(set_attr "type" "fp")
662    (set_attr "fp_type" "fp_maddsub_d")])
664 (define_insn "*vsx_nfmsv4sf4"
665   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
666         (neg:V4SF
667          (fma:V4SF
668            (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
669            (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
670            (neg:V4SF
671              (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
672   "VECTOR_UNIT_VSX_P (V4SFmode)"
673   "@
674    xvnmsubasp %x0,%x1,%x2
675    xvnmsubmsp %x0,%x1,%x3
676    xvnmsubasp %x0,%x1,%x2
677    xvnmsubmsp %x0,%x1,%x3
678    vnmsubfp %0,%1,%2,%3"
679   [(set_attr "type" "vecfloat")])
681 (define_insn "*vsx_nfmsv2df4"
682   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
683         (neg:V2DF
684          (fma:V2DF
685            (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
686            (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
687            (neg:V2DF
688              (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
689   "VECTOR_UNIT_VSX_P (V2DFmode)"
690   "@
691    xvnmsubadp %x0,%x1,%x2
692    xvnmsubmdp %x0,%x1,%x3
693    xvnmsubadp %x0,%x1,%x2
694    xvnmsubmdp %x0,%x1,%x3"
695   [(set_attr "type" "vecdouble")])
697 ;; Vector conditional expressions (no scalar version for these instructions)
698 (define_insn "vsx_eq<mode>"
699   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
700         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
701                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
702   "VECTOR_UNIT_VSX_P (<MODE>mode)"
703   "xvcmpeq<VSs> %x0,%x1,%x2"
704   [(set_attr "type" "<VStype_simple>")
705    (set_attr "fp_type" "<VSfptype_simple>")])
707 (define_insn "vsx_gt<mode>"
708   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
709         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
710                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
711   "VECTOR_UNIT_VSX_P (<MODE>mode)"
712   "xvcmpgt<VSs> %x0,%x1,%x2"
713   [(set_attr "type" "<VStype_simple>")
714    (set_attr "fp_type" "<VSfptype_simple>")])
716 (define_insn "*vsx_ge<mode>"
717   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
718         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
719                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
720   "VECTOR_UNIT_VSX_P (<MODE>mode)"
721   "xvcmpge<VSs> %x0,%x1,%x2"
722   [(set_attr "type" "<VStype_simple>")
723    (set_attr "fp_type" "<VSfptype_simple>")])
725 ;; Floating point scalar compare
726 (define_insn "*vsx_cmpdf_internal1"
727   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
728         (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
729                       (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
730   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
731    && VECTOR_UNIT_VSX_P (DFmode)"
732   "xscmpudp %0,%x1,%x2"
733   [(set_attr "type" "fpcompare")])
735 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
736 ;; indicate a combined status
737 (define_insn "*vsx_eq_<mode>_p"
738   [(set (reg:CC 74)
739         (unspec:CC
740          [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
741                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
742          UNSPEC_PREDICATE))
743    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
744         (eq:VSX_F (match_dup 1)
745                   (match_dup 2)))]
746   "VECTOR_UNIT_VSX_P (<MODE>mode)"
747   "xvcmpeq<VSs>. %x0,%x1,%x2"
748   [(set_attr "type" "<VStype_simple>")])
750 (define_insn "*vsx_gt_<mode>_p"
751   [(set (reg:CC 74)
752         (unspec:CC
753          [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
754                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
755          UNSPEC_PREDICATE))
756    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
757         (gt:VSX_F (match_dup 1)
758                   (match_dup 2)))]
759   "VECTOR_UNIT_VSX_P (<MODE>mode)"
760   "xvcmpgt<VSs>. %x0,%x1,%x2"
761   [(set_attr "type" "<VStype_simple>")])
763 (define_insn "*vsx_ge_<mode>_p"
764   [(set (reg:CC 74)
765         (unspec:CC
766          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
767                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
768          UNSPEC_PREDICATE))
769    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
770         (ge:VSX_F (match_dup 1)
771                   (match_dup 2)))]
772   "VECTOR_UNIT_VSX_P (<MODE>mode)"
773   "xvcmpge<VSs>. %x0,%x1,%x2"
774   [(set_attr "type" "<VStype_simple>")])
776 ;; Vector select
777 (define_insn "*vsx_xxsel<mode>"
778   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
779         (if_then_else:VSX_L
780          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
781                 (match_operand:VSX_L 4 "zero_constant" ""))
782          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
783          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
784   "VECTOR_MEM_VSX_P (<MODE>mode)"
785   "xxsel %x0,%x3,%x2,%x1"
786   [(set_attr "type" "vecperm")])
788 (define_insn "*vsx_xxsel<mode>_uns"
789   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
790         (if_then_else:VSX_L
791          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
792                    (match_operand:VSX_L 4 "zero_constant" ""))
793          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
794          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
795   "VECTOR_MEM_VSX_P (<MODE>mode)"
796   "xxsel %x0,%x3,%x2,%x1"
797   [(set_attr "type" "vecperm")])
799 ;; Copy sign
800 (define_insn "vsx_copysign<mode>3"
801   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
802         (unspec:VSX_B
803          [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
804           (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
805          UNSPEC_COPYSIGN))]
806   "VECTOR_UNIT_VSX_P (<MODE>mode)"
807   "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
808   [(set_attr "type" "<VStype_simple>")
809    (set_attr "fp_type" "<VSfptype_simple>")])
811 ;; For the conversions, limit the register class for the integer value to be
812 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
813 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
814 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
815 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
816 (define_insn "vsx_float<VSi><mode>2"
817   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
818         (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
819   "VECTOR_UNIT_VSX_P (<MODE>mode)"
820   "x<VSv>cvsx<VSc><VSs> %x0,%x1"
821   [(set_attr "type" "<VStype_simple>")
822    (set_attr "fp_type" "<VSfptype_simple>")])
824 (define_insn "vsx_floatuns<VSi><mode>2"
825   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
826         (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
827   "VECTOR_UNIT_VSX_P (<MODE>mode)"
828   "x<VSv>cvux<VSc><VSs> %x0,%x1"
829   [(set_attr "type" "<VStype_simple>")
830    (set_attr "fp_type" "<VSfptype_simple>")])
832 (define_insn "vsx_fix_trunc<mode><VSi>2"
833   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
834         (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
835   "VECTOR_UNIT_VSX_P (<MODE>mode)"
836   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
837   [(set_attr "type" "<VStype_simple>")
838    (set_attr "fp_type" "<VSfptype_simple>")])
840 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
841   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
842         (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
843   "VECTOR_UNIT_VSX_P (<MODE>mode)"
844   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
845   [(set_attr "type" "<VStype_simple>")
846    (set_attr "fp_type" "<VSfptype_simple>")])
848 ;; Math rounding functions
849 (define_insn "vsx_x<VSv>r<VSs>i"
850   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
851         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
852                       UNSPEC_VSX_ROUND_I))]
853   "VECTOR_UNIT_VSX_P (<MODE>mode)"
854   "x<VSv>r<VSs>i %x0,%x1"
855   [(set_attr "type" "<VStype_simple>")
856    (set_attr "fp_type" "<VSfptype_simple>")])
858 (define_insn "vsx_x<VSv>r<VSs>ic"
859   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
860         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
861                       UNSPEC_VSX_ROUND_IC))]
862   "VECTOR_UNIT_VSX_P (<MODE>mode)"
863   "x<VSv>r<VSs>ic %x0,%x1"
864   [(set_attr "type" "<VStype_simple>")
865    (set_attr "fp_type" "<VSfptype_simple>")])
867 (define_insn "vsx_btrunc<mode>2"
868   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
869         (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
870   "VECTOR_UNIT_VSX_P (<MODE>mode)"
871   "x<VSv>r<VSs>iz %x0,%x1"
872   [(set_attr "type" "<VStype_simple>")
873    (set_attr "fp_type" "<VSfptype_simple>")])
875 (define_insn "*vsx_b2trunc<mode>2"
876   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
877         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
878                       UNSPEC_FRIZ))]
879   "VECTOR_UNIT_VSX_P (<MODE>mode)"
880   "x<VSv>r<VSs>iz %x0,%x1"
881   [(set_attr "type" "<VStype_simple>")
882    (set_attr "fp_type" "<VSfptype_simple>")])
884 (define_insn "vsx_floor<mode>2"
885   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
886         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
887                       UNSPEC_FRIM))]
888   "VECTOR_UNIT_VSX_P (<MODE>mode)"
889   "x<VSv>r<VSs>im %x0,%x1"
890   [(set_attr "type" "<VStype_simple>")
891    (set_attr "fp_type" "<VSfptype_simple>")])
893 (define_insn "vsx_ceil<mode>2"
894   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
895         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
896                       UNSPEC_FRIP))]
897   "VECTOR_UNIT_VSX_P (<MODE>mode)"
898   "x<VSv>r<VSs>ip %x0,%x1"
899   [(set_attr "type" "<VStype_simple>")
900    (set_attr "fp_type" "<VSfptype_simple>")])
903 ;; VSX convert to/from double vector
905 ;; Convert between single and double precision
906 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
907 ;; scalar single precision instructions internally use the double format.
908 ;; Prefer the altivec registers, since we likely will need to do a vperm
909 (define_insn "vsx_<VS_spdp_insn>"
910   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
911         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
912                               UNSPEC_VSX_CVSPDP))]
913   "VECTOR_UNIT_VSX_P (<MODE>mode)"
914   "<VS_spdp_insn> %x0,%x1"
915   [(set_attr "type" "<VS_spdp_type>")])
917 ;; xscvspdp, represent the scalar SF type as V4SF
918 (define_insn "vsx_xscvspdp"
919   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
920         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
921                    UNSPEC_VSX_CVSPDP))]
922   "VECTOR_UNIT_VSX_P (V4SFmode)"
923   "xscvspdp %x0,%x1"
924   [(set_attr "type" "fp")])
926 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
927 ;; format of scalars is actually DF.
928 (define_insn "vsx_xscvdpsp_scalar"
929   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
930         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
931                      UNSPEC_VSX_CVSPDP))]
932   "VECTOR_UNIT_VSX_P (V4SFmode)"
933   "xscvdpsp %x0,%x1"
934   [(set_attr "type" "fp")])
936 ;; Same as vsx_xscvspdp, but use SF as the type
937 (define_insn "vsx_xscvspdp_scalar2"
938   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
939         (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
940                    UNSPEC_VSX_CVSPDP))]
941   "VECTOR_UNIT_VSX_P (V4SFmode)"
942   "xscvspdp %x0,%x1"
943   [(set_attr "type" "fp")])
945 ;; Convert from 64-bit to 32-bit types
946 ;; Note, favor the Altivec registers since the usual use of these instructions
947 ;; is in vector converts and we need to use the Altivec vperm instruction.
949 (define_insn "vsx_xvcvdpsxws"
950   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
951         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
952                      UNSPEC_VSX_CVDPSXWS))]
953   "VECTOR_UNIT_VSX_P (V2DFmode)"
954   "xvcvdpsxws %x0,%x1"
955   [(set_attr "type" "vecdouble")])
957 (define_insn "vsx_xvcvdpuxws"
958   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
959         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
960                      UNSPEC_VSX_CVDPUXWS))]
961   "VECTOR_UNIT_VSX_P (V2DFmode)"
962   "xvcvdpuxws %x0,%x1"
963   [(set_attr "type" "vecdouble")])
965 (define_insn "vsx_xvcvsxdsp"
966   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
967         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
968                      UNSPEC_VSX_CVSXDSP))]
969   "VECTOR_UNIT_VSX_P (V2DFmode)"
970   "xvcvsxdsp %x0,%x1"
971   [(set_attr "type" "vecfloat")])
973 (define_insn "vsx_xvcvuxdsp"
974   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
975         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
976                      UNSPEC_VSX_CVUXDSP))]
977   "VECTOR_UNIT_VSX_P (V2DFmode)"
978   "xvcvuxwdp %x0,%x1"
979   [(set_attr "type" "vecdouble")])
981 ;; Convert from 32-bit to 64-bit types
982 (define_insn "vsx_xvcvsxwdp"
983   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
984         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
985                      UNSPEC_VSX_CVSXWDP))]
986   "VECTOR_UNIT_VSX_P (V2DFmode)"
987   "xvcvsxwdp %x0,%x1"
988   [(set_attr "type" "vecdouble")])
990 (define_insn "vsx_xvcvuxwdp"
991   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
992         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
993                      UNSPEC_VSX_CVUXWDP))]
994   "VECTOR_UNIT_VSX_P (V2DFmode)"
995   "xvcvuxwdp %x0,%x1"
996   [(set_attr "type" "vecdouble")])
998 (define_insn "vsx_xvcvspsxds"
999   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1000         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1001                      UNSPEC_VSX_CVSPSXDS))]
1002   "VECTOR_UNIT_VSX_P (V2DFmode)"
1003   "xvcvspsxds %x0,%x1"
1004   [(set_attr "type" "vecdouble")])
1006 (define_insn "vsx_xvcvspuxds"
1007   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1008         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1009                      UNSPEC_VSX_CVSPUXDS))]
1010   "VECTOR_UNIT_VSX_P (V2DFmode)"
1011   "xvcvspuxds %x0,%x1"
1012   [(set_attr "type" "vecdouble")])
1014 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1015 ;; since the xsrdpiz instruction does not truncate the value if the floating
1016 ;; point value is < LONG_MIN or > LONG_MAX.
1017 (define_insn "*vsx_float_fix_<mode>2"
1018   [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
1019         (float:VSX_DF
1020          (fix:<VSI>
1021           (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
1022   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1023    && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
1024    && !flag_trapping_math && TARGET_FRIZ"
1025   "x<VSv>r<VSs>iz %x0,%x1"
1026   [(set_attr "type" "<VStype_simple>")
1027    (set_attr "fp_type" "<VSfptype_simple>")])
1030 ;; Logical and permute operations
1031 (define_insn "*vsx_and<mode>3"
1032   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1033         (and:VSX_L
1034          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1035          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1036   "VECTOR_MEM_VSX_P (<MODE>mode)"
1037   "xxland %x0,%x1,%x2"
1038   [(set_attr "type" "vecsimple")])
1040 (define_insn "*vsx_ior<mode>3"
1041   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1042         (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1043                    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1044   "VECTOR_MEM_VSX_P (<MODE>mode)"
1045   "xxlor %x0,%x1,%x2"
1046   [(set_attr "type" "vecsimple")])
1048 (define_insn "*vsx_xor<mode>3"
1049   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1050         (xor:VSX_L
1051          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1052          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
1053   "VECTOR_MEM_VSX_P (<MODE>mode)"
1054   "xxlxor %x0,%x1,%x2"
1055   [(set_attr "type" "vecsimple")])
1057 (define_insn "*vsx_one_cmpl<mode>2"
1058   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1059         (not:VSX_L
1060          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1061   "VECTOR_MEM_VSX_P (<MODE>mode)"
1062   "xxlnor %x0,%x1,%x1"
1063   [(set_attr "type" "vecsimple")])
1064   
1065 (define_insn "*vsx_nor<mode>3"
1066   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1067         (not:VSX_L
1068          (ior:VSX_L
1069           (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
1070           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
1071   "VECTOR_MEM_VSX_P (<MODE>mode)"
1072   "xxlnor %x0,%x1,%x2"
1073   [(set_attr "type" "vecsimple")])
1075 (define_insn "*vsx_andc<mode>3"
1076   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
1077         (and:VSX_L
1078          (not:VSX_L
1079           (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
1080          (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
1081   "VECTOR_MEM_VSX_P (<MODE>mode)"
1082   "xxlandc %x0,%x1,%x2"
1083   [(set_attr "type" "vecsimple")])
1086 ;; Permute operations
1088 ;; Build a V2DF/V2DI vector from two scalars
1089 (define_insn "vsx_concat_<mode>"
1090   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1091         (unspec:VSX_D
1092          [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
1093           (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
1094          UNSPEC_VSX_CONCAT))]
1095   "VECTOR_MEM_VSX_P (<MODE>mode)"
1096   "xxpermdi %x0,%x1,%x2,0"
1097   [(set_attr "type" "vecperm")])
1099 ;; Special purpose concat using xxpermdi to glue two single precision values
1100 ;; together, relying on the fact that internally scalar floats are represented
1101 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
1102 (define_insn "vsx_concat_v2sf"
1103   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1104         (unspec:V2DF
1105          [(match_operand:SF 1 "vsx_register_operand" "f,f")
1106           (match_operand:SF 2 "vsx_register_operand" "f,f")]
1107          UNSPEC_VSX_CONCAT))]
1108   "VECTOR_MEM_VSX_P (V2DFmode)"
1109   "xxpermdi %x0,%x1,%x2,0"
1110   [(set_attr "type" "vecperm")])
1112 ;; Set the element of a V2DI/VD2F mode
1113 (define_insn "vsx_set_<mode>"
1114   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
1115         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
1116                        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
1117                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
1118                       UNSPEC_VSX_SET))]
1119   "VECTOR_MEM_VSX_P (<MODE>mode)"
1121   if (INTVAL (operands[3]) == 0)
1122     return \"xxpermdi %x0,%x2,%x1,1\";
1123   else if (INTVAL (operands[3]) == 1)
1124     return \"xxpermdi %x0,%x1,%x2,0\";
1125   else
1126     gcc_unreachable ();
1128   [(set_attr "type" "vecperm")])
1130 ;; Extract a DF/DI element from V2DF/V2DI
1131 (define_insn "vsx_extract_<mode>"
1132   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1133         (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1134                        (parallel
1135                         [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1136   "VECTOR_MEM_VSX_P (<MODE>mode)"
1138   gcc_assert (UINTVAL (operands[2]) <= 1);
1139   operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1140   return \"xxpermdi %x0,%x1,%x1,%3\";
1142   [(set_attr "type" "vecperm")])
1144 ;; Optimize extracting element 0 from memory
1145 (define_insn "*vsx_extract_<mode>_zero"
1146   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1147         (vec_select:<VS_scalar>
1148          (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1149          (parallel [(const_int 0)])))]
1150   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1151   "lxsd%U1x %x0,%y1"
1152   [(set_attr "type" "fpload")
1153    (set_attr "length" "4")])  
1155 ;; Extract a SF element from V4SF
1156 (define_insn_and_split "vsx_extract_v4sf"
1157   [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
1158         (vec_select:SF
1159          (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
1160          (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
1161    (clobber (match_scratch:V4SF 3 "=X,0"))]
1162   "VECTOR_UNIT_VSX_P (V4SFmode)"
1163   "@
1164    xscvspdp %x0,%x1
1165    #"
1166   ""
1167   [(const_int 0)]
1168   "
1170   rtx op0 = operands[0];
1171   rtx op1 = operands[1];
1172   rtx op2 = operands[2];
1173   rtx op3 = operands[3];
1174   rtx tmp;
1175   HOST_WIDE_INT ele = INTVAL (op2);
1177   if (ele == 0)
1178     tmp = op1;
1179   else
1180     {
1181       if (GET_CODE (op3) == SCRATCH)
1182         op3 = gen_reg_rtx (V4SFmode);
1183       emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, op2));
1184       tmp = op3;
1185     }
1186   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
1187   DONE;
1189   [(set_attr "length" "4,8")
1190    (set_attr "type" "fp")])
1192 ;; Expand the builtin form of xxpermdi to canonical rtl.
1193 (define_expand "vsx_xxpermdi_<mode>"
1194   [(match_operand:VSX_L 0 "vsx_register_operand" "")
1195    (match_operand:VSX_L 1 "vsx_register_operand" "")
1196    (match_operand:VSX_L 2 "vsx_register_operand" "")
1197    (match_operand:QI 3 "u5bit_cint_operand" "")]
1198   "VECTOR_MEM_VSX_P (<MODE>mode)"
1200   rtx target = operands[0];
1201   rtx op0 = operands[1];
1202   rtx op1 = operands[2];
1203   int mask = INTVAL (operands[3]);
1204   rtx perm0 = GEN_INT ((mask >> 1) & 1);
1205   rtx perm1 = GEN_INT ((mask & 1) + 2);
1206   rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
1208   if (<MODE>mode == V2DFmode)
1209     gen = gen_vsx_xxpermdi2_v2df_1;
1210   else
1211     {
1212       gen = gen_vsx_xxpermdi2_v2di_1;
1213       if (<MODE>mode != V2DImode)
1214         {
1215           target = gen_lowpart (V2DImode, target);
1216           op0 = gen_lowpart (V2DImode, target);
1217           op1 = gen_lowpart (V2DImode, target);
1218         }
1219     }
1220   emit_insn (gen (target, op0, op1, perm0, perm1));
1221   DONE;
1224 (define_insn "vsx_xxpermdi2_<mode>_1"
1225   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1226         (vec_select:VSX_D
1227           (vec_concat:<VS_double>
1228             (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1229             (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
1230           (parallel [(match_operand 3 "const_0_to_1_operand" "")
1231                      (match_operand 4 "const_2_to_3_operand" "")])))]
1232   "VECTOR_MEM_VSX_P (<MODE>mode)"
1234   int mask = (INTVAL (operands[3]) << 1) | (INTVAL (operands[4]) - 2);
1235   operands[3] = GEN_INT (mask);
1236   return "xxpermdi %x0,%x1,%x2,%3";
1238   [(set_attr "type" "vecperm")])
1240 (define_expand "vec_perm_const<mode>"
1241   [(match_operand:VSX_D 0 "vsx_register_operand" "")
1242    (match_operand:VSX_D 1 "vsx_register_operand" "")
1243    (match_operand:VSX_D 2 "vsx_register_operand" "")
1244    (match_operand:V2DI  3 "" "")]
1245   "VECTOR_MEM_VSX_P (<MODE>mode)"
1247   if (rs6000_expand_vec_perm_const (operands))
1248     DONE;
1249   else
1250     FAIL;
1253 ;; Expanders for builtins
1254 (define_expand "vsx_mergel_<mode>"
1255   [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1256         (vec_select:VSX_D
1257           (vec_concat:<VS_double>
1258             (match_operand:VSX_D 1 "vsx_register_operand" "")
1259             (match_operand:VSX_D 2 "vsx_register_operand" ""))
1260           (parallel [(const_int 1) (const_int 3)])))]
1261   "VECTOR_MEM_VSX_P (<MODE>mode)"
1262   "")
1264 (define_expand "vsx_mergeh_<mode>"
1265   [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1266         (vec_select:VSX_D
1267           (vec_concat:<VS_double>
1268             (match_operand:VSX_D 1 "vsx_register_operand" "")
1269             (match_operand:VSX_D 2 "vsx_register_operand" ""))
1270           (parallel [(const_int 0) (const_int 2)])))]
1271   "VECTOR_MEM_VSX_P (<MODE>mode)"
1272   "")
1274 ;; V2DF/V2DI splat
1275 (define_insn "vsx_splat_<mode>"
1276   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1277         (vec_duplicate:VSX_D
1278          (match_operand:<VS_scalar> 1 "splat_input_operand" "ws,f,Z,wa,wa,Z")))]
1279   "VECTOR_MEM_VSX_P (<MODE>mode)"
1280   "@
1281    xxpermdi %x0,%x1,%x1,0
1282    xxpermdi %x0,%x1,%x1,0
1283    lxvdsx %x0,%y1
1284    xxpermdi %x0,%x1,%x1,0
1285    xxpermdi %x0,%x1,%x1,0
1286    lxvdsx %x0,%y1"
1287   [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1289 ;; V4SF/V4SI splat
1290 (define_insn "vsx_xxspltw_<mode>"
1291   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1292         (vec_duplicate:VSX_W
1293          (vec_select:<VS_scalar>
1294           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1295           (parallel
1296            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1297   "VECTOR_MEM_VSX_P (<MODE>mode)"
1298   "xxspltw %x0,%x1,%2"
1299   [(set_attr "type" "vecperm")])
1301 ;; V4SF/V4SI interleave
1302 (define_insn "vsx_xxmrghw_<mode>"
1303   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1304         (vec_select:VSX_W
1305           (vec_concat:<VS_double>
1306             (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1307             (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa"))
1308           (parallel [(const_int 0) (const_int 4)
1309                      (const_int 1) (const_int 5)])))]
1310   "VECTOR_MEM_VSX_P (<MODE>mode)"
1311   "xxmrghw %x0,%x1,%x2"
1312   [(set_attr "type" "vecperm")])
1314 (define_insn "vsx_xxmrglw_<mode>"
1315   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1316         (vec_select:VSX_W
1317           (vec_concat:<VS_double>
1318             (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1319             (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa"))
1320           (parallel [(const_int 2) (const_int 6)
1321                      (const_int 3) (const_int 7)])))]
1322   "VECTOR_MEM_VSX_P (<MODE>mode)"
1323   "xxmrglw %x0,%x1,%x2"
1324   [(set_attr "type" "vecperm")])
1326 ;; Shift left double by word immediate
1327 (define_insn "vsx_xxsldwi_<mode>"
1328   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1329         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1330                        (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1331                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
1332                       UNSPEC_VSX_SLDWI))]
1333   "VECTOR_MEM_VSX_P (<MODE>mode)"
1334   "xxsldwi %x0,%x1,%x2,%3"
1335   [(set_attr "type" "vecperm")])
1338 ;; Vector reduction insns and splitters
1340 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df"
1341   [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
1342         (VEC_reduc:V2DF
1343          (vec_concat:V2DF
1344           (vec_select:DF
1345            (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1346            (parallel [(const_int 1)]))
1347           (vec_select:DF
1348            (match_dup 1)
1349            (parallel [(const_int 0)])))
1350          (match_dup 1)))
1351    (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
1352   "VECTOR_UNIT_VSX_P (V2DFmode)"
1353   "#"
1354   ""
1355   [(const_int 0)]
1356   "
1358   rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
1359              ? gen_reg_rtx (V2DFmode)
1360              : operands[2];
1361   emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
1362   emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
1363   DONE;
1365   [(set_attr "length" "8")
1366    (set_attr "type" "veccomplex")])
1368 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf"
1369   [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
1370         (VEC_reduc:V4SF
1371          (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1372          (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
1373    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1374    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
1375   "VECTOR_UNIT_VSX_P (V4SFmode)"
1376   "#"
1377   ""
1378   [(const_int 0)]
1379   "
1381   rtx op0 = operands[0];
1382   rtx op1 = operands[1];
1383   rtx tmp2, tmp3, tmp4;
1385   if (can_create_pseudo_p ())
1386     {
1387       tmp2 = gen_reg_rtx (V4SFmode);
1388       tmp3 = gen_reg_rtx (V4SFmode);
1389       tmp4 = gen_reg_rtx (V4SFmode);
1390     }
1391   else
1392     {
1393       tmp2 = operands[2];
1394       tmp3 = operands[3];
1395       tmp4 = tmp2;
1396     }
1398   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1399   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1400   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1401   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
1402   DONE;
1404   [(set_attr "length" "16")
1405    (set_attr "type" "veccomplex")])
1407 ;; Combiner patterns with the vector reduction patterns that knows we can get
1408 ;; to the top element of the V2DF array without doing an extract.
1410 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
1411   [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?wa,ws,?wa")
1412         (vec_select:DF
1413          (VEC_reduc:V2DF
1414           (vec_concat:V2DF
1415            (vec_select:DF
1416             (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1417             (parallel [(const_int 1)]))
1418            (vec_select:DF
1419             (match_dup 1)
1420             (parallel [(const_int 0)])))
1421           (match_dup 1))
1422          (parallel [(const_int 1)])))
1423    (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
1424   "VECTOR_UNIT_VSX_P (V2DFmode)"
1425   "#"
1426   ""
1427   [(const_int 0)]
1428   "
1430   rtx hi = gen_highpart (DFmode, operands[1]);
1431   rtx lo = (GET_CODE (operands[2]) == SCRATCH)
1432             ? gen_reg_rtx (DFmode)
1433             : operands[2];
1435   emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
1436   emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
1437   DONE;
1439   [(set_attr "length" "8")
1440    (set_attr "type" "veccomplex")])
1442 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
1443   [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
1444         (vec_select:SF
1445          (VEC_reduc:V4SF
1446           (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1447           (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
1448          (parallel [(const_int 3)])))
1449    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1450    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
1451    (clobber (match_scratch:V4SF 4 "=0,0"))]
1452   "VECTOR_UNIT_VSX_P (V4SFmode)"
1453   "#"
1454   ""
1455   [(const_int 0)]
1456   "
1458   rtx op0 = operands[0];
1459   rtx op1 = operands[1];
1460   rtx tmp2, tmp3, tmp4, tmp5;
1462   if (can_create_pseudo_p ())
1463     {
1464       tmp2 = gen_reg_rtx (V4SFmode);
1465       tmp3 = gen_reg_rtx (V4SFmode);
1466       tmp4 = gen_reg_rtx (V4SFmode);
1467       tmp5 = gen_reg_rtx (V4SFmode);
1468     }
1469   else
1470     {
1471       tmp2 = operands[2];
1472       tmp3 = operands[3];
1473       tmp4 = tmp2;
1474       tmp5 = operands[4];
1475     }
1477   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1478   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1479   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1480   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
1481   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
1482   DONE;
1484   [(set_attr "length" "20")
1485    (set_attr "type" "veccomplex")])