re PR target/71720 (initialization of a vector of floats generates incorrect code...
[official-gcc.git] / gcc / config / rs6000 / vsx.md
blob861b1479a2e1db896ddb966f8d06ec36f22d221a
1 ;; VSX patterns.
2 ;; Copyright (C) 2009-2016 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 64-bit vector types + 128-bit types that are loaded with
28 ;; lxvd2x to properly handle swapping words on little endian
29 (define_mode_iterator VSX_LE [V2DF V2DI V1TI])
31 ;; Mode iterator to handle swapping words on little endian for the 128-bit
32 ;; types that goes in a single vector register.
33 (define_mode_iterator VSX_LE_128 [(KF   "FLOAT128_VECTOR_P (KFmode)")
34                                   (TF   "FLOAT128_VECTOR_P (TFmode)")
35                                   (TI   "TARGET_VSX_TIMODE")])
37 ;; Iterator for the 2 32-bit vector types
38 (define_mode_iterator VSX_W [V4SF V4SI])
40 ;; Iterator for the DF types
41 (define_mode_iterator VSX_DF [V2DF DF])
43 ;; Iterator for vector floating point types supported by VSX
44 (define_mode_iterator VSX_F [V4SF V2DF])
46 ;; Iterator for logical types supported by VSX
47 (define_mode_iterator VSX_L [V16QI
48                              V8HI
49                              V4SI
50                              V2DI
51                              V4SF
52                              V2DF
53                              V1TI
54                              TI
55                              (KF        "FLOAT128_VECTOR_P (KFmode)")
56                              (TF        "FLOAT128_VECTOR_P (TFmode)")])
58 ;; Iterator for memory moves.
59 (define_mode_iterator VSX_M [V16QI
60                              V8HI
61                              V4SI
62                              V2DI
63                              V4SF
64                              V2DF
65                              V1TI
66                              (KF        "FLOAT128_VECTOR_P (KFmode)")
67                              (TF        "FLOAT128_VECTOR_P (TFmode)")
68                              (TI        "TARGET_VSX_TIMODE")])
70 ;; Map into the appropriate load/store name based on the type
71 (define_mode_attr VSm  [(V16QI "vw4")
72                         (V8HI  "vw4")
73                         (V4SI  "vw4")
74                         (V4SF  "vw4")
75                         (V2DF  "vd2")
76                         (V2DI  "vd2")
77                         (DF    "d")
78                         (TF    "vd2")
79                         (KF    "vd2")
80                         (V1TI  "vd2")
81                         (TI    "vd2")])
83 ;; Map into the appropriate suffix based on the type
84 (define_mode_attr VSs   [(V16QI "sp")
85                          (V8HI  "sp")
86                          (V4SI  "sp")
87                          (V4SF  "sp")
88                          (V2DF  "dp")
89                          (V2DI  "dp")
90                          (DF    "dp")
91                          (SF    "sp")
92                          (TF    "dp")
93                          (KF    "dp")
94                          (V1TI  "dp")
95                          (TI    "dp")])
97 ;; Map the register class used
98 (define_mode_attr VSr   [(V16QI "v")
99                          (V8HI  "v")
100                          (V4SI  "v")
101                          (V4SF  "wf")
102                          (V2DI  "wd")
103                          (V2DF  "wd")
104                          (DI    "wi")
105                          (DF    "ws")
106                          (SF    "ww")
107                          (TF    "wp")
108                          (KF    "wq")
109                          (V1TI  "v")
110                          (TI    "wt")])
112 ;; Map the register class used for float<->int conversions (floating point side)
113 ;; VSr2 is the preferred register class, VSr3 is any register class that will
114 ;; hold the data
115 (define_mode_attr VSr2  [(V2DF  "wd")
116                          (V4SF  "wf")
117                          (DF    "ws")
118                          (SF    "ww")
119                          (DI    "wi")])
121 (define_mode_attr VSr3  [(V2DF  "wa")
122                          (V4SF  "wa")
123                          (DF    "ws")
124                          (SF    "ww")
125                          (DI    "wi")])
127 ;; Map the register class for sp<->dp float conversions, destination
128 (define_mode_attr VSr4  [(SF    "ws")
129                          (DF    "f")
130                          (V2DF  "wd")
131                          (V4SF  "v")])
133 ;; Map the register class for sp<->dp float conversions, source
134 (define_mode_attr VSr5  [(SF    "ws")
135                          (DF    "f")
136                          (V2DF  "v")
137                          (V4SF  "wd")])
139 ;; The VSX register class that a type can occupy, even if it is not the
140 ;; preferred register class (VSr is the preferred register class that will get
141 ;; allocated first).
142 (define_mode_attr VSa   [(V16QI "wa")
143                          (V8HI  "wa")
144                          (V4SI  "wa")
145                          (V4SF  "wa")
146                          (V2DI  "wa")
147                          (V2DF  "wa")
148                          (DI    "wi")
149                          (DF    "ws")
150                          (SF    "ww")
151                          (V1TI  "wa")
152                          (TI    "wt")
153                          (TF    "wp")
154                          (KF    "wq")])
156 ;; Same size integer type for floating point data
157 (define_mode_attr VSi [(V4SF  "v4si")
158                        (V2DF  "v2di")
159                        (DF    "di")])
161 (define_mode_attr VSI [(V4SF  "V4SI")
162                        (V2DF  "V2DI")
163                        (DF    "DI")])
165 ;; Word size for same size conversion
166 (define_mode_attr VSc [(V4SF "w")
167                        (V2DF "d")
168                        (DF   "d")])
170 ;; Map into either s or v, depending on whether this is a scalar or vector
171 ;; operation
172 (define_mode_attr VSv   [(V16QI "v")
173                          (V8HI  "v")
174                          (V4SI  "v")
175                          (V4SF  "v")
176                          (V2DI  "v")
177                          (V2DF  "v")
178                          (V1TI  "v")
179                          (DF    "s")
180                          (KF    "v")])
182 ;; Appropriate type for add ops (and other simple FP ops)
183 (define_mode_attr VStype_simple [(V2DF "vecdouble")
184                                  (V4SF "vecfloat")
185                                  (DF   "fp")])
187 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
188                                    (V4SF "fp_addsub_s")
189                                    (DF   "fp_addsub_d")])
191 ;; Appropriate type for multiply ops
192 (define_mode_attr VStype_mul    [(V2DF "vecdouble")
193                                  (V4SF "vecfloat")
194                                  (DF   "dmul")])
196 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
197                                  (V4SF "fp_mul_s")
198                                  (DF   "fp_mul_d")])
200 ;; Appropriate type for divide ops.
201 (define_mode_attr VStype_div    [(V2DF "vecdiv")
202                                  (V4SF "vecfdiv")
203                                  (DF   "ddiv")])
205 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
206                                  (V4SF "fp_div_s")
207                                  (DF   "fp_div_d")])
209 ;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
210 ;; the scalar sqrt
211 (define_mode_attr VStype_sqrt   [(V2DF "dsqrt")
212                                  (V4SF "ssqrt")
213                                  (DF   "dsqrt")])
215 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
216                                  (V4SF "fp_sqrt_s")
217                                  (DF   "fp_sqrt_d")])
219 ;; Iterator and modes for sp<->dp conversions
220 ;; Because scalar SF values are represented internally as double, use the
221 ;; V4SF type to represent this than SF.
222 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
224 (define_mode_attr VS_spdp_res [(DF      "V4SF")
225                                (V4SF    "V2DF")
226                                (V2DF    "V4SF")])
228 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
229                                 (V4SF   "xvcvspdp")
230                                 (V2DF   "xvcvdpsp")])
232 (define_mode_attr VS_spdp_type [(DF     "fp")
233                                 (V4SF   "vecdouble")
234                                 (V2DF   "vecdouble")])
236 ;; Map the scalar mode for a vector type
237 (define_mode_attr VS_scalar [(V1TI      "TI")
238                              (V2DF      "DF")
239                              (V2DI      "DI")
240                              (V4SF      "SF")
241                              (V4SI      "SI")
242                              (V8HI      "HI")
243                              (V16QI     "QI")])
245 ;; Map to a double-sized vector mode
246 (define_mode_attr VS_double [(V4SI      "V8SI")
247                              (V4SF      "V8SF")
248                              (V2DI      "V4DI")
249                              (V2DF      "V4DF")
250                              (V1TI      "V2TI")])
252 ;; Map register class for 64-bit element in 128-bit vector for direct moves
253 ;; to/from gprs
254 (define_mode_attr VS_64dm [(V2DF        "wk")
255                            (V2DI        "wj")])
257 ;; Map register class for 64-bit element in 128-bit vector for normal register
258 ;; to register moves
259 (define_mode_attr VS_64reg [(V2DF       "ws")
260                             (V2DI       "wi")])
262 ;; Iterators for loading constants with xxspltib
263 (define_mode_iterator VSINT_84  [V4SI V2DI DI])
264 (define_mode_iterator VSINT_842 [V8HI V4SI V2DI])
266 ;; Iterator for ISA 3.0 vector extract/insert of integer vectors
267 (define_mode_iterator VSX_EXTRACT_I [V16QI V8HI V4SI])
269 ;; Mode attribute to give the correct predicate for ISA 3.0 vector extract and
270 ;; insert to validate the operand number.
271 (define_mode_attr VSX_EXTRACT_PREDICATE [(V16QI "const_0_to_15_operand")
272                                          (V8HI  "const_0_to_7_operand")
273                                          (V4SI  "const_0_to_3_operand")])
275 ;; Mode attribute to give the constraint for vector extract and insert
276 ;; operations.
277 (define_mode_attr VSX_EX [(V16QI "v")
278                           (V8HI  "v")
279                           (V4SI  "wa")])
281 ;; Constants for creating unspecs
282 (define_c_enum "unspec"
283   [UNSPEC_VSX_CONCAT
284    UNSPEC_VSX_CVDPSXWS
285    UNSPEC_VSX_CVDPUXWS
286    UNSPEC_VSX_CVSPDP
287    UNSPEC_VSX_CVSPDPN
288    UNSPEC_VSX_CVDPSPN
289    UNSPEC_VSX_CVSXWDP
290    UNSPEC_VSX_CVUXWDP
291    UNSPEC_VSX_CVSXDSP
292    UNSPEC_VSX_CVUXDSP
293    UNSPEC_VSX_CVSPSXDS
294    UNSPEC_VSX_CVSPUXDS
295    UNSPEC_VSX_TDIV
296    UNSPEC_VSX_TSQRT
297    UNSPEC_VSX_SET
298    UNSPEC_VSX_ROUND_I
299    UNSPEC_VSX_ROUND_IC
300    UNSPEC_VSX_SLDWI
301    UNSPEC_VSX_XXSPLTW
302    UNSPEC_VSX_XXSPLTD
303    UNSPEC_VSX_DIVSD
304    UNSPEC_VSX_DIVUD
305    UNSPEC_VSX_MULSD
306    UNSPEC_VSX_XVCVSXDDP
307    UNSPEC_VSX_XVCVUXDDP
308    UNSPEC_VSX_XVCVDPSXDS
309    UNSPEC_VSX_XVCVDPUXDS
310    UNSPEC_VSX_SIGN_EXTEND
311    UNSPEC_P9_MEMORY
312   ])
314 ;; VSX moves
316 ;; The patterns for LE permuted loads and stores come before the general
317 ;; VSX moves so they match first.
318 (define_insn_and_split "*vsx_le_perm_load_<mode>"
319   [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
320         (match_operand:VSX_LE 1 "memory_operand" "Z"))]
321   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
322   "#"
323   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
324   [(set (match_dup 2)
325         (vec_select:<MODE>
326           (match_dup 1)
327           (parallel [(const_int 1) (const_int 0)])))
328    (set (match_dup 0)
329         (vec_select:<MODE>
330           (match_dup 2)
331           (parallel [(const_int 1) (const_int 0)])))]
332   "
334   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
335                                        : operands[0];
337   "
338   [(set_attr "type" "vecload")
339    (set_attr "length" "8")])
341 (define_insn_and_split "*vsx_le_perm_load_<mode>"
342   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
343         (match_operand:VSX_W 1 "memory_operand" "Z"))]
344   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
345   "#"
346   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
347   [(set (match_dup 2)
348         (vec_select:<MODE>
349           (match_dup 1)
350           (parallel [(const_int 2) (const_int 3)
351                      (const_int 0) (const_int 1)])))
352    (set (match_dup 0)
353         (vec_select:<MODE>
354           (match_dup 2)
355           (parallel [(const_int 2) (const_int 3)
356                      (const_int 0) (const_int 1)])))]
357   "
359   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
360                                        : operands[0];
362   "
363   [(set_attr "type" "vecload")
364    (set_attr "length" "8")])
366 (define_insn_and_split "*vsx_le_perm_load_v8hi"
367   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
368         (match_operand:V8HI 1 "memory_operand" "Z"))]
369   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
370   "#"
371   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
372   [(set (match_dup 2)
373         (vec_select:V8HI
374           (match_dup 1)
375           (parallel [(const_int 4) (const_int 5)
376                      (const_int 6) (const_int 7)
377                      (const_int 0) (const_int 1)
378                      (const_int 2) (const_int 3)])))
379    (set (match_dup 0)
380         (vec_select:V8HI
381           (match_dup 2)
382           (parallel [(const_int 4) (const_int 5)
383                      (const_int 6) (const_int 7)
384                      (const_int 0) (const_int 1)
385                      (const_int 2) (const_int 3)])))]
386   "
388   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
389                                        : operands[0];
391   "
392   [(set_attr "type" "vecload")
393    (set_attr "length" "8")])
395 (define_insn_and_split "*vsx_le_perm_load_v16qi"
396   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
397         (match_operand:V16QI 1 "memory_operand" "Z"))]
398   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
399   "#"
400   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
401   [(set (match_dup 2)
402         (vec_select:V16QI
403           (match_dup 1)
404           (parallel [(const_int 8) (const_int 9)
405                      (const_int 10) (const_int 11)
406                      (const_int 12) (const_int 13)
407                      (const_int 14) (const_int 15)
408                      (const_int 0) (const_int 1)
409                      (const_int 2) (const_int 3)
410                      (const_int 4) (const_int 5)
411                      (const_int 6) (const_int 7)])))
412    (set (match_dup 0)
413         (vec_select:V16QI
414           (match_dup 2)
415           (parallel [(const_int 8) (const_int 9)
416                      (const_int 10) (const_int 11)
417                      (const_int 12) (const_int 13)
418                      (const_int 14) (const_int 15)
419                      (const_int 0) (const_int 1)
420                      (const_int 2) (const_int 3)
421                      (const_int 4) (const_int 5)
422                      (const_int 6) (const_int 7)])))]
423   "
425   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
426                                        : operands[0];
428   "
429   [(set_attr "type" "vecload")
430    (set_attr "length" "8")])
432 (define_insn "*vsx_le_perm_store_<mode>"
433   [(set (match_operand:VSX_LE 0 "memory_operand" "=Z")
434         (match_operand:VSX_LE 1 "vsx_register_operand" "+<VSa>"))]
435   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
436   "#"
437   [(set_attr "type" "vecstore")
438    (set_attr "length" "12")])
440 (define_split
441   [(set (match_operand:VSX_LE 0 "memory_operand" "")
442         (match_operand:VSX_LE 1 "vsx_register_operand" ""))]
443   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
444   [(set (match_dup 2)
445         (vec_select:<MODE>
446           (match_dup 1)
447           (parallel [(const_int 1) (const_int 0)])))
448    (set (match_dup 0)
449         (vec_select:<MODE>
450           (match_dup 2)
451           (parallel [(const_int 1) (const_int 0)])))]
453   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
454                                        : operands[1];
457 ;; The post-reload split requires that we re-permute the source
458 ;; register in case it is still live.
459 (define_split
460   [(set (match_operand:VSX_LE 0 "memory_operand" "")
461         (match_operand:VSX_LE 1 "vsx_register_operand" ""))]
462   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
463   [(set (match_dup 1)
464         (vec_select:<MODE>
465           (match_dup 1)
466           (parallel [(const_int 1) (const_int 0)])))
467    (set (match_dup 0)
468         (vec_select:<MODE>
469           (match_dup 1)
470           (parallel [(const_int 1) (const_int 0)])))
471    (set (match_dup 1)
472         (vec_select:<MODE>
473           (match_dup 1)
474           (parallel [(const_int 1) (const_int 0)])))]
475   "")
477 (define_insn "*vsx_le_perm_store_<mode>"
478   [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
479         (match_operand:VSX_W 1 "vsx_register_operand" "+<VSa>"))]
480   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
481   "#"
482   [(set_attr "type" "vecstore")
483    (set_attr "length" "12")])
485 (define_split
486   [(set (match_operand:VSX_W 0 "memory_operand" "")
487         (match_operand:VSX_W 1 "vsx_register_operand" ""))]
488   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
489   [(set (match_dup 2)
490         (vec_select:<MODE>
491           (match_dup 1)
492           (parallel [(const_int 2) (const_int 3)
493                      (const_int 0) (const_int 1)])))
494    (set (match_dup 0)
495         (vec_select:<MODE>
496           (match_dup 2)
497           (parallel [(const_int 2) (const_int 3)
498                      (const_int 0) (const_int 1)])))]
500   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
501                                        : operands[1];
504 ;; The post-reload split requires that we re-permute the source
505 ;; register in case it is still live.
506 (define_split
507   [(set (match_operand:VSX_W 0 "memory_operand" "")
508         (match_operand:VSX_W 1 "vsx_register_operand" ""))]
509   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
510   [(set (match_dup 1)
511         (vec_select:<MODE>
512           (match_dup 1)
513           (parallel [(const_int 2) (const_int 3)
514                      (const_int 0) (const_int 1)])))
515    (set (match_dup 0)
516         (vec_select:<MODE>
517           (match_dup 1)
518           (parallel [(const_int 2) (const_int 3)
519                      (const_int 0) (const_int 1)])))
520    (set (match_dup 1)
521         (vec_select:<MODE>
522           (match_dup 1)
523           (parallel [(const_int 2) (const_int 3)
524                      (const_int 0) (const_int 1)])))]
525   "")
527 (define_insn "*vsx_le_perm_store_v8hi"
528   [(set (match_operand:V8HI 0 "memory_operand" "=Z")
529         (match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
530   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
531   "#"
532   [(set_attr "type" "vecstore")
533    (set_attr "length" "12")])
535 (define_split
536   [(set (match_operand:V8HI 0 "memory_operand" "")
537         (match_operand:V8HI 1 "vsx_register_operand" ""))]
538   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
539   [(set (match_dup 2)
540         (vec_select:V8HI
541           (match_dup 1)
542           (parallel [(const_int 4) (const_int 5)
543                      (const_int 6) (const_int 7)
544                      (const_int 0) (const_int 1)
545                      (const_int 2) (const_int 3)])))
546    (set (match_dup 0)
547         (vec_select:V8HI
548           (match_dup 2)
549           (parallel [(const_int 4) (const_int 5)
550                      (const_int 6) (const_int 7)
551                      (const_int 0) (const_int 1)
552                      (const_int 2) (const_int 3)])))]
554   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
555                                        : operands[1];
558 ;; The post-reload split requires that we re-permute the source
559 ;; register in case it is still live.
560 (define_split
561   [(set (match_operand:V8HI 0 "memory_operand" "")
562         (match_operand:V8HI 1 "vsx_register_operand" ""))]
563   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
564   [(set (match_dup 1)
565         (vec_select:V8HI
566           (match_dup 1)
567           (parallel [(const_int 4) (const_int 5)
568                      (const_int 6) (const_int 7)
569                      (const_int 0) (const_int 1)
570                      (const_int 2) (const_int 3)])))
571    (set (match_dup 0)
572         (vec_select:V8HI
573           (match_dup 1)
574           (parallel [(const_int 4) (const_int 5)
575                      (const_int 6) (const_int 7)
576                      (const_int 0) (const_int 1)
577                      (const_int 2) (const_int 3)])))
578    (set (match_dup 1)
579         (vec_select:V8HI
580           (match_dup 1)
581           (parallel [(const_int 4) (const_int 5)
582                      (const_int 6) (const_int 7)
583                      (const_int 0) (const_int 1)
584                      (const_int 2) (const_int 3)])))]
585   "")
587 (define_insn "*vsx_le_perm_store_v16qi"
588   [(set (match_operand:V16QI 0 "memory_operand" "=Z")
589         (match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
590   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
591   "#"
592   [(set_attr "type" "vecstore")
593    (set_attr "length" "12")])
595 (define_split
596   [(set (match_operand:V16QI 0 "memory_operand" "")
597         (match_operand:V16QI 1 "vsx_register_operand" ""))]
598   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
599   [(set (match_dup 2)
600         (vec_select:V16QI
601           (match_dup 1)
602           (parallel [(const_int 8) (const_int 9)
603                      (const_int 10) (const_int 11)
604                      (const_int 12) (const_int 13)
605                      (const_int 14) (const_int 15)
606                      (const_int 0) (const_int 1)
607                      (const_int 2) (const_int 3)
608                      (const_int 4) (const_int 5)
609                      (const_int 6) (const_int 7)])))
610    (set (match_dup 0)
611         (vec_select:V16QI
612           (match_dup 2)
613           (parallel [(const_int 8) (const_int 9)
614                      (const_int 10) (const_int 11)
615                      (const_int 12) (const_int 13)
616                      (const_int 14) (const_int 15)
617                      (const_int 0) (const_int 1)
618                      (const_int 2) (const_int 3)
619                      (const_int 4) (const_int 5)
620                      (const_int 6) (const_int 7)])))]
622   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
623                                        : operands[1];
626 ;; The post-reload split requires that we re-permute the source
627 ;; register in case it is still live.
628 (define_split
629   [(set (match_operand:V16QI 0 "memory_operand" "")
630         (match_operand:V16QI 1 "vsx_register_operand" ""))]
631   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
632   [(set (match_dup 1)
633         (vec_select:V16QI
634           (match_dup 1)
635           (parallel [(const_int 8) (const_int 9)
636                      (const_int 10) (const_int 11)
637                      (const_int 12) (const_int 13)
638                      (const_int 14) (const_int 15)
639                      (const_int 0) (const_int 1)
640                      (const_int 2) (const_int 3)
641                      (const_int 4) (const_int 5)
642                      (const_int 6) (const_int 7)])))
643    (set (match_dup 0)
644         (vec_select:V16QI
645           (match_dup 1)
646           (parallel [(const_int 8) (const_int 9)
647                      (const_int 10) (const_int 11)
648                      (const_int 12) (const_int 13)
649                      (const_int 14) (const_int 15)
650                      (const_int 0) (const_int 1)
651                      (const_int 2) (const_int 3)
652                      (const_int 4) (const_int 5)
653                      (const_int 6) (const_int 7)])))
654    (set (match_dup 1)
655         (vec_select:V16QI
656           (match_dup 1)
657           (parallel [(const_int 8) (const_int 9)
658                      (const_int 10) (const_int 11)
659                      (const_int 12) (const_int 13)
660                      (const_int 14) (const_int 15)
661                      (const_int 0) (const_int 1)
662                      (const_int 2) (const_int 3)
663                      (const_int 4) (const_int 5)
664                      (const_int 6) (const_int 7)])))]
665   "")
667 ;; Little endian word swapping for 128-bit types that are either scalars or the
668 ;; special V1TI container class, which it is not appropriate to use vec_select
669 ;; for the type.
670 (define_insn "*vsx_le_permute_<mode>"
671   [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
672         (rotate:VSX_LE_128
673          (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
674          (const_int 64)))]
675   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
676   "@
677    xxpermdi %x0,%x1,%x1,2
678    lxvd2x %x0,%y1
679    stxvd2x %x1,%y0"
680   [(set_attr "length" "4")
681    (set_attr "type" "vecperm,vecload,vecstore")])
683 (define_insn_and_split "*vsx_le_undo_permute_<mode>"
684   [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
685         (rotate:VSX_LE_128
686          (rotate:VSX_LE_128
687           (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
688           (const_int 64))
689          (const_int 64)))]
690   "!BYTES_BIG_ENDIAN && TARGET_VSX"
691   "@
692    #
693    xxlor %x0,%x1"
694   ""
695   [(set (match_dup 0) (match_dup 1))]
697   if (reload_completed && REGNO (operands[0]) == REGNO (operands[1]))
698     {
699       emit_note (NOTE_INSN_DELETED);
700       DONE;
701     }
703   [(set_attr "length" "0,4")
704    (set_attr "type" "veclogical")])
706 (define_insn_and_split "*vsx_le_perm_load_<mode>"
707   [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>")
708         (match_operand:VSX_LE_128 1 "memory_operand" "Z"))]
709   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
710   "#"
711   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
712   [(set (match_dup 2)
713         (rotate:VSX_LE_128 (match_dup 1)
714                            (const_int 64)))
715    (set (match_dup 0)
716         (rotate:VSX_LE_128 (match_dup 2)
717                            (const_int 64)))]
718   "
720   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
721                                        : operands[0];
723   "
724   [(set_attr "type" "vecload")
725    (set_attr "length" "8")])
727 (define_insn "*vsx_le_perm_store_<mode>"
728   [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z")
729         (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>"))]
730   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
731   "#"
732   [(set_attr "type" "vecstore")
733    (set_attr "length" "12")])
735 (define_split
736   [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
737         (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
738   "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed && !TARGET_P9_VECTOR"
739   [(set (match_dup 2)
740         (rotate:VSX_LE_128 (match_dup 1)
741                            (const_int 64)))
742    (set (match_dup 0)
743         (rotate:VSX_LE_128 (match_dup 2)
744                            (const_int 64)))]
746   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
747                                        : operands[0];
750 ;; Peephole to catch memory to memory transfers for TImode if TImode landed in
751 ;; VSX registers on a little endian system.  The vector types and IEEE 128-bit
752 ;; floating point are handled by the more generic swap elimination pass.
753 (define_peephole2
754   [(set (match_operand:TI 0 "vsx_register_operand" "")
755         (rotate:TI (match_operand:TI 1 "vsx_register_operand" "")
756                    (const_int 64)))
757    (set (match_operand:TI 2 "vsx_register_operand" "")
758         (rotate:TI (match_dup 0)
759                    (const_int 64)))]
760   "!BYTES_BIG_ENDIAN && TARGET_VSX && TARGET_VSX_TIMODE && !TARGET_P9_VECTOR
761    && (rtx_equal_p (operands[0], operands[2])
762        || peep2_reg_dead_p (2, operands[0]))"
763    [(set (match_dup 2) (match_dup 1))])
765 ;; The post-reload split requires that we re-permute the source
766 ;; register in case it is still live.
767 (define_split
768   [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
769         (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
770   "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed && !TARGET_P9_VECTOR"
771   [(set (match_dup 1)
772         (rotate:VSX_LE_128 (match_dup 1)
773                            (const_int 64)))
774    (set (match_dup 0)
775         (rotate:VSX_LE_128 (match_dup 1)
776                            (const_int 64)))
777    (set (match_dup 1)
778         (rotate:VSX_LE_128 (match_dup 1)
779                            (const_int 64)))]
780   "")
782 ;; Vector constants that can be generated with XXSPLTIB that was added in ISA
783 ;; 3.0.  Both (const_vector [..]) and (vec_duplicate ...) forms are recognized.
784 (define_insn "xxspltib_v16qi"
785   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
786         (vec_duplicate:V16QI (match_operand:SI 1 "s8bit_cint_operand" "n")))]
787   "TARGET_P9_VECTOR"
789   operands[2] = GEN_INT (INTVAL (operands[1]) & 0xff);
790   return "xxspltib %x0,%2";
792   [(set_attr "type" "vecperm")])
794 (define_insn "xxspltib_<mode>_nosplit"
795   [(set (match_operand:VSINT_842 0 "vsx_register_operand" "=wa,wa")
796         (match_operand:VSINT_842 1 "xxspltib_constant_nosplit" "jwM,wE"))]
797   "TARGET_P9_VECTOR"
799   rtx op1 = operands[1];
800   int value = 256;
801   int num_insns = -1;
803   if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
804       || num_insns != 1)
805     gcc_unreachable ();
807   operands[2] = GEN_INT (value & 0xff);
808   return "xxspltib %x0,%2";
810   [(set_attr "type" "vecperm")])
812 (define_insn_and_split "*xxspltib_<mode>_split"
813   [(set (match_operand:VSINT_842 0 "altivec_register_operand" "=v")
814         (match_operand:VSINT_842 1 "xxspltib_constant_split" "wS"))]
815   "TARGET_P9_VECTOR"
816   "#"
817   "&& 1"
818   [(const_int 0)]
820   int value = 256;
821   int num_insns = -1;
822   rtx op0 = operands[0];
823   rtx op1 = operands[1];
824   rtx tmp = ((can_create_pseudo_p ())
825              ? gen_reg_rtx (V16QImode)
826              : gen_lowpart (V16QImode, op0));
828   if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
829       || num_insns != 2)
830     gcc_unreachable ();
832   emit_insn (gen_xxspltib_v16qi (tmp, GEN_INT (value)));
834   if (<MODE>mode == V2DImode)
835     emit_insn (gen_vsx_sign_extend_qi_v2di (op0, tmp));
837   else if (<MODE>mode == V4SImode)
838     emit_insn (gen_vsx_sign_extend_qi_v4si (op0, tmp));
840   else if (<MODE>mode == V8HImode)
841     emit_insn (gen_altivec_vupkhsb  (op0, tmp));
843   else
844     gcc_unreachable ();
846   DONE;
848   [(set_attr "type" "vecperm")
849    (set_attr "length" "8")])
852 ;; Prefer using vector registers over GPRs.  Prefer using ISA 3.0's XXSPLTISB
853 ;; or Altivec VSPLITW 0/-1 over XXLXOR/XXLORC to set a register to all 0's or
854 ;; all 1's, since the machine does not have to wait for the previous
855 ;; instruction using the register being set (such as a store waiting on a slow
856 ;; instruction). But generate XXLXOR/XXLORC if it will avoid a register move.
858 ;;              VSX store  VSX load   VSX move  VSX->GPR   GPR->VSX    LQ (GPR)
859 ;;              STQ (GPR)  GPR load   GPR store GPR move   XXSPLTIB    VSPLTISW
860 ;;              VSX 0/-1   GPR 0/-1   VMX const GPR const  LVX (VMX)   STVX (VMX)
861 (define_insn "*vsx_mov<mode>_64bit"
862   [(set (match_operand:VSX_M 0 "nonimmediate_operand"
863                "=ZwO,      <VSa>,     <VSa>,     r,         we,        ?wQ,
864                 ?&r,       ??r,       ??Y,       ??r,       wo,        v,
865                 ?<VSa>,    *r,        v,         ??r,       wZ,        v")
867         (match_operand:VSX_M 1 "input_operand" 
868                "<VSa>,     ZwO,       <VSa>,     we,        r,         r,
869                 wQ,        Y,         r,         r,         wE,        jwM,
870                 ?jwM,      jwM,       W,         W,         v,         wZ"))]
872   "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
873    && (register_operand (operands[0], <MODE>mode) 
874        || register_operand (operands[1], <MODE>mode))"
876   return rs6000_output_move_128bit (operands);
878   [(set_attr "type"
879                "vecstore,  vecload,   vecsimple, mffgpr,    mftgpr,    load,
880                 store,     load,      store,     *,         vecsimple, vecsimple,
881                 vecsimple, *,         *,         *,         vecstore,  vecload")
883    (set_attr "length"
884                "4,         4,         4,         8,         4,         8,
885                 8,         8,         8,         8,         4,         4,
886                 4,         8,         20,        20,        4,         4")])
888 ;;              VSX store  VSX load   VSX move   GPR load   GPR store  GPR move
889 ;;              XXSPLTIB   VSPLTISW   VSX 0/-1   GPR 0/-1   VMX const  GPR const
890 ;;              LVX (VMX)  STVX (VMX)
891 (define_insn "*vsx_mov<mode>_32bit"
892   [(set (match_operand:VSX_M 0 "nonimmediate_operand"
893                "=ZwO,      <VSa>,     <VSa>,     ??r,       ??Y,       ??r,
894                 wo,        v,         ?<VSa>,    *r,        v,         ??r,
895                 wZ,        v")
897         (match_operand:VSX_M 1 "input_operand" 
898                "<VSa>,     ZwO,       <VSa>,     Y,         r,         r,
899                 wE,        jwM,       ?jwM,      jwM,       W,         W,
900                 v,         wZ"))]
902   "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
903    && (register_operand (operands[0], <MODE>mode) 
904        || register_operand (operands[1], <MODE>mode))"
906   return rs6000_output_move_128bit (operands);
908   [(set_attr "type"
909                "vecstore,  vecload,   vecsimple, load,      store,    *,
910                 vecsimple, vecsimple, vecsimple, *,         *,        *,
911                 vecstore,  vecload")
913    (set_attr "length"
914                "4,         4,         4,         16,        16,        16,
915                 4,         4,         4,         16,        20,        32,
916                 4,         4")])
918 ;; Explicit  load/store expanders for the builtin functions
919 (define_expand "vsx_load_<mode>"
920   [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
921         (match_operand:VSX_M 1 "memory_operand" ""))]
922   "VECTOR_MEM_VSX_P (<MODE>mode)"
923   "")
925 (define_expand "vsx_store_<mode>"
926   [(set (match_operand:VSX_M 0 "memory_operand" "")
927         (match_operand:VSX_M 1 "vsx_register_operand" ""))]
928   "VECTOR_MEM_VSX_P (<MODE>mode)"
929   "")
931 ;; Explicit load/store expanders for the builtin functions for lxvd2x, etc.,
932 ;; when you really want their element-reversing behavior.
933 (define_insn "vsx_ld_elemrev_v2di"
934   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
935         (vec_select:V2DI
936           (match_operand:V2DI 1 "memory_operand" "Z")
937           (parallel [(const_int 1) (const_int 0)])))]
938   "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
939   "lxvd2x %x0,%y1"
940   [(set_attr "type" "vecload")])
942 (define_insn "vsx_ld_elemrev_v2df"
943   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
944         (vec_select:V2DF
945           (match_operand:V2DF 1 "memory_operand" "Z")
946           (parallel [(const_int 1) (const_int 0)])))]
947   "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
948   "lxvd2x %x0,%y1"
949   [(set_attr "type" "vecload")])
951 (define_insn "vsx_ld_elemrev_v4si"
952   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
953         (vec_select:V4SI
954           (match_operand:V4SI 1 "memory_operand" "Z")
955           (parallel [(const_int 3) (const_int 2)
956                      (const_int 1) (const_int 0)])))]
957   "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
958   "lxvw4x %x0,%y1"
959   [(set_attr "type" "vecload")])
961 (define_insn "vsx_ld_elemrev_v4sf"
962   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
963         (vec_select:V4SF
964           (match_operand:V4SF 1 "memory_operand" "Z")
965           (parallel [(const_int 3) (const_int 2)
966                      (const_int 1) (const_int 0)])))]
967   "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
968   "lxvw4x %x0,%y1"
969   [(set_attr "type" "vecload")])
971 (define_insn "vsx_ld_elemrev_v8hi"
972   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
973         (vec_select:V8HI
974           (match_operand:V8HI 1 "memory_operand" "Z")
975           (parallel [(const_int 7) (const_int 6)
976                      (const_int 5) (const_int 4)
977                      (const_int 3) (const_int 2)
978                      (const_int 1) (const_int 0)])))]
979   "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
980   "lxvh8x %x0,%y1"
981   [(set_attr "type" "vecload")])
983 (define_insn "vsx_ld_elemrev_v16qi"
984   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
985         (vec_select:V16QI
986           (match_operand:V16QI 1 "memory_operand" "Z")
987           (parallel [(const_int 15) (const_int 14)
988                      (const_int 13) (const_int 12)
989                      (const_int 11) (const_int 10)
990                      (const_int  9) (const_int  8)
991                      (const_int  7) (const_int  6)
992                      (const_int  5) (const_int  4)
993                      (const_int  3) (const_int  2)
994                      (const_int  1) (const_int  0)])))]
995   "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
996   "lxvb16x %x0,%y1"
997   [(set_attr "type" "vecload")])
999 (define_insn "vsx_st_elemrev_v2df"
1000   [(set (match_operand:V2DF 0 "memory_operand" "=Z")
1001         (vec_select:V2DF
1002           (match_operand:V2DF 1 "vsx_register_operand" "wa")
1003           (parallel [(const_int 1) (const_int 0)])))]
1004   "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1005   "stxvd2x %x1,%y0"
1006   [(set_attr "type" "vecstore")])
1008 (define_insn "vsx_st_elemrev_v2di"
1009   [(set (match_operand:V2DI 0 "memory_operand" "=Z")
1010         (vec_select:V2DI
1011           (match_operand:V2DI 1 "vsx_register_operand" "wa")
1012           (parallel [(const_int 1) (const_int 0)])))]
1013   "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1014   "stxvd2x %x1,%y0"
1015   [(set_attr "type" "vecstore")])
1017 (define_insn "vsx_st_elemrev_v4sf"
1018   [(set (match_operand:V4SF 0 "memory_operand" "=Z")
1019         (vec_select:V4SF
1020           (match_operand:V4SF 1 "vsx_register_operand" "wa")
1021           (parallel [(const_int 3) (const_int 2)
1022                      (const_int 1) (const_int 0)])))]
1023   "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1024   "stxvw4x %x1,%y0"
1025   [(set_attr "type" "vecstore")])
1027 (define_insn "vsx_st_elemrev_v4si"
1028   [(set (match_operand:V4SI 0 "memory_operand" "=Z")
1029         (vec_select:V4SI
1030           (match_operand:V4SI 1 "vsx_register_operand" "wa")
1031           (parallel [(const_int 3) (const_int 2)
1032                      (const_int 1) (const_int 0)])))]
1033   "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1034   "stxvw4x %x1,%y0"
1035   [(set_attr "type" "vecstore")])
1037 (define_insn "vsx_st_elemrev_v8hi"
1038   [(set (match_operand:V8HI 0 "memory_operand" "=Z")
1039         (vec_select:V8HI
1040           (match_operand:V8HI 1 "vsx_register_operand" "wa")
1041           (parallel [(const_int 7) (const_int 6)
1042                      (const_int 5) (const_int 4)
1043                      (const_int 3) (const_int 2)
1044                      (const_int 1) (const_int 0)])))]
1045   "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1046   "stxvh8x %x1,%y0"
1047   [(set_attr "type" "vecstore")])
1049 (define_insn "vsx_st_elemrev_v16qi"
1050   [(set (match_operand:V16QI 0 "memory_operand" "=Z")
1051         (vec_select:V16QI
1052           (match_operand:V16QI 1 "vsx_register_operand" "wa")
1053           (parallel [(const_int 15) (const_int 14)
1054                      (const_int 13) (const_int 12)
1055                      (const_int 11) (const_int 10)
1056                      (const_int  9) (const_int  8)
1057                      (const_int  7) (const_int  6)
1058                      (const_int  5) (const_int  4)
1059                      (const_int  3) (const_int  2)
1060                      (const_int  1) (const_int  0)])))]
1061   "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1062   "stxvb16x %x1,%y0"
1063   [(set_attr "type" "vecstore")])
1066 ;; VSX vector floating point arithmetic instructions.  The VSX scalar
1067 ;; instructions are now combined with the insn for the traditional floating
1068 ;; point unit.
1069 (define_insn "*vsx_add<mode>3"
1070   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1071         (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1072                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1073   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1074   "xvadd<VSs> %x0,%x1,%x2"
1075   [(set_attr "type" "<VStype_simple>")
1076    (set_attr "fp_type" "<VSfptype_simple>")])
1078 (define_insn "*vsx_sub<mode>3"
1079   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1080         (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1081                      (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1082   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1083   "xvsub<VSs> %x0,%x1,%x2"
1084   [(set_attr "type" "<VStype_simple>")
1085    (set_attr "fp_type" "<VSfptype_simple>")])
1087 (define_insn "*vsx_mul<mode>3"
1088   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1089         (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1090                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1091   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1092   "xvmul<VSs> %x0,%x1,%x2"
1093   [(set_attr "type" "<VStype_simple>")
1094    (set_attr "fp_type" "<VSfptype_mul>")])
1096 ; Emulate vector with scalar for vec_mul in V2DImode
1097 (define_insn_and_split "vsx_mul_v2di"
1098   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1099         (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1100                       (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1101                      UNSPEC_VSX_MULSD))]
1102   "VECTOR_MEM_VSX_P (V2DImode)"
1103   "#"
1104   "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1105   [(const_int 0)]
1106   "
1108   rtx op0 = operands[0];
1109   rtx op1 = operands[1];
1110   rtx op2 = operands[2];
1111   rtx op3 = gen_reg_rtx (DImode);
1112   rtx op4 = gen_reg_rtx (DImode);
1113   rtx op5 = gen_reg_rtx (DImode);
1114   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1115   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1116   emit_insn (gen_muldi3 (op5, op3, op4));
1117   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1118   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1119   emit_insn (gen_muldi3 (op3, op3, op4));
1120   emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1121   DONE;
1123   [(set_attr "type" "mul")])
1125 (define_insn "*vsx_div<mode>3"
1126   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1127         (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1128                    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1129   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1130   "xvdiv<VSs> %x0,%x1,%x2"
1131   [(set_attr "type" "<VStype_div>")
1132    (set_attr "fp_type" "<VSfptype_div>")])
1134 ; Emulate vector with scalar for vec_div in V2DImode
1135 (define_insn_and_split "vsx_div_v2di"
1136   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1137         (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1138                       (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1139                      UNSPEC_VSX_DIVSD))]
1140   "VECTOR_MEM_VSX_P (V2DImode)"
1141   "#"
1142   "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1143   [(const_int 0)]
1144   "
1146   rtx op0 = operands[0];
1147   rtx op1 = operands[1];
1148   rtx op2 = operands[2];
1149   rtx op3 = gen_reg_rtx (DImode);
1150   rtx op4 = gen_reg_rtx (DImode);
1151   rtx op5 = gen_reg_rtx (DImode);
1152   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1153   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1154   emit_insn (gen_divdi3 (op5, op3, op4));
1155   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1156   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1157   emit_insn (gen_divdi3 (op3, op3, op4));
1158   emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1159   DONE;
1161   [(set_attr "type" "div")])
1163 (define_insn_and_split "vsx_udiv_v2di"
1164   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1165         (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1166                       (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1167                      UNSPEC_VSX_DIVUD))]
1168   "VECTOR_MEM_VSX_P (V2DImode)"
1169   "#"
1170   "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1171   [(const_int 0)]
1172   "
1174   rtx op0 = operands[0];
1175   rtx op1 = operands[1];
1176   rtx op2 = operands[2];
1177   rtx op3 = gen_reg_rtx (DImode);
1178   rtx op4 = gen_reg_rtx (DImode);
1179   rtx op5 = gen_reg_rtx (DImode);
1180   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1181   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1182   emit_insn (gen_udivdi3 (op5, op3, op4));
1183   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1184   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1185   emit_insn (gen_udivdi3 (op3, op3, op4));
1186   emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1187   DONE;
1189   [(set_attr "type" "div")])
1191 ;; *tdiv* instruction returning the FG flag
1192 (define_expand "vsx_tdiv<mode>3_fg"
1193   [(set (match_dup 3)
1194         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1195                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
1196                      UNSPEC_VSX_TDIV))
1197    (set (match_operand:SI 0 "gpc_reg_operand" "")
1198         (gt:SI (match_dup 3)
1199                (const_int 0)))]
1200   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1202   operands[3] = gen_reg_rtx (CCFPmode);
1205 ;; *tdiv* instruction returning the FE flag
1206 (define_expand "vsx_tdiv<mode>3_fe"
1207   [(set (match_dup 3)
1208         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1209                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
1210                      UNSPEC_VSX_TDIV))
1211    (set (match_operand:SI 0 "gpc_reg_operand" "")
1212         (eq:SI (match_dup 3)
1213                (const_int 0)))]
1214   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1216   operands[3] = gen_reg_rtx (CCFPmode);
1219 (define_insn "*vsx_tdiv<mode>3_internal"
1220   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1221         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")
1222                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,<VSa>")]
1223                    UNSPEC_VSX_TDIV))]
1224   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1225   "x<VSv>tdiv<VSs> %0,%x1,%x2"
1226   [(set_attr "type" "<VStype_simple>")
1227    (set_attr "fp_type" "<VSfptype_simple>")])
1229 (define_insn "vsx_fre<mode>2"
1230   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1231         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1232                       UNSPEC_FRES))]
1233   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1234   "xvre<VSs> %x0,%x1"
1235   [(set_attr "type" "<VStype_simple>")
1236    (set_attr "fp_type" "<VSfptype_simple>")])
1238 (define_insn "*vsx_neg<mode>2"
1239   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1240         (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1241   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1242   "xvneg<VSs> %x0,%x1"
1243   [(set_attr "type" "<VStype_simple>")
1244    (set_attr "fp_type" "<VSfptype_simple>")])
1246 (define_insn "*vsx_abs<mode>2"
1247   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1248         (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1249   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1250   "xvabs<VSs> %x0,%x1"
1251   [(set_attr "type" "<VStype_simple>")
1252    (set_attr "fp_type" "<VSfptype_simple>")])
1254 (define_insn "vsx_nabs<mode>2"
1255   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1256         (neg:VSX_F
1257          (abs:VSX_F
1258           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>"))))]
1259   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1260   "xvnabs<VSs> %x0,%x1"
1261   [(set_attr "type" "<VStype_simple>")
1262    (set_attr "fp_type" "<VSfptype_simple>")])
1264 (define_insn "vsx_smax<mode>3"
1265   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1266         (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1267                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1268   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1269   "xvmax<VSs> %x0,%x1,%x2"
1270   [(set_attr "type" "<VStype_simple>")
1271    (set_attr "fp_type" "<VSfptype_simple>")])
1273 (define_insn "*vsx_smin<mode>3"
1274   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1275         (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1276                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1277   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1278   "xvmin<VSs> %x0,%x1,%x2"
1279   [(set_attr "type" "<VStype_simple>")
1280    (set_attr "fp_type" "<VSfptype_simple>")])
1282 (define_insn "*vsx_sqrt<mode>2"
1283   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1284         (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1285   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1286   "xvsqrt<VSs> %x0,%x1"
1287   [(set_attr "type" "<VStype_sqrt>")
1288    (set_attr "fp_type" "<VSfptype_sqrt>")])
1290 (define_insn "*vsx_rsqrte<mode>2"
1291   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1292         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1293                       UNSPEC_RSQRT))]
1294   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1295   "xvrsqrte<VSs> %x0,%x1"
1296   [(set_attr "type" "<VStype_simple>")
1297    (set_attr "fp_type" "<VSfptype_simple>")])
1299 ;; *tsqrt* returning the fg flag
1300 (define_expand "vsx_tsqrt<mode>2_fg"
1301   [(set (match_dup 3)
1302         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1303                      UNSPEC_VSX_TSQRT))
1304    (set (match_operand:SI 0 "gpc_reg_operand" "")
1305         (gt:SI (match_dup 3)
1306                (const_int 0)))]
1307   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1309   operands[3] = gen_reg_rtx (CCFPmode);
1312 ;; *tsqrt* returning the fe flag
1313 (define_expand "vsx_tsqrt<mode>2_fe"
1314   [(set (match_dup 3)
1315         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1316                      UNSPEC_VSX_TSQRT))
1317    (set (match_operand:SI 0 "gpc_reg_operand" "")
1318         (eq:SI (match_dup 3)
1319                (const_int 0)))]
1320   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1322   operands[3] = gen_reg_rtx (CCFPmode);
1325 (define_insn "*vsx_tsqrt<mode>2_internal"
1326   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1327         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1328                      UNSPEC_VSX_TSQRT))]
1329   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1330   "x<VSv>tsqrt<VSs> %0,%x1"
1331   [(set_attr "type" "<VStype_simple>")
1332    (set_attr "fp_type" "<VSfptype_simple>")])
1334 ;; Fused vector multiply/add instructions. Support the classical Altivec
1335 ;; versions of fma, which allows the target to be a separate register from the
1336 ;; 3 inputs.  Under VSX, the target must be either the addend or the first
1337 ;; multiply.
1339 (define_insn "*vsx_fmav4sf4"
1340   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1341         (fma:V4SF
1342           (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1343           (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1344           (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))]
1345   "VECTOR_UNIT_VSX_P (V4SFmode)"
1346   "@
1347    xvmaddasp %x0,%x1,%x2
1348    xvmaddmsp %x0,%x1,%x3
1349    xvmaddasp %x0,%x1,%x2
1350    xvmaddmsp %x0,%x1,%x3
1351    vmaddfp %0,%1,%2,%3"
1352   [(set_attr "type" "vecfloat")])
1354 (define_insn "*vsx_fmav2df4"
1355   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1356         (fma:V2DF
1357           (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1358           (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1359           (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))]
1360   "VECTOR_UNIT_VSX_P (V2DFmode)"
1361   "@
1362    xvmaddadp %x0,%x1,%x2
1363    xvmaddmdp %x0,%x1,%x3
1364    xvmaddadp %x0,%x1,%x2
1365    xvmaddmdp %x0,%x1,%x3"
1366   [(set_attr "type" "vecdouble")])
1368 (define_insn "*vsx_fms<mode>4"
1369   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1370         (fma:VSX_F
1371           (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,<VSa>,<VSa>")
1372           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1373           (neg:VSX_F
1374             (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1375   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1376   "@
1377    xvmsuba<VSs> %x0,%x1,%x2
1378    xvmsubm<VSs> %x0,%x1,%x3
1379    xvmsuba<VSs> %x0,%x1,%x2
1380    xvmsubm<VSs> %x0,%x1,%x3"
1381   [(set_attr "type" "<VStype_mul>")])
1383 (define_insn "*vsx_nfma<mode>4"
1384   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1385         (neg:VSX_F
1386          (fma:VSX_F
1387           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,<VSa>,<VSa>")
1388           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1389           (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1390   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1391   "@
1392    xvnmadda<VSs> %x0,%x1,%x2
1393    xvnmaddm<VSs> %x0,%x1,%x3
1394    xvnmadda<VSs> %x0,%x1,%x2
1395    xvnmaddm<VSs> %x0,%x1,%x3"
1396   [(set_attr "type" "<VStype_mul>")
1397    (set_attr "fp_type" "<VSfptype_mul>")])
1399 (define_insn "*vsx_nfmsv4sf4"
1400   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1401         (neg:V4SF
1402          (fma:V4SF
1403            (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1404            (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1405            (neg:V4SF
1406              (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
1407   "VECTOR_UNIT_VSX_P (V4SFmode)"
1408   "@
1409    xvnmsubasp %x0,%x1,%x2
1410    xvnmsubmsp %x0,%x1,%x3
1411    xvnmsubasp %x0,%x1,%x2
1412    xvnmsubmsp %x0,%x1,%x3
1413    vnmsubfp %0,%1,%2,%3"
1414   [(set_attr "type" "vecfloat")])
1416 (define_insn "*vsx_nfmsv2df4"
1417   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1418         (neg:V2DF
1419          (fma:V2DF
1420            (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1421            (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1422            (neg:V2DF
1423              (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
1424   "VECTOR_UNIT_VSX_P (V2DFmode)"
1425   "@
1426    xvnmsubadp %x0,%x1,%x2
1427    xvnmsubmdp %x0,%x1,%x3
1428    xvnmsubadp %x0,%x1,%x2
1429    xvnmsubmdp %x0,%x1,%x3"
1430   [(set_attr "type" "vecdouble")])
1432 ;; Vector conditional expressions (no scalar version for these instructions)
1433 (define_insn "vsx_eq<mode>"
1434   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1435         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1436                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1437   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1438   "xvcmpeq<VSs> %x0,%x1,%x2"
1439   [(set_attr "type" "<VStype_simple>")
1440    (set_attr "fp_type" "<VSfptype_simple>")])
1442 (define_insn "vsx_gt<mode>"
1443   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1444         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1445                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1446   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1447   "xvcmpgt<VSs> %x0,%x1,%x2"
1448   [(set_attr "type" "<VStype_simple>")
1449    (set_attr "fp_type" "<VSfptype_simple>")])
1451 (define_insn "*vsx_ge<mode>"
1452   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1453         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1454                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1455   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1456   "xvcmpge<VSs> %x0,%x1,%x2"
1457   [(set_attr "type" "<VStype_simple>")
1458    (set_attr "fp_type" "<VSfptype_simple>")])
1460 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
1461 ;; indicate a combined status
1462 (define_insn "*vsx_eq_<mode>_p"
1463   [(set (reg:CC 74)
1464         (unspec:CC
1465          [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1466                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1467          UNSPEC_PREDICATE))
1468    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1469         (eq:VSX_F (match_dup 1)
1470                   (match_dup 2)))]
1471   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1472   "xvcmpeq<VSs>. %x0,%x1,%x2"
1473   [(set_attr "type" "<VStype_simple>")])
1475 (define_insn "*vsx_gt_<mode>_p"
1476   [(set (reg:CC 74)
1477         (unspec:CC
1478          [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1479                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1480          UNSPEC_PREDICATE))
1481    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1482         (gt:VSX_F (match_dup 1)
1483                   (match_dup 2)))]
1484   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1485   "xvcmpgt<VSs>. %x0,%x1,%x2"
1486   [(set_attr "type" "<VStype_simple>")])
1488 (define_insn "*vsx_ge_<mode>_p"
1489   [(set (reg:CC 74)
1490         (unspec:CC
1491          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1492                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1493          UNSPEC_PREDICATE))
1494    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1495         (ge:VSX_F (match_dup 1)
1496                   (match_dup 2)))]
1497   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1498   "xvcmpge<VSs>. %x0,%x1,%x2"
1499   [(set_attr "type" "<VStype_simple>")])
1501 ;; Vector select
1502 (define_insn "*vsx_xxsel<mode>"
1503   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1504         (if_then_else:VSX_L
1505          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1506                 (match_operand:VSX_L 4 "zero_constant" ""))
1507          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1508          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1509   "VECTOR_MEM_VSX_P (<MODE>mode)"
1510   "xxsel %x0,%x3,%x2,%x1"
1511   [(set_attr "type" "vecmove")])
1513 (define_insn "*vsx_xxsel<mode>_uns"
1514   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1515         (if_then_else:VSX_L
1516          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1517                    (match_operand:VSX_L 4 "zero_constant" ""))
1518          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1519          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1520   "VECTOR_MEM_VSX_P (<MODE>mode)"
1521   "xxsel %x0,%x3,%x2,%x1"
1522   [(set_attr "type" "vecmove")])
1524 ;; Copy sign
1525 (define_insn "vsx_copysign<mode>3"
1526   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1527         (unspec:VSX_F
1528          [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1529           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")]
1530          UNSPEC_COPYSIGN))]
1531   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1532   "xvcpsgn<VSs> %x0,%x2,%x1"
1533   [(set_attr "type" "<VStype_simple>")
1534    (set_attr "fp_type" "<VSfptype_simple>")])
1536 ;; For the conversions, limit the register class for the integer value to be
1537 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
1538 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
1539 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
1540 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md
1541 ;; in allowing virtual registers.
1542 (define_insn "vsx_float<VSi><mode>2"
1543   [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1544         (float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1545   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1546   "xvcvsx<VSc><VSs> %x0,%x1"
1547   [(set_attr "type" "<VStype_simple>")
1548    (set_attr "fp_type" "<VSfptype_simple>")])
1550 (define_insn "vsx_floatuns<VSi><mode>2"
1551   [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1552         (unsigned_float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1553   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1554   "xvcvux<VSc><VSs> %x0,%x1"
1555   [(set_attr "type" "<VStype_simple>")
1556    (set_attr "fp_type" "<VSfptype_simple>")])
1558 (define_insn "vsx_fix_trunc<mode><VSi>2"
1559   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1560         (fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1561   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1562   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
1563   [(set_attr "type" "<VStype_simple>")
1564    (set_attr "fp_type" "<VSfptype_simple>")])
1566 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
1567   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1568         (unsigned_fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1569   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1570   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
1571   [(set_attr "type" "<VStype_simple>")
1572    (set_attr "fp_type" "<VSfptype_simple>")])
1574 ;; Math rounding functions
1575 (define_insn "vsx_x<VSv>r<VSs>i"
1576   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1577         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1578                       UNSPEC_VSX_ROUND_I))]
1579   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1580   "x<VSv>r<VSs>i %x0,%x1"
1581   [(set_attr "type" "<VStype_simple>")
1582    (set_attr "fp_type" "<VSfptype_simple>")])
1584 (define_insn "vsx_x<VSv>r<VSs>ic"
1585   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1586         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1587                       UNSPEC_VSX_ROUND_IC))]
1588   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1589   "x<VSv>r<VSs>ic %x0,%x1"
1590   [(set_attr "type" "<VStype_simple>")
1591    (set_attr "fp_type" "<VSfptype_simple>")])
1593 (define_insn "vsx_btrunc<mode>2"
1594   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1595         (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1596   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1597   "xvr<VSs>iz %x0,%x1"
1598   [(set_attr "type" "<VStype_simple>")
1599    (set_attr "fp_type" "<VSfptype_simple>")])
1601 (define_insn "*vsx_b2trunc<mode>2"
1602   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1603         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1604                       UNSPEC_FRIZ))]
1605   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1606   "x<VSv>r<VSs>iz %x0,%x1"
1607   [(set_attr "type" "<VStype_simple>")
1608    (set_attr "fp_type" "<VSfptype_simple>")])
1610 (define_insn "vsx_floor<mode>2"
1611   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1612         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1613                       UNSPEC_FRIM))]
1614   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1615   "xvr<VSs>im %x0,%x1"
1616   [(set_attr "type" "<VStype_simple>")
1617    (set_attr "fp_type" "<VSfptype_simple>")])
1619 (define_insn "vsx_ceil<mode>2"
1620   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1621         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1622                       UNSPEC_FRIP))]
1623   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1624   "xvr<VSs>ip %x0,%x1"
1625   [(set_attr "type" "<VStype_simple>")
1626    (set_attr "fp_type" "<VSfptype_simple>")])
1629 ;; VSX convert to/from double vector
1631 ;; Convert between single and double precision
1632 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
1633 ;; scalar single precision instructions internally use the double format.
1634 ;; Prefer the altivec registers, since we likely will need to do a vperm
1635 (define_insn "vsx_<VS_spdp_insn>"
1636   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?<VSa>")
1637         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,<VSa>")]
1638                               UNSPEC_VSX_CVSPDP))]
1639   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1640   "<VS_spdp_insn> %x0,%x1"
1641   [(set_attr "type" "<VS_spdp_type>")])
1643 ;; xscvspdp, represent the scalar SF type as V4SF
1644 (define_insn "vsx_xscvspdp"
1645   [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
1646         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1647                    UNSPEC_VSX_CVSPDP))]
1648   "VECTOR_UNIT_VSX_P (V4SFmode)"
1649   "xscvspdp %x0,%x1"
1650   [(set_attr "type" "fp")])
1652 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
1653 ;; format of scalars is actually DF.
1654 (define_insn "vsx_xscvdpsp_scalar"
1655   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1656         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
1657                      UNSPEC_VSX_CVSPDP))]
1658   "VECTOR_UNIT_VSX_P (V4SFmode)"
1659   "xscvdpsp %x0,%x1"
1660   [(set_attr "type" "fp")])
1662 ;; Same as vsx_xscvspdp, but use SF as the type
1663 (define_insn "vsx_xscvspdp_scalar2"
1664   [(set (match_operand:SF 0 "vsx_register_operand" "=f")
1665         (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1666                    UNSPEC_VSX_CVSPDP))]
1667   "VECTOR_UNIT_VSX_P (V4SFmode)"
1668   "xscvspdp %x0,%x1"
1669   [(set_attr "type" "fp")])
1671 ;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
1672 (define_insn "vsx_xscvdpspn"
1673   [(set (match_operand:V4SF 0 "vsx_register_operand" "=ww,?ww")
1674         (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wd,wa")]
1675                      UNSPEC_VSX_CVDPSPN))]
1676   "TARGET_XSCVDPSPN"
1677   "xscvdpspn %x0,%x1"
1678   [(set_attr "type" "fp")])
1680 (define_insn "vsx_xscvspdpn"
1681   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?ws")
1682         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
1683                    UNSPEC_VSX_CVSPDPN))]
1684   "TARGET_XSCVSPDPN"
1685   "xscvspdpn %x0,%x1"
1686   [(set_attr "type" "fp")])
1688 (define_insn "vsx_xscvdpspn_scalar"
1689   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa")
1690         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "ww,ww")]
1691                      UNSPEC_VSX_CVDPSPN))]
1692   "TARGET_XSCVDPSPN"
1693   "xscvdpspn %x0,%x1"
1694   [(set_attr "type" "fp")])
1696 ;; Used by direct move to move a SFmode value from GPR to VSX register
1697 (define_insn "vsx_xscvspdpn_directmove"
1698   [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
1699         (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
1700                    UNSPEC_VSX_CVSPDPN))]
1701   "TARGET_XSCVSPDPN"
1702   "xscvspdpn %x0,%x1"
1703   [(set_attr "type" "fp")])
1705 ;; Convert and scale (used by vec_ctf, vec_cts, vec_ctu for double/long long)
1707 (define_expand "vsx_xvcvsxddp_scale"
1708   [(match_operand:V2DF 0 "vsx_register_operand" "")
1709    (match_operand:V2DI 1 "vsx_register_operand" "")
1710    (match_operand:QI 2 "immediate_operand" "")]
1711   "VECTOR_UNIT_VSX_P (V2DFmode)"
1713   rtx op0 = operands[0];
1714   rtx op1 = operands[1];
1715   int scale = INTVAL(operands[2]);
1716   emit_insn (gen_vsx_xvcvsxddp (op0, op1));
1717   if (scale != 0)
1718     rs6000_scale_v2df (op0, op0, -scale);
1719   DONE;
1722 (define_insn "vsx_xvcvsxddp"
1723   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1724         (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1725                      UNSPEC_VSX_XVCVSXDDP))]
1726   "VECTOR_UNIT_VSX_P (V2DFmode)"
1727   "xvcvsxddp %x0,%x1"
1728   [(set_attr "type" "vecdouble")])
1730 (define_expand "vsx_xvcvuxddp_scale"
1731   [(match_operand:V2DF 0 "vsx_register_operand" "")
1732    (match_operand:V2DI 1 "vsx_register_operand" "")
1733    (match_operand:QI 2 "immediate_operand" "")]
1734   "VECTOR_UNIT_VSX_P (V2DFmode)"
1736   rtx op0 = operands[0];
1737   rtx op1 = operands[1];
1738   int scale = INTVAL(operands[2]);
1739   emit_insn (gen_vsx_xvcvuxddp (op0, op1));
1740   if (scale != 0)
1741     rs6000_scale_v2df (op0, op0, -scale);
1742   DONE;
1745 (define_insn "vsx_xvcvuxddp"
1746   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1747         (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1748                      UNSPEC_VSX_XVCVUXDDP))]
1749   "VECTOR_UNIT_VSX_P (V2DFmode)"
1750   "xvcvuxddp %x0,%x1"
1751   [(set_attr "type" "vecdouble")])
1753 (define_expand "vsx_xvcvdpsxds_scale"
1754   [(match_operand:V2DI 0 "vsx_register_operand" "")
1755    (match_operand:V2DF 1 "vsx_register_operand" "")
1756    (match_operand:QI 2 "immediate_operand" "")]
1757   "VECTOR_UNIT_VSX_P (V2DFmode)"
1759   rtx op0 = operands[0];
1760   rtx op1 = operands[1];
1761   rtx tmp;
1762   int scale = INTVAL (operands[2]);
1763   if (scale == 0)
1764     tmp = op1;
1765   else
1766     {
1767       tmp  = gen_reg_rtx (V2DFmode);
1768       rs6000_scale_v2df (tmp, op1, scale);
1769     }
1770   emit_insn (gen_vsx_xvcvdpsxds (op0, tmp));
1771   DONE;
1774 (define_insn "vsx_xvcvdpsxds"
1775   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1776         (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1777                      UNSPEC_VSX_XVCVDPSXDS))]
1778   "VECTOR_UNIT_VSX_P (V2DFmode)"
1779   "xvcvdpsxds %x0,%x1"
1780   [(set_attr "type" "vecdouble")])
1782 (define_expand "vsx_xvcvdpuxds_scale"
1783   [(match_operand:V2DI 0 "vsx_register_operand" "")
1784    (match_operand:V2DF 1 "vsx_register_operand" "")
1785    (match_operand:QI 2 "immediate_operand" "")]
1786   "VECTOR_UNIT_VSX_P (V2DFmode)"
1788   rtx op0 = operands[0];
1789   rtx op1 = operands[1];
1790   rtx tmp;
1791   int scale = INTVAL (operands[2]);
1792   if (scale == 0)
1793     tmp = op1;
1794   else
1795     {
1796       tmp = gen_reg_rtx (V2DFmode);
1797       rs6000_scale_v2df (tmp, op1, scale);
1798     }
1799   emit_insn (gen_vsx_xvcvdpuxds (op0, tmp));
1800   DONE;
1803 (define_insn "vsx_xvcvdpuxds"
1804   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1805         (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1806                      UNSPEC_VSX_XVCVDPUXDS))]
1807   "VECTOR_UNIT_VSX_P (V2DFmode)"
1808   "xvcvdpuxds %x0,%x1"
1809   [(set_attr "type" "vecdouble")])
1811 ;; Convert from 64-bit to 32-bit types
1812 ;; Note, favor the Altivec registers since the usual use of these instructions
1813 ;; is in vector converts and we need to use the Altivec vperm instruction.
1815 (define_insn "vsx_xvcvdpsxws"
1816   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1817         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1818                      UNSPEC_VSX_CVDPSXWS))]
1819   "VECTOR_UNIT_VSX_P (V2DFmode)"
1820   "xvcvdpsxws %x0,%x1"
1821   [(set_attr "type" "vecdouble")])
1823 (define_insn "vsx_xvcvdpuxws"
1824   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1825         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1826                      UNSPEC_VSX_CVDPUXWS))]
1827   "VECTOR_UNIT_VSX_P (V2DFmode)"
1828   "xvcvdpuxws %x0,%x1"
1829   [(set_attr "type" "vecdouble")])
1831 (define_insn "vsx_xvcvsxdsp"
1832   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1833         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1834                      UNSPEC_VSX_CVSXDSP))]
1835   "VECTOR_UNIT_VSX_P (V2DFmode)"
1836   "xvcvsxdsp %x0,%x1"
1837   [(set_attr "type" "vecfloat")])
1839 (define_insn "vsx_xvcvuxdsp"
1840   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1841         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1842                      UNSPEC_VSX_CVUXDSP))]
1843   "VECTOR_UNIT_VSX_P (V2DFmode)"
1844   "xvcvuxwdp %x0,%x1"
1845   [(set_attr "type" "vecdouble")])
1847 ;; Convert from 32-bit to 64-bit types
1848 (define_insn "vsx_xvcvsxwdp"
1849   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1850         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1851                      UNSPEC_VSX_CVSXWDP))]
1852   "VECTOR_UNIT_VSX_P (V2DFmode)"
1853   "xvcvsxwdp %x0,%x1"
1854   [(set_attr "type" "vecdouble")])
1856 (define_insn "vsx_xvcvuxwdp"
1857   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1858         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1859                      UNSPEC_VSX_CVUXWDP))]
1860   "VECTOR_UNIT_VSX_P (V2DFmode)"
1861   "xvcvuxwdp %x0,%x1"
1862   [(set_attr "type" "vecdouble")])
1864 (define_insn "vsx_xvcvspsxds"
1865   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1866         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1867                      UNSPEC_VSX_CVSPSXDS))]
1868   "VECTOR_UNIT_VSX_P (V2DFmode)"
1869   "xvcvspsxds %x0,%x1"
1870   [(set_attr "type" "vecdouble")])
1872 (define_insn "vsx_xvcvspuxds"
1873   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1874         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1875                      UNSPEC_VSX_CVSPUXDS))]
1876   "VECTOR_UNIT_VSX_P (V2DFmode)"
1877   "xvcvspuxds %x0,%x1"
1878   [(set_attr "type" "vecdouble")])
1880 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1881 ;; since the xvrdpiz instruction does not truncate the value if the floating
1882 ;; point value is < LONG_MIN or > LONG_MAX.
1883 (define_insn "*vsx_float_fix_v2df2"
1884   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1885         (float:V2DF
1886          (fix:V2DI
1887           (match_operand:V2DF 1 "vsx_register_operand" "wd,?wa"))))]
1888   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1889    && VECTOR_UNIT_VSX_P (V2DFmode) && flag_unsafe_math_optimizations
1890    && !flag_trapping_math && TARGET_FRIZ"
1891   "xvrdpiz %x0,%x1"
1892   [(set_attr "type" "vecdouble")
1893    (set_attr "fp_type" "fp_addsub_d")])
1896 ;; Permute operations
1898 ;; Build a V2DF/V2DI vector from two scalars
1899 (define_insn "vsx_concat_<mode>"
1900   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1901         (vec_concat:VSX_D
1902          (match_operand:<VS_scalar> 1 "vsx_register_operand" "<VS_64reg>,<VSa>")
1903          (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")))]
1904   "VECTOR_MEM_VSX_P (<MODE>mode)"
1906   if (BYTES_BIG_ENDIAN)
1907     return "xxpermdi %x0,%x1,%x2,0";
1908   else
1909     return "xxpermdi %x0,%x2,%x1,0";
1911   [(set_attr "type" "vecperm")])
1913 ;; Special purpose concat using xxpermdi to glue two single precision values
1914 ;; together, relying on the fact that internally scalar floats are represented
1915 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
1916 (define_insn "vsx_concat_v2sf"
1917   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1918         (unspec:V2DF
1919          [(match_operand:SF 1 "vsx_register_operand" "f,f")
1920           (match_operand:SF 2 "vsx_register_operand" "f,f")]
1921          UNSPEC_VSX_CONCAT))]
1922   "VECTOR_MEM_VSX_P (V2DFmode)"
1924   if (BYTES_BIG_ENDIAN)
1925     return "xxpermdi %x0,%x1,%x2,0";
1926   else
1927     return "xxpermdi %x0,%x2,%x1,0";
1929   [(set_attr "type" "vecperm")])
1931 ;; xxpermdi for little endian loads and stores.  We need several of
1932 ;; these since the form of the PARALLEL differs by mode.
1933 (define_insn "*vsx_xxpermdi2_le_<mode>"
1934   [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
1935         (vec_select:VSX_LE
1936           (match_operand:VSX_LE 1 "vsx_register_operand" "<VSa>")
1937           (parallel [(const_int 1) (const_int 0)])))]
1938   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
1939   "xxpermdi %x0,%x1,%x1,2"
1940   [(set_attr "type" "vecperm")])
1942 (define_insn "*vsx_xxpermdi4_le_<mode>"
1943   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
1944         (vec_select:VSX_W
1945           (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
1946           (parallel [(const_int 2) (const_int 3)
1947                      (const_int 0) (const_int 1)])))]
1948   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
1949   "xxpermdi %x0,%x1,%x1,2"
1950   [(set_attr "type" "vecperm")])
1952 (define_insn "*vsx_xxpermdi8_le_V8HI"
1953   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
1954         (vec_select:V8HI
1955           (match_operand:V8HI 1 "vsx_register_operand" "wa")
1956           (parallel [(const_int 4) (const_int 5)
1957                      (const_int 6) (const_int 7)
1958                      (const_int 0) (const_int 1)
1959                      (const_int 2) (const_int 3)])))]
1960   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
1961   "xxpermdi %x0,%x1,%x1,2"
1962   [(set_attr "type" "vecperm")])
1964 (define_insn "*vsx_xxpermdi16_le_V16QI"
1965   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
1966         (vec_select:V16QI
1967           (match_operand:V16QI 1 "vsx_register_operand" "wa")
1968           (parallel [(const_int 8) (const_int 9)
1969                      (const_int 10) (const_int 11)
1970                      (const_int 12) (const_int 13)
1971                      (const_int 14) (const_int 15)
1972                      (const_int 0) (const_int 1)
1973                      (const_int 2) (const_int 3)
1974                      (const_int 4) (const_int 5)
1975                      (const_int 6) (const_int 7)])))]
1976   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
1977   "xxpermdi %x0,%x1,%x1,2"
1978   [(set_attr "type" "vecperm")])
1980 ;; lxvd2x for little endian loads.  We need several of
1981 ;; these since the form of the PARALLEL differs by mode.
1982 (define_insn "*vsx_lxvd2x2_le_<mode>"
1983   [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
1984         (vec_select:VSX_LE
1985           (match_operand:VSX_LE 1 "memory_operand" "Z")
1986           (parallel [(const_int 1) (const_int 0)])))]
1987   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
1988   "lxvd2x %x0,%y1"
1989   [(set_attr "type" "vecload")])
1991 (define_insn "*vsx_lxvd2x4_le_<mode>"
1992   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
1993         (vec_select:VSX_W
1994           (match_operand:VSX_W 1 "memory_operand" "Z")
1995           (parallel [(const_int 2) (const_int 3)
1996                      (const_int 0) (const_int 1)])))]
1997   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
1998   "lxvd2x %x0,%y1"
1999   [(set_attr "type" "vecload")])
2001 (define_insn "*vsx_lxvd2x8_le_V8HI"
2002   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
2003         (vec_select:V8HI
2004           (match_operand:V8HI 1 "memory_operand" "Z")
2005           (parallel [(const_int 4) (const_int 5)
2006                      (const_int 6) (const_int 7)
2007                      (const_int 0) (const_int 1)
2008                      (const_int 2) (const_int 3)])))]
2009   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2010   "lxvd2x %x0,%y1"
2011   [(set_attr "type" "vecload")])
2013 (define_insn "*vsx_lxvd2x16_le_V16QI"
2014   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
2015         (vec_select:V16QI
2016           (match_operand:V16QI 1 "memory_operand" "Z")
2017           (parallel [(const_int 8) (const_int 9)
2018                      (const_int 10) (const_int 11)
2019                      (const_int 12) (const_int 13)
2020                      (const_int 14) (const_int 15)
2021                      (const_int 0) (const_int 1)
2022                      (const_int 2) (const_int 3)
2023                      (const_int 4) (const_int 5)
2024                      (const_int 6) (const_int 7)])))]
2025   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2026   "lxvd2x %x0,%y1"
2027   [(set_attr "type" "vecload")])
2029 ;; stxvd2x for little endian stores.  We need several of
2030 ;; these since the form of the PARALLEL differs by mode.
2031 (define_insn "*vsx_stxvd2x2_le_<mode>"
2032   [(set (match_operand:VSX_LE 0 "memory_operand" "=Z")
2033         (vec_select:VSX_LE
2034           (match_operand:VSX_LE 1 "vsx_register_operand" "<VSa>")
2035           (parallel [(const_int 1) (const_int 0)])))]
2036   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2037   "stxvd2x %x1,%y0"
2038   [(set_attr "type" "vecstore")])
2040 (define_insn "*vsx_stxvd2x4_le_<mode>"
2041   [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
2042         (vec_select:VSX_W
2043           (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2044           (parallel [(const_int 2) (const_int 3)
2045                      (const_int 0) (const_int 1)])))]
2046   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2047   "stxvd2x %x1,%y0"
2048   [(set_attr "type" "vecstore")])
2050 (define_insn "*vsx_stxvd2x8_le_V8HI"
2051   [(set (match_operand:V8HI 0 "memory_operand" "=Z")
2052         (vec_select:V8HI
2053           (match_operand:V8HI 1 "vsx_register_operand" "wa")
2054           (parallel [(const_int 4) (const_int 5)
2055                      (const_int 6) (const_int 7)
2056                      (const_int 0) (const_int 1)
2057                      (const_int 2) (const_int 3)])))]
2058   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2059   "stxvd2x %x1,%y0"
2060   [(set_attr "type" "vecstore")])
2062 (define_insn "*vsx_stxvd2x16_le_V16QI"
2063   [(set (match_operand:V16QI 0 "memory_operand" "=Z")
2064         (vec_select:V16QI
2065           (match_operand:V16QI 1 "vsx_register_operand" "wa")
2066           (parallel [(const_int 8) (const_int 9)
2067                      (const_int 10) (const_int 11)
2068                      (const_int 12) (const_int 13)
2069                      (const_int 14) (const_int 15)
2070                      (const_int 0) (const_int 1)
2071                      (const_int 2) (const_int 3)
2072                      (const_int 4) (const_int 5)
2073                      (const_int 6) (const_int 7)])))]
2074   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2075   "stxvd2x %x1,%y0"
2076   [(set_attr "type" "vecstore")])
2078 ;; Convert a TImode value into V1TImode
2079 (define_expand "vsx_set_v1ti"
2080   [(match_operand:V1TI 0 "nonimmediate_operand" "")
2081    (match_operand:V1TI 1 "nonimmediate_operand" "")
2082    (match_operand:TI 2 "input_operand" "")
2083    (match_operand:QI 3 "u5bit_cint_operand" "")]
2084   "VECTOR_MEM_VSX_P (V1TImode)"
2086   if (operands[3] != const0_rtx)
2087     gcc_unreachable ();
2089   emit_move_insn (operands[0], gen_lowpart (V1TImode, operands[1]));
2090   DONE;
2093 ;; Set the element of a V2DI/VD2F mode
2094 (define_insn "vsx_set_<mode>"
2095   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?<VSa>")
2096         (unspec:VSX_D
2097          [(match_operand:VSX_D 1 "vsx_register_operand" "wd,<VSa>")
2098           (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")
2099           (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
2100          UNSPEC_VSX_SET))]
2101   "VECTOR_MEM_VSX_P (<MODE>mode)"
2103   int idx_first = BYTES_BIG_ENDIAN ? 0 : 1;
2104   if (INTVAL (operands[3]) == idx_first)
2105     return \"xxpermdi %x0,%x2,%x1,1\";
2106   else if (INTVAL (operands[3]) == 1 - idx_first)
2107     return \"xxpermdi %x0,%x1,%x2,0\";
2108   else
2109     gcc_unreachable ();
2111   [(set_attr "type" "vecperm")])
2113 ;; Extract a DF/DI element from V2DF/V2DI
2114 ;; Optimize cases were we can do a simple or direct move.
2115 ;; Or see if we can avoid doing the move at all
2117 ;; There are some unresolved problems with reload that show up if an Altivec
2118 ;; register was picked.  Limit the scalar value to FPRs for now.
2120 (define_insn "vsx_extract_<mode>"
2121   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand"
2122             "=d,     wm,      wo,    d")
2124         (vec_select:<VS_scalar>
2125          (match_operand:VSX_D 1 "gpc_reg_operand"
2126             "<VSa>, <VSa>,  <VSa>,  <VSa>")
2128          (parallel
2129           [(match_operand:QI 2 "const_0_to_1_operand"
2130             "wD,    wD,     wL,     n")])))]
2131   "VECTOR_MEM_VSX_P (<MODE>mode)"
2133   int element = INTVAL (operands[2]);
2134   int op0_regno = REGNO (operands[0]);
2135   int op1_regno = REGNO (operands[1]);
2136   int fldDM;
2138   gcc_assert (IN_RANGE (element, 0, 1));
2139   gcc_assert (VSX_REGNO_P (op1_regno));
2141   if (element == VECTOR_ELEMENT_SCALAR_64BIT)
2142     {
2143       if (op0_regno == op1_regno)
2144         return ASM_COMMENT_START " vec_extract to same register";
2146       else if (INT_REGNO_P (op0_regno) && TARGET_DIRECT_MOVE
2147                && TARGET_POWERPC64)
2148         return "mfvsrd %0,%x1";
2150       else if (FP_REGNO_P (op0_regno) && FP_REGNO_P (op1_regno))
2151         return "fmr %0,%1";
2153       else if (VSX_REGNO_P (op0_regno))
2154         return "xxlor %x0,%x1,%x1";
2156       else
2157         gcc_unreachable ();
2158     }
2160   else if (element == VECTOR_ELEMENT_MFVSRLD_64BIT && INT_REGNO_P (op0_regno)
2161            && TARGET_P9_VECTOR && TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
2162     return "mfvsrdl %0,%x1";
2164   else if (VSX_REGNO_P (op0_regno))
2165     {
2166       fldDM = element << 1;
2167       if (!BYTES_BIG_ENDIAN)
2168         fldDM = 3 - fldDM;
2169       operands[3] = GEN_INT (fldDM);
2170       return "xxpermdi %x0,%x1,%x1,%3";
2171     }
2173   else
2174     gcc_unreachable ();
2176   [(set_attr "type" "veclogical,mftgpr,mftgpr,vecperm")])
2178 ;; Optimize extracting a single scalar element from memory if the scalar is in
2179 ;; the correct location to use a single load.
2180 (define_insn "*vsx_extract_<mode>_load"
2181   [(set (match_operand:<VS_scalar> 0 "register_operand" "=d,wv,wr")
2182         (vec_select:<VS_scalar>
2183          (match_operand:VSX_D 1 "memory_operand" "m,Z,m")
2184          (parallel [(const_int 0)])))]
2185   "VECTOR_MEM_VSX_P (<MODE>mode)"
2186   "@
2187    lfd%U1%X1 %0,%1
2188    lxsd%U1x %x0,%y1
2189    ld%U1%X1 %0,%1"
2190   [(set_attr "type" "fpload,fpload,load")
2191    (set_attr "length" "4")])
2193 ;; Optimize storing a single scalar element that is the right location to
2194 ;; memory
2195 (define_insn "*vsx_extract_<mode>_store"
2196   [(set (match_operand:<VS_scalar> 0 "memory_operand" "=m,Z,?Z")
2197         (vec_select:<VS_scalar>
2198          (match_operand:VSX_D 1 "register_operand" "d,wd,<VSa>")
2199          (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))]
2200   "VECTOR_MEM_VSX_P (<MODE>mode)"
2201   "@
2202    stfd%U0%X0 %1,%0
2203    stxsd%U0x %x1,%y0
2204    stxsd%U0x %x1,%y0"
2205   [(set_attr "type" "fpstore")
2206    (set_attr "length" "4")])
2208 ;; Extract a SF element from V4SF
2209 (define_insn_and_split "vsx_extract_v4sf"
2210   [(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
2211         (vec_select:SF
2212          (match_operand:V4SF 1 "vsx_register_operand" "wa,wa")
2213          (parallel [(match_operand:QI 2 "u5bit_cint_operand" "O,i")])))
2214    (clobber (match_scratch:V4SF 3 "=X,0"))]
2215   "VECTOR_UNIT_VSX_P (V4SFmode)"
2216   "@
2217    xscvspdp %x0,%x1
2218    #"
2219   ""
2220   [(const_int 0)]
2221   "
2223   rtx op0 = operands[0];
2224   rtx op1 = operands[1];
2225   rtx op2 = operands[2];
2226   rtx op3 = operands[3];
2227   rtx tmp;
2228   HOST_WIDE_INT ele = BYTES_BIG_ENDIAN ? INTVAL (op2) : 3 - INTVAL (op2);
2230   if (ele == 0)
2231     tmp = op1;
2232   else
2233     {
2234       if (GET_CODE (op3) == SCRATCH)
2235         op3 = gen_reg_rtx (V4SFmode);
2236       emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, GEN_INT (ele)));
2237       tmp = op3;
2238     }
2239   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
2240   DONE;
2242   [(set_attr "length" "4,8")
2243    (set_attr "type" "fp")])
2245 ;; Expand the builtin form of xxpermdi to canonical rtl.
2246 (define_expand "vsx_xxpermdi_<mode>"
2247   [(match_operand:VSX_L 0 "vsx_register_operand" "")
2248    (match_operand:VSX_L 1 "vsx_register_operand" "")
2249    (match_operand:VSX_L 2 "vsx_register_operand" "")
2250    (match_operand:QI 3 "u5bit_cint_operand" "")]
2251   "VECTOR_MEM_VSX_P (<MODE>mode)"
2253   rtx target = operands[0];
2254   rtx op0 = operands[1];
2255   rtx op1 = operands[2];
2256   int mask = INTVAL (operands[3]);
2257   rtx perm0 = GEN_INT ((mask >> 1) & 1);
2258   rtx perm1 = GEN_INT ((mask & 1) + 2);
2259   rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2261   if (<MODE>mode == V2DFmode)
2262     gen = gen_vsx_xxpermdi2_v2df_1;
2263   else
2264     {
2265       gen = gen_vsx_xxpermdi2_v2di_1;
2266       if (<MODE>mode != V2DImode)
2267         {
2268           target = gen_lowpart (V2DImode, target);
2269           op0 = gen_lowpart (V2DImode, op0);
2270           op1 = gen_lowpart (V2DImode, op1);
2271         }
2272     }
2273   /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
2274      transformation we don't want; it is necessary for
2275      rs6000_expand_vec_perm_const_1 but not for this use.  So we
2276      prepare for that by reversing the transformation here.  */
2277   if (BYTES_BIG_ENDIAN)
2278     emit_insn (gen (target, op0, op1, perm0, perm1));
2279   else
2280     {
2281       rtx p0 = GEN_INT (3 - INTVAL (perm1));
2282       rtx p1 = GEN_INT (3 - INTVAL (perm0));
2283       emit_insn (gen (target, op1, op0, p0, p1));
2284     }
2285   DONE;
2288 (define_insn "vsx_xxpermdi2_<mode>_1"
2289   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
2290         (vec_select:VSX_D
2291           (vec_concat:<VS_double>
2292             (match_operand:VSX_D 1 "vsx_register_operand" "wd")
2293             (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
2294           (parallel [(match_operand 3 "const_0_to_1_operand" "")
2295                      (match_operand 4 "const_2_to_3_operand" "")])))]
2296   "VECTOR_MEM_VSX_P (<MODE>mode)"
2298   int op3, op4, mask;
2300   /* For little endian, swap operands and invert/swap selectors
2301      to get the correct xxpermdi.  The operand swap sets up the
2302      inputs as a little endian array.  The selectors are swapped
2303      because they are defined to use big endian ordering.  The
2304      selectors are inverted to get the correct doublewords for
2305      little endian ordering.  */
2306   if (BYTES_BIG_ENDIAN)
2307     {
2308       op3 = INTVAL (operands[3]);
2309       op4 = INTVAL (operands[4]);
2310     }
2311   else
2312     {
2313       op3 = 3 - INTVAL (operands[4]);
2314       op4 = 3 - INTVAL (operands[3]);
2315     }
2317   mask = (op3 << 1) | (op4 - 2);
2318   operands[3] = GEN_INT (mask);
2320   if (BYTES_BIG_ENDIAN)
2321     return "xxpermdi %x0,%x1,%x2,%3";
2322   else
2323     return "xxpermdi %x0,%x2,%x1,%3";
2325   [(set_attr "type" "vecperm")])
2327 (define_expand "vec_perm_const<mode>"
2328   [(match_operand:VSX_D 0 "vsx_register_operand" "")
2329    (match_operand:VSX_D 1 "vsx_register_operand" "")
2330    (match_operand:VSX_D 2 "vsx_register_operand" "")
2331    (match_operand:V2DI  3 "" "")]
2332   "VECTOR_MEM_VSX_P (<MODE>mode)"
2334   if (rs6000_expand_vec_perm_const (operands))
2335     DONE;
2336   else
2337     FAIL;
2340 ;; Extraction of a single element in a small integer vector.  None of the small
2341 ;; types are currently allowed in a vector register, so we extract to a DImode
2342 ;; and either do a direct move or store.
2343 (define_insn_and_split  "vsx_extract_<mode>"
2344   [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r,Z")
2345         (vec_select:<VS_scalar>
2346          (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>,<VSX_EX>")
2347          (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
2348    (clobber (match_scratch:DI 3 "=<VSX_EX>,<VSX_EX>"))]
2349   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
2350   "#"
2351   "&& (reload_completed || MEM_P (operands[0]))"
2352   [(const_int 0)]
2354   rtx dest = operands[0];
2355   rtx src = operands[1];
2356   rtx element = operands[2];
2357   rtx di_tmp = operands[3];
2359   if (GET_CODE (di_tmp) == SCRATCH)
2360     di_tmp = gen_reg_rtx (DImode);
2362   emit_insn (gen_vsx_extract_<mode>_di (di_tmp, src, element));
2364   if (REG_P (dest))
2365     emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)), di_tmp);
2366   else if (SUBREG_P (dest))
2367     emit_move_insn (gen_rtx_REG (DImode, subreg_regno (dest)), di_tmp);
2368   else if (MEM_P (operands[0]))
2369     {
2370       if (can_create_pseudo_p ())
2371         dest = rs6000_address_for_fpconvert (dest);
2373       if (<MODE>mode == V16QImode)
2374         emit_insn (gen_p9_stxsibx (dest, di_tmp));
2375       else if (<MODE>mode == V8HImode)
2376         emit_insn (gen_p9_stxsihx (dest, di_tmp));
2377       else if (<MODE>mode == V4SImode)
2378         emit_insn (gen_stfiwx (dest, di_tmp));
2379       else
2380         gcc_unreachable ();
2381     }
2382   else
2383     gcc_unreachable ();
2385   DONE;
2387   [(set_attr "type" "vecsimple,fpstore")])
2389 (define_insn  "vsx_extract_<mode>_di"
2390   [(set (match_operand:DI 0 "gpc_reg_operand" "=<VSX_EX>")
2391         (zero_extend:DI
2392          (vec_select:<VS_scalar>
2393           (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>")
2394           (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")]))))]
2395   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
2397   int element = INTVAL (operands[2]);
2398   int unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
2399   int offset = ((VECTOR_ELT_ORDER_BIG)
2400                 ? unit_size * element
2401                 : unit_size * (GET_MODE_NUNITS (<MODE>mode) - 1 - element));
2403   operands[2] = GEN_INT (offset);
2404   if (unit_size == 4)
2405     return "xxextractuw %x0,%x1,%2";
2406   else
2407     return "vextractu<wd> %0,%1,%2";
2409   [(set_attr "type" "vecsimple")])
2412 ;; Expanders for builtins
2413 (define_expand "vsx_mergel_<mode>"
2414   [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
2415    (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
2416    (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
2417   "VECTOR_MEM_VSX_P (<MODE>mode)"
2419   rtvec v;
2420   rtx x;
2422   /* Special handling for LE with -maltivec=be.  */
2423   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2424     {
2425       v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
2426       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
2427     }
2428   else
2429     {
2430       v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
2431       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
2432     }
2434   x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
2435   emit_insn (gen_rtx_SET (operands[0], x));
2436   DONE;
2439 (define_expand "vsx_mergeh_<mode>"
2440   [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
2441    (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
2442    (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
2443   "VECTOR_MEM_VSX_P (<MODE>mode)"
2445   rtvec v;
2446   rtx x;
2448   /* Special handling for LE with -maltivec=be.  */
2449   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2450     {
2451       v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
2452       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
2453     }
2454   else
2455     {
2456       v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
2457       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
2458     }
2460   x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
2461   emit_insn (gen_rtx_SET (operands[0], x));
2462   DONE;
2465 ;; V2DF/V2DI splat
2466 (define_insn "vsx_splat_<mode>"
2467   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>,<VSa>,we")
2468         (vec_duplicate:VSX_D
2469          (match_operand:<VS_scalar> 1 "splat_input_operand" "<VS_64reg>,Z,b")))]
2470   "VECTOR_MEM_VSX_P (<MODE>mode)"
2471   "@
2472    xxpermdi %x0,%x1,%x1,0
2473    lxvdsx %x0,%y1
2474    mtvsrdd %x0,%1,%1"
2475   [(set_attr "type" "vecperm,vecload,mftgpr")])
2477 ;; V4SI splat (ISA 3.0)
2478 ;; When SI's are allowed in VSX registers, add XXSPLTW support
2479 (define_expand "vsx_splat_<mode>"
2480   [(set (match_operand:VSX_W 0 "vsx_register_operand" "")
2481         (vec_duplicate:VSX_W
2482          (match_operand:<VS_scalar> 1 "splat_input_operand" "")))]
2483   "TARGET_P9_VECTOR"
2485   if (MEM_P (operands[1]))
2486     operands[1] = rs6000_address_for_fpconvert (operands[1]);
2487   else if (!REG_P (operands[1]))
2488     operands[1] = force_reg (<VS_scalar>mode, operands[1]);
2491 (define_insn "*vsx_splat_v4si_internal"
2492   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,wa")
2493         (vec_duplicate:V4SI
2494          (match_operand:SI 1 "splat_input_operand" "r,Z")))]
2495   "TARGET_P9_VECTOR"
2496   "@
2497    mtvsrws %x0,%1
2498    lxvwsx %x0,%y1"
2499   [(set_attr "type" "mftgpr,vecload")])
2501 ;; V4SF splat (ISA 3.0)
2502 (define_insn_and_split "*vsx_splat_v4sf_internal"
2503   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,wa")
2504         (vec_duplicate:V4SF
2505          (match_operand:SF 1 "splat_input_operand" "Z,wy,r")))]
2506   "TARGET_P9_VECTOR"
2507   "@
2508    lxvwsx %x0,%y1
2509    #
2510    mtvsrws %x0,%1"
2511   "&& reload_completed && vsx_register_operand (operands[1], SFmode)"
2512   [(set (match_dup 0)
2513         (unspec:V4SF [(match_dup 1)] UNSPEC_VSX_CVDPSPN))
2514    (set (match_dup 0)
2515         (unspec:V4SF [(match_dup 0)
2516                       (const_int 0)] UNSPEC_VSX_XXSPLTW))]
2517   ""
2518   [(set_attr "type" "vecload,vecperm,mftgpr")
2519    (set_attr "length" "4,8,4")])
2521 ;; V4SF/V4SI splat from a vector element
2522 (define_insn "vsx_xxspltw_<mode>"
2523   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2524         (vec_duplicate:VSX_W
2525          (vec_select:<VS_scalar>
2526           (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2527           (parallel
2528            [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
2529   "VECTOR_MEM_VSX_P (<MODE>mode)"
2531   if (!BYTES_BIG_ENDIAN)
2532     operands[2] = GEN_INT (3 - INTVAL (operands[2]));
2534   return "xxspltw %x0,%x1,%2";
2536   [(set_attr "type" "vecperm")])
2538 (define_insn "vsx_xxspltw_<mode>_direct"
2539   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2540         (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2541                        (match_operand:QI 2 "u5bit_cint_operand" "i,i")]
2542                       UNSPEC_VSX_XXSPLTW))]
2543   "VECTOR_MEM_VSX_P (<MODE>mode)"
2544   "xxspltw %x0,%x1,%2"
2545   [(set_attr "type" "vecperm")])
2547 ;; V2DF/V2DI splat for use by vec_splat builtin
2548 (define_insn "vsx_xxspltd_<mode>"
2549   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
2550         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa")
2551                        (match_operand:QI 2 "u5bit_cint_operand" "i")]
2552                       UNSPEC_VSX_XXSPLTD))]
2553   "VECTOR_MEM_VSX_P (<MODE>mode)"
2555   if ((VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 0)
2556       || (!VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 1))
2557     return "xxpermdi %x0,%x1,%x1,0";
2558   else
2559     return "xxpermdi %x0,%x1,%x1,3";
2561   [(set_attr "type" "vecperm")])
2563 ;; V4SF/V4SI interleave
2564 (define_insn "vsx_xxmrghw_<mode>"
2565   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2566         (vec_select:VSX_W
2567           (vec_concat:<VS_double>
2568             (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2569             (match_operand:VSX_W 2 "vsx_register_operand" "wf,<VSa>"))
2570           (parallel [(const_int 0) (const_int 4)
2571                      (const_int 1) (const_int 5)])))]
2572   "VECTOR_MEM_VSX_P (<MODE>mode)"
2574   if (BYTES_BIG_ENDIAN)
2575     return "xxmrghw %x0,%x1,%x2";
2576   else
2577     return "xxmrglw %x0,%x2,%x1";
2579   [(set_attr "type" "vecperm")])
2581 (define_insn "vsx_xxmrglw_<mode>"
2582   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2583         (vec_select:VSX_W
2584           (vec_concat:<VS_double>
2585             (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2586             (match_operand:VSX_W 2 "vsx_register_operand" "wf,?<VSa>"))
2587           (parallel [(const_int 2) (const_int 6)
2588                      (const_int 3) (const_int 7)])))]
2589   "VECTOR_MEM_VSX_P (<MODE>mode)"
2591   if (BYTES_BIG_ENDIAN)
2592     return "xxmrglw %x0,%x1,%x2";
2593   else
2594     return "xxmrghw %x0,%x2,%x1";
2596   [(set_attr "type" "vecperm")])
2598 ;; Shift left double by word immediate
2599 (define_insn "vsx_xxsldwi_<mode>"
2600   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSa>")
2601         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "<VSa>")
2602                        (match_operand:VSX_L 2 "vsx_register_operand" "<VSa>")
2603                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
2604                       UNSPEC_VSX_SLDWI))]
2605   "VECTOR_MEM_VSX_P (<MODE>mode)"
2606   "xxsldwi %x0,%x1,%x2,%3"
2607   [(set_attr "type" "vecperm")])
2610 ;; Vector reduction insns and splitters
2612 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
2613   [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
2614         (VEC_reduc:V2DF
2615          (vec_concat:V2DF
2616           (vec_select:DF
2617            (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
2618            (parallel [(const_int 1)]))
2619           (vec_select:DF
2620            (match_dup 1)
2621            (parallel [(const_int 0)])))
2622          (match_dup 1)))
2623    (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
2624   "VECTOR_UNIT_VSX_P (V2DFmode)"
2625   "#"
2626   ""
2627   [(const_int 0)]
2628   "
2630   rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
2631              ? gen_reg_rtx (V2DFmode)
2632              : operands[2];
2633   emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
2634   emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
2635   DONE;
2637   [(set_attr "length" "8")
2638    (set_attr "type" "veccomplex")])
2640 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
2641   [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
2642         (VEC_reduc:V4SF
2643          (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
2644          (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
2645    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
2646    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
2647   "VECTOR_UNIT_VSX_P (V4SFmode)"
2648   "#"
2649   ""
2650   [(const_int 0)]
2651   "
2653   rtx op0 = operands[0];
2654   rtx op1 = operands[1];
2655   rtx tmp2, tmp3, tmp4;
2657   if (can_create_pseudo_p ())
2658     {
2659       tmp2 = gen_reg_rtx (V4SFmode);
2660       tmp3 = gen_reg_rtx (V4SFmode);
2661       tmp4 = gen_reg_rtx (V4SFmode);
2662     }
2663   else
2664     {
2665       tmp2 = operands[2];
2666       tmp3 = operands[3];
2667       tmp4 = tmp2;
2668     }
2670   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
2671   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
2672   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
2673   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
2674   DONE;
2676   [(set_attr "length" "16")
2677    (set_attr "type" "veccomplex")])
2679 ;; Combiner patterns with the vector reduction patterns that knows we can get
2680 ;; to the top element of the V2DF array without doing an extract.
2682 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
2683   [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws")
2684         (vec_select:DF
2685          (VEC_reduc:V2DF
2686           (vec_concat:V2DF
2687            (vec_select:DF
2688             (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
2689             (parallel [(const_int 1)]))
2690            (vec_select:DF
2691             (match_dup 1)
2692             (parallel [(const_int 0)])))
2693           (match_dup 1))
2694          (parallel [(const_int 1)])))
2695    (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
2696   "VECTOR_UNIT_VSX_P (V2DFmode)"
2697   "#"
2698   ""
2699   [(const_int 0)]
2700   "
2702   rtx hi = gen_highpart (DFmode, operands[1]);
2703   rtx lo = (GET_CODE (operands[2]) == SCRATCH)
2704             ? gen_reg_rtx (DFmode)
2705             : operands[2];
2707   emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
2708   emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
2709   DONE;
2711   [(set_attr "length" "8")
2712    (set_attr "type" "veccomplex")])
2714 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
2715   [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
2716         (vec_select:SF
2717          (VEC_reduc:V4SF
2718           (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
2719           (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
2720          (parallel [(const_int 3)])))
2721    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
2722    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
2723    (clobber (match_scratch:V4SF 4 "=0,0"))]
2724   "VECTOR_UNIT_VSX_P (V4SFmode)"
2725   "#"
2726   ""
2727   [(const_int 0)]
2728   "
2730   rtx op0 = operands[0];
2731   rtx op1 = operands[1];
2732   rtx tmp2, tmp3, tmp4, tmp5;
2734   if (can_create_pseudo_p ())
2735     {
2736       tmp2 = gen_reg_rtx (V4SFmode);
2737       tmp3 = gen_reg_rtx (V4SFmode);
2738       tmp4 = gen_reg_rtx (V4SFmode);
2739       tmp5 = gen_reg_rtx (V4SFmode);
2740     }
2741   else
2742     {
2743       tmp2 = operands[2];
2744       tmp3 = operands[3];
2745       tmp4 = tmp2;
2746       tmp5 = operands[4];
2747     }
2749   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
2750   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
2751   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
2752   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
2753   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
2754   DONE;
2756   [(set_attr "length" "20")
2757    (set_attr "type" "veccomplex")])
2760 ;; Power8 Vector fusion.  The fused ops must be physically adjacent.
2761 (define_peephole
2762   [(set (match_operand:P 0 "base_reg_operand" "")
2763         (match_operand:P 1 "short_cint_operand" ""))
2764    (set (match_operand:VSX_M 2 "vsx_register_operand" "")
2765         (mem:VSX_M (plus:P (match_dup 0)
2766                            (match_operand:P 3 "int_reg_operand" ""))))]
2767   "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
2768   "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"  
2769   [(set_attr "length" "8")
2770    (set_attr "type" "vecload")])
2772 (define_peephole
2773   [(set (match_operand:P 0 "base_reg_operand" "")
2774         (match_operand:P 1 "short_cint_operand" ""))
2775    (set (match_operand:VSX_M 2 "vsx_register_operand" "")
2776         (mem:VSX_M (plus:P (match_operand:P 3 "int_reg_operand" "")
2777                            (match_dup 0))))]
2778   "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
2779   "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"  
2780   [(set_attr "length" "8")
2781    (set_attr "type" "vecload")])
2784 ;; ISA 3.0 vector extend sign support
2786 (define_insn "vsx_sign_extend_qi_<mode>"
2787   [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
2788         (unspec:VSINT_84
2789          [(match_operand:V16QI 1 "vsx_register_operand" "v")]
2790          UNSPEC_VSX_SIGN_EXTEND))]
2791   "TARGET_P9_VECTOR"
2792   "vextsb2<wd> %0,%1"
2793   [(set_attr "type" "vecexts")])
2795 (define_insn "vsx_sign_extend_hi_<mode>"
2796   [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
2797         (unspec:VSINT_84
2798          [(match_operand:V8HI 1 "vsx_register_operand" "v")]
2799          UNSPEC_VSX_SIGN_EXTEND))]
2800   "TARGET_P9_VECTOR"
2801   "vextsh2<wd> %0,%1"
2802   [(set_attr "type" "vecexts")])
2804 (define_insn "*vsx_sign_extend_si_v2di"
2805   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v")
2806         (unspec:V2DI [(match_operand:V4SI 1 "vsx_register_operand" "v")]
2807                      UNSPEC_VSX_SIGN_EXTEND))]
2808   "TARGET_P9_VECTOR"
2809   "vextsw2d %0,%1"
2810   [(set_attr "type" "vecexts")])
2813 ;; ISA 3.0 memory operations
2814 (define_insn "p9_lxsi<wd>zx"
2815   [(set (match_operand:DI 0 "vsx_register_operand" "=wi")
2816         (unspec:DI [(zero_extend:DI
2817                      (match_operand:QHI 1 "indexed_or_indirect_operand" "Z"))]
2818                    UNSPEC_P9_MEMORY))]
2819   "TARGET_P9_VECTOR"
2820   "lxsi<wd>zx %x0,%y1"
2821   [(set_attr "type" "fpload")])
2823 (define_insn "p9_stxsi<wd>x"
2824   [(set (match_operand:QHI 0 "reg_or_indexed_operand" "=r,Z")
2825         (unspec:QHI [(match_operand:DI 1 "vsx_register_operand" "wi,wi")]
2826                     UNSPEC_P9_MEMORY))]
2827   "TARGET_P9_VECTOR"
2828   "@
2829    mfvsrd %0,%x1
2830    stxsi<wd>x %x1,%y0"
2831   [(set_attr "type" "mffgpr,fpstore")])