rs6000-builtin.def (XSRDPIM): Use floatdf2, ceildf2, btruncdf2, instead of vsx_*...
[official-gcc.git] / gcc / config / rs6000 / vsx.md
blob988842f9fe85166ec24f456222717ef8f9002364
1 ;; VSX patterns.
2 ;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
3 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; License for more details.
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/>.
21 ;; Iterator for both scalar and vector floating point types supported by VSX
22 (define_mode_iterator VSX_B [DF V4SF V2DF])
24 ;; Iterator for the 2 64-bit vector types
25 (define_mode_iterator VSX_D [V2DF V2DI])
27 ;; Iterator for the 2 32-bit vector types
28 (define_mode_iterator VSX_W [V4SF V4SI])
30 ;; Iterator for the DF types
31 (define_mode_iterator VSX_DF [V2DF DF])
33 ;; Iterator for vector floating point types supported by VSX
34 (define_mode_iterator VSX_F [V4SF V2DF])
36 ;; Iterator for logical types supported by VSX
37 (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
39 ;; Iterator for memory move.  Handle TImode specially to allow
40 ;; it to use gprs as well as vsx registers.
41 (define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
43 (define_mode_iterator VSX_M2 [V16QI
44                               V8HI
45                               V4SI
46                               V2DI
47                               V4SF
48                               V2DF
49                               (TI       "TARGET_VSX_TIMODE")])
51 ;; Map into the appropriate load/store name based on the type
52 (define_mode_attr VSm  [(V16QI "vw4")
53                         (V8HI  "vw4")
54                         (V4SI  "vw4")
55                         (V4SF  "vw4")
56                         (V2DF  "vd2")
57                         (V2DI  "vd2")
58                         (DF    "d")
59                         (TI    "vd2")])
61 ;; Map into the appropriate suffix based on the type
62 (define_mode_attr VSs   [(V16QI "sp")
63                          (V8HI  "sp")
64                          (V4SI  "sp")
65                          (V4SF  "sp")
66                          (V2DF  "dp")
67                          (V2DI  "dp")
68                          (DF    "dp")
69                          (SF    "sp")
70                          (TI    "dp")])
72 ;; Map the register class used
73 (define_mode_attr VSr   [(V16QI "v")
74                          (V8HI  "v")
75                          (V4SI  "v")
76                          (V4SF  "wf")
77                          (V2DI  "wd")
78                          (V2DF  "wd")
79                          (DF    "ws")
80                          (SF    "d")
81                          (TI    "wt")])
83 ;; Map the register class used for float<->int conversions
84 (define_mode_attr VSr2  [(V2DF  "wd")
85                          (V4SF  "wf")
86                          (DF    "ws")])
88 (define_mode_attr VSr3  [(V2DF  "wa")
89                          (V4SF  "wa")
90                          (DF    "ws")])
92 ;; Map the register class for sp<->dp float conversions, destination
93 (define_mode_attr VSr4  [(SF    "ws")
94                          (DF    "f")
95                          (V2DF  "wd")
96                          (V4SF  "v")])
98 ;; Map the register class for sp<->dp float conversions, destination
99 (define_mode_attr VSr5  [(SF    "ws")
100                          (DF    "f")
101                          (V2DF  "v")
102                          (V4SF  "wd")])
104 ;; Same size integer type for floating point data
105 (define_mode_attr VSi [(V4SF  "v4si")
106                        (V2DF  "v2di")
107                        (DF    "di")])
109 (define_mode_attr VSI [(V4SF  "V4SI")
110                        (V2DF  "V2DI")
111                        (DF    "DI")])
113 ;; Word size for same size conversion
114 (define_mode_attr VSc [(V4SF "w")
115                        (V2DF "d")
116                        (DF   "d")])
118 ;; Map into either s or v, depending on whether this is a scalar or vector
119 ;; operation
120 (define_mode_attr VSv   [(V16QI "v")
121                          (V8HI  "v")
122                          (V4SI  "v")
123                          (V4SF  "v")
124                          (V2DI  "v")
125                          (V2DF  "v")
126                          (DF    "s")])
128 ;; Appropriate type for add ops (and other simple FP ops)
129 (define_mode_attr VStype_simple [(V2DF "vecdouble")
130                                  (V4SF "vecfloat")
131                                  (DF   "fp")])
133 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
134                                    (V4SF "fp_addsub_s")
135                                    (DF   "fp_addsub_d")])
137 ;; Appropriate type for multiply ops
138 (define_mode_attr VStype_mul    [(V2DF "vecdouble")
139                                  (V4SF "vecfloat")
140                                  (DF   "dmul")])
142 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
143                                  (V4SF "fp_mul_s")
144                                  (DF   "fp_mul_d")])
146 ;; Appropriate type for divide ops.
147 (define_mode_attr VStype_div    [(V2DF "vecdiv")
148                                  (V4SF "vecfdiv")
149                                  (DF   "ddiv")])
151 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
152                                  (V4SF "fp_div_s")
153                                  (DF   "fp_div_d")])
155 ;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
156 ;; the scalar sqrt
157 (define_mode_attr VStype_sqrt   [(V2DF "dsqrt")
158                                  (V4SF "ssqrt")
159                                  (DF   "dsqrt")])
161 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
162                                  (V4SF "fp_sqrt_s")
163                                  (DF   "fp_sqrt_d")])
165 ;; Iterator and modes for sp<->dp conversions
166 ;; Because scalar SF values are represented internally as double, use the
167 ;; V4SF type to represent this than SF.
168 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
170 (define_mode_attr VS_spdp_res [(DF      "V4SF")
171                                (V4SF    "V2DF")
172                                (V2DF    "V4SF")])
174 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
175                                 (V4SF   "xvcvspdp")
176                                 (V2DF   "xvcvdpsp")])
178 (define_mode_attr VS_spdp_type [(DF     "fp")
179                                 (V4SF   "vecdouble")
180                                 (V2DF   "vecdouble")])
182 ;; Map the scalar mode for a vector type
183 (define_mode_attr VS_scalar [(V2DF      "DF")
184                              (V2DI      "DI")
185                              (V4SF      "SF")
186                              (V4SI      "SI")
187                              (V8HI      "HI")
188                              (V16QI     "QI")])
190 ;; Map to a double-sized vector mode
191 (define_mode_attr VS_double [(V4SI      "V8SI")
192                              (V4SF      "V8SF")
193                              (V2DI      "V4DI")
194                              (V2DF      "V4DF")])
196 ;; Constants for creating unspecs
197 (define_c_enum "unspec"
198   [UNSPEC_VSX_CONCAT
199    UNSPEC_VSX_CVDPSXWS
200    UNSPEC_VSX_CVDPUXWS
201    UNSPEC_VSX_CVSPDP
202    UNSPEC_VSX_CVSPDPN
203    UNSPEC_VSX_CVDPSPN
204    UNSPEC_VSX_CVSXWDP
205    UNSPEC_VSX_CVUXWDP
206    UNSPEC_VSX_CVSXDSP
207    UNSPEC_VSX_CVUXDSP
208    UNSPEC_VSX_CVSPSXDS
209    UNSPEC_VSX_CVSPUXDS
210    UNSPEC_VSX_TDIV
211    UNSPEC_VSX_TSQRT
212    UNSPEC_VSX_SET
213    UNSPEC_VSX_ROUND_I
214    UNSPEC_VSX_ROUND_IC
215    UNSPEC_VSX_SLDWI
216   ])
218 ;; VSX moves
219 (define_insn "*vsx_mov<mode>"
220   [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,wQ,?&r,??Y,??r,??r,<VSr>,?wa,*r,v,wZ, v")
221         (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,wQ,r,Y,r,j,j,j,W,v,wZ"))]
222   "VECTOR_MEM_VSX_P (<MODE>mode)
223    && (register_operand (operands[0], <MODE>mode) 
224        || register_operand (operands[1], <MODE>mode))"
226   return rs6000_output_move_128bit (operands);
228   [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,load,store,store,load, *,vecsimple,vecsimple,*, *,vecstore,vecload")
229    (set_attr "length" "4,4,4,4,4,4,12,12,12,12,16,4,4,*,16,4,4")])
231 ;; Unlike other VSX moves, allow the GPRs even for reloading, since a normal
232 ;; use of TImode is for unions.  However for plain data movement, slightly
233 ;; favor the vector loads
234 (define_insn "*vsx_movti_64bit"
235   [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v,v,wZ,wQ,&r,Y,r,r,?r")
236         (match_operand:TI 1 "input_operand" "wa,Z,wa,O,W,wZ,v,r,wQ,r,Y,r,n"))]
237   "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
238    && (register_operand (operands[0], TImode) 
239        || register_operand (operands[1], TImode))"
241   return rs6000_output_move_128bit (operands);
243   [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store,load,store,load,*,*")
244    (set_attr "length" "4,4,4,4,16,4,4,8,8,8,8,8,8")])
246 (define_insn "*vsx_movti_32bit"
247   [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,Q,Y,????r,????r,????r,r")
248         (match_operand:TI 1 "input_operand"        "wa, Z,wa, O,W,wZ, v,r,r,    Q,    Y,    r,n"))]
249   "! TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
250    && (register_operand (operands[0], TImode)
251        || register_operand (operands[1], TImode))"
253   switch (which_alternative)
254     {
255     case 0:
256       return "stxvd2x %x1,%y0";
258     case 1:
259       return "lxvd2x %x0,%y1";
261     case 2:
262       return "xxlor %x0,%x1,%x1";
264     case 3:
265       return "xxlxor %x0,%x0,%x0";
267     case 4:
268       return output_vec_const_move (operands);
270     case 5:
271       return "stvx %1,%y0";
273     case 6:
274       return "lvx %0,%y1";
276     case 7:
277       if (TARGET_STRING)
278         return \"stswi %1,%P0,16\";
280     case 8:
281       return \"#\";
283     case 9:
284       /* If the address is not used in the output, we can use lsi.  Otherwise,
285          fall through to generating four loads.  */
286       if (TARGET_STRING
287           && ! reg_overlap_mentioned_p (operands[0], operands[1]))
288         return \"lswi %0,%P1,16\";
289       /* ... fall through ...  */
291     case 10:
292     case 11:
293     case 12:
294       return \"#\";
295     default:
296       gcc_unreachable ();
297     }
299   [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store_ux,store_ux,load_ux,load_ux, *, *")
300    (set_attr "length" "     4,      4,        4,       4,         8,       4,      4,      16,      16,     16,     16,16,16")
301    (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
302                                           (const_string "always")
303                                           (const_string "conditional")))])
305 ;; Explicit  load/store expanders for the builtin functions
306 (define_expand "vsx_load_<mode>"
307   [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
308         (match_operand:VSX_M 1 "memory_operand" ""))]
309   "VECTOR_MEM_VSX_P (<MODE>mode)"
310   "")
312 (define_expand "vsx_store_<mode>"
313   [(set (match_operand:VSX_M 0 "memory_operand" "")
314         (match_operand:VSX_M 1 "vsx_register_operand" ""))]
315   "VECTOR_MEM_VSX_P (<MODE>mode)"
316   "")
319 ;; VSX vector floating point arithmetic instructions.  The VSX scalar
320 ;; instructions are now combined with the insn for the traditional floating
321 ;; point unit.
322 (define_insn "*vsx_add<mode>3"
323   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
324         (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
325                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
326   "VECTOR_UNIT_VSX_P (<MODE>mode)"
327   "xvadd<VSs> %x0,%x1,%x2"
328   [(set_attr "type" "<VStype_simple>")
329    (set_attr "fp_type" "<VSfptype_simple>")])
331 (define_insn "*vsx_sub<mode>3"
332   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
333         (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
334                      (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
335   "VECTOR_UNIT_VSX_P (<MODE>mode)"
336   "xvsub<VSs> %x0,%x1,%x2"
337   [(set_attr "type" "<VStype_simple>")
338    (set_attr "fp_type" "<VSfptype_simple>")])
340 (define_insn "*vsx_mul<mode>3"
341   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
342         (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
343                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
344   "VECTOR_UNIT_VSX_P (<MODE>mode)"
345   "xvmul<VSs> %x0,%x1,%x2"
346   [(set_attr "type" "<VStype_simple>")
347    (set_attr "fp_type" "<VSfptype_mul>")])
349 (define_insn "*vsx_div<mode>3"
350   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
351         (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
352                    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
353   "VECTOR_UNIT_VSX_P (<MODE>mode)"
354   "xvdiv<VSs> %x0,%x1,%x2"
355   [(set_attr "type" "<VStype_div>")
356    (set_attr "fp_type" "<VSfptype_div>")])
358 ;; *tdiv* instruction returning the FG flag
359 (define_expand "vsx_tdiv<mode>3_fg"
360   [(set (match_dup 3)
361         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
362                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
363                      UNSPEC_VSX_TDIV))
364    (set (match_operand:SI 0 "gpc_reg_operand" "")
365         (gt:SI (match_dup 3)
366                (const_int 0)))]
367   "VECTOR_UNIT_VSX_P (<MODE>mode)"
369   operands[3] = gen_reg_rtx (CCFPmode);
372 ;; *tdiv* instruction returning the FE flag
373 (define_expand "vsx_tdiv<mode>3_fe"
374   [(set (match_dup 3)
375         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
376                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
377                      UNSPEC_VSX_TDIV))
378    (set (match_operand:SI 0 "gpc_reg_operand" "")
379         (eq:SI (match_dup 3)
380                (const_int 0)))]
381   "VECTOR_UNIT_VSX_P (<MODE>mode)"
383   operands[3] = gen_reg_rtx (CCFPmode);
386 (define_insn "*vsx_tdiv<mode>3_internal"
387   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
388         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
389                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
390                    UNSPEC_VSX_TDIV))]
391   "VECTOR_UNIT_VSX_P (<MODE>mode)"
392   "x<VSv>tdiv<VSs> %0,%x1,%x2"
393   [(set_attr "type" "<VStype_simple>")
394    (set_attr "fp_type" "<VSfptype_simple>")])
396 (define_insn "vsx_fre<mode>2"
397   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
398         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
399                       UNSPEC_FRES))]
400   "VECTOR_UNIT_VSX_P (<MODE>mode)"
401   "xvre<VSs> %x0,%x1"
402   [(set_attr "type" "<VStype_simple>")
403    (set_attr "fp_type" "<VSfptype_simple>")])
405 (define_insn "*vsx_neg<mode>2"
406   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
407         (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
408   "VECTOR_UNIT_VSX_P (<MODE>mode)"
409   "xvneg<VSs> %x0,%x1"
410   [(set_attr "type" "<VStype_simple>")
411    (set_attr "fp_type" "<VSfptype_simple>")])
413 (define_insn "*vsx_abs<mode>2"
414   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
415         (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
416   "VECTOR_UNIT_VSX_P (<MODE>mode)"
417   "xvabs<VSs> %x0,%x1"
418   [(set_attr "type" "<VStype_simple>")
419    (set_attr "fp_type" "<VSfptype_simple>")])
421 (define_insn "vsx_nabs<mode>2"
422   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
423         (neg:VSX_F
424          (abs:VSX_F
425           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa"))))]
426   "VECTOR_UNIT_VSX_P (<MODE>mode)"
427   "xvnabs<VSs> %x0,%x1"
428   [(set_attr "type" "<VStype_simple>")
429    (set_attr "fp_type" "<VSfptype_simple>")])
431 (define_insn "vsx_smax<mode>3"
432   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
433         (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
434                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
435   "VECTOR_UNIT_VSX_P (<MODE>mode)"
436   "xvmax<VSs> %x0,%x1,%x2"
437   [(set_attr "type" "<VStype_simple>")
438    (set_attr "fp_type" "<VSfptype_simple>")])
440 (define_insn "*vsx_smin<mode>3"
441   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
442         (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
443                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
444   "VECTOR_UNIT_VSX_P (<MODE>mode)"
445   "xvmin<VSs> %x0,%x1,%x2"
446   [(set_attr "type" "<VStype_simple>")
447    (set_attr "fp_type" "<VSfptype_simple>")])
449 (define_insn "*vsx_sqrt<mode>2"
450   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
451         (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
452   "VECTOR_UNIT_VSX_P (<MODE>mode)"
453   "xvsqrt<VSs> %x0,%x1"
454   [(set_attr "type" "<VStype_sqrt>")
455    (set_attr "fp_type" "<VSfptype_sqrt>")])
457 (define_insn "*vsx_rsqrte<mode>2"
458   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
459         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
460                       UNSPEC_RSQRT))]
461   "VECTOR_UNIT_VSX_P (<MODE>mode)"
462   "xvrsqrte<VSs> %x0,%x1"
463   [(set_attr "type" "<VStype_simple>")
464    (set_attr "fp_type" "<VSfptype_simple>")])
466 ;; *tsqrt* returning the fg flag
467 (define_expand "vsx_tsqrt<mode>2_fg"
468   [(set (match_dup 3)
469         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
470                      UNSPEC_VSX_TSQRT))
471    (set (match_operand:SI 0 "gpc_reg_operand" "")
472         (gt:SI (match_dup 3)
473                (const_int 0)))]
474   "VECTOR_UNIT_VSX_P (<MODE>mode)"
476   operands[3] = gen_reg_rtx (CCFPmode);
479 ;; *tsqrt* returning the fe flag
480 (define_expand "vsx_tsqrt<mode>2_fe"
481   [(set (match_dup 3)
482         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
483                      UNSPEC_VSX_TSQRT))
484    (set (match_operand:SI 0 "gpc_reg_operand" "")
485         (eq:SI (match_dup 3)
486                (const_int 0)))]
487   "VECTOR_UNIT_VSX_P (<MODE>mode)"
489   operands[3] = gen_reg_rtx (CCFPmode);
492 (define_insn "*vsx_tsqrt<mode>2_internal"
493   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
494         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
495                      UNSPEC_VSX_TSQRT))]
496   "VECTOR_UNIT_VSX_P (<MODE>mode)"
497   "x<VSv>tsqrt<VSs> %0,%x1"
498   [(set_attr "type" "<VStype_simple>")
499    (set_attr "fp_type" "<VSfptype_simple>")])
501 ;; Fused vector multiply/add instructions. Support the classical Altivec
502 ;; versions of fma, which allows the target to be a separate register from the
503 ;; 3 inputs.  Under VSX, the target must be either the addend or the first
504 ;; multiply.
506 (define_insn "*vsx_fmav4sf4"
507   [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
508         (fma:V4SF
509           (match_operand:V4SF 1 "vsx_register_operand" "%ws,ws,wa,wa,v")
510           (match_operand:V4SF 2 "vsx_register_operand" "ws,0,wa,0,v")
511           (match_operand:V4SF 3 "vsx_register_operand" "0,ws,0,wa,v")))]
512   "VECTOR_UNIT_VSX_P (V4SFmode)"
513   "@
514    xvmaddasp %x0,%x1,%x2
515    xvmaddmsp %x0,%x1,%x3
516    xvmaddasp %x0,%x1,%x2
517    xvmaddmsp %x0,%x1,%x3
518    vmaddfp %0,%1,%2,%3"
519   [(set_attr "type" "vecfloat")])
521 (define_insn "*vsx_fmav2df4"
522   [(set (match_operand:V2DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa")
523         (fma:V2DF
524           (match_operand:V2DF 1 "vsx_register_operand" "%ws,ws,wa,wa")
525           (match_operand:V2DF 2 "vsx_register_operand" "ws,0,wa,0")
526           (match_operand:V2DF 3 "vsx_register_operand" "0,ws,0,wa")))]
527   "VECTOR_UNIT_VSX_P (V2DFmode)"
528   "@
529    xvmaddadp %x0,%x1,%x2
530    xvmaddmdp %x0,%x1,%x3
531    xvmaddadp %x0,%x1,%x2
532    xvmaddmdp %x0,%x1,%x3"
533   [(set_attr "type" "vecdouble")])
535 (define_insn "*vsx_fms<mode>4"
536   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
537         (fma:VSX_F
538           (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
539           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
540           (neg:VSX_F
541             (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
542   "VECTOR_UNIT_VSX_P (<MODE>mode)"
543   "@
544    xvmsuba<VSs> %x0,%x1,%x2
545    xvmsubm<VSs> %x0,%x1,%x3
546    xvmsuba<VSs> %x0,%x1,%x2
547    xvmsubm<VSs> %x0,%x1,%x3"
548   [(set_attr "type" "<VStype_mul>")])
550 (define_insn "*vsx_nfma<mode>4"
551   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
552         (neg:VSX_F
553          (fma:VSX_F
554           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
555           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,wa,0")
556           (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
557   "VECTOR_UNIT_VSX_P (<MODE>mode)"
558   "@
559    xvnmadda<VSs> %x0,%x1,%x2
560    xvnmaddm<VSs> %x0,%x1,%x3
561    xvnmadda<VSs> %x0,%x1,%x2
562    xvnmaddm<VSs> %x0,%x1,%x3"
563   [(set_attr "type" "<VStype_mul>")
564    (set_attr "fp_type" "<VSfptype_mul>")])
566 (define_insn "*vsx_nfmsv4sf4"
567   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
568         (neg:V4SF
569          (fma:V4SF
570            (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
571            (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
572            (neg:V4SF
573              (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
574   "VECTOR_UNIT_VSX_P (V4SFmode)"
575   "@
576    xvnmsubasp %x0,%x1,%x2
577    xvnmsubmsp %x0,%x1,%x3
578    xvnmsubasp %x0,%x1,%x2
579    xvnmsubmsp %x0,%x1,%x3
580    vnmsubfp %0,%1,%2,%3"
581   [(set_attr "type" "vecfloat")])
583 (define_insn "*vsx_nfmsv2df4"
584   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
585         (neg:V2DF
586          (fma:V2DF
587            (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
588            (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
589            (neg:V2DF
590              (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
591   "VECTOR_UNIT_VSX_P (V2DFmode)"
592   "@
593    xvnmsubadp %x0,%x1,%x2
594    xvnmsubmdp %x0,%x1,%x3
595    xvnmsubadp %x0,%x1,%x2
596    xvnmsubmdp %x0,%x1,%x3"
597   [(set_attr "type" "vecdouble")])
599 ;; Vector conditional expressions (no scalar version for these instructions)
600 (define_insn "vsx_eq<mode>"
601   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
602         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
603                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
604   "VECTOR_UNIT_VSX_P (<MODE>mode)"
605   "xvcmpeq<VSs> %x0,%x1,%x2"
606   [(set_attr "type" "<VStype_simple>")
607    (set_attr "fp_type" "<VSfptype_simple>")])
609 (define_insn "vsx_gt<mode>"
610   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
611         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
612                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
613   "VECTOR_UNIT_VSX_P (<MODE>mode)"
614   "xvcmpgt<VSs> %x0,%x1,%x2"
615   [(set_attr "type" "<VStype_simple>")
616    (set_attr "fp_type" "<VSfptype_simple>")])
618 (define_insn "*vsx_ge<mode>"
619   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
620         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
621                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
622   "VECTOR_UNIT_VSX_P (<MODE>mode)"
623   "xvcmpge<VSs> %x0,%x1,%x2"
624   [(set_attr "type" "<VStype_simple>")
625    (set_attr "fp_type" "<VSfptype_simple>")])
627 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
628 ;; indicate a combined status
629 (define_insn "*vsx_eq_<mode>_p"
630   [(set (reg:CC 74)
631         (unspec:CC
632          [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
633                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
634          UNSPEC_PREDICATE))
635    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
636         (eq:VSX_F (match_dup 1)
637                   (match_dup 2)))]
638   "VECTOR_UNIT_VSX_P (<MODE>mode)"
639   "xvcmpeq<VSs>. %x0,%x1,%x2"
640   [(set_attr "type" "<VStype_simple>")])
642 (define_insn "*vsx_gt_<mode>_p"
643   [(set (reg:CC 74)
644         (unspec:CC
645          [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
646                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
647          UNSPEC_PREDICATE))
648    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
649         (gt:VSX_F (match_dup 1)
650                   (match_dup 2)))]
651   "VECTOR_UNIT_VSX_P (<MODE>mode)"
652   "xvcmpgt<VSs>. %x0,%x1,%x2"
653   [(set_attr "type" "<VStype_simple>")])
655 (define_insn "*vsx_ge_<mode>_p"
656   [(set (reg:CC 74)
657         (unspec:CC
658          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
659                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
660          UNSPEC_PREDICATE))
661    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
662         (ge:VSX_F (match_dup 1)
663                   (match_dup 2)))]
664   "VECTOR_UNIT_VSX_P (<MODE>mode)"
665   "xvcmpge<VSs>. %x0,%x1,%x2"
666   [(set_attr "type" "<VStype_simple>")])
668 ;; Vector select
669 (define_insn "*vsx_xxsel<mode>"
670   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
671         (if_then_else:VSX_L
672          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
673                 (match_operand:VSX_L 4 "zero_constant" ""))
674          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
675          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
676   "VECTOR_MEM_VSX_P (<MODE>mode)"
677   "xxsel %x0,%x3,%x2,%x1"
678   [(set_attr "type" "vecperm")])
680 (define_insn "*vsx_xxsel<mode>_uns"
681   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
682         (if_then_else:VSX_L
683          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
684                    (match_operand:VSX_L 4 "zero_constant" ""))
685          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
686          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
687   "VECTOR_MEM_VSX_P (<MODE>mode)"
688   "xxsel %x0,%x3,%x2,%x1"
689   [(set_attr "type" "vecperm")])
691 ;; Copy sign
692 (define_insn "vsx_copysign<mode>3"
693   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
694         (unspec:VSX_F
695          [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
696           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")]
697          UNSPEC_COPYSIGN))]
698   "VECTOR_UNIT_VSX_P (<MODE>mode)"
699   "xvcpsgn<VSs> %x0,%x2,%x1"
700   [(set_attr "type" "<VStype_simple>")
701    (set_attr "fp_type" "<VSfptype_simple>")])
703 ;; For the conversions, limit the register class for the integer value to be
704 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
705 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
706 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
707 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md.
708 (define_insn "vsx_float<VSi><mode>2"
709   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
710         (float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
711   "VECTOR_UNIT_VSX_P (<MODE>mode)"
712   "x<VSv>cvsx<VSc><VSs> %x0,%x1"
713   [(set_attr "type" "<VStype_simple>")
714    (set_attr "fp_type" "<VSfptype_simple>")])
716 (define_insn "vsx_floatuns<VSi><mode>2"
717   [(set (match_operand:VSX_B 0 "gpc_reg_operand" "=<VSr>,?wa")
718         (unsigned_float:VSX_B (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
719   "VECTOR_UNIT_VSX_P (<MODE>mode)"
720   "x<VSv>cvux<VSc><VSs> %x0,%x1"
721   [(set_attr "type" "<VStype_simple>")
722    (set_attr "fp_type" "<VSfptype_simple>")])
724 (define_insn "vsx_fix_trunc<mode><VSi>2"
725   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
726         (fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
727   "VECTOR_UNIT_VSX_P (<MODE>mode)"
728   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
729   [(set_attr "type" "<VStype_simple>")
730    (set_attr "fp_type" "<VSfptype_simple>")])
732 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
733   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
734         (unsigned_fix:<VSI> (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,wa")))]
735   "VECTOR_UNIT_VSX_P (<MODE>mode)"
736   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
737   [(set_attr "type" "<VStype_simple>")
738    (set_attr "fp_type" "<VSfptype_simple>")])
740 ;; Math rounding functions
741 (define_insn "vsx_x<VSv>r<VSs>i"
742   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
743         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
744                       UNSPEC_VSX_ROUND_I))]
745   "VECTOR_UNIT_VSX_P (<MODE>mode)"
746   "x<VSv>r<VSs>i %x0,%x1"
747   [(set_attr "type" "<VStype_simple>")
748    (set_attr "fp_type" "<VSfptype_simple>")])
750 (define_insn "vsx_x<VSv>r<VSs>ic"
751   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
752         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
753                       UNSPEC_VSX_ROUND_IC))]
754   "VECTOR_UNIT_VSX_P (<MODE>mode)"
755   "x<VSv>r<VSs>ic %x0,%x1"
756   [(set_attr "type" "<VStype_simple>")
757    (set_attr "fp_type" "<VSfptype_simple>")])
759 (define_insn "vsx_btrunc<mode>2"
760   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
761         (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
762   "VECTOR_UNIT_VSX_P (<MODE>mode)"
763   "xvr<VSs>iz %x0,%x1"
764   [(set_attr "type" "<VStype_simple>")
765    (set_attr "fp_type" "<VSfptype_simple>")])
767 (define_insn "*vsx_b2trunc<mode>2"
768   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
769         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
770                       UNSPEC_FRIZ))]
771   "VECTOR_UNIT_VSX_P (<MODE>mode)"
772   "x<VSv>r<VSs>iz %x0,%x1"
773   [(set_attr "type" "<VStype_simple>")
774    (set_attr "fp_type" "<VSfptype_simple>")])
776 (define_insn "vsx_floor<mode>2"
777   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
778         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
779                       UNSPEC_FRIM))]
780   "VECTOR_UNIT_VSX_P (<MODE>mode)"
781   "xvr<VSs>im %x0,%x1"
782   [(set_attr "type" "<VStype_simple>")
783    (set_attr "fp_type" "<VSfptype_simple>")])
785 (define_insn "vsx_ceil<mode>2"
786   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
787         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
788                       UNSPEC_FRIP))]
789   "VECTOR_UNIT_VSX_P (<MODE>mode)"
790   "xvr<VSs>ip %x0,%x1"
791   [(set_attr "type" "<VStype_simple>")
792    (set_attr "fp_type" "<VSfptype_simple>")])
795 ;; VSX convert to/from double vector
797 ;; Convert between single and double precision
798 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
799 ;; scalar single precision instructions internally use the double format.
800 ;; Prefer the altivec registers, since we likely will need to do a vperm
801 (define_insn "vsx_<VS_spdp_insn>"
802   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
803         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
804                               UNSPEC_VSX_CVSPDP))]
805   "VECTOR_UNIT_VSX_P (<MODE>mode)"
806   "<VS_spdp_insn> %x0,%x1"
807   [(set_attr "type" "<VS_spdp_type>")])
809 ;; xscvspdp, represent the scalar SF type as V4SF
810 (define_insn "vsx_xscvspdp"
811   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
812         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
813                    UNSPEC_VSX_CVSPDP))]
814   "VECTOR_UNIT_VSX_P (V4SFmode)"
815   "xscvspdp %x0,%x1"
816   [(set_attr "type" "fp")])
818 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
819 ;; format of scalars is actually DF.
820 (define_insn "vsx_xscvdpsp_scalar"
821   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
822         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
823                      UNSPEC_VSX_CVSPDP))]
824   "VECTOR_UNIT_VSX_P (V4SFmode)"
825   "xscvdpsp %x0,%x1"
826   [(set_attr "type" "fp")])
828 ;; Same as vsx_xscvspdp, but use SF as the type
829 (define_insn "vsx_xscvspdp_scalar2"
830   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
831         (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
832                    UNSPEC_VSX_CVSPDP))]
833   "VECTOR_UNIT_VSX_P (V4SFmode)"
834   "xscvspdp %x0,%x1"
835   [(set_attr "type" "fp")])
837 ;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
838 (define_insn "vsx_xscvdpspn"
839   [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,?wa")
840         (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wd,wa")]
841                      UNSPEC_VSX_CVDPSPN))]
842   "TARGET_XSCVDPSPN"
843   "xscvdpspn %x0,%x1"
844   [(set_attr "type" "fp")])
846 (define_insn "vsx_xscvspdpn"
847   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
848         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
849                    UNSPEC_VSX_CVSPDPN))]
850   "TARGET_XSCVSPDPN"
851   "xscvspdpn %x0,%x1"
852   [(set_attr "type" "fp")])
854 (define_insn "vsx_xscvdpspn_scalar"
855   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
856         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
857                      UNSPEC_VSX_CVDPSPN))]
858   "TARGET_XSCVDPSPN"
859   "xscvdpspn %x0,%x1"
860   [(set_attr "type" "fp")])
862 ;; Used by direct move to move a SFmode value from GPR to VSX register
863 (define_insn "vsx_xscvspdpn_directmove"
864   [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
865         (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
866                    UNSPEC_VSX_CVSPDPN))]
867   "TARGET_XSCVSPDPN"
868   "xscvspdpn %x0,%x1"
869   [(set_attr "type" "fp")])
871 ;; Convert from 64-bit to 32-bit types
872 ;; Note, favor the Altivec registers since the usual use of these instructions
873 ;; is in vector converts and we need to use the Altivec vperm instruction.
875 (define_insn "vsx_xvcvdpsxws"
876   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
877         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
878                      UNSPEC_VSX_CVDPSXWS))]
879   "VECTOR_UNIT_VSX_P (V2DFmode)"
880   "xvcvdpsxws %x0,%x1"
881   [(set_attr "type" "vecdouble")])
883 (define_insn "vsx_xvcvdpuxws"
884   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
885         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
886                      UNSPEC_VSX_CVDPUXWS))]
887   "VECTOR_UNIT_VSX_P (V2DFmode)"
888   "xvcvdpuxws %x0,%x1"
889   [(set_attr "type" "vecdouble")])
891 (define_insn "vsx_xvcvsxdsp"
892   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
893         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
894                      UNSPEC_VSX_CVSXDSP))]
895   "VECTOR_UNIT_VSX_P (V2DFmode)"
896   "xvcvsxdsp %x0,%x1"
897   [(set_attr "type" "vecfloat")])
899 (define_insn "vsx_xvcvuxdsp"
900   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
901         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
902                      UNSPEC_VSX_CVUXDSP))]
903   "VECTOR_UNIT_VSX_P (V2DFmode)"
904   "xvcvuxwdp %x0,%x1"
905   [(set_attr "type" "vecdouble")])
907 ;; Convert from 32-bit to 64-bit types
908 (define_insn "vsx_xvcvsxwdp"
909   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
910         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
911                      UNSPEC_VSX_CVSXWDP))]
912   "VECTOR_UNIT_VSX_P (V2DFmode)"
913   "xvcvsxwdp %x0,%x1"
914   [(set_attr "type" "vecdouble")])
916 (define_insn "vsx_xvcvuxwdp"
917   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
918         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
919                      UNSPEC_VSX_CVUXWDP))]
920   "VECTOR_UNIT_VSX_P (V2DFmode)"
921   "xvcvuxwdp %x0,%x1"
922   [(set_attr "type" "vecdouble")])
924 (define_insn "vsx_xvcvspsxds"
925   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
926         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
927                      UNSPEC_VSX_CVSPSXDS))]
928   "VECTOR_UNIT_VSX_P (V2DFmode)"
929   "xvcvspsxds %x0,%x1"
930   [(set_attr "type" "vecdouble")])
932 (define_insn "vsx_xvcvspuxds"
933   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
934         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
935                      UNSPEC_VSX_CVSPUXDS))]
936   "VECTOR_UNIT_VSX_P (V2DFmode)"
937   "xvcvspuxds %x0,%x1"
938   [(set_attr "type" "vecdouble")])
940 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
941 ;; since the xsrdpiz instruction does not truncate the value if the floating
942 ;; point value is < LONG_MIN or > LONG_MAX.
943 (define_insn "*vsx_float_fix_<mode>2"
944   [(set (match_operand:VSX_DF 0 "vsx_register_operand" "=<VSr>,?wa")
945         (float:VSX_DF
946          (fix:<VSI>
947           (match_operand:VSX_DF 1 "vsx_register_operand" "<VSr>,?wa"))))]
948   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
949    && VECTOR_UNIT_VSX_P (<MODE>mode) && flag_unsafe_math_optimizations
950    && !flag_trapping_math && TARGET_FRIZ"
951   "x<VSv>r<VSs>iz %x0,%x1"
952   [(set_attr "type" "<VStype_simple>")
953    (set_attr "fp_type" "<VSfptype_simple>")])
956 ;; Permute operations
958 ;; Build a V2DF/V2DI vector from two scalars
959 (define_insn "vsx_concat_<mode>"
960   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?wa")
961         (vec_concat:VSX_D
962          (match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
963          (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")))]
964   "VECTOR_MEM_VSX_P (<MODE>mode)"
965   "xxpermdi %x0,%x1,%x2,0"
966   [(set_attr "type" "vecperm")])
968 ;; Special purpose concat using xxpermdi to glue two single precision values
969 ;; together, relying on the fact that internally scalar floats are represented
970 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
971 (define_insn "vsx_concat_v2sf"
972   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
973         (unspec:V2DF
974          [(match_operand:SF 1 "vsx_register_operand" "f,f")
975           (match_operand:SF 2 "vsx_register_operand" "f,f")]
976          UNSPEC_VSX_CONCAT))]
977   "VECTOR_MEM_VSX_P (V2DFmode)"
978   "xxpermdi %x0,%x1,%x2,0"
979   [(set_attr "type" "vecperm")])
981 ;; Set the element of a V2DI/VD2F mode
982 (define_insn "vsx_set_<mode>"
983   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
984         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
985                        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
986                        (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
987                       UNSPEC_VSX_SET))]
988   "VECTOR_MEM_VSX_P (<MODE>mode)"
990   if (INTVAL (operands[3]) == 0)
991     return \"xxpermdi %x0,%x2,%x1,1\";
992   else if (INTVAL (operands[3]) == 1)
993     return \"xxpermdi %x0,%x1,%x2,0\";
994   else
995     gcc_unreachable ();
997   [(set_attr "type" "vecperm")])
999 ;; Extract a DF/DI element from V2DF/V2DI
1000 (define_insn "vsx_extract_<mode>"
1001   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1002         (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
1003                        (parallel
1004                         [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
1005   "VECTOR_MEM_VSX_P (<MODE>mode)"
1007   gcc_assert (UINTVAL (operands[2]) <= 1);
1008   operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
1009   return \"xxpermdi %x0,%x1,%x1,%3\";
1011   [(set_attr "type" "vecperm")])
1013 ;; Optimize extracting element 0 from memory
1014 (define_insn "*vsx_extract_<mode>_zero"
1015   [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
1016         (vec_select:<VS_scalar>
1017          (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
1018          (parallel [(const_int 0)])))]
1019   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
1020   "lxsd%U1x %x0,%y1"
1021   [(set (attr "type")
1022       (if_then_else
1023         (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
1024         (const_string "fpload_ux")
1025         (const_string "fpload")))
1026    (set_attr "length" "4")])  
1028 ;; Extract a SF element from V4SF
1029 (define_insn_and_split "vsx_extract_v4sf"
1030   [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
1031         (vec_select:SF
1032          (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
1033          (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
1034    (clobber (match_scratch:V4SF 3 "=X,0"))]
1035   "VECTOR_UNIT_VSX_P (V4SFmode)"
1036   "@
1037    xscvspdp %x0,%x1
1038    #"
1039   ""
1040   [(const_int 0)]
1041   "
1043   rtx op0 = operands[0];
1044   rtx op1 = operands[1];
1045   rtx op2 = operands[2];
1046   rtx op3 = operands[3];
1047   rtx tmp;
1048   HOST_WIDE_INT ele = INTVAL (op2);
1050   if (ele == 0)
1051     tmp = op1;
1052   else
1053     {
1054       if (GET_CODE (op3) == SCRATCH)
1055         op3 = gen_reg_rtx (V4SFmode);
1056       emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, op2));
1057       tmp = op3;
1058     }
1059   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
1060   DONE;
1062   [(set_attr "length" "4,8")
1063    (set_attr "type" "fp")])
1065 ;; Expand the builtin form of xxpermdi to canonical rtl.
1066 (define_expand "vsx_xxpermdi_<mode>"
1067   [(match_operand:VSX_L 0 "vsx_register_operand" "")
1068    (match_operand:VSX_L 1 "vsx_register_operand" "")
1069    (match_operand:VSX_L 2 "vsx_register_operand" "")
1070    (match_operand:QI 3 "u5bit_cint_operand" "")]
1071   "VECTOR_MEM_VSX_P (<MODE>mode)"
1073   rtx target = operands[0];
1074   rtx op0 = operands[1];
1075   rtx op1 = operands[2];
1076   int mask = INTVAL (operands[3]);
1077   rtx perm0 = GEN_INT ((mask >> 1) & 1);
1078   rtx perm1 = GEN_INT ((mask & 1) + 2);
1079   rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
1081   if (<MODE>mode == V2DFmode)
1082     gen = gen_vsx_xxpermdi2_v2df_1;
1083   else
1084     {
1085       gen = gen_vsx_xxpermdi2_v2di_1;
1086       if (<MODE>mode != V2DImode)
1087         {
1088           target = gen_lowpart (V2DImode, target);
1089           op0 = gen_lowpart (V2DImode, op0);
1090           op1 = gen_lowpart (V2DImode, op1);
1091         }
1092     }
1093   emit_insn (gen (target, op0, op1, perm0, perm1));
1094   DONE;
1097 (define_insn "vsx_xxpermdi2_<mode>_1"
1098   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
1099         (vec_select:VSX_D
1100           (vec_concat:<VS_double>
1101             (match_operand:VSX_D 1 "vsx_register_operand" "wd")
1102             (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
1103           (parallel [(match_operand 3 "const_0_to_1_operand" "")
1104                      (match_operand 4 "const_2_to_3_operand" "")])))]
1105   "VECTOR_MEM_VSX_P (<MODE>mode)"
1107   int mask = (INTVAL (operands[3]) << 1) | (INTVAL (operands[4]) - 2);
1108   operands[3] = GEN_INT (mask);
1109   return "xxpermdi %x0,%x1,%x2,%3";
1111   [(set_attr "type" "vecperm")])
1113 (define_expand "vec_perm_const<mode>"
1114   [(match_operand:VSX_D 0 "vsx_register_operand" "")
1115    (match_operand:VSX_D 1 "vsx_register_operand" "")
1116    (match_operand:VSX_D 2 "vsx_register_operand" "")
1117    (match_operand:V2DI  3 "" "")]
1118   "VECTOR_MEM_VSX_P (<MODE>mode)"
1120   if (rs6000_expand_vec_perm_const (operands))
1121     DONE;
1122   else
1123     FAIL;
1126 ;; Expanders for builtins
1127 (define_expand "vsx_mergel_<mode>"
1128   [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1129         (vec_select:VSX_D
1130           (vec_concat:<VS_double>
1131             (match_operand:VSX_D 1 "vsx_register_operand" "")
1132             (match_operand:VSX_D 2 "vsx_register_operand" ""))
1133           (parallel [(const_int 1) (const_int 3)])))]
1134   "VECTOR_MEM_VSX_P (<MODE>mode)"
1135   "")
1137 (define_expand "vsx_mergeh_<mode>"
1138   [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
1139         (vec_select:VSX_D
1140           (vec_concat:<VS_double>
1141             (match_operand:VSX_D 1 "vsx_register_operand" "")
1142             (match_operand:VSX_D 2 "vsx_register_operand" ""))
1143           (parallel [(const_int 0) (const_int 2)])))]
1144   "VECTOR_MEM_VSX_P (<MODE>mode)"
1145   "")
1147 ;; V2DF/V2DI splat
1148 (define_insn "vsx_splat_<mode>"
1149   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
1150         (vec_duplicate:VSX_D
1151          (match_operand:<VS_scalar> 1 "splat_input_operand" "ws,f,Z,wa,wa,Z")))]
1152   "VECTOR_MEM_VSX_P (<MODE>mode)"
1153   "@
1154    xxpermdi %x0,%x1,%x1,0
1155    xxpermdi %x0,%x1,%x1,0
1156    lxvdsx %x0,%y1
1157    xxpermdi %x0,%x1,%x1,0
1158    xxpermdi %x0,%x1,%x1,0
1159    lxvdsx %x0,%y1"
1160   [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
1162 ;; V4SF/V4SI splat
1163 (define_insn "vsx_xxspltw_<mode>"
1164   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1165         (vec_duplicate:VSX_W
1166          (vec_select:<VS_scalar>
1167           (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1168           (parallel
1169            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
1170   "VECTOR_MEM_VSX_P (<MODE>mode)"
1171   "xxspltw %x0,%x1,%2"
1172   [(set_attr "type" "vecperm")])
1174 ;; V4SF/V4SI interleave
1175 (define_insn "vsx_xxmrghw_<mode>"
1176   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1177         (vec_select:VSX_W
1178           (vec_concat:<VS_double>
1179             (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1180             (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa"))
1181           (parallel [(const_int 0) (const_int 4)
1182                      (const_int 1) (const_int 5)])))]
1183   "VECTOR_MEM_VSX_P (<MODE>mode)"
1184   "xxmrghw %x0,%x1,%x2"
1185   [(set_attr "type" "vecperm")])
1187 (define_insn "vsx_xxmrglw_<mode>"
1188   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
1189         (vec_select:VSX_W
1190           (vec_concat:<VS_double>
1191             (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
1192             (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa"))
1193           (parallel [(const_int 2) (const_int 6)
1194                      (const_int 3) (const_int 7)])))]
1195   "VECTOR_MEM_VSX_P (<MODE>mode)"
1196   "xxmrglw %x0,%x1,%x2"
1197   [(set_attr "type" "vecperm")])
1199 ;; Shift left double by word immediate
1200 (define_insn "vsx_xxsldwi_<mode>"
1201   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
1202         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
1203                        (match_operand:VSX_L 2 "vsx_register_operand" "wa")
1204                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
1205                       UNSPEC_VSX_SLDWI))]
1206   "VECTOR_MEM_VSX_P (<MODE>mode)"
1207   "xxsldwi %x0,%x1,%x2,%3"
1208   [(set_attr "type" "vecperm")])
1211 ;; Vector reduction insns and splitters
1213 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df"
1214   [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
1215         (VEC_reduc:V2DF
1216          (vec_concat:V2DF
1217           (vec_select:DF
1218            (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1219            (parallel [(const_int 1)]))
1220           (vec_select:DF
1221            (match_dup 1)
1222            (parallel [(const_int 0)])))
1223          (match_dup 1)))
1224    (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
1225   "VECTOR_UNIT_VSX_P (V2DFmode)"
1226   "#"
1227   ""
1228   [(const_int 0)]
1229   "
1231   rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
1232              ? gen_reg_rtx (V2DFmode)
1233              : operands[2];
1234   emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
1235   emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
1236   DONE;
1238   [(set_attr "length" "8")
1239    (set_attr "type" "veccomplex")])
1241 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf"
1242   [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
1243         (VEC_reduc:V4SF
1244          (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1245          (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
1246    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1247    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
1248   "VECTOR_UNIT_VSX_P (V4SFmode)"
1249   "#"
1250   ""
1251   [(const_int 0)]
1252   "
1254   rtx op0 = operands[0];
1255   rtx op1 = operands[1];
1256   rtx tmp2, tmp3, tmp4;
1258   if (can_create_pseudo_p ())
1259     {
1260       tmp2 = gen_reg_rtx (V4SFmode);
1261       tmp3 = gen_reg_rtx (V4SFmode);
1262       tmp4 = gen_reg_rtx (V4SFmode);
1263     }
1264   else
1265     {
1266       tmp2 = operands[2];
1267       tmp3 = operands[3];
1268       tmp4 = tmp2;
1269     }
1271   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1272   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1273   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1274   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
1275   DONE;
1277   [(set_attr "length" "16")
1278    (set_attr "type" "veccomplex")])
1280 ;; Combiner patterns with the vector reduction patterns that knows we can get
1281 ;; to the top element of the V2DF array without doing an extract.
1283 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
1284   [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?wa,ws,?wa")
1285         (vec_select:DF
1286          (VEC_reduc:V2DF
1287           (vec_concat:V2DF
1288            (vec_select:DF
1289             (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
1290             (parallel [(const_int 1)]))
1291            (vec_select:DF
1292             (match_dup 1)
1293             (parallel [(const_int 0)])))
1294           (match_dup 1))
1295          (parallel [(const_int 1)])))
1296    (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
1297   "VECTOR_UNIT_VSX_P (V2DFmode)"
1298   "#"
1299   ""
1300   [(const_int 0)]
1301   "
1303   rtx hi = gen_highpart (DFmode, operands[1]);
1304   rtx lo = (GET_CODE (operands[2]) == SCRATCH)
1305             ? gen_reg_rtx (DFmode)
1306             : operands[2];
1308   emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
1309   emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
1310   DONE;
1312   [(set_attr "length" "8")
1313    (set_attr "type" "veccomplex")])
1315 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
1316   [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
1317         (vec_select:SF
1318          (VEC_reduc:V4SF
1319           (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1320           (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
1321          (parallel [(const_int 3)])))
1322    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
1323    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
1324    (clobber (match_scratch:V4SF 4 "=0,0"))]
1325   "VECTOR_UNIT_VSX_P (V4SFmode)"
1326   "#"
1327   ""
1328   [(const_int 0)]
1329   "
1331   rtx op0 = operands[0];
1332   rtx op1 = operands[1];
1333   rtx tmp2, tmp3, tmp4, tmp5;
1335   if (can_create_pseudo_p ())
1336     {
1337       tmp2 = gen_reg_rtx (V4SFmode);
1338       tmp3 = gen_reg_rtx (V4SFmode);
1339       tmp4 = gen_reg_rtx (V4SFmode);
1340       tmp5 = gen_reg_rtx (V4SFmode);
1341     }
1342   else
1343     {
1344       tmp2 = operands[2];
1345       tmp3 = operands[3];
1346       tmp4 = tmp2;
1347       tmp5 = operands[4];
1348     }
1350   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
1351   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
1352   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
1353   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
1354   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
1355   DONE;
1357   [(set_attr "length" "20")
1358    (set_attr "type" "veccomplex")])
1361 ;; Power8 Vector fusion.  The fused ops must be physically adjacent.
1362 (define_peephole
1363   [(set (match_operand:P 0 "base_reg_operand" "")
1364         (match_operand:P 1 "short_cint_operand" ""))
1365    (set (match_operand:VSX_M2 2 "vsx_register_operand" "")
1366         (mem:VSX_M2 (plus:P (match_dup 0)
1367                             (match_operand:P 3 "int_reg_operand" ""))))]
1368   "TARGET_P8_FUSION"
1369   "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M2:VSm>x %x2,%0,%3"  
1370   [(set_attr "length" "8")
1371    (set_attr "type" "vecload")])
1373 (define_peephole
1374   [(set (match_operand:P 0 "base_reg_operand" "")
1375         (match_operand:P 1 "short_cint_operand" ""))
1376    (set (match_operand:VSX_M2 2 "vsx_register_operand" "")
1377         (mem:VSX_M2 (plus:P (match_operand:P 3 "int_reg_operand" "")
1378                             (match_dup 0))))]
1379   "TARGET_P8_FUSION"
1380   "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M2:VSm>x %x2,%0,%3"  
1381   [(set_attr "length" "8")
1382    (set_attr "type" "vecload")])