[gcc]
[official-gcc.git] / gcc / config / rs6000 / vsx.md
blob18f3e86e29f237b4d6a92911271208645b0e7e37
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 comparison types
22 (define_code_iterator CMP_TEST [eq lt gt unordered])
24 ;; Iterator for both scalar and vector floating point types supported by VSX
25 (define_mode_iterator VSX_B [DF V4SF V2DF])
27 ;; Iterator for the 2 64-bit vector types
28 (define_mode_iterator VSX_D [V2DF V2DI])
30 ;; Iterator for the 2 64-bit vector types + 128-bit types that are loaded with
31 ;; lxvd2x to properly handle swapping words on little endian
32 (define_mode_iterator VSX_LE [V2DF V2DI V1TI])
34 ;; Mode iterator to handle swapping words on little endian for the 128-bit
35 ;; types that goes in a single vector register.
36 (define_mode_iterator VSX_LE_128 [(KF   "FLOAT128_VECTOR_P (KFmode)")
37                                   (TF   "FLOAT128_VECTOR_P (TFmode)")
38                                   (TI   "TARGET_VSX_TIMODE")])
40 ;; Iterator for the 2 32-bit vector types
41 (define_mode_iterator VSX_W [V4SF V4SI])
43 ;; Iterator for the DF types
44 (define_mode_iterator VSX_DF [V2DF DF])
46 ;; Iterator for vector floating point types supported by VSX
47 (define_mode_iterator VSX_F [V4SF V2DF])
49 ;; Iterator for logical types supported by VSX
50 (define_mode_iterator VSX_L [V16QI
51                              V8HI
52                              V4SI
53                              V2DI
54                              V4SF
55                              V2DF
56                              V1TI
57                              TI
58                              (KF        "FLOAT128_VECTOR_P (KFmode)")
59                              (TF        "FLOAT128_VECTOR_P (TFmode)")])
61 ;; Iterator for memory moves.
62 (define_mode_iterator VSX_M [V16QI
63                              V8HI
64                              V4SI
65                              V2DI
66                              V4SF
67                              V2DF
68                              V1TI
69                              (KF        "FLOAT128_VECTOR_P (KFmode)")
70                              (TF        "FLOAT128_VECTOR_P (TFmode)")
71                              (TI        "TARGET_VSX_TIMODE")])
73 ;; Map into the appropriate load/store name based on the type
74 (define_mode_attr VSm  [(V16QI "vw4")
75                         (V8HI  "vw4")
76                         (V4SI  "vw4")
77                         (V4SF  "vw4")
78                         (V2DF  "vd2")
79                         (V2DI  "vd2")
80                         (DF    "d")
81                         (TF    "vd2")
82                         (KF    "vd2")
83                         (V1TI  "vd2")
84                         (TI    "vd2")])
86 ;; Map into the appropriate suffix based on the type
87 (define_mode_attr VSs   [(V16QI "sp")
88                          (V8HI  "sp")
89                          (V4SI  "sp")
90                          (V4SF  "sp")
91                          (V2DF  "dp")
92                          (V2DI  "dp")
93                          (DF    "dp")
94                          (SF    "sp")
95                          (TF    "dp")
96                          (KF    "dp")
97                          (V1TI  "dp")
98                          (TI    "dp")])
100 ;; Map the register class used
101 (define_mode_attr VSr   [(V16QI "v")
102                          (V8HI  "v")
103                          (V4SI  "v")
104                          (V4SF  "wf")
105                          (V2DI  "wd")
106                          (V2DF  "wd")
107                          (DI    "wi")
108                          (DF    "ws")
109                          (SF    "ww")
110                          (TF    "wp")
111                          (KF    "wq")
112                          (V1TI  "v")
113                          (TI    "wt")])
115 ;; Map the register class used for float<->int conversions (floating point side)
116 ;; VSr2 is the preferred register class, VSr3 is any register class that will
117 ;; hold the data
118 (define_mode_attr VSr2  [(V2DF  "wd")
119                          (V4SF  "wf")
120                          (DF    "ws")
121                          (SF    "ww")
122                          (DI    "wi")])
124 (define_mode_attr VSr3  [(V2DF  "wa")
125                          (V4SF  "wa")
126                          (DF    "ws")
127                          (SF    "ww")
128                          (DI    "wi")])
130 ;; Map the register class for sp<->dp float conversions, destination
131 (define_mode_attr VSr4  [(SF    "ws")
132                          (DF    "f")
133                          (V2DF  "wd")
134                          (V4SF  "v")])
136 ;; Map the register class for sp<->dp float conversions, source
137 (define_mode_attr VSr5  [(SF    "ws")
138                          (DF    "f")
139                          (V2DF  "v")
140                          (V4SF  "wd")])
142 ;; The VSX register class that a type can occupy, even if it is not the
143 ;; preferred register class (VSr is the preferred register class that will get
144 ;; allocated first).
145 (define_mode_attr VSa   [(V16QI "wa")
146                          (V8HI  "wa")
147                          (V4SI  "wa")
148                          (V4SF  "wa")
149                          (V2DI  "wa")
150                          (V2DF  "wa")
151                          (DI    "wi")
152                          (DF    "ws")
153                          (SF    "ww")
154                          (V1TI  "wa")
155                          (TI    "wt")
156                          (TF    "wp")
157                          (KF    "wq")])
159 ;; Same size integer type for floating point data
160 (define_mode_attr VSi [(V4SF  "v4si")
161                        (V2DF  "v2di")
162                        (DF    "di")])
164 (define_mode_attr VSI [(V4SF  "V4SI")
165                        (V2DF  "V2DI")
166                        (DF    "DI")])
168 ;; Word size for same size conversion
169 (define_mode_attr VSc [(V4SF "w")
170                        (V2DF "d")
171                        (DF   "d")])
173 ;; Map into either s or v, depending on whether this is a scalar or vector
174 ;; operation
175 (define_mode_attr VSv   [(V16QI "v")
176                          (V8HI  "v")
177                          (V4SI  "v")
178                          (V4SF  "v")
179                          (V2DI  "v")
180                          (V2DF  "v")
181                          (V1TI  "v")
182                          (DF    "s")
183                          (KF    "v")])
185 ;; Appropriate type for add ops (and other simple FP ops)
186 (define_mode_attr VStype_simple [(V2DF "vecdouble")
187                                  (V4SF "vecfloat")
188                                  (DF   "fp")])
190 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
191                                    (V4SF "fp_addsub_s")
192                                    (DF   "fp_addsub_d")])
194 ;; Appropriate type for multiply ops
195 (define_mode_attr VStype_mul    [(V2DF "vecdouble")
196                                  (V4SF "vecfloat")
197                                  (DF   "dmul")])
199 (define_mode_attr VSfptype_mul  [(V2DF "fp_mul_d")
200                                  (V4SF "fp_mul_s")
201                                  (DF   "fp_mul_d")])
203 ;; Appropriate type for divide ops.
204 (define_mode_attr VStype_div    [(V2DF "vecdiv")
205                                  (V4SF "vecfdiv")
206                                  (DF   "ddiv")])
208 (define_mode_attr VSfptype_div  [(V2DF "fp_div_d")
209                                  (V4SF "fp_div_s")
210                                  (DF   "fp_div_d")])
212 ;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
213 ;; the scalar sqrt
214 (define_mode_attr VStype_sqrt   [(V2DF "dsqrt")
215                                  (V4SF "ssqrt")
216                                  (DF   "dsqrt")])
218 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
219                                  (V4SF "fp_sqrt_s")
220                                  (DF   "fp_sqrt_d")])
222 ;; Iterator and modes for sp<->dp conversions
223 ;; Because scalar SF values are represented internally as double, use the
224 ;; V4SF type to represent this than SF.
225 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
227 (define_mode_attr VS_spdp_res [(DF      "V4SF")
228                                (V4SF    "V2DF")
229                                (V2DF    "V4SF")])
231 (define_mode_attr VS_spdp_insn [(DF     "xscvdpsp")
232                                 (V4SF   "xvcvspdp")
233                                 (V2DF   "xvcvdpsp")])
235 (define_mode_attr VS_spdp_type [(DF     "fp")
236                                 (V4SF   "vecdouble")
237                                 (V2DF   "vecdouble")])
239 ;; Map the scalar mode for a vector type
240 (define_mode_attr VS_scalar [(V1TI      "TI")
241                              (V2DF      "DF")
242                              (V2DI      "DI")
243                              (V4SF      "SF")
244                              (V4SI      "SI")
245                              (V8HI      "HI")
246                              (V16QI     "QI")])
248 ;; Map to a double-sized vector mode
249 (define_mode_attr VS_double [(V4SI      "V8SI")
250                              (V4SF      "V8SF")
251                              (V2DI      "V4DI")
252                              (V2DF      "V4DF")
253                              (V1TI      "V2TI")])
255 ;; Map register class for 64-bit element in 128-bit vector for direct moves
256 ;; to/from gprs
257 (define_mode_attr VS_64dm [(V2DF        "wk")
258                            (V2DI        "wj")])
260 ;; Map register class for 64-bit element in 128-bit vector for normal register
261 ;; to register moves
262 (define_mode_attr VS_64reg [(V2DF       "ws")
263                             (V2DI       "wi")])
265 ;; Iterators for loading constants with xxspltib
266 (define_mode_iterator VSINT_84  [V4SI V2DI DI SI])
267 (define_mode_iterator VSINT_842 [V8HI V4SI V2DI])
269 ;; Iterator for ISA 3.0 vector extract/insert of small integer vectors.
270 ;; VSX_EXTRACT_I2 doesn't include V4SImode because SI extracts can be
271 ;; done on ISA 2.07 and not just ISA 3.0.
272 (define_mode_iterator VSX_EXTRACT_I  [V16QI V8HI V4SI])
273 (define_mode_iterator VSX_EXTRACT_I2 [V16QI V8HI])
275 (define_mode_attr VSX_EXTRACT_WIDTH [(V16QI "b")
276                                      (V8HI "h")
277                                      (V4SI "w")])
279 ;; Mode attribute to give the correct predicate for ISA 3.0 vector extract and
280 ;; insert to validate the operand number.
281 (define_mode_attr VSX_EXTRACT_PREDICATE [(V16QI "const_0_to_15_operand")
282                                          (V8HI  "const_0_to_7_operand")
283                                          (V4SI  "const_0_to_3_operand")])
285 ;; Mode attribute to give the constraint for vector extract and insert
286 ;; operations.
287 (define_mode_attr VSX_EX [(V16QI "v")
288                           (V8HI  "v")
289                           (V4SI  "wa")])
291 ;; Iterator for the 2 short vector types to do a splat from an integer
292 (define_mode_iterator VSX_SPLAT_I [V16QI V8HI])
294 ;; Mode attribute to give the count for the splat instruction to splat
295 ;; the value in the 64-bit integer slot
296 (define_mode_attr VSX_SPLAT_COUNT [(V16QI "7") (V8HI "3")])
298 ;; Mode attribute to give the suffix for the splat instruction
299 (define_mode_attr VSX_SPLAT_SUFFIX [(V16QI "b") (V8HI "h")])
301 ;; Constants for creating unspecs
302 (define_c_enum "unspec"
303   [UNSPEC_VSX_CONCAT
304    UNSPEC_VSX_CVDPSXWS
305    UNSPEC_VSX_CVDPUXWS
306    UNSPEC_VSX_CVSPDP
307    UNSPEC_VSX_CVSPDPN
308    UNSPEC_VSX_CVDPSPN
309    UNSPEC_VSX_CVSXWDP
310    UNSPEC_VSX_CVUXWDP
311    UNSPEC_VSX_CVSXDSP
312    UNSPEC_VSX_CVUXDSP
313    UNSPEC_VSX_CVSPSXDS
314    UNSPEC_VSX_CVSPUXDS
315    UNSPEC_VSX_TDIV
316    UNSPEC_VSX_TSQRT
317    UNSPEC_VSX_SET
318    UNSPEC_VSX_ROUND_I
319    UNSPEC_VSX_ROUND_IC
320    UNSPEC_VSX_SLDWI
321    UNSPEC_VSX_XXSPLTW
322    UNSPEC_VSX_XXSPLTD
323    UNSPEC_VSX_DIVSD
324    UNSPEC_VSX_DIVUD
325    UNSPEC_VSX_MULSD
326    UNSPEC_VSX_XVCVSXDDP
327    UNSPEC_VSX_XVCVUXDDP
328    UNSPEC_VSX_XVCVDPSXDS
329    UNSPEC_VSX_XVCVDPUXDS
330    UNSPEC_VSX_SIGN_EXTEND
331    UNSPEC_P9_MEMORY
332    UNSPEC_VSX_VSLO
333    UNSPEC_VSX_EXTRACT
334    UNSPEC_VSX_SXEXPDP
335    UNSPEC_VSX_SXSIGDP
336    UNSPEC_VSX_SIEXPDP
337    UNSPEC_VSX_SCMPEXPDP
338    UNSPEC_VSX_STSTDC
339    UNSPEC_VSX_VXEXP
340    UNSPEC_VSX_VXSIG
341    UNSPEC_VSX_VIEXP
342    UNSPEC_VSX_VTSTDC
343    UNSPEC_VSX_VEC_INIT
344    UNSPEC_LXVL
345    UNSPEC_STXVL
346    UNSPEC_VCLZLSBB
347    UNSPEC_VCTZLSBB
348    UNSPEC_VEXTUBLX
349    UNSPEC_VEXTUHLX
350    UNSPEC_VEXTUWLX
351    UNSPEC_VEXTUBRX
352    UNSPEC_VEXTUHRX
353    UNSPEC_VEXTUWRX
354    UNSPEC_VCMPNEB
355    UNSPEC_VCMPNEZB
356    UNSPEC_VCMPNEH
357    UNSPEC_VCMPNEZH
358    UNSPEC_VCMPNEW
359    UNSPEC_VCMPNEZW
360   ])
362 ;; VSX moves
364 ;; The patterns for LE permuted loads and stores come before the general
365 ;; VSX moves so they match first.
366 (define_insn_and_split "*vsx_le_perm_load_<mode>"
367   [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
368         (match_operand:VSX_LE 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:<MODE>
374           (match_dup 1)
375           (parallel [(const_int 1) (const_int 0)])))
376    (set (match_dup 0)
377         (vec_select:<MODE>
378           (match_dup 2)
379           (parallel [(const_int 1) (const_int 0)])))]
380   "
382   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
383                                        : operands[0];
385   "
386   [(set_attr "type" "vecload")
387    (set_attr "length" "8")])
389 (define_insn_and_split "*vsx_le_perm_load_<mode>"
390   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
391         (match_operand:VSX_W 1 "memory_operand" "Z"))]
392   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
393   "#"
394   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
395   [(set (match_dup 2)
396         (vec_select:<MODE>
397           (match_dup 1)
398           (parallel [(const_int 2) (const_int 3)
399                      (const_int 0) (const_int 1)])))
400    (set (match_dup 0)
401         (vec_select:<MODE>
402           (match_dup 2)
403           (parallel [(const_int 2) (const_int 3)
404                      (const_int 0) (const_int 1)])))]
405   "
407   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
408                                        : operands[0];
410   "
411   [(set_attr "type" "vecload")
412    (set_attr "length" "8")])
414 (define_insn_and_split "*vsx_le_perm_load_v8hi"
415   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
416         (match_operand:V8HI 1 "memory_operand" "Z"))]
417   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
418   "#"
419   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
420   [(set (match_dup 2)
421         (vec_select:V8HI
422           (match_dup 1)
423           (parallel [(const_int 4) (const_int 5)
424                      (const_int 6) (const_int 7)
425                      (const_int 0) (const_int 1)
426                      (const_int 2) (const_int 3)])))
427    (set (match_dup 0)
428         (vec_select:V8HI
429           (match_dup 2)
430           (parallel [(const_int 4) (const_int 5)
431                      (const_int 6) (const_int 7)
432                      (const_int 0) (const_int 1)
433                      (const_int 2) (const_int 3)])))]
434   "
436   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
437                                        : operands[0];
439   "
440   [(set_attr "type" "vecload")
441    (set_attr "length" "8")])
443 (define_insn_and_split "*vsx_le_perm_load_v16qi"
444   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
445         (match_operand:V16QI 1 "memory_operand" "Z"))]
446   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
447   "#"
448   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
449   [(set (match_dup 2)
450         (vec_select:V16QI
451           (match_dup 1)
452           (parallel [(const_int 8) (const_int 9)
453                      (const_int 10) (const_int 11)
454                      (const_int 12) (const_int 13)
455                      (const_int 14) (const_int 15)
456                      (const_int 0) (const_int 1)
457                      (const_int 2) (const_int 3)
458                      (const_int 4) (const_int 5)
459                      (const_int 6) (const_int 7)])))
460    (set (match_dup 0)
461         (vec_select:V16QI
462           (match_dup 2)
463           (parallel [(const_int 8) (const_int 9)
464                      (const_int 10) (const_int 11)
465                      (const_int 12) (const_int 13)
466                      (const_int 14) (const_int 15)
467                      (const_int 0) (const_int 1)
468                      (const_int 2) (const_int 3)
469                      (const_int 4) (const_int 5)
470                      (const_int 6) (const_int 7)])))]
471   "
473   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
474                                        : operands[0];
476   "
477   [(set_attr "type" "vecload")
478    (set_attr "length" "8")])
480 (define_insn "*vsx_le_perm_store_<mode>"
481   [(set (match_operand:VSX_LE 0 "memory_operand" "=Z")
482         (match_operand:VSX_LE 1 "vsx_register_operand" "+<VSa>"))]
483   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
484   "#"
485   [(set_attr "type" "vecstore")
486    (set_attr "length" "12")])
488 (define_split
489   [(set (match_operand:VSX_LE 0 "memory_operand" "")
490         (match_operand:VSX_LE 1 "vsx_register_operand" ""))]
491   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
492   [(set (match_dup 2)
493         (vec_select:<MODE>
494           (match_dup 1)
495           (parallel [(const_int 1) (const_int 0)])))
496    (set (match_dup 0)
497         (vec_select:<MODE>
498           (match_dup 2)
499           (parallel [(const_int 1) (const_int 0)])))]
501   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
502                                        : operands[1];
505 ;; The post-reload split requires that we re-permute the source
506 ;; register in case it is still live.
507 (define_split
508   [(set (match_operand:VSX_LE 0 "memory_operand" "")
509         (match_operand:VSX_LE 1 "vsx_register_operand" ""))]
510   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
511   [(set (match_dup 1)
512         (vec_select:<MODE>
513           (match_dup 1)
514           (parallel [(const_int 1) (const_int 0)])))
515    (set (match_dup 0)
516         (vec_select:<MODE>
517           (match_dup 1)
518           (parallel [(const_int 1) (const_int 0)])))
519    (set (match_dup 1)
520         (vec_select:<MODE>
521           (match_dup 1)
522           (parallel [(const_int 1) (const_int 0)])))]
523   "")
525 (define_insn "*vsx_le_perm_store_<mode>"
526   [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
527         (match_operand:VSX_W 1 "vsx_register_operand" "+<VSa>"))]
528   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
529   "#"
530   [(set_attr "type" "vecstore")
531    (set_attr "length" "12")])
533 (define_split
534   [(set (match_operand:VSX_W 0 "memory_operand" "")
535         (match_operand:VSX_W 1 "vsx_register_operand" ""))]
536   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
537   [(set (match_dup 2)
538         (vec_select:<MODE>
539           (match_dup 1)
540           (parallel [(const_int 2) (const_int 3)
541                      (const_int 0) (const_int 1)])))
542    (set (match_dup 0)
543         (vec_select:<MODE>
544           (match_dup 2)
545           (parallel [(const_int 2) (const_int 3)
546                      (const_int 0) (const_int 1)])))]
548   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
549                                        : operands[1];
552 ;; The post-reload split requires that we re-permute the source
553 ;; register in case it is still live.
554 (define_split
555   [(set (match_operand:VSX_W 0 "memory_operand" "")
556         (match_operand:VSX_W 1 "vsx_register_operand" ""))]
557   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
558   [(set (match_dup 1)
559         (vec_select:<MODE>
560           (match_dup 1)
561           (parallel [(const_int 2) (const_int 3)
562                      (const_int 0) (const_int 1)])))
563    (set (match_dup 0)
564         (vec_select:<MODE>
565           (match_dup 1)
566           (parallel [(const_int 2) (const_int 3)
567                      (const_int 0) (const_int 1)])))
568    (set (match_dup 1)
569         (vec_select:<MODE>
570           (match_dup 1)
571           (parallel [(const_int 2) (const_int 3)
572                      (const_int 0) (const_int 1)])))]
573   "")
575 (define_insn "*vsx_le_perm_store_v8hi"
576   [(set (match_operand:V8HI 0 "memory_operand" "=Z")
577         (match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
578   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
579   "#"
580   [(set_attr "type" "vecstore")
581    (set_attr "length" "12")])
583 (define_split
584   [(set (match_operand:V8HI 0 "memory_operand" "")
585         (match_operand:V8HI 1 "vsx_register_operand" ""))]
586   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
587   [(set (match_dup 2)
588         (vec_select:V8HI
589           (match_dup 1)
590           (parallel [(const_int 4) (const_int 5)
591                      (const_int 6) (const_int 7)
592                      (const_int 0) (const_int 1)
593                      (const_int 2) (const_int 3)])))
594    (set (match_dup 0)
595         (vec_select:V8HI
596           (match_dup 2)
597           (parallel [(const_int 4) (const_int 5)
598                      (const_int 6) (const_int 7)
599                      (const_int 0) (const_int 1)
600                      (const_int 2) (const_int 3)])))]
602   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
603                                        : operands[1];
606 ;; The post-reload split requires that we re-permute the source
607 ;; register in case it is still live.
608 (define_split
609   [(set (match_operand:V8HI 0 "memory_operand" "")
610         (match_operand:V8HI 1 "vsx_register_operand" ""))]
611   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
612   [(set (match_dup 1)
613         (vec_select:V8HI
614           (match_dup 1)
615           (parallel [(const_int 4) (const_int 5)
616                      (const_int 6) (const_int 7)
617                      (const_int 0) (const_int 1)
618                      (const_int 2) (const_int 3)])))
619    (set (match_dup 0)
620         (vec_select:V8HI
621           (match_dup 1)
622           (parallel [(const_int 4) (const_int 5)
623                      (const_int 6) (const_int 7)
624                      (const_int 0) (const_int 1)
625                      (const_int 2) (const_int 3)])))
626    (set (match_dup 1)
627         (vec_select:V8HI
628           (match_dup 1)
629           (parallel [(const_int 4) (const_int 5)
630                      (const_int 6) (const_int 7)
631                      (const_int 0) (const_int 1)
632                      (const_int 2) (const_int 3)])))]
633   "")
635 (define_insn "*vsx_le_perm_store_v16qi"
636   [(set (match_operand:V16QI 0 "memory_operand" "=Z")
637         (match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
638   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
639   "#"
640   [(set_attr "type" "vecstore")
641    (set_attr "length" "12")])
643 (define_split
644   [(set (match_operand:V16QI 0 "memory_operand" "")
645         (match_operand:V16QI 1 "vsx_register_operand" ""))]
646   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
647   [(set (match_dup 2)
648         (vec_select:V16QI
649           (match_dup 1)
650           (parallel [(const_int 8) (const_int 9)
651                      (const_int 10) (const_int 11)
652                      (const_int 12) (const_int 13)
653                      (const_int 14) (const_int 15)
654                      (const_int 0) (const_int 1)
655                      (const_int 2) (const_int 3)
656                      (const_int 4) (const_int 5)
657                      (const_int 6) (const_int 7)])))
658    (set (match_dup 0)
659         (vec_select:V16QI
660           (match_dup 2)
661           (parallel [(const_int 8) (const_int 9)
662                      (const_int 10) (const_int 11)
663                      (const_int 12) (const_int 13)
664                      (const_int 14) (const_int 15)
665                      (const_int 0) (const_int 1)
666                      (const_int 2) (const_int 3)
667                      (const_int 4) (const_int 5)
668                      (const_int 6) (const_int 7)])))]
670   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) 
671                                        : operands[1];
674 ;; The post-reload split requires that we re-permute the source
675 ;; register in case it is still live.
676 (define_split
677   [(set (match_operand:V16QI 0 "memory_operand" "")
678         (match_operand:V16QI 1 "vsx_register_operand" ""))]
679   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
680   [(set (match_dup 1)
681         (vec_select:V16QI
682           (match_dup 1)
683           (parallel [(const_int 8) (const_int 9)
684                      (const_int 10) (const_int 11)
685                      (const_int 12) (const_int 13)
686                      (const_int 14) (const_int 15)
687                      (const_int 0) (const_int 1)
688                      (const_int 2) (const_int 3)
689                      (const_int 4) (const_int 5)
690                      (const_int 6) (const_int 7)])))
691    (set (match_dup 0)
692         (vec_select:V16QI
693           (match_dup 1)
694           (parallel [(const_int 8) (const_int 9)
695                      (const_int 10) (const_int 11)
696                      (const_int 12) (const_int 13)
697                      (const_int 14) (const_int 15)
698                      (const_int 0) (const_int 1)
699                      (const_int 2) (const_int 3)
700                      (const_int 4) (const_int 5)
701                      (const_int 6) (const_int 7)])))
702    (set (match_dup 1)
703         (vec_select:V16QI
704           (match_dup 1)
705           (parallel [(const_int 8) (const_int 9)
706                      (const_int 10) (const_int 11)
707                      (const_int 12) (const_int 13)
708                      (const_int 14) (const_int 15)
709                      (const_int 0) (const_int 1)
710                      (const_int 2) (const_int 3)
711                      (const_int 4) (const_int 5)
712                      (const_int 6) (const_int 7)])))]
713   "")
715 ;; Little endian word swapping for 128-bit types that are either scalars or the
716 ;; special V1TI container class, which it is not appropriate to use vec_select
717 ;; for the type.
718 (define_insn "*vsx_le_permute_<mode>"
719   [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
720         (rotate:VSX_LE_128
721          (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
722          (const_int 64)))]
723   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
724   "@
725    xxpermdi %x0,%x1,%x1,2
726    lxvd2x %x0,%y1
727    stxvd2x %x1,%y0"
728   [(set_attr "length" "4")
729    (set_attr "type" "vecperm,vecload,vecstore")])
731 (define_insn_and_split "*vsx_le_undo_permute_<mode>"
732   [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
733         (rotate:VSX_LE_128
734          (rotate:VSX_LE_128
735           (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
736           (const_int 64))
737          (const_int 64)))]
738   "!BYTES_BIG_ENDIAN && TARGET_VSX"
739   "@
740    #
741    xxlor %x0,%x1"
742   ""
743   [(set (match_dup 0) (match_dup 1))]
745   if (reload_completed && REGNO (operands[0]) == REGNO (operands[1]))
746     {
747       emit_note (NOTE_INSN_DELETED);
748       DONE;
749     }
751   [(set_attr "length" "0,4")
752    (set_attr "type" "veclogical")])
754 (define_insn_and_split "*vsx_le_perm_load_<mode>"
755   [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>")
756         (match_operand:VSX_LE_128 1 "memory_operand" "Z"))]
757   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
758   "#"
759   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
760   [(set (match_dup 2)
761         (rotate:VSX_LE_128 (match_dup 1)
762                            (const_int 64)))
763    (set (match_dup 0)
764         (rotate:VSX_LE_128 (match_dup 2)
765                            (const_int 64)))]
766   "
768   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
769                                        : operands[0];
771   "
772   [(set_attr "type" "vecload")
773    (set_attr "length" "8")])
775 (define_insn "*vsx_le_perm_store_<mode>"
776   [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z")
777         (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>"))]
778   "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
779   "#"
780   [(set_attr "type" "vecstore")
781    (set_attr "length" "12")])
783 (define_split
784   [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
785         (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
786   "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed && !TARGET_P9_VECTOR"
787   [(set (match_dup 2)
788         (rotate:VSX_LE_128 (match_dup 1)
789                            (const_int 64)))
790    (set (match_dup 0)
791         (rotate:VSX_LE_128 (match_dup 2)
792                            (const_int 64)))]
794   operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
795                                        : operands[0];
798 ;; Peephole to catch memory to memory transfers for TImode if TImode landed in
799 ;; VSX registers on a little endian system.  The vector types and IEEE 128-bit
800 ;; floating point are handled by the more generic swap elimination pass.
801 (define_peephole2
802   [(set (match_operand:TI 0 "vsx_register_operand" "")
803         (rotate:TI (match_operand:TI 1 "vsx_register_operand" "")
804                    (const_int 64)))
805    (set (match_operand:TI 2 "vsx_register_operand" "")
806         (rotate:TI (match_dup 0)
807                    (const_int 64)))]
808   "!BYTES_BIG_ENDIAN && TARGET_VSX && TARGET_VSX_TIMODE && !TARGET_P9_VECTOR
809    && (rtx_equal_p (operands[0], operands[2])
810        || peep2_reg_dead_p (2, operands[0]))"
811    [(set (match_dup 2) (match_dup 1))])
813 ;; The post-reload split requires that we re-permute the source
814 ;; register in case it is still live.
815 (define_split
816   [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
817         (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
818   "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed && !TARGET_P9_VECTOR"
819   [(set (match_dup 1)
820         (rotate:VSX_LE_128 (match_dup 1)
821                            (const_int 64)))
822    (set (match_dup 0)
823         (rotate:VSX_LE_128 (match_dup 1)
824                            (const_int 64)))
825    (set (match_dup 1)
826         (rotate:VSX_LE_128 (match_dup 1)
827                            (const_int 64)))]
828   "")
830 ;; Vector constants that can be generated with XXSPLTIB that was added in ISA
831 ;; 3.0.  Both (const_vector [..]) and (vec_duplicate ...) forms are recognized.
832 (define_insn "xxspltib_v16qi"
833   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
834         (vec_duplicate:V16QI (match_operand:SI 1 "s8bit_cint_operand" "n")))]
835   "TARGET_P9_VECTOR"
837   operands[2] = GEN_INT (INTVAL (operands[1]) & 0xff);
838   return "xxspltib %x0,%2";
840   [(set_attr "type" "vecperm")])
842 (define_insn "xxspltib_<mode>_nosplit"
843   [(set (match_operand:VSINT_842 0 "vsx_register_operand" "=wa,wa")
844         (match_operand:VSINT_842 1 "xxspltib_constant_nosplit" "jwM,wE"))]
845   "TARGET_P9_VECTOR"
847   rtx op1 = operands[1];
848   int value = 256;
849   int num_insns = -1;
851   if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
852       || num_insns != 1)
853     gcc_unreachable ();
855   operands[2] = GEN_INT (value & 0xff);
856   return "xxspltib %x0,%2";
858   [(set_attr "type" "vecperm")])
860 (define_insn_and_split "*xxspltib_<mode>_split"
861   [(set (match_operand:VSINT_842 0 "altivec_register_operand" "=v")
862         (match_operand:VSINT_842 1 "xxspltib_constant_split" "wS"))]
863   "TARGET_P9_VECTOR"
864   "#"
865   "&& 1"
866   [(const_int 0)]
868   int value = 256;
869   int num_insns = -1;
870   rtx op0 = operands[0];
871   rtx op1 = operands[1];
872   rtx tmp = ((can_create_pseudo_p ())
873              ? gen_reg_rtx (V16QImode)
874              : gen_lowpart (V16QImode, op0));
876   if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
877       || num_insns != 2)
878     gcc_unreachable ();
880   emit_insn (gen_xxspltib_v16qi (tmp, GEN_INT (value)));
882   if (<MODE>mode == V2DImode)
883     emit_insn (gen_vsx_sign_extend_qi_v2di (op0, tmp));
885   else if (<MODE>mode == V4SImode)
886     emit_insn (gen_vsx_sign_extend_qi_v4si (op0, tmp));
888   else if (<MODE>mode == V8HImode)
889     emit_insn (gen_altivec_vupkhsb  (op0, tmp));
891   else
892     gcc_unreachable ();
894   DONE;
896   [(set_attr "type" "vecperm")
897    (set_attr "length" "8")])
900 ;; Prefer using vector registers over GPRs.  Prefer using ISA 3.0's XXSPLTISB
901 ;; or Altivec VSPLITW 0/-1 over XXLXOR/XXLORC to set a register to all 0's or
902 ;; all 1's, since the machine does not have to wait for the previous
903 ;; instruction using the register being set (such as a store waiting on a slow
904 ;; instruction). But generate XXLXOR/XXLORC if it will avoid a register move.
906 ;;              VSX store  VSX load   VSX move  VSX->GPR   GPR->VSX    LQ (GPR)
907 ;;              STQ (GPR)  GPR load   GPR store GPR move   XXSPLTIB    VSPLTISW
908 ;;              VSX 0/-1   GPR 0/-1   VMX const GPR const  LVX (VMX)   STVX (VMX)
909 (define_insn "*vsx_mov<mode>_64bit"
910   [(set (match_operand:VSX_M 0 "nonimmediate_operand"
911                "=ZwO,      <VSa>,     <VSa>,     r,         we,        ?wQ,
912                 ?&r,       ??r,       ??Y,       ??r,       wo,        v,
913                 ?<VSa>,    *r,        v,         ??r,       wZ,        v")
915         (match_operand:VSX_M 1 "input_operand" 
916                "<VSa>,     ZwO,       <VSa>,     we,        r,         r,
917                 wQ,        Y,         r,         r,         wE,        jwM,
918                 ?jwM,      jwM,       W,         W,         v,         wZ"))]
920   "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
921    && (register_operand (operands[0], <MODE>mode) 
922        || register_operand (operands[1], <MODE>mode))"
924   return rs6000_output_move_128bit (operands);
926   [(set_attr "type"
927                "vecstore,  vecload,   vecsimple, mffgpr,    mftgpr,    load,
928                 store,     load,      store,     *,         vecsimple, vecsimple,
929                 vecsimple, *,         *,         *,         vecstore,  vecload")
931    (set_attr "length"
932                "4,         4,         4,         8,         4,         8,
933                 8,         8,         8,         8,         4,         4,
934                 4,         8,         20,        20,        4,         4")])
936 ;;              VSX store  VSX load   VSX move   GPR load   GPR store  GPR move
937 ;;              XXSPLTIB   VSPLTISW   VSX 0/-1   GPR 0/-1   VMX const  GPR const
938 ;;              LVX (VMX)  STVX (VMX)
939 (define_insn "*vsx_mov<mode>_32bit"
940   [(set (match_operand:VSX_M 0 "nonimmediate_operand"
941                "=ZwO,      <VSa>,     <VSa>,     ??r,       ??Y,       ??r,
942                 wo,        v,         ?<VSa>,    *r,        v,         ??r,
943                 wZ,        v")
945         (match_operand:VSX_M 1 "input_operand" 
946                "<VSa>,     ZwO,       <VSa>,     Y,         r,         r,
947                 wE,        jwM,       ?jwM,      jwM,       W,         W,
948                 v,         wZ"))]
950   "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
951    && (register_operand (operands[0], <MODE>mode) 
952        || register_operand (operands[1], <MODE>mode))"
954   return rs6000_output_move_128bit (operands);
956   [(set_attr "type"
957                "vecstore,  vecload,   vecsimple, load,      store,    *,
958                 vecsimple, vecsimple, vecsimple, *,         *,        *,
959                 vecstore,  vecload")
961    (set_attr "length"
962                "4,         4,         4,         16,        16,        16,
963                 4,         4,         4,         16,        20,        32,
964                 4,         4")])
966 ;; Explicit  load/store expanders for the builtin functions
967 (define_expand "vsx_load_<mode>"
968   [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
969         (match_operand:VSX_M 1 "memory_operand" ""))]
970   "VECTOR_MEM_VSX_P (<MODE>mode)"
972   /* Expand to swaps if needed, prior to swap optimization.  */
973   if (!BYTES_BIG_ENDIAN && !TARGET_P9_VECTOR)
974     {
975       rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
976       DONE;
977     }
980 (define_expand "vsx_store_<mode>"
981   [(set (match_operand:VSX_M 0 "memory_operand" "")
982         (match_operand:VSX_M 1 "vsx_register_operand" ""))]
983   "VECTOR_MEM_VSX_P (<MODE>mode)"
985   /* Expand to swaps if needed, prior to swap optimization.  */
986   if (!BYTES_BIG_ENDIAN && !TARGET_P9_VECTOR)
987     {
988       rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
989       DONE;
990     }
993 ;; Explicit load/store expanders for the builtin functions for lxvd2x, etc.,
994 ;; when you really want their element-reversing behavior.
995 (define_insn "vsx_ld_elemrev_v2di"
996   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
997         (vec_select:V2DI
998           (match_operand:V2DI 1 "memory_operand" "Z")
999           (parallel [(const_int 1) (const_int 0)])))]
1000   "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1001   "lxvd2x %x0,%y1"
1002   [(set_attr "type" "vecload")])
1004 (define_insn "vsx_ld_elemrev_v2df"
1005   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1006         (vec_select:V2DF
1007           (match_operand:V2DF 1 "memory_operand" "Z")
1008           (parallel [(const_int 1) (const_int 0)])))]
1009   "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1010   "lxvd2x %x0,%y1"
1011   [(set_attr "type" "vecload")])
1013 (define_insn "vsx_ld_elemrev_v4si"
1014   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
1015         (vec_select:V4SI
1016           (match_operand:V4SI 1 "memory_operand" "Z")
1017           (parallel [(const_int 3) (const_int 2)
1018                      (const_int 1) (const_int 0)])))]
1019   "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1020   "lxvw4x %x0,%y1"
1021   [(set_attr "type" "vecload")])
1023 (define_insn "vsx_ld_elemrev_v4sf"
1024   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1025         (vec_select:V4SF
1026           (match_operand:V4SF 1 "memory_operand" "Z")
1027           (parallel [(const_int 3) (const_int 2)
1028                      (const_int 1) (const_int 0)])))]
1029   "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1030   "lxvw4x %x0,%y1"
1031   [(set_attr "type" "vecload")])
1033 (define_insn "vsx_ld_elemrev_v8hi"
1034   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
1035         (vec_select:V8HI
1036           (match_operand:V8HI 1 "memory_operand" "Z")
1037           (parallel [(const_int 7) (const_int 6)
1038                      (const_int 5) (const_int 4)
1039                      (const_int 3) (const_int 2)
1040                      (const_int 1) (const_int 0)])))]
1041   "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1042   "lxvh8x %x0,%y1"
1043   [(set_attr "type" "vecload")])
1045 (define_insn "vsx_ld_elemrev_v16qi"
1046   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
1047         (vec_select:V16QI
1048           (match_operand:V16QI 1 "memory_operand" "Z")
1049           (parallel [(const_int 15) (const_int 14)
1050                      (const_int 13) (const_int 12)
1051                      (const_int 11) (const_int 10)
1052                      (const_int  9) (const_int  8)
1053                      (const_int  7) (const_int  6)
1054                      (const_int  5) (const_int  4)
1055                      (const_int  3) (const_int  2)
1056                      (const_int  1) (const_int  0)])))]
1057   "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1058   "lxvb16x %x0,%y1"
1059   [(set_attr "type" "vecload")])
1061 (define_insn "vsx_st_elemrev_v2df"
1062   [(set (match_operand:V2DF 0 "memory_operand" "=Z")
1063         (vec_select:V2DF
1064           (match_operand:V2DF 1 "vsx_register_operand" "wa")
1065           (parallel [(const_int 1) (const_int 0)])))]
1066   "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1067   "stxvd2x %x1,%y0"
1068   [(set_attr "type" "vecstore")])
1070 (define_insn "vsx_st_elemrev_v2di"
1071   [(set (match_operand:V2DI 0 "memory_operand" "=Z")
1072         (vec_select:V2DI
1073           (match_operand:V2DI 1 "vsx_register_operand" "wa")
1074           (parallel [(const_int 1) (const_int 0)])))]
1075   "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1076   "stxvd2x %x1,%y0"
1077   [(set_attr "type" "vecstore")])
1079 (define_insn "vsx_st_elemrev_v4sf"
1080   [(set (match_operand:V4SF 0 "memory_operand" "=Z")
1081         (vec_select:V4SF
1082           (match_operand:V4SF 1 "vsx_register_operand" "wa")
1083           (parallel [(const_int 3) (const_int 2)
1084                      (const_int 1) (const_int 0)])))]
1085   "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1086   "stxvw4x %x1,%y0"
1087   [(set_attr "type" "vecstore")])
1089 (define_insn "vsx_st_elemrev_v4si"
1090   [(set (match_operand:V4SI 0 "memory_operand" "=Z")
1091         (vec_select:V4SI
1092           (match_operand:V4SI 1 "vsx_register_operand" "wa")
1093           (parallel [(const_int 3) (const_int 2)
1094                      (const_int 1) (const_int 0)])))]
1095   "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1096   "stxvw4x %x1,%y0"
1097   [(set_attr "type" "vecstore")])
1099 (define_insn "vsx_st_elemrev_v8hi"
1100   [(set (match_operand:V8HI 0 "memory_operand" "=Z")
1101         (vec_select:V8HI
1102           (match_operand:V8HI 1 "vsx_register_operand" "wa")
1103           (parallel [(const_int 7) (const_int 6)
1104                      (const_int 5) (const_int 4)
1105                      (const_int 3) (const_int 2)
1106                      (const_int 1) (const_int 0)])))]
1107   "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1108   "stxvh8x %x1,%y0"
1109   [(set_attr "type" "vecstore")])
1111 (define_insn "vsx_st_elemrev_v16qi"
1112   [(set (match_operand:V16QI 0 "memory_operand" "=Z")
1113         (vec_select:V16QI
1114           (match_operand:V16QI 1 "vsx_register_operand" "wa")
1115           (parallel [(const_int 15) (const_int 14)
1116                      (const_int 13) (const_int 12)
1117                      (const_int 11) (const_int 10)
1118                      (const_int  9) (const_int  8)
1119                      (const_int  7) (const_int  6)
1120                      (const_int  5) (const_int  4)
1121                      (const_int  3) (const_int  2)
1122                      (const_int  1) (const_int  0)])))]
1123   "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1124   "stxvb16x %x1,%y0"
1125   [(set_attr "type" "vecstore")])
1128 ;; VSX vector floating point arithmetic instructions.  The VSX scalar
1129 ;; instructions are now combined with the insn for the traditional floating
1130 ;; point unit.
1131 (define_insn "*vsx_add<mode>3"
1132   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1133         (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1134                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1135   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1136   "xvadd<VSs> %x0,%x1,%x2"
1137   [(set_attr "type" "<VStype_simple>")
1138    (set_attr "fp_type" "<VSfptype_simple>")])
1140 (define_insn "*vsx_sub<mode>3"
1141   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1142         (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1143                      (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1144   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1145   "xvsub<VSs> %x0,%x1,%x2"
1146   [(set_attr "type" "<VStype_simple>")
1147    (set_attr "fp_type" "<VSfptype_simple>")])
1149 (define_insn "*vsx_mul<mode>3"
1150   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1151         (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1152                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1153   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1154   "xvmul<VSs> %x0,%x1,%x2"
1155   [(set_attr "type" "<VStype_simple>")
1156    (set_attr "fp_type" "<VSfptype_mul>")])
1158 ; Emulate vector with scalar for vec_mul in V2DImode
1159 (define_insn_and_split "vsx_mul_v2di"
1160   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1161         (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1162                       (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1163                      UNSPEC_VSX_MULSD))]
1164   "VECTOR_MEM_VSX_P (V2DImode)"
1165   "#"
1166   "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1167   [(const_int 0)]
1168   "
1170   rtx op0 = operands[0];
1171   rtx op1 = operands[1];
1172   rtx op2 = operands[2];
1173   rtx op3 = gen_reg_rtx (DImode);
1174   rtx op4 = gen_reg_rtx (DImode);
1175   rtx op5 = gen_reg_rtx (DImode);
1176   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1177   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1178   emit_insn (gen_muldi3 (op5, op3, op4));
1179   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1180   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1181   emit_insn (gen_muldi3 (op3, op3, op4));
1182   emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1183   DONE;
1185   [(set_attr "type" "mul")])
1187 (define_insn "*vsx_div<mode>3"
1188   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1189         (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1190                    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1191   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1192   "xvdiv<VSs> %x0,%x1,%x2"
1193   [(set_attr "type" "<VStype_div>")
1194    (set_attr "fp_type" "<VSfptype_div>")])
1196 ; Emulate vector with scalar for vec_div in V2DImode
1197 (define_insn_and_split "vsx_div_v2di"
1198   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1199         (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1200                       (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1201                      UNSPEC_VSX_DIVSD))]
1202   "VECTOR_MEM_VSX_P (V2DImode)"
1203   "#"
1204   "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1205   [(const_int 0)]
1206   "
1208   rtx op0 = operands[0];
1209   rtx op1 = operands[1];
1210   rtx op2 = operands[2];
1211   rtx op3 = gen_reg_rtx (DImode);
1212   rtx op4 = gen_reg_rtx (DImode);
1213   rtx op5 = gen_reg_rtx (DImode);
1214   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1215   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1216   emit_insn (gen_divdi3 (op5, op3, op4));
1217   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1218   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1219   emit_insn (gen_divdi3 (op3, op3, op4));
1220   emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1221   DONE;
1223   [(set_attr "type" "div")])
1225 (define_insn_and_split "vsx_udiv_v2di"
1226   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1227         (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1228                       (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1229                      UNSPEC_VSX_DIVUD))]
1230   "VECTOR_MEM_VSX_P (V2DImode)"
1231   "#"
1232   "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1233   [(const_int 0)]
1234   "
1236   rtx op0 = operands[0];
1237   rtx op1 = operands[1];
1238   rtx op2 = operands[2];
1239   rtx op3 = gen_reg_rtx (DImode);
1240   rtx op4 = gen_reg_rtx (DImode);
1241   rtx op5 = gen_reg_rtx (DImode);
1242   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1243   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1244   emit_insn (gen_udivdi3 (op5, op3, op4));
1245   emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1246   emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1247   emit_insn (gen_udivdi3 (op3, op3, op4));
1248   emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1249   DONE;
1251   [(set_attr "type" "div")])
1253 ;; *tdiv* instruction returning the FG flag
1254 (define_expand "vsx_tdiv<mode>3_fg"
1255   [(set (match_dup 3)
1256         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1257                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
1258                      UNSPEC_VSX_TDIV))
1259    (set (match_operand:SI 0 "gpc_reg_operand" "")
1260         (gt:SI (match_dup 3)
1261                (const_int 0)))]
1262   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1264   operands[3] = gen_reg_rtx (CCFPmode);
1267 ;; *tdiv* instruction returning the FE flag
1268 (define_expand "vsx_tdiv<mode>3_fe"
1269   [(set (match_dup 3)
1270         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1271                       (match_operand:VSX_B 2 "vsx_register_operand" "")]
1272                      UNSPEC_VSX_TDIV))
1273    (set (match_operand:SI 0 "gpc_reg_operand" "")
1274         (eq:SI (match_dup 3)
1275                (const_int 0)))]
1276   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1278   operands[3] = gen_reg_rtx (CCFPmode);
1281 (define_insn "*vsx_tdiv<mode>3_internal"
1282   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1283         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")
1284                       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,<VSa>")]
1285                    UNSPEC_VSX_TDIV))]
1286   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1287   "x<VSv>tdiv<VSs> %0,%x1,%x2"
1288   [(set_attr "type" "<VStype_simple>")
1289    (set_attr "fp_type" "<VSfptype_simple>")])
1291 (define_insn "vsx_fre<mode>2"
1292   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1293         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1294                       UNSPEC_FRES))]
1295   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1296   "xvre<VSs> %x0,%x1"
1297   [(set_attr "type" "<VStype_simple>")
1298    (set_attr "fp_type" "<VSfptype_simple>")])
1300 (define_insn "*vsx_neg<mode>2"
1301   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1302         (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1303   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1304   "xvneg<VSs> %x0,%x1"
1305   [(set_attr "type" "<VStype_simple>")
1306    (set_attr "fp_type" "<VSfptype_simple>")])
1308 (define_insn "*vsx_abs<mode>2"
1309   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1310         (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1311   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1312   "xvabs<VSs> %x0,%x1"
1313   [(set_attr "type" "<VStype_simple>")
1314    (set_attr "fp_type" "<VSfptype_simple>")])
1316 (define_insn "vsx_nabs<mode>2"
1317   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1318         (neg:VSX_F
1319          (abs:VSX_F
1320           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>"))))]
1321   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1322   "xvnabs<VSs> %x0,%x1"
1323   [(set_attr "type" "<VStype_simple>")
1324    (set_attr "fp_type" "<VSfptype_simple>")])
1326 (define_insn "vsx_smax<mode>3"
1327   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1328         (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1329                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1330   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1331   "xvmax<VSs> %x0,%x1,%x2"
1332   [(set_attr "type" "<VStype_simple>")
1333    (set_attr "fp_type" "<VSfptype_simple>")])
1335 (define_insn "*vsx_smin<mode>3"
1336   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1337         (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1338                     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1339   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1340   "xvmin<VSs> %x0,%x1,%x2"
1341   [(set_attr "type" "<VStype_simple>")
1342    (set_attr "fp_type" "<VSfptype_simple>")])
1344 (define_insn "*vsx_sqrt<mode>2"
1345   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1346         (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1347   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1348   "xvsqrt<VSs> %x0,%x1"
1349   [(set_attr "type" "<VStype_sqrt>")
1350    (set_attr "fp_type" "<VSfptype_sqrt>")])
1352 (define_insn "*vsx_rsqrte<mode>2"
1353   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1354         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1355                       UNSPEC_RSQRT))]
1356   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1357   "xvrsqrte<VSs> %x0,%x1"
1358   [(set_attr "type" "<VStype_simple>")
1359    (set_attr "fp_type" "<VSfptype_simple>")])
1361 ;; *tsqrt* returning the fg flag
1362 (define_expand "vsx_tsqrt<mode>2_fg"
1363   [(set (match_dup 3)
1364         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1365                      UNSPEC_VSX_TSQRT))
1366    (set (match_operand:SI 0 "gpc_reg_operand" "")
1367         (gt:SI (match_dup 3)
1368                (const_int 0)))]
1369   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1371   operands[3] = gen_reg_rtx (CCFPmode);
1374 ;; *tsqrt* returning the fe flag
1375 (define_expand "vsx_tsqrt<mode>2_fe"
1376   [(set (match_dup 3)
1377         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1378                      UNSPEC_VSX_TSQRT))
1379    (set (match_operand:SI 0 "gpc_reg_operand" "")
1380         (eq:SI (match_dup 3)
1381                (const_int 0)))]
1382   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1384   operands[3] = gen_reg_rtx (CCFPmode);
1387 (define_insn "*vsx_tsqrt<mode>2_internal"
1388   [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1389         (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1390                      UNSPEC_VSX_TSQRT))]
1391   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1392   "x<VSv>tsqrt<VSs> %0,%x1"
1393   [(set_attr "type" "<VStype_simple>")
1394    (set_attr "fp_type" "<VSfptype_simple>")])
1396 ;; Fused vector multiply/add instructions. Support the classical Altivec
1397 ;; versions of fma, which allows the target to be a separate register from the
1398 ;; 3 inputs.  Under VSX, the target must be either the addend or the first
1399 ;; multiply.
1401 (define_insn "*vsx_fmav4sf4"
1402   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1403         (fma:V4SF
1404           (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1405           (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1406           (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))]
1407   "VECTOR_UNIT_VSX_P (V4SFmode)"
1408   "@
1409    xvmaddasp %x0,%x1,%x2
1410    xvmaddmsp %x0,%x1,%x3
1411    xvmaddasp %x0,%x1,%x2
1412    xvmaddmsp %x0,%x1,%x3
1413    vmaddfp %0,%1,%2,%3"
1414   [(set_attr "type" "vecfloat")])
1416 (define_insn "*vsx_fmav2df4"
1417   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1418         (fma:V2DF
1419           (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1420           (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1421           (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))]
1422   "VECTOR_UNIT_VSX_P (V2DFmode)"
1423   "@
1424    xvmaddadp %x0,%x1,%x2
1425    xvmaddmdp %x0,%x1,%x3
1426    xvmaddadp %x0,%x1,%x2
1427    xvmaddmdp %x0,%x1,%x3"
1428   [(set_attr "type" "vecdouble")])
1430 (define_insn "*vsx_fms<mode>4"
1431   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1432         (fma:VSX_F
1433           (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,<VSa>,<VSa>")
1434           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1435           (neg:VSX_F
1436             (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1437   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1438   "@
1439    xvmsuba<VSs> %x0,%x1,%x2
1440    xvmsubm<VSs> %x0,%x1,%x3
1441    xvmsuba<VSs> %x0,%x1,%x2
1442    xvmsubm<VSs> %x0,%x1,%x3"
1443   [(set_attr "type" "<VStype_mul>")])
1445 (define_insn "*vsx_nfma<mode>4"
1446   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1447         (neg:VSX_F
1448          (fma:VSX_F
1449           (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,<VSa>,<VSa>")
1450           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1451           (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1452   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1453   "@
1454    xvnmadda<VSs> %x0,%x1,%x2
1455    xvnmaddm<VSs> %x0,%x1,%x3
1456    xvnmadda<VSs> %x0,%x1,%x2
1457    xvnmaddm<VSs> %x0,%x1,%x3"
1458   [(set_attr "type" "<VStype_mul>")
1459    (set_attr "fp_type" "<VSfptype_mul>")])
1461 (define_insn "*vsx_nfmsv4sf4"
1462   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1463         (neg:V4SF
1464          (fma:V4SF
1465            (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1466            (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1467            (neg:V4SF
1468              (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
1469   "VECTOR_UNIT_VSX_P (V4SFmode)"
1470   "@
1471    xvnmsubasp %x0,%x1,%x2
1472    xvnmsubmsp %x0,%x1,%x3
1473    xvnmsubasp %x0,%x1,%x2
1474    xvnmsubmsp %x0,%x1,%x3
1475    vnmsubfp %0,%1,%2,%3"
1476   [(set_attr "type" "vecfloat")])
1478 (define_insn "*vsx_nfmsv2df4"
1479   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1480         (neg:V2DF
1481          (fma:V2DF
1482            (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1483            (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1484            (neg:V2DF
1485              (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
1486   "VECTOR_UNIT_VSX_P (V2DFmode)"
1487   "@
1488    xvnmsubadp %x0,%x1,%x2
1489    xvnmsubmdp %x0,%x1,%x3
1490    xvnmsubadp %x0,%x1,%x2
1491    xvnmsubmdp %x0,%x1,%x3"
1492   [(set_attr "type" "vecdouble")])
1494 ;; Vector conditional expressions (no scalar version for these instructions)
1495 (define_insn "vsx_eq<mode>"
1496   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1497         (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1498                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1499   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1500   "xvcmpeq<VSs> %x0,%x1,%x2"
1501   [(set_attr "type" "<VStype_simple>")
1502    (set_attr "fp_type" "<VSfptype_simple>")])
1504 (define_insn "vsx_gt<mode>"
1505   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1506         (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1507                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1508   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1509   "xvcmpgt<VSs> %x0,%x1,%x2"
1510   [(set_attr "type" "<VStype_simple>")
1511    (set_attr "fp_type" "<VSfptype_simple>")])
1513 (define_insn "*vsx_ge<mode>"
1514   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1515         (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1516                   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1517   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1518   "xvcmpge<VSs> %x0,%x1,%x2"
1519   [(set_attr "type" "<VStype_simple>")
1520    (set_attr "fp_type" "<VSfptype_simple>")])
1522 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
1523 ;; indicate a combined status
1524 (define_insn "*vsx_eq_<mode>_p"
1525   [(set (reg:CC CR6_REGNO)
1526         (unspec:CC
1527          [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1528                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1529          UNSPEC_PREDICATE))
1530    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1531         (eq:VSX_F (match_dup 1)
1532                   (match_dup 2)))]
1533   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1534   "xvcmpeq<VSs>. %x0,%x1,%x2"
1535   [(set_attr "type" "<VStype_simple>")])
1537 (define_insn "*vsx_gt_<mode>_p"
1538   [(set (reg:CC CR6_REGNO)
1539         (unspec:CC
1540          [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1541                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1542          UNSPEC_PREDICATE))
1543    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1544         (gt:VSX_F (match_dup 1)
1545                   (match_dup 2)))]
1546   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1547   "xvcmpgt<VSs>. %x0,%x1,%x2"
1548   [(set_attr "type" "<VStype_simple>")])
1550 (define_insn "*vsx_ge_<mode>_p"
1551   [(set (reg:CC CR6_REGNO)
1552         (unspec:CC
1553          [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1554                  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1555          UNSPEC_PREDICATE))
1556    (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1557         (ge:VSX_F (match_dup 1)
1558                   (match_dup 2)))]
1559   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1560   "xvcmpge<VSs>. %x0,%x1,%x2"
1561   [(set_attr "type" "<VStype_simple>")])
1563 ;; Vector select
1564 (define_insn "*vsx_xxsel<mode>"
1565   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1566         (if_then_else:VSX_L
1567          (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1568                 (match_operand:VSX_L 4 "zero_constant" ""))
1569          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1570          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1571   "VECTOR_MEM_VSX_P (<MODE>mode)"
1572   "xxsel %x0,%x3,%x2,%x1"
1573   [(set_attr "type" "vecmove")])
1575 (define_insn "*vsx_xxsel<mode>_uns"
1576   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1577         (if_then_else:VSX_L
1578          (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1579                    (match_operand:VSX_L 4 "zero_constant" ""))
1580          (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1581          (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1582   "VECTOR_MEM_VSX_P (<MODE>mode)"
1583   "xxsel %x0,%x3,%x2,%x1"
1584   [(set_attr "type" "vecmove")])
1586 ;; Copy sign
1587 (define_insn "vsx_copysign<mode>3"
1588   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1589         (unspec:VSX_F
1590          [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1591           (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")]
1592          UNSPEC_COPYSIGN))]
1593   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1594   "xvcpsgn<VSs> %x0,%x2,%x1"
1595   [(set_attr "type" "<VStype_simple>")
1596    (set_attr "fp_type" "<VSfptype_simple>")])
1598 ;; For the conversions, limit the register class for the integer value to be
1599 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
1600 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
1601 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
1602 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md
1603 ;; in allowing virtual registers.
1604 (define_insn "vsx_float<VSi><mode>2"
1605   [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1606         (float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1607   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1608   "xvcvsx<VSc><VSs> %x0,%x1"
1609   [(set_attr "type" "<VStype_simple>")
1610    (set_attr "fp_type" "<VSfptype_simple>")])
1612 (define_insn "vsx_floatuns<VSi><mode>2"
1613   [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1614         (unsigned_float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1615   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1616   "xvcvux<VSc><VSs> %x0,%x1"
1617   [(set_attr "type" "<VStype_simple>")
1618    (set_attr "fp_type" "<VSfptype_simple>")])
1620 (define_insn "vsx_fix_trunc<mode><VSi>2"
1621   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1622         (fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1623   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1624   "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
1625   [(set_attr "type" "<VStype_simple>")
1626    (set_attr "fp_type" "<VSfptype_simple>")])
1628 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
1629   [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1630         (unsigned_fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1631   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1632   "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
1633   [(set_attr "type" "<VStype_simple>")
1634    (set_attr "fp_type" "<VSfptype_simple>")])
1636 ;; Math rounding functions
1637 (define_insn "vsx_x<VSv>r<VSs>i"
1638   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1639         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1640                       UNSPEC_VSX_ROUND_I))]
1641   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1642   "x<VSv>r<VSs>i %x0,%x1"
1643   [(set_attr "type" "<VStype_simple>")
1644    (set_attr "fp_type" "<VSfptype_simple>")])
1646 (define_insn "vsx_x<VSv>r<VSs>ic"
1647   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1648         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1649                       UNSPEC_VSX_ROUND_IC))]
1650   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1651   "x<VSv>r<VSs>ic %x0,%x1"
1652   [(set_attr "type" "<VStype_simple>")
1653    (set_attr "fp_type" "<VSfptype_simple>")])
1655 (define_insn "vsx_btrunc<mode>2"
1656   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1657         (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1658   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1659   "xvr<VSs>iz %x0,%x1"
1660   [(set_attr "type" "<VStype_simple>")
1661    (set_attr "fp_type" "<VSfptype_simple>")])
1663 (define_insn "*vsx_b2trunc<mode>2"
1664   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1665         (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1666                       UNSPEC_FRIZ))]
1667   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1668   "x<VSv>r<VSs>iz %x0,%x1"
1669   [(set_attr "type" "<VStype_simple>")
1670    (set_attr "fp_type" "<VSfptype_simple>")])
1672 (define_insn "vsx_floor<mode>2"
1673   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1674         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1675                       UNSPEC_FRIM))]
1676   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1677   "xvr<VSs>im %x0,%x1"
1678   [(set_attr "type" "<VStype_simple>")
1679    (set_attr "fp_type" "<VSfptype_simple>")])
1681 (define_insn "vsx_ceil<mode>2"
1682   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1683         (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1684                       UNSPEC_FRIP))]
1685   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1686   "xvr<VSs>ip %x0,%x1"
1687   [(set_attr "type" "<VStype_simple>")
1688    (set_attr "fp_type" "<VSfptype_simple>")])
1691 ;; VSX convert to/from double vector
1693 ;; Convert between single and double precision
1694 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
1695 ;; scalar single precision instructions internally use the double format.
1696 ;; Prefer the altivec registers, since we likely will need to do a vperm
1697 (define_insn "vsx_<VS_spdp_insn>"
1698   [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?<VSa>")
1699         (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,<VSa>")]
1700                               UNSPEC_VSX_CVSPDP))]
1701   "VECTOR_UNIT_VSX_P (<MODE>mode)"
1702   "<VS_spdp_insn> %x0,%x1"
1703   [(set_attr "type" "<VS_spdp_type>")])
1705 ;; xscvspdp, represent the scalar SF type as V4SF
1706 (define_insn "vsx_xscvspdp"
1707   [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
1708         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1709                    UNSPEC_VSX_CVSPDP))]
1710   "VECTOR_UNIT_VSX_P (V4SFmode)"
1711   "xscvspdp %x0,%x1"
1712   [(set_attr "type" "fp")])
1714 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
1715 ;; format of scalars is actually DF.
1716 (define_insn "vsx_xscvdpsp_scalar"
1717   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1718         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
1719                      UNSPEC_VSX_CVSPDP))]
1720   "VECTOR_UNIT_VSX_P (V4SFmode)"
1721   "xscvdpsp %x0,%x1"
1722   [(set_attr "type" "fp")])
1724 ;; Same as vsx_xscvspdp, but use SF as the type
1725 (define_insn "vsx_xscvspdp_scalar2"
1726   [(set (match_operand:SF 0 "vsx_register_operand" "=ww")
1727         (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1728                    UNSPEC_VSX_CVSPDP))]
1729   "VECTOR_UNIT_VSX_P (V4SFmode)"
1730   "xscvspdp %x0,%x1"
1731   [(set_attr "type" "fp")])
1733 ;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
1734 (define_insn "vsx_xscvdpspn"
1735   [(set (match_operand:V4SF 0 "vsx_register_operand" "=ww,?ww")
1736         (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wd,wa")]
1737                      UNSPEC_VSX_CVDPSPN))]
1738   "TARGET_XSCVDPSPN"
1739   "xscvdpspn %x0,%x1"
1740   [(set_attr "type" "fp")])
1742 (define_insn "vsx_xscvspdpn"
1743   [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?ws")
1744         (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
1745                    UNSPEC_VSX_CVSPDPN))]
1746   "TARGET_XSCVSPDPN"
1747   "xscvspdpn %x0,%x1"
1748   [(set_attr "type" "fp")])
1750 (define_insn "vsx_xscvdpspn_scalar"
1751   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa")
1752         (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "ww,ww")]
1753                      UNSPEC_VSX_CVDPSPN))]
1754   "TARGET_XSCVDPSPN"
1755   "xscvdpspn %x0,%x1"
1756   [(set_attr "type" "fp")])
1758 ;; Used by direct move to move a SFmode value from GPR to VSX register
1759 (define_insn "vsx_xscvspdpn_directmove"
1760   [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
1761         (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
1762                    UNSPEC_VSX_CVSPDPN))]
1763   "TARGET_XSCVSPDPN"
1764   "xscvspdpn %x0,%x1"
1765   [(set_attr "type" "fp")])
1767 ;; Convert and scale (used by vec_ctf, vec_cts, vec_ctu for double/long long)
1769 (define_expand "vsx_xvcvsxddp_scale"
1770   [(match_operand:V2DF 0 "vsx_register_operand" "")
1771    (match_operand:V2DI 1 "vsx_register_operand" "")
1772    (match_operand:QI 2 "immediate_operand" "")]
1773   "VECTOR_UNIT_VSX_P (V2DFmode)"
1775   rtx op0 = operands[0];
1776   rtx op1 = operands[1];
1777   int scale = INTVAL(operands[2]);
1778   emit_insn (gen_vsx_xvcvsxddp (op0, op1));
1779   if (scale != 0)
1780     rs6000_scale_v2df (op0, op0, -scale);
1781   DONE;
1784 (define_insn "vsx_xvcvsxddp"
1785   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1786         (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1787                      UNSPEC_VSX_XVCVSXDDP))]
1788   "VECTOR_UNIT_VSX_P (V2DFmode)"
1789   "xvcvsxddp %x0,%x1"
1790   [(set_attr "type" "vecdouble")])
1792 (define_expand "vsx_xvcvuxddp_scale"
1793   [(match_operand:V2DF 0 "vsx_register_operand" "")
1794    (match_operand:V2DI 1 "vsx_register_operand" "")
1795    (match_operand:QI 2 "immediate_operand" "")]
1796   "VECTOR_UNIT_VSX_P (V2DFmode)"
1798   rtx op0 = operands[0];
1799   rtx op1 = operands[1];
1800   int scale = INTVAL(operands[2]);
1801   emit_insn (gen_vsx_xvcvuxddp (op0, op1));
1802   if (scale != 0)
1803     rs6000_scale_v2df (op0, op0, -scale);
1804   DONE;
1807 (define_insn "vsx_xvcvuxddp"
1808   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1809         (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1810                      UNSPEC_VSX_XVCVUXDDP))]
1811   "VECTOR_UNIT_VSX_P (V2DFmode)"
1812   "xvcvuxddp %x0,%x1"
1813   [(set_attr "type" "vecdouble")])
1815 (define_expand "vsx_xvcvdpsxds_scale"
1816   [(match_operand:V2DI 0 "vsx_register_operand" "")
1817    (match_operand:V2DF 1 "vsx_register_operand" "")
1818    (match_operand:QI 2 "immediate_operand" "")]
1819   "VECTOR_UNIT_VSX_P (V2DFmode)"
1821   rtx op0 = operands[0];
1822   rtx op1 = operands[1];
1823   rtx tmp;
1824   int scale = INTVAL (operands[2]);
1825   if (scale == 0)
1826     tmp = op1;
1827   else
1828     {
1829       tmp  = gen_reg_rtx (V2DFmode);
1830       rs6000_scale_v2df (tmp, op1, scale);
1831     }
1832   emit_insn (gen_vsx_xvcvdpsxds (op0, tmp));
1833   DONE;
1836 (define_insn "vsx_xvcvdpsxds"
1837   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1838         (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1839                      UNSPEC_VSX_XVCVDPSXDS))]
1840   "VECTOR_UNIT_VSX_P (V2DFmode)"
1841   "xvcvdpsxds %x0,%x1"
1842   [(set_attr "type" "vecdouble")])
1844 (define_expand "vsx_xvcvdpuxds_scale"
1845   [(match_operand:V2DI 0 "vsx_register_operand" "")
1846    (match_operand:V2DF 1 "vsx_register_operand" "")
1847    (match_operand:QI 2 "immediate_operand" "")]
1848   "VECTOR_UNIT_VSX_P (V2DFmode)"
1850   rtx op0 = operands[0];
1851   rtx op1 = operands[1];
1852   rtx tmp;
1853   int scale = INTVAL (operands[2]);
1854   if (scale == 0)
1855     tmp = op1;
1856   else
1857     {
1858       tmp = gen_reg_rtx (V2DFmode);
1859       rs6000_scale_v2df (tmp, op1, scale);
1860     }
1861   emit_insn (gen_vsx_xvcvdpuxds (op0, tmp));
1862   DONE;
1865 (define_insn "vsx_xvcvdpuxds"
1866   [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1867         (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1868                      UNSPEC_VSX_XVCVDPUXDS))]
1869   "VECTOR_UNIT_VSX_P (V2DFmode)"
1870   "xvcvdpuxds %x0,%x1"
1871   [(set_attr "type" "vecdouble")])
1873 ;; Convert from 64-bit to 32-bit types
1874 ;; Note, favor the Altivec registers since the usual use of these instructions
1875 ;; is in vector converts and we need to use the Altivec vperm instruction.
1877 (define_insn "vsx_xvcvdpsxws"
1878   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1879         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1880                      UNSPEC_VSX_CVDPSXWS))]
1881   "VECTOR_UNIT_VSX_P (V2DFmode)"
1882   "xvcvdpsxws %x0,%x1"
1883   [(set_attr "type" "vecdouble")])
1885 (define_insn "vsx_xvcvdpuxws"
1886   [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1887         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1888                      UNSPEC_VSX_CVDPUXWS))]
1889   "VECTOR_UNIT_VSX_P (V2DFmode)"
1890   "xvcvdpuxws %x0,%x1"
1891   [(set_attr "type" "vecdouble")])
1893 (define_insn "vsx_xvcvsxdsp"
1894   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1895         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1896                      UNSPEC_VSX_CVSXDSP))]
1897   "VECTOR_UNIT_VSX_P (V2DFmode)"
1898   "xvcvsxdsp %x0,%x1"
1899   [(set_attr "type" "vecfloat")])
1901 (define_insn "vsx_xvcvuxdsp"
1902   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
1903         (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
1904                      UNSPEC_VSX_CVUXDSP))]
1905   "VECTOR_UNIT_VSX_P (V2DFmode)"
1906   "xvcvuxwdp %x0,%x1"
1907   [(set_attr "type" "vecdouble")])
1909 ;; Convert from 32-bit to 64-bit types
1910 (define_insn "vsx_xvcvsxwdp"
1911   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1912         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1913                      UNSPEC_VSX_CVSXWDP))]
1914   "VECTOR_UNIT_VSX_P (V2DFmode)"
1915   "xvcvsxwdp %x0,%x1"
1916   [(set_attr "type" "vecdouble")])
1918 (define_insn "vsx_xvcvuxwdp"
1919   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1920         (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1921                      UNSPEC_VSX_CVUXWDP))]
1922   "VECTOR_UNIT_VSX_P (V2DFmode)"
1923   "xvcvuxwdp %x0,%x1"
1924   [(set_attr "type" "vecdouble")])
1926 (define_insn "vsx_xvcvspsxds"
1927   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1928         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1929                      UNSPEC_VSX_CVSPSXDS))]
1930   "VECTOR_UNIT_VSX_P (V2DFmode)"
1931   "xvcvspsxds %x0,%x1"
1932   [(set_attr "type" "vecdouble")])
1934 (define_insn "vsx_xvcvspuxds"
1935   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1936         (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1937                      UNSPEC_VSX_CVSPUXDS))]
1938   "VECTOR_UNIT_VSX_P (V2DFmode)"
1939   "xvcvspuxds %x0,%x1"
1940   [(set_attr "type" "vecdouble")])
1942 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1943 ;; since the xvrdpiz instruction does not truncate the value if the floating
1944 ;; point value is < LONG_MIN or > LONG_MAX.
1945 (define_insn "*vsx_float_fix_v2df2"
1946   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1947         (float:V2DF
1948          (fix:V2DI
1949           (match_operand:V2DF 1 "vsx_register_operand" "wd,?wa"))))]
1950   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1951    && VECTOR_UNIT_VSX_P (V2DFmode) && flag_unsafe_math_optimizations
1952    && !flag_trapping_math && TARGET_FRIZ"
1953   "xvrdpiz %x0,%x1"
1954   [(set_attr "type" "vecdouble")
1955    (set_attr "fp_type" "fp_addsub_d")])
1958 ;; Permute operations
1960 ;; Build a V2DF/V2DI vector from two scalars
1961 (define_insn "vsx_concat_<mode>"
1962   [(set (match_operand:VSX_D 0 "gpc_reg_operand" "=<VSa>,we")
1963         (vec_concat:VSX_D
1964          (match_operand:<VS_scalar> 1 "gpc_reg_operand" "<VS_64reg>,b")
1965          (match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VS_64reg>,b")))]
1966   "VECTOR_MEM_VSX_P (<MODE>mode)"
1968   if (which_alternative == 0)
1969     return (BYTES_BIG_ENDIAN
1970             ? "xxpermdi %x0,%x1,%x2,0"
1971             : "xxpermdi %x0,%x2,%x1,0");
1973   else if (which_alternative == 1)
1974     return (BYTES_BIG_ENDIAN
1975             ? "mtvsrdd %x0,%1,%2"
1976             : "mtvsrdd %x0,%2,%1");
1978   else
1979     gcc_unreachable ();
1981   [(set_attr "type" "vecperm")])
1983 ;; Special purpose concat using xxpermdi to glue two single precision values
1984 ;; together, relying on the fact that internally scalar floats are represented
1985 ;; as doubles.  This is used to initialize a V4SF vector with 4 floats
1986 (define_insn "vsx_concat_v2sf"
1987   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1988         (unspec:V2DF
1989          [(match_operand:SF 1 "vsx_register_operand" "ww")
1990           (match_operand:SF 2 "vsx_register_operand" "ww")]
1991          UNSPEC_VSX_CONCAT))]
1992   "VECTOR_MEM_VSX_P (V2DFmode)"
1994   if (BYTES_BIG_ENDIAN)
1995     return "xxpermdi %x0,%x1,%x2,0";
1996   else
1997     return "xxpermdi %x0,%x2,%x1,0";
1999   [(set_attr "type" "vecperm")])
2001 ;; V4SImode initialization splitter
2002 (define_insn_and_split "vsx_init_v4si"
2003   [(set (match_operand:V4SI 0 "gpc_reg_operand" "=&r")
2004         (unspec:V4SI
2005          [(match_operand:SI 1 "reg_or_cint_operand" "rn")
2006           (match_operand:SI 2 "reg_or_cint_operand" "rn")
2007           (match_operand:SI 3 "reg_or_cint_operand" "rn")
2008           (match_operand:SI 4 "reg_or_cint_operand" "rn")]
2009          UNSPEC_VSX_VEC_INIT))
2010    (clobber (match_scratch:DI 5 "=&r"))
2011    (clobber (match_scratch:DI 6 "=&r"))]
2012    "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2013    "#"
2014    "&& reload_completed"
2015    [(const_int 0)]
2017   rs6000_split_v4si_init (operands);
2018   DONE;
2021 ;; xxpermdi for little endian loads and stores.  We need several of
2022 ;; these since the form of the PARALLEL differs by mode.
2023 (define_insn "*vsx_xxpermdi2_le_<mode>"
2024   [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
2025         (vec_select:VSX_LE
2026           (match_operand:VSX_LE 1 "vsx_register_operand" "<VSa>")
2027           (parallel [(const_int 1) (const_int 0)])))]
2028   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
2029   "xxpermdi %x0,%x1,%x1,2"
2030   [(set_attr "type" "vecperm")])
2032 (define_insn "*vsx_xxpermdi4_le_<mode>"
2033   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
2034         (vec_select:VSX_W
2035           (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2036           (parallel [(const_int 2) (const_int 3)
2037                      (const_int 0) (const_int 1)])))]
2038   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
2039   "xxpermdi %x0,%x1,%x1,2"
2040   [(set_attr "type" "vecperm")])
2042 (define_insn "*vsx_xxpermdi8_le_V8HI"
2043   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
2044         (vec_select:V8HI
2045           (match_operand:V8HI 1 "vsx_register_operand" "wa")
2046           (parallel [(const_int 4) (const_int 5)
2047                      (const_int 6) (const_int 7)
2048                      (const_int 0) (const_int 1)
2049                      (const_int 2) (const_int 3)])))]
2050   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
2051   "xxpermdi %x0,%x1,%x1,2"
2052   [(set_attr "type" "vecperm")])
2054 (define_insn "*vsx_xxpermdi16_le_V16QI"
2055   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
2056         (vec_select:V16QI
2057           (match_operand:V16QI 1 "vsx_register_operand" "wa")
2058           (parallel [(const_int 8) (const_int 9)
2059                      (const_int 10) (const_int 11)
2060                      (const_int 12) (const_int 13)
2061                      (const_int 14) (const_int 15)
2062                      (const_int 0) (const_int 1)
2063                      (const_int 2) (const_int 3)
2064                      (const_int 4) (const_int 5)
2065                      (const_int 6) (const_int 7)])))]
2066   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
2067   "xxpermdi %x0,%x1,%x1,2"
2068   [(set_attr "type" "vecperm")])
2070 ;; lxvd2x for little endian loads.  We need several of
2071 ;; these since the form of the PARALLEL differs by mode.
2072 (define_insn "*vsx_lxvd2x2_le_<mode>"
2073   [(set (match_operand:VSX_LE 0 "vsx_register_operand" "=<VSa>")
2074         (vec_select:VSX_LE
2075           (match_operand:VSX_LE 1 "memory_operand" "Z")
2076           (parallel [(const_int 1) (const_int 0)])))]
2077   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2078   "lxvd2x %x0,%y1"
2079   [(set_attr "type" "vecload")])
2081 (define_insn "*vsx_lxvd2x4_le_<mode>"
2082   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
2083         (vec_select:VSX_W
2084           (match_operand:VSX_W 1 "memory_operand" "Z")
2085           (parallel [(const_int 2) (const_int 3)
2086                      (const_int 0) (const_int 1)])))]
2087   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2088   "lxvd2x %x0,%y1"
2089   [(set_attr "type" "vecload")])
2091 (define_insn "*vsx_lxvd2x8_le_V8HI"
2092   [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
2093         (vec_select:V8HI
2094           (match_operand:V8HI 1 "memory_operand" "Z")
2095           (parallel [(const_int 4) (const_int 5)
2096                      (const_int 6) (const_int 7)
2097                      (const_int 0) (const_int 1)
2098                      (const_int 2) (const_int 3)])))]
2099   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2100   "lxvd2x %x0,%y1"
2101   [(set_attr "type" "vecload")])
2103 (define_insn "*vsx_lxvd2x16_le_V16QI"
2104   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
2105         (vec_select:V16QI
2106           (match_operand:V16QI 1 "memory_operand" "Z")
2107           (parallel [(const_int 8) (const_int 9)
2108                      (const_int 10) (const_int 11)
2109                      (const_int 12) (const_int 13)
2110                      (const_int 14) (const_int 15)
2111                      (const_int 0) (const_int 1)
2112                      (const_int 2) (const_int 3)
2113                      (const_int 4) (const_int 5)
2114                      (const_int 6) (const_int 7)])))]
2115   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2116   "lxvd2x %x0,%y1"
2117   [(set_attr "type" "vecload")])
2119 ;; stxvd2x for little endian stores.  We need several of
2120 ;; these since the form of the PARALLEL differs by mode.
2121 (define_insn "*vsx_stxvd2x2_le_<mode>"
2122   [(set (match_operand:VSX_LE 0 "memory_operand" "=Z")
2123         (vec_select:VSX_LE
2124           (match_operand:VSX_LE 1 "vsx_register_operand" "<VSa>")
2125           (parallel [(const_int 1) (const_int 0)])))]
2126   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2127   "stxvd2x %x1,%y0"
2128   [(set_attr "type" "vecstore")])
2130 (define_insn "*vsx_stxvd2x4_le_<mode>"
2131   [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
2132         (vec_select:VSX_W
2133           (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2134           (parallel [(const_int 2) (const_int 3)
2135                      (const_int 0) (const_int 1)])))]
2136   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2137   "stxvd2x %x1,%y0"
2138   [(set_attr "type" "vecstore")])
2140 (define_insn "*vsx_stxvd2x8_le_V8HI"
2141   [(set (match_operand:V8HI 0 "memory_operand" "=Z")
2142         (vec_select:V8HI
2143           (match_operand:V8HI 1 "vsx_register_operand" "wa")
2144           (parallel [(const_int 4) (const_int 5)
2145                      (const_int 6) (const_int 7)
2146                      (const_int 0) (const_int 1)
2147                      (const_int 2) (const_int 3)])))]
2148   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2149   "stxvd2x %x1,%y0"
2150   [(set_attr "type" "vecstore")])
2152 (define_insn "*vsx_stxvd2x16_le_V16QI"
2153   [(set (match_operand:V16QI 0 "memory_operand" "=Z")
2154         (vec_select:V16QI
2155           (match_operand:V16QI 1 "vsx_register_operand" "wa")
2156           (parallel [(const_int 8) (const_int 9)
2157                      (const_int 10) (const_int 11)
2158                      (const_int 12) (const_int 13)
2159                      (const_int 14) (const_int 15)
2160                      (const_int 0) (const_int 1)
2161                      (const_int 2) (const_int 3)
2162                      (const_int 4) (const_int 5)
2163                      (const_int 6) (const_int 7)])))]
2164   "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2165   "stxvd2x %x1,%y0"
2166   [(set_attr "type" "vecstore")])
2168 ;; Convert a TImode value into V1TImode
2169 (define_expand "vsx_set_v1ti"
2170   [(match_operand:V1TI 0 "nonimmediate_operand" "")
2171    (match_operand:V1TI 1 "nonimmediate_operand" "")
2172    (match_operand:TI 2 "input_operand" "")
2173    (match_operand:QI 3 "u5bit_cint_operand" "")]
2174   "VECTOR_MEM_VSX_P (V1TImode)"
2176   if (operands[3] != const0_rtx)
2177     gcc_unreachable ();
2179   emit_move_insn (operands[0], gen_lowpart (V1TImode, operands[1]));
2180   DONE;
2183 ;; Set the element of a V2DI/VD2F mode
2184 (define_insn "vsx_set_<mode>"
2185   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?<VSa>")
2186         (unspec:VSX_D
2187          [(match_operand:VSX_D 1 "vsx_register_operand" "wd,<VSa>")
2188           (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")
2189           (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
2190          UNSPEC_VSX_SET))]
2191   "VECTOR_MEM_VSX_P (<MODE>mode)"
2193   int idx_first = BYTES_BIG_ENDIAN ? 0 : 1;
2194   if (INTVAL (operands[3]) == idx_first)
2195     return \"xxpermdi %x0,%x2,%x1,1\";
2196   else if (INTVAL (operands[3]) == 1 - idx_first)
2197     return \"xxpermdi %x0,%x1,%x2,0\";
2198   else
2199     gcc_unreachable ();
2201   [(set_attr "type" "vecperm")])
2203 ;; Extract a DF/DI element from V2DF/V2DI
2204 ;; Optimize cases were we can do a simple or direct move.
2205 ;; Or see if we can avoid doing the move at all
2207 ;; There are some unresolved problems with reload that show up if an Altivec
2208 ;; register was picked.  Limit the scalar value to FPRs for now.
2210 (define_insn "vsx_extract_<mode>"
2211   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=d,    d,     wr, wr")
2213         (vec_select:<VS_scalar>
2214          (match_operand:VSX_D 1 "gpc_reg_operand"      "<VSa>, <VSa>, wm, wo")
2216          (parallel
2217           [(match_operand:QI 2 "const_0_to_1_operand"  "wD,    n,     wD, n")])))]
2218   "VECTOR_MEM_VSX_P (<MODE>mode)"
2220   int element = INTVAL (operands[2]);
2221   int op0_regno = REGNO (operands[0]);
2222   int op1_regno = REGNO (operands[1]);
2223   int fldDM;
2225   gcc_assert (IN_RANGE (element, 0, 1));
2226   gcc_assert (VSX_REGNO_P (op1_regno));
2228   if (element == VECTOR_ELEMENT_SCALAR_64BIT)
2229     {
2230       if (op0_regno == op1_regno)
2231         return ASM_COMMENT_START " vec_extract to same register";
2233       else if (INT_REGNO_P (op0_regno) && TARGET_DIRECT_MOVE
2234                && TARGET_POWERPC64)
2235         return "mfvsrd %0,%x1";
2237       else if (FP_REGNO_P (op0_regno) && FP_REGNO_P (op1_regno))
2238         return "fmr %0,%1";
2240       else if (VSX_REGNO_P (op0_regno))
2241         return "xxlor %x0,%x1,%x1";
2243       else
2244         gcc_unreachable ();
2245     }
2247   else if (element == VECTOR_ELEMENT_MFVSRLD_64BIT && INT_REGNO_P (op0_regno)
2248            && TARGET_P9_VECTOR && TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
2249     return "mfvsrld %0,%x1";
2251   else if (VSX_REGNO_P (op0_regno))
2252     {
2253       fldDM = element << 1;
2254       if (!BYTES_BIG_ENDIAN)
2255         fldDM = 3 - fldDM;
2256       operands[3] = GEN_INT (fldDM);
2257       return "xxpermdi %x0,%x1,%x1,%3";
2258     }
2260   else
2261     gcc_unreachable ();
2263   [(set_attr "type" "veclogical,mftgpr,mftgpr,vecperm")])
2265 ;; Optimize extracting a single scalar element from memory.
2266 (define_insn_and_split "*vsx_extract_<P:mode>_<VSX_D:mode>_load"
2267   [(set (match_operand:<VS_scalar> 0 "register_operand" "=<VSX_D:VS_64reg>,wr")
2268         (vec_select:<VSX_D:VS_scalar>
2269          (match_operand:VSX_D 1 "memory_operand" "m,m")
2270          (parallel [(match_operand:QI 2 "const_0_to_1_operand" "n,n")])))
2271    (clobber (match_scratch:P 3 "=&b,&b"))]
2272   "VECTOR_MEM_VSX_P (<VSX_D:MODE>mode)"
2273   "#"
2274   "&& reload_completed"
2275   [(set (match_dup 0) (match_dup 4))]
2277   operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2278                                            operands[3], <VSX_D:VS_scalar>mode);
2280   [(set_attr "type" "fpload,load")
2281    (set_attr "length" "8")])
2283 ;; Optimize storing a single scalar element that is the right location to
2284 ;; memory
2285 (define_insn "*vsx_extract_<mode>_store"
2286   [(set (match_operand:<VS_scalar> 0 "memory_operand" "=m,Z,o")
2287         (vec_select:<VS_scalar>
2288          (match_operand:VSX_D 1 "register_operand" "d,wv,wb")
2289          (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))]
2290   "VECTOR_MEM_VSX_P (<MODE>mode)"
2291   "@
2292    stfd%U0%X0 %1,%0
2293    stxsd%U0x %x1,%y0
2294    stxsd %1,%0"
2295   [(set_attr "type" "fpstore")
2296    (set_attr "length" "4")])
2298 ;; Variable V2DI/V2DF extract shift
2299 (define_insn "vsx_vslo_<mode>"
2300   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v")
2301         (unspec:<VS_scalar> [(match_operand:VSX_D 1 "gpc_reg_operand" "v")
2302                              (match_operand:V2DI 2 "gpc_reg_operand" "v")]
2303                             UNSPEC_VSX_VSLO))]
2304   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2305   "vslo %0,%1,%2"
2306   [(set_attr "type" "vecperm")])
2308 ;; Variable V2DI/V2DF extract
2309 (define_insn_and_split "vsx_extract_<mode>_var"
2310   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,<VSa>,r")
2311         (unspec:<VS_scalar> [(match_operand:VSX_D 1 "input_operand" "v,m,m")
2312                              (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2313                             UNSPEC_VSX_EXTRACT))
2314    (clobber (match_scratch:DI 3 "=r,&b,&b"))
2315    (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
2316   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2317   "#"
2318   "&& reload_completed"
2319   [(const_int 0)]
2321   rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2322                                 operands[3], operands[4]);
2323   DONE;
2326 ;; Extract a SF element from V4SF
2327 (define_insn_and_split "vsx_extract_v4sf"
2328   [(set (match_operand:SF 0 "vsx_register_operand" "=ww")
2329         (vec_select:SF
2330          (match_operand:V4SF 1 "vsx_register_operand" "wa")
2331          (parallel [(match_operand:QI 2 "u5bit_cint_operand" "n")])))
2332    (clobber (match_scratch:V4SF 3 "=0"))]
2333   "VECTOR_UNIT_VSX_P (V4SFmode)"
2334   "#"
2335   "&& 1"
2336   [(const_int 0)]
2338   rtx op0 = operands[0];
2339   rtx op1 = operands[1];
2340   rtx op2 = operands[2];
2341   rtx op3 = operands[3];
2342   rtx tmp;
2343   HOST_WIDE_INT ele = BYTES_BIG_ENDIAN ? INTVAL (op2) : 3 - INTVAL (op2);
2345   if (ele == 0)
2346     tmp = op1;
2347   else
2348     {
2349       if (GET_CODE (op3) == SCRATCH)
2350         op3 = gen_reg_rtx (V4SFmode);
2351       emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, GEN_INT (ele)));
2352       tmp = op3;
2353     }
2354   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
2355   DONE;
2357   [(set_attr "length" "8")
2358    (set_attr "type" "fp")])
2360 (define_insn_and_split "*vsx_extract_v4sf_<mode>_load"
2361   [(set (match_operand:SF 0 "register_operand" "=f,wv,wb,?r")
2362         (vec_select:SF
2363          (match_operand:V4SF 1 "memory_operand" "m,Z,m,m")
2364          (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n,n")])))
2365    (clobber (match_scratch:P 3 "=&b,&b,&b,&b"))]
2366   "VECTOR_MEM_VSX_P (V4SFmode)"
2367   "#"
2368   "&& reload_completed"
2369   [(set (match_dup 0) (match_dup 4))]
2371   operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2372                                            operands[3], SFmode);
2374   [(set_attr "type" "fpload,fpload,fpload,load")
2375    (set_attr "length" "8")])
2377 ;; Variable V4SF extract
2378 (define_insn_and_split "vsx_extract_v4sf_var"
2379   [(set (match_operand:SF 0 "gpc_reg_operand" "=ww,ww,?r")
2380         (unspec:SF [(match_operand:V4SF 1 "input_operand" "v,m,m")
2381                     (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2382                    UNSPEC_VSX_EXTRACT))
2383    (clobber (match_scratch:DI 3 "=r,&b,&b"))
2384    (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
2385   "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT
2386    && TARGET_UPPER_REGS_SF"
2387   "#"
2388   "&& reload_completed"
2389   [(const_int 0)]
2391   rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2392                                 operands[3], operands[4]);
2393   DONE;
2396 ;; Expand the builtin form of xxpermdi to canonical rtl.
2397 (define_expand "vsx_xxpermdi_<mode>"
2398   [(match_operand:VSX_L 0 "vsx_register_operand" "")
2399    (match_operand:VSX_L 1 "vsx_register_operand" "")
2400    (match_operand:VSX_L 2 "vsx_register_operand" "")
2401    (match_operand:QI 3 "u5bit_cint_operand" "")]
2402   "VECTOR_MEM_VSX_P (<MODE>mode)"
2404   rtx target = operands[0];
2405   rtx op0 = operands[1];
2406   rtx op1 = operands[2];
2407   int mask = INTVAL (operands[3]);
2408   rtx perm0 = GEN_INT ((mask >> 1) & 1);
2409   rtx perm1 = GEN_INT ((mask & 1) + 2);
2410   rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2412   if (<MODE>mode == V2DFmode)
2413     gen = gen_vsx_xxpermdi2_v2df_1;
2414   else
2415     {
2416       gen = gen_vsx_xxpermdi2_v2di_1;
2417       if (<MODE>mode != V2DImode)
2418         {
2419           target = gen_lowpart (V2DImode, target);
2420           op0 = gen_lowpart (V2DImode, op0);
2421           op1 = gen_lowpart (V2DImode, op1);
2422         }
2423     }
2424   /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
2425      transformation we don't want; it is necessary for
2426      rs6000_expand_vec_perm_const_1 but not for this use.  So we
2427      prepare for that by reversing the transformation here.  */
2428   if (BYTES_BIG_ENDIAN)
2429     emit_insn (gen (target, op0, op1, perm0, perm1));
2430   else
2431     {
2432       rtx p0 = GEN_INT (3 - INTVAL (perm1));
2433       rtx p1 = GEN_INT (3 - INTVAL (perm0));
2434       emit_insn (gen (target, op1, op0, p0, p1));
2435     }
2436   DONE;
2439 (define_insn "vsx_xxpermdi2_<mode>_1"
2440   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
2441         (vec_select:VSX_D
2442           (vec_concat:<VS_double>
2443             (match_operand:VSX_D 1 "vsx_register_operand" "wd")
2444             (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
2445           (parallel [(match_operand 3 "const_0_to_1_operand" "")
2446                      (match_operand 4 "const_2_to_3_operand" "")])))]
2447   "VECTOR_MEM_VSX_P (<MODE>mode)"
2449   int op3, op4, mask;
2451   /* For little endian, swap operands and invert/swap selectors
2452      to get the correct xxpermdi.  The operand swap sets up the
2453      inputs as a little endian array.  The selectors are swapped
2454      because they are defined to use big endian ordering.  The
2455      selectors are inverted to get the correct doublewords for
2456      little endian ordering.  */
2457   if (BYTES_BIG_ENDIAN)
2458     {
2459       op3 = INTVAL (operands[3]);
2460       op4 = INTVAL (operands[4]);
2461     }
2462   else
2463     {
2464       op3 = 3 - INTVAL (operands[4]);
2465       op4 = 3 - INTVAL (operands[3]);
2466     }
2468   mask = (op3 << 1) | (op4 - 2);
2469   operands[3] = GEN_INT (mask);
2471   if (BYTES_BIG_ENDIAN)
2472     return "xxpermdi %x0,%x1,%x2,%3";
2473   else
2474     return "xxpermdi %x0,%x2,%x1,%3";
2476   [(set_attr "type" "vecperm")])
2478 (define_expand "vec_perm_const<mode>"
2479   [(match_operand:VSX_D 0 "vsx_register_operand" "")
2480    (match_operand:VSX_D 1 "vsx_register_operand" "")
2481    (match_operand:VSX_D 2 "vsx_register_operand" "")
2482    (match_operand:V2DI  3 "" "")]
2483   "VECTOR_MEM_VSX_P (<MODE>mode)"
2485   if (rs6000_expand_vec_perm_const (operands))
2486     DONE;
2487   else
2488     FAIL;
2491 ;; Extraction of a single element in a small integer vector.  None of the small
2492 ;; types are currently allowed in a vector register, so we extract to a DImode
2493 ;; and either do a direct move or store.
2494 (define_expand  "vsx_extract_<mode>"
2495   [(parallel [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand")
2496                    (vec_select:<VS_scalar>
2497                     (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand")
2498                     (parallel [(match_operand:QI 2 "const_int_operand")])))
2499               (clobber (match_dup 3))])]
2500   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2502   machine_mode smode = ((<MODE>mode != V4SImode && TARGET_VEXTRACTUB)
2503                         ? DImode : <MODE>mode);
2504   operands[3] = gen_rtx_SCRATCH (smode);
2507 ;; Under ISA 3.0, we can use the byte/half-word/word integer stores if we are
2508 ;; extracting a vector element and storing it to memory, rather than using
2509 ;; direct move to a GPR and a GPR store.
2510 (define_insn_and_split  "*vsx_extract_<mode>_p9"
2511   [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r,Z")
2512         (vec_select:<VS_scalar>
2513          (match_operand:VSX_EXTRACT_I2 1 "gpc_reg_operand" "v,v")
2514          (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
2515    (clobber (match_scratch:DI 3 "=v,v"))]
2516   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
2517   "#"
2518   "&& (reload_completed || MEM_P (operands[0]))"
2519   [(const_int 0)]
2521   rtx dest = operands[0];
2522   rtx src = operands[1];
2523   rtx element = operands[2];
2524   rtx di_tmp = operands[3];
2526   if (GET_CODE (di_tmp) == SCRATCH)
2527     di_tmp = gen_reg_rtx (DImode);
2529   emit_insn (gen_vsx_extract_<mode>_di (di_tmp, src, element));
2531   if (REG_P (dest))
2532     emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)), di_tmp);
2533   else if (SUBREG_P (dest))
2534     emit_move_insn (gen_rtx_REG (DImode, subreg_regno (dest)), di_tmp);
2535   else if (MEM_P (operands[0]))
2536     {
2537       if (can_create_pseudo_p ())
2538         dest = rs6000_address_for_fpconvert (dest);
2540       if (<MODE>mode == V16QImode)
2541         emit_insn (gen_p9_stxsibx (dest, di_tmp));
2542       else if (<MODE>mode == V8HImode)
2543         emit_insn (gen_p9_stxsihx (dest, di_tmp));
2544       else
2545         gcc_unreachable ();
2546     }
2547   else
2548     gcc_unreachable ();
2550   DONE;
2552   [(set_attr "type" "vecsimple,fpstore")])
2554 (define_insn  "vsx_extract_<mode>_di"
2555   [(set (match_operand:DI 0 "gpc_reg_operand" "=<VSX_EX>")
2556         (zero_extend:DI
2557          (vec_select:<VS_scalar>
2558           (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>")
2559           (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")]))))]
2560   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
2562   int element = INTVAL (operands[2]);
2563   int unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
2564   int offset = ((VECTOR_ELT_ORDER_BIG)
2565                 ? unit_size * element
2566                 : unit_size * (GET_MODE_NUNITS (<MODE>mode) - 1 - element));
2568   operands[2] = GEN_INT (offset);
2569   if (unit_size == 4)
2570     return "xxextractuw %x0,%x1,%2";
2571   else
2572     return "vextractu<wd> %0,%1,%2";
2574   [(set_attr "type" "vecsimple")])
2576 (define_insn_and_split  "*vsx_extract_si"
2577   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Z,Z,wJwK")
2578         (vec_select:SI
2579          (match_operand:V4SI 1 "gpc_reg_operand" "v,wJwK,v,v")
2580          (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n,n")])))
2581    (clobber (match_scratch:V4SI 3 "=v,wJwK,v,v"))]
2582   "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2583   "#"
2584   "&& reload_completed"
2585   [(const_int 0)]
2587   rtx dest = operands[0];
2588   rtx src = operands[1];
2589   rtx element = operands[2];
2590   rtx vec_tmp = operands[3];
2591   int value;
2593   if (!VECTOR_ELT_ORDER_BIG)
2594     element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2596   /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2597      instruction.  */
2598   value = INTVAL (element);
2599   if (value != 1)
2600     {
2601       if (TARGET_VEXTRACTUB)
2602         {
2603           rtx di_tmp = gen_rtx_REG (DImode, REGNO (vec_tmp));
2604           emit_insn (gen_vsx_extract_v4si_di (di_tmp,src, element));
2605         }
2606       else
2607         emit_insn (gen_altivec_vspltw_direct (vec_tmp, src, element));
2608     }
2609   else
2610     vec_tmp = src;
2612   if (MEM_P (operands[0]))
2613     {
2614       if (can_create_pseudo_p ())
2615         dest = rs6000_address_for_fpconvert (dest);
2617       if (TARGET_VSX_SMALL_INTEGER)
2618         emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
2619       else
2620         emit_insn (gen_stfiwx (dest, gen_rtx_REG (DImode, REGNO (vec_tmp))));
2621     }
2623   else if (TARGET_VSX_SMALL_INTEGER)
2624     emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
2625   else
2626     emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
2627                     gen_rtx_REG (DImode, REGNO (vec_tmp)));
2629   DONE;
2631   [(set_attr "type" "mftgpr,fpstore,fpstore,vecsimple")
2632    (set_attr "length" "8")])
2634 (define_insn_and_split  "*vsx_extract_<mode>_p8"
2635   [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r")
2636         (vec_select:<VS_scalar>
2637          (match_operand:VSX_EXTRACT_I2 1 "gpc_reg_operand" "v")
2638          (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
2639    (clobber (match_scratch:VSX_EXTRACT_I2 3 "=v"))]
2640   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2641   "#"
2642   "&& reload_completed"
2643   [(const_int 0)]
2645   rtx dest = operands[0];
2646   rtx src = operands[1];
2647   rtx element = operands[2];
2648   rtx vec_tmp = operands[3];
2649   int value;
2651   if (!VECTOR_ELT_ORDER_BIG)
2652     element = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1 - INTVAL (element));
2654   /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2655      instruction.  */
2656   value = INTVAL (element);
2657   if (<MODE>mode == V16QImode)
2658     {
2659       if (value != 7)
2660         emit_insn (gen_altivec_vspltb_direct (vec_tmp, src, element));
2661       else
2662         vec_tmp = src;
2663     }
2664   else if (<MODE>mode == V8HImode)
2665     {
2666       if (value != 3)
2667         emit_insn (gen_altivec_vsplth_direct (vec_tmp, src, element));
2668       else
2669         vec_tmp = src;
2670     }
2671   else
2672     gcc_unreachable ();
2674   emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
2675                   gen_rtx_REG (DImode, REGNO (vec_tmp)));
2676   DONE;
2678   [(set_attr "type" "mftgpr")])
2680 ;; Optimize extracting a single scalar element from memory.
2681 (define_insn_and_split "*vsx_extract_<mode>_load"
2682   [(set (match_operand:<VS_scalar> 0 "register_operand" "=r")
2683         (vec_select:<VS_scalar>
2684          (match_operand:VSX_EXTRACT_I 1 "memory_operand" "m")
2685          (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
2686    (clobber (match_scratch:DI 3 "=&b"))]
2687   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2688   "#"
2689   "&& reload_completed"
2690   [(set (match_dup 0) (match_dup 4))]
2692   operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2693                                            operands[3], <VS_scalar>mode);
2695   [(set_attr "type" "load")
2696    (set_attr "length" "8")])
2698 ;; Variable V16QI/V8HI/V4SI extract
2699 (define_insn_and_split "vsx_extract_<mode>_var"
2700   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r")
2701         (unspec:<VS_scalar>
2702          [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,m")
2703           (match_operand:DI 2 "gpc_reg_operand" "r,r")]
2704          UNSPEC_VSX_EXTRACT))
2705    (clobber (match_scratch:DI 3 "=r,&b"))
2706    (clobber (match_scratch:V2DI 4 "=&v,X"))]
2707   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2708   "#"
2709   "&& reload_completed"
2710   [(const_int 0)]
2712   rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2713                                 operands[3], operands[4]);
2714   DONE;
2717 ;; Expanders for builtins
2718 (define_expand "vsx_mergel_<mode>"
2719   [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
2720    (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
2721    (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
2722   "VECTOR_MEM_VSX_P (<MODE>mode)"
2724   rtvec v;
2725   rtx x;
2727   /* Special handling for LE with -maltivec=be.  */
2728   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2729     {
2730       v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
2731       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
2732     }
2733   else
2734     {
2735       v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
2736       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
2737     }
2739   x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
2740   emit_insn (gen_rtx_SET (operands[0], x));
2741   DONE;
2744 (define_expand "vsx_mergeh_<mode>"
2745   [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
2746    (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
2747    (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
2748   "VECTOR_MEM_VSX_P (<MODE>mode)"
2750   rtvec v;
2751   rtx x;
2753   /* Special handling for LE with -maltivec=be.  */
2754   if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
2755     {
2756       v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
2757       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
2758     }
2759   else
2760     {
2761       v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
2762       x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
2763     }
2765   x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
2766   emit_insn (gen_rtx_SET (operands[0], x));
2767   DONE;
2770 ;; V2DF/V2DI splat
2771 (define_insn "vsx_splat_<mode>"
2772   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>,<VSa>,we")
2773         (vec_duplicate:VSX_D
2774          (match_operand:<VS_scalar> 1 "splat_input_operand" "<VS_64reg>,Z,b")))]
2775   "VECTOR_MEM_VSX_P (<MODE>mode)"
2776   "@
2777    xxpermdi %x0,%x1,%x1,0
2778    lxvdsx %x0,%y1
2779    mtvsrdd %x0,%1,%1"
2780   [(set_attr "type" "vecperm,vecload,vecperm")])
2782 ;; V4SI splat support
2783 (define_insn "vsx_splat_v4si"
2784   [(set (match_operand:V4SI 0 "vsx_register_operand" "=we,we")
2785         (vec_duplicate:V4SI
2786          (match_operand:SI 1 "splat_input_operand" "r,Z")))]
2787   "TARGET_P9_VECTOR"
2788   "@
2789    mtvsrws %x0,%1
2790    lxvwsx %x0,%y1"
2791   [(set_attr "type" "vecperm,vecload")])
2793 ;; SImode is not currently allowed in vector registers.  This pattern
2794 ;; allows us to use direct move to get the value in a vector register
2795 ;; so that we can use XXSPLTW
2796 (define_insn "vsx_splat_v4si_di"
2797   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,we")
2798         (vec_duplicate:V4SI
2799          (truncate:SI
2800           (match_operand:DI 1 "gpc_reg_operand" "wj,r"))))]
2801   "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2802   "@
2803    xxspltw %x0,%x1,1
2804    mtvsrws %x0,%1"
2805   [(set_attr "type" "vecperm")])
2807 ;; V4SF splat (ISA 3.0)
2808 (define_insn_and_split "vsx_splat_v4sf"
2809   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,wa")
2810         (vec_duplicate:V4SF
2811          (match_operand:SF 1 "splat_input_operand" "Z,wy,r")))]
2812   "TARGET_P9_VECTOR"
2813   "@
2814    lxvwsx %x0,%y1
2815    #
2816    mtvsrws %x0,%1"
2817   "&& reload_completed && vsx_register_operand (operands[1], SFmode)"
2818   [(set (match_dup 0)
2819         (unspec:V4SF [(match_dup 1)] UNSPEC_VSX_CVDPSPN))
2820    (set (match_dup 0)
2821         (unspec:V4SF [(match_dup 0)
2822                       (const_int 0)] UNSPEC_VSX_XXSPLTW))]
2823   ""
2824   [(set_attr "type" "vecload,vecperm,mftgpr")
2825    (set_attr "length" "4,8,4")])
2827 ;; V4SF/V4SI splat from a vector element
2828 (define_insn "vsx_xxspltw_<mode>"
2829   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
2830         (vec_duplicate:VSX_W
2831          (vec_select:<VS_scalar>
2832           (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2833           (parallel
2834            [(match_operand:QI 2 "u5bit_cint_operand" "n")]))))]
2835   "VECTOR_MEM_VSX_P (<MODE>mode)"
2837   if (!BYTES_BIG_ENDIAN)
2838     operands[2] = GEN_INT (3 - INTVAL (operands[2]));
2840   return "xxspltw %x0,%x1,%2";
2842   [(set_attr "type" "vecperm")])
2844 (define_insn "vsx_xxspltw_<mode>_direct"
2845   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
2846         (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2847                        (match_operand:QI 2 "u5bit_cint_operand" "i")]
2848                       UNSPEC_VSX_XXSPLTW))]
2849   "VECTOR_MEM_VSX_P (<MODE>mode)"
2850   "xxspltw %x0,%x1,%2"
2851   [(set_attr "type" "vecperm")])
2853 ;; V16QI/V8HI splat support on ISA 2.07
2854 (define_insn "vsx_vsplt<VSX_SPLAT_SUFFIX>_di"
2855   [(set (match_operand:VSX_SPLAT_I 0 "altivec_register_operand" "=v")
2856         (vec_duplicate:VSX_SPLAT_I
2857          (truncate:<VS_scalar>
2858           (match_operand:DI 1 "altivec_register_operand" "v"))))]
2859   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2860   "vsplt<VSX_SPLAT_SUFFIX> %0,%1,<VSX_SPLAT_COUNT>"
2861   [(set_attr "type" "vecperm")])
2863 ;; V2DF/V2DI splat for use by vec_splat builtin
2864 (define_insn "vsx_xxspltd_<mode>"
2865   [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
2866         (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa")
2867                        (match_operand:QI 2 "u5bit_cint_operand" "i")]
2868                       UNSPEC_VSX_XXSPLTD))]
2869   "VECTOR_MEM_VSX_P (<MODE>mode)"
2871   if ((VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 0)
2872       || (!VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 1))
2873     return "xxpermdi %x0,%x1,%x1,0";
2874   else
2875     return "xxpermdi %x0,%x1,%x1,3";
2877   [(set_attr "type" "vecperm")])
2879 ;; V4SF/V4SI interleave
2880 (define_insn "vsx_xxmrghw_<mode>"
2881   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2882         (vec_select:VSX_W
2883           (vec_concat:<VS_double>
2884             (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2885             (match_operand:VSX_W 2 "vsx_register_operand" "wf,<VSa>"))
2886           (parallel [(const_int 0) (const_int 4)
2887                      (const_int 1) (const_int 5)])))]
2888   "VECTOR_MEM_VSX_P (<MODE>mode)"
2890   if (BYTES_BIG_ENDIAN)
2891     return "xxmrghw %x0,%x1,%x2";
2892   else
2893     return "xxmrglw %x0,%x2,%x1";
2895   [(set_attr "type" "vecperm")])
2897 (define_insn "vsx_xxmrglw_<mode>"
2898   [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
2899         (vec_select:VSX_W
2900           (vec_concat:<VS_double>
2901             (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
2902             (match_operand:VSX_W 2 "vsx_register_operand" "wf,?<VSa>"))
2903           (parallel [(const_int 2) (const_int 6)
2904                      (const_int 3) (const_int 7)])))]
2905   "VECTOR_MEM_VSX_P (<MODE>mode)"
2907   if (BYTES_BIG_ENDIAN)
2908     return "xxmrglw %x0,%x1,%x2";
2909   else
2910     return "xxmrghw %x0,%x2,%x1";
2912   [(set_attr "type" "vecperm")])
2914 ;; Shift left double by word immediate
2915 (define_insn "vsx_xxsldwi_<mode>"
2916   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSa>")
2917         (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "<VSa>")
2918                        (match_operand:VSX_L 2 "vsx_register_operand" "<VSa>")
2919                        (match_operand:QI 3 "u5bit_cint_operand" "i")]
2920                       UNSPEC_VSX_SLDWI))]
2921   "VECTOR_MEM_VSX_P (<MODE>mode)"
2922   "xxsldwi %x0,%x1,%x2,%3"
2923   [(set_attr "type" "vecperm")])
2926 ;; Vector reduction insns and splitters
2928 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
2929   [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
2930         (VEC_reduc:V2DF
2931          (vec_concat:V2DF
2932           (vec_select:DF
2933            (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
2934            (parallel [(const_int 1)]))
2935           (vec_select:DF
2936            (match_dup 1)
2937            (parallel [(const_int 0)])))
2938          (match_dup 1)))
2939    (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
2940   "VECTOR_UNIT_VSX_P (V2DFmode)"
2941   "#"
2942   ""
2943   [(const_int 0)]
2944   "
2946   rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
2947              ? gen_reg_rtx (V2DFmode)
2948              : operands[2];
2949   emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
2950   emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
2951   DONE;
2953   [(set_attr "length" "8")
2954    (set_attr "type" "veccomplex")])
2956 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
2957   [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
2958         (VEC_reduc:V4SF
2959          (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
2960          (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
2961    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
2962    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
2963   "VECTOR_UNIT_VSX_P (V4SFmode)"
2964   "#"
2965   ""
2966   [(const_int 0)]
2967   "
2969   rtx op0 = operands[0];
2970   rtx op1 = operands[1];
2971   rtx tmp2, tmp3, tmp4;
2973   if (can_create_pseudo_p ())
2974     {
2975       tmp2 = gen_reg_rtx (V4SFmode);
2976       tmp3 = gen_reg_rtx (V4SFmode);
2977       tmp4 = gen_reg_rtx (V4SFmode);
2978     }
2979   else
2980     {
2981       tmp2 = operands[2];
2982       tmp3 = operands[3];
2983       tmp4 = tmp2;
2984     }
2986   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
2987   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
2988   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
2989   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
2990   DONE;
2992   [(set_attr "length" "16")
2993    (set_attr "type" "veccomplex")])
2995 ;; Combiner patterns with the vector reduction patterns that knows we can get
2996 ;; to the top element of the V2DF array without doing an extract.
2998 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
2999   [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws")
3000         (vec_select:DF
3001          (VEC_reduc:V2DF
3002           (vec_concat:V2DF
3003            (vec_select:DF
3004             (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
3005             (parallel [(const_int 1)]))
3006            (vec_select:DF
3007             (match_dup 1)
3008             (parallel [(const_int 0)])))
3009           (match_dup 1))
3010          (parallel [(const_int 1)])))
3011    (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
3012   "VECTOR_UNIT_VSX_P (V2DFmode)"
3013   "#"
3014   ""
3015   [(const_int 0)]
3016   "
3018   rtx hi = gen_highpart (DFmode, operands[1]);
3019   rtx lo = (GET_CODE (operands[2]) == SCRATCH)
3020             ? gen_reg_rtx (DFmode)
3021             : operands[2];
3023   emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
3024   emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
3025   DONE;
3027   [(set_attr "length" "8")
3028    (set_attr "type" "veccomplex")])
3030 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
3031   [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
3032         (vec_select:SF
3033          (VEC_reduc:V4SF
3034           (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
3035           (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
3036          (parallel [(const_int 3)])))
3037    (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
3038    (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
3039    (clobber (match_scratch:V4SF 4 "=0,0"))]
3040   "VECTOR_UNIT_VSX_P (V4SFmode)"
3041   "#"
3042   ""
3043   [(const_int 0)]
3044   "
3046   rtx op0 = operands[0];
3047   rtx op1 = operands[1];
3048   rtx tmp2, tmp3, tmp4, tmp5;
3050   if (can_create_pseudo_p ())
3051     {
3052       tmp2 = gen_reg_rtx (V4SFmode);
3053       tmp3 = gen_reg_rtx (V4SFmode);
3054       tmp4 = gen_reg_rtx (V4SFmode);
3055       tmp5 = gen_reg_rtx (V4SFmode);
3056     }
3057   else
3058     {
3059       tmp2 = operands[2];
3060       tmp3 = operands[3];
3061       tmp4 = tmp2;
3062       tmp5 = operands[4];
3063     }
3065   emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
3066   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
3067   emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
3068   emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
3069   emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
3070   DONE;
3072   [(set_attr "length" "20")
3073    (set_attr "type" "veccomplex")])
3076 ;; Power8 Vector fusion.  The fused ops must be physically adjacent.
3077 (define_peephole
3078   [(set (match_operand:P 0 "base_reg_operand" "")
3079         (match_operand:P 1 "short_cint_operand" ""))
3080    (set (match_operand:VSX_M 2 "vsx_register_operand" "")
3081         (mem:VSX_M (plus:P (match_dup 0)
3082                            (match_operand:P 3 "int_reg_operand" ""))))]
3083   "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
3084   "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"  
3085   [(set_attr "length" "8")
3086    (set_attr "type" "vecload")])
3088 (define_peephole
3089   [(set (match_operand:P 0 "base_reg_operand" "")
3090         (match_operand:P 1 "short_cint_operand" ""))
3091    (set (match_operand:VSX_M 2 "vsx_register_operand" "")
3092         (mem:VSX_M (plus:P (match_operand:P 3 "int_reg_operand" "")
3093                            (match_dup 0))))]
3094   "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
3095   "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"  
3096   [(set_attr "length" "8")
3097    (set_attr "type" "vecload")])
3100 ;; ISA 3.0 vector extend sign support
3102 (define_insn "vsx_sign_extend_qi_<mode>"
3103   [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
3104         (unspec:VSINT_84
3105          [(match_operand:V16QI 1 "vsx_register_operand" "v")]
3106          UNSPEC_VSX_SIGN_EXTEND))]
3107   "TARGET_P9_VECTOR"
3108   "vextsb2<wd> %0,%1"
3109   [(set_attr "type" "vecexts")])
3111 (define_insn "vsx_sign_extend_hi_<mode>"
3112   [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
3113         (unspec:VSINT_84
3114          [(match_operand:V8HI 1 "vsx_register_operand" "v")]
3115          UNSPEC_VSX_SIGN_EXTEND))]
3116   "TARGET_P9_VECTOR"
3117   "vextsh2<wd> %0,%1"
3118   [(set_attr "type" "vecexts")])
3120 (define_insn "*vsx_sign_extend_si_v2di"
3121   [(set (match_operand:V2DI 0 "vsx_register_operand" "=v")
3122         (unspec:V2DI [(match_operand:V4SI 1 "vsx_register_operand" "v")]
3123                      UNSPEC_VSX_SIGN_EXTEND))]
3124   "TARGET_P9_VECTOR"
3125   "vextsw2d %0,%1"
3126   [(set_attr "type" "vecexts")])
3129 ;; ISA 3.0 memory operations
3130 (define_insn "p9_lxsi<wd>zx"
3131   [(set (match_operand:DI 0 "vsx_register_operand" "=wi")
3132         (unspec:DI [(zero_extend:DI
3133                      (match_operand:QHI 1 "indexed_or_indirect_operand" "Z"))]
3134                    UNSPEC_P9_MEMORY))]
3135   "TARGET_P9_VECTOR"
3136   "lxsi<wd>zx %x0,%y1"
3137   [(set_attr "type" "fpload")])
3139 (define_insn "p9_stxsi<wd>x"
3140   [(set (match_operand:QHI 0 "reg_or_indexed_operand" "=r,Z")
3141         (unspec:QHI [(match_operand:DI 1 "vsx_register_operand" "wi,wi")]
3142                     UNSPEC_P9_MEMORY))]
3143   "TARGET_P9_VECTOR"
3144   "@
3145    mfvsrd %0,%x1
3146    stxsi<wd>x %x1,%y0"
3147   [(set_attr "type" "mffgpr,fpstore")])
3149 ;; ISA 3.0 Binary Floating-Point Support
3151 ;; VSX Scalar Extract Exponent Double-Precision
3152 (define_insn "xsxexpdp"
3153   [(set (match_operand:DI 0 "register_operand" "=r")
3154         (unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
3155          UNSPEC_VSX_SXEXPDP))]
3156   "TARGET_P9_VECTOR && TARGET_64BIT"
3157   "xsxexpdp %0,%x1"
3158   [(set_attr "type" "integer")])
3160 ;; VSX Scalar Extract Significand Double-Precision
3161 (define_insn "xsxsigdp"
3162   [(set (match_operand:DI 0 "register_operand" "=r")
3163         (unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
3164          UNSPEC_VSX_SXSIGDP))]
3165   "TARGET_P9_VECTOR && TARGET_64BIT"
3166   "xsxsigdp %0,%x1"
3167   [(set_attr "type" "integer")])
3169 ;; VSX Scalar Insert Exponent Double-Precision
3170 (define_insn "xsiexpdp"
3171   [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
3172         (unspec:DF [(match_operand:DI 1 "register_operand" "r")
3173                     (match_operand:DI 2 "register_operand" "r")]
3174          UNSPEC_VSX_SIEXPDP))]
3175   "TARGET_P9_VECTOR && TARGET_64BIT"
3176   "xsiexpdp %x0,%1,%2"
3177   [(set_attr "type" "fpsimple")])
3179 ;; VSX Scalar Compare Exponents Double-Precision
3180 (define_expand "xscmpexpdp_<code>"
3181   [(set (match_dup 3)
3182         (compare:CCFP
3183          (unspec:DF
3184           [(match_operand:DF 1 "vsx_register_operand" "wa")
3185            (match_operand:DF 2 "vsx_register_operand" "wa")]
3186           UNSPEC_VSX_SCMPEXPDP)
3187          (const_int 0)))
3188    (set (match_operand:SI 0 "register_operand" "=r")
3189         (CMP_TEST:SI (match_dup 3)
3190                      (const_int 0)))]
3191   "TARGET_P9_VECTOR"
3193   operands[3] = gen_reg_rtx (CCFPmode);
3196 (define_insn "*xscmpexpdp"
3197   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
3198         (compare:CCFP
3199          (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "wa")
3200                      (match_operand:DF 2 "vsx_register_operand" "wa")]
3201           UNSPEC_VSX_SCMPEXPDP)
3202          (match_operand:SI 3 "zero_constant" "j")))]
3203   "TARGET_P9_VECTOR"
3204   "xscmpexpdp %0,%x1,%x2"
3205   [(set_attr "type" "fpcompare")])
3207 ;; VSX Scalar Test Data Class Double- and Single-Precision
3208 ;;  (The lt bit is set if operand 1 is negative.  The eq bit is set
3209 ;;   if any of the conditions tested by operand 2 are satisfied.
3210 ;;   The gt and unordered bits are cleared to zero.)
3211 (define_expand "xststdc<Fvsx>"
3212   [(set (match_dup 3)
3213         (compare:CCFP
3214          (unspec:SFDF
3215           [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3216            (match_operand:SI 2 "u7bit_cint_operand" "n")]
3217           UNSPEC_VSX_STSTDC)
3218          (match_dup 4)))
3219    (set (match_operand:SI 0 "register_operand" "=r")
3220         (eq:SI (match_dup 3)
3221                (const_int 0)))]
3222   "TARGET_P9_VECTOR"
3224   operands[3] = gen_reg_rtx (CCFPmode);
3225   operands[4] = CONST0_RTX (SImode);
3228 ;; The VSX Scalar Test Data Class Double- and Single-Precision
3229 ;; instruction may also be used to test for negative value.
3230 (define_expand "xststdcneg<Fvsx>"
3231   [(set (match_dup 2)
3232         (compare:CCFP
3233          (unspec:SFDF
3234           [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3235            (const_int 0)]
3236           UNSPEC_VSX_STSTDC)
3237          (match_dup 3)))
3238    (set (match_operand:SI 0 "register_operand" "=r")
3239         (lt:SI (match_dup 2)
3240                (const_int 0)))]
3241   "TARGET_P9_VECTOR"
3243   operands[2] = gen_reg_rtx (CCFPmode);
3244   operands[3] = CONST0_RTX (SImode);
3247 (define_insn "*xststdc<Fvsx>"
3248   [(set (match_operand:CCFP 0 "" "=y")
3249         (compare:CCFP
3250          (unspec:SFDF [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3251                        (match_operand:SI 2 "u7bit_cint_operand" "n")]
3252           UNSPEC_VSX_STSTDC)
3253          (match_operand:SI 3 "zero_constant" "j")))]
3254   "TARGET_P9_VECTOR"
3255   "xststdc<Fvsx> %0,%x1,%2"
3256   [(set_attr "type" "fpcompare")])
3258 ;; VSX Vector Extract Exponent Double and Single Precision
3259 (define_insn "xvxexp<VSs>"
3260   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3261         (unspec:VSX_F
3262          [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
3263          UNSPEC_VSX_VXEXP))]
3264   "TARGET_P9_VECTOR"
3265   "xvxexp<VSs> %x0,%x1"
3266   [(set_attr "type" "vecsimple")])
3268 ;; VSX Vector Extract Significand Double and Single Precision
3269 (define_insn "xvxsig<VSs>"
3270   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3271         (unspec:VSX_F
3272          [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
3273          UNSPEC_VSX_VXSIG))]
3274   "TARGET_P9_VECTOR"
3275   "xvxsig<VSs> %x0,%x1"
3276   [(set_attr "type" "vecsimple")])
3278 ;; VSX Vector Insert Exponent Double and Single Precision
3279 (define_insn "xviexp<VSs>"
3280   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3281         (unspec:VSX_F
3282          [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3283           (match_operand:VSX_F 2 "vsx_register_operand" "wa")]
3284          UNSPEC_VSX_VIEXP))]
3285   "TARGET_P9_VECTOR"
3286   "xviexp<VSs> %x0,%x1,%x2"
3287   [(set_attr "type" "vecsimple")])
3289 ;; VSX Vector Test Data Class Double and Single Precision
3290 ;; The corresponding elements of the result vector are all ones
3291 ;; if any of the conditions tested by operand 3 are satisfied.
3292 (define_insn "xvtstdc<VSs>"
3293   [(set (match_operand:<VSI> 0 "vsx_register_operand" "=wa")
3294         (unspec:<VSI>
3295          [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3296           (match_operand:SI 2 "u7bit_cint_operand" "n")]
3297          UNSPEC_VSX_VTSTDC))]
3298   "TARGET_P9_VECTOR"
3299   "xvtstdc<VSs> %x0,%x1,%2"
3300   [(set_attr "type" "vecsimple")])
3302 ;; ISA 3.0 String Operations Support
3304 ;; Compare vectors producing a vector result and a predicate, setting CR6
3305 ;; to indicate a combined status.  This pattern matches v16qi, v8hi, and
3306 ;; v4si modes.  It does not match v2df, v4sf, or v2di modes.  There's no
3307 ;; need to match the v2di mode because that is expanded into v4si.
3308 (define_insn "*vsx_ne_<mode>_p"
3309   [(set (reg:CC CR6_REGNO)
3310         (unspec:CC
3311          [(ne:CC (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
3312                  (match_operand:VSX_EXTRACT_I 2 "gpc_reg_operand" "v"))]
3313          UNSPEC_PREDICATE))
3314    (set (match_operand:VSX_EXTRACT_I 0 "gpc_reg_operand" "=v")
3315         (ne:VSX_EXTRACT_I (match_dup 1)
3316                           (match_dup 2)))]
3317   "TARGET_P9_VECTOR"
3318   "xvcmpne<VSX_EXTRACT_WIDTH>. %0,%1,%2"
3319   [(set_attr "type" "vecsimple")])
3321 ;; Compare vectors producing a vector result and a predicate, setting CR6
3322 ;; to indicate a combined status, for v4sf and v2df operands.
3323 (define_insn "*vsx_ne_<mode>_p"
3324   [(set (reg:CC CR6_REGNO)
3325         (unspec:CC [(ne:CC
3326                      (match_operand:VSX_F 1 "vsx_register_operand" "wa")
3327                      (match_operand:VSX_F 2 "vsx_register_operand" "wa"))]
3328          UNSPEC_PREDICATE))
3329    (set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3330         (ne:VSX_F (match_dup 1)
3331                   (match_dup 2)))]
3332   "TARGET_P9_VECTOR"
3333   "xvcmpne<VSs>. %x0,%x1,%x2"
3334   [(set_attr "type" "vecsimple")])
3336 (define_insn "*vector_nez_<mode>_p"
3337   [(set (reg:CC CR6_REGNO)
3338         (unspec:CC [(unspec:VI
3339                      [(match_operand:VI 1 "gpc_reg_operand" "v")
3340                       (match_operand:VI 2 "gpc_reg_operand" "v")]
3341                      UNSPEC_NEZ_P)]
3342          UNSPEC_PREDICATE))
3343    (set (match_operand:VI 0 "gpc_reg_operand" "=v")
3344         (unspec:VI [(match_dup 1)
3345                     (match_dup 2)]
3346          UNSPEC_NEZ_P))]
3347   "TARGET_P9_VECTOR"
3348   "vcmpnez<VSX_EXTRACT_WIDTH>. %0,%1,%2"
3349   [(set_attr "type" "vecsimple")])
3351 ;; Load VSX Vector with Length
3352 (define_expand "lxvl"
3353   [(set (match_dup 3)
3354         (match_operand:DI 2 "register_operand"))
3355    (set (match_operand:V16QI 0 "vsx_register_operand")
3356         (unspec:V16QI
3357          [(match_operand:DI 1 "gpc_reg_operand")
3358           (match_dup 3)]
3359          UNSPEC_LXVL))]
3360   "TARGET_P9_VECTOR && TARGET_64BIT"
3362   operands[3] = gen_reg_rtx (DImode);
3365 (define_insn "*lxvl"
3366   [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3367         (unspec:V16QI
3368          [(match_operand:DI 1 "gpc_reg_operand" "b")
3369           (match_operand:DI 2 "register_operand" "+r")]
3370          UNSPEC_LXVL))]
3371   "TARGET_P9_VECTOR && TARGET_64BIT"
3372   "sldi %2,%2, 56\; lxvl %x0,%1,%2"
3373   [(set_attr "length" "8")
3374    (set_attr "type" "vecload")])
3376 ;; Store VSX Vector with Length
3377 (define_expand "stxvl"
3378   [(set (match_dup 3)
3379         (match_operand:DI 2 "register_operand"))
3380    (set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand"))
3381         (unspec:V16QI
3382          [(match_operand:V16QI 0 "vsx_register_operand")
3383           (match_dup 3)]
3384          UNSPEC_STXVL))]
3385   "TARGET_P9_VECTOR && TARGET_64BIT"
3387   operands[3] = gen_reg_rtx (DImode);
3390 (define_insn "*stxvl"
3391   [(set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand" "b"))
3392         (unspec:V16QI
3393          [(match_operand:V16QI 0 "vsx_register_operand" "wa")
3394           (match_operand:DI 2 "register_operand" "+r")]
3395          UNSPEC_STXVL))]
3396   "TARGET_P9_VECTOR && TARGET_64BIT"
3397   "sldi %2,%2\;stxvl %x0,%1,%2"
3398   [(set_attr "length" "8")
3399    (set_attr "type" "vecstore")])
3401 ;; Vector Compare Not Equal Byte
3402 (define_insn "vcmpneb"
3403   [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
3404         (unspec:V16QI [(match_operand:V16QI 1 "altivec_register_operand" "v")
3405                        (match_operand:V16QI 2 "altivec_register_operand" "v")]
3406          UNSPEC_VCMPNEB))]
3407   "TARGET_P9_VECTOR"
3408   "vcmpneb %0,%1,%2"
3409   [(set_attr "type" "vecsimple")])
3411 ;; Vector Compare Not Equal or Zero Byte
3412 (define_insn "vcmpnezb"
3413   [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
3414         (unspec:V16QI
3415          [(match_operand:V16QI 1 "altivec_register_operand" "v")
3416           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3417          UNSPEC_VCMPNEZB))]
3418   "TARGET_P9_VECTOR"
3419   "vcmpnezb %0,%1,%2"
3420   [(set_attr "type" "vecsimple")])
3422 ;; Vector Compare Not Equal Half Word
3423 (define_insn "vcmpneh"
3424   [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
3425         (unspec:V8HI [(match_operand:V8HI 1 "altivec_register_operand" "v")
3426                       (match_operand:V8HI 2 "altivec_register_operand" "v")]
3427          UNSPEC_VCMPNEH))]
3428   "TARGET_P9_VECTOR"
3429   "vcmpneh %0,%1,%2"
3430   [(set_attr "type" "vecsimple")])
3432 ;; Vector Compare Not Equal or Zero Half Word
3433 (define_insn "vcmpnezh"
3434   [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
3435         (unspec:V8HI [(match_operand:V8HI 1 "altivec_register_operand" "v")
3436                       (match_operand:V8HI 2 "altivec_register_operand" "v")]
3437          UNSPEC_VCMPNEZH))]
3438   "TARGET_P9_VECTOR"
3439   "vcmpnezh %0,%1,%2"
3440   [(set_attr "type" "vecsimple")])
3442 ;; Vector Compare Not Equal Word
3443 (define_insn "vcmpnew"
3444   [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
3445         (unspec:V4SI
3446          [(match_operand:V4SI 1 "altivec_register_operand" "v")
3447           (match_operand:V4SI 2 "altivec_register_operand" "v")]
3448          UNSPEC_VCMPNEH))]
3449   "TARGET_P9_VECTOR"
3450   "vcmpnew %0,%1,%2"
3451   [(set_attr "type" "vecsimple")])
3453 ;; Vector Compare Not Equal Float or Double
3454 (define_insn "vcmpne<VSs>"
3455   [(set (match_operand:<VSI> 0 "vsx_register_operand" "=wa")
3456         (unspec:<VSI>
3457          [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3458           (match_operand:VSX_F 2 "vsx_register_operand" "wa")]
3459          UNSPEC_VCMPNEH))]
3460   "TARGET_P9_VECTOR"
3461   "xvcmpne<VSs> %x0,%x1,%x2"
3462   [(set_attr "type" "vecsimple")])
3464 ;; Vector Compare Not Equal or Zero Word
3465 (define_insn "vcmpnezw"
3466   [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
3467         (unspec:V4SI [(match_operand:V4SI 1 "altivec_register_operand" "v")
3468                       (match_operand:V4SI 2 "altivec_register_operand" "v")]
3469          UNSPEC_VCMPNEZW))]
3470   "TARGET_P9_VECTOR"
3471   "vcmpnezw %0,%1,%2"
3472   [(set_attr "type" "vecsimple")])
3474 ;; Vector Count Leading Zero Least-Significant Bits Byte
3475 (define_insn "vclzlsbb"
3476   [(set (match_operand:SI 0 "register_operand" "=r")
3477         (unspec:SI
3478          [(match_operand:V16QI 1 "altivec_register_operand" "v")]
3479          UNSPEC_VCLZLSBB))]
3480   "TARGET_P9_VECTOR"
3481   "vclzlsbb %0,%1"
3482   [(set_attr "type" "vecsimple")])
3484 ;; Vector Count Trailing Zero Least-Significant Bits Byte
3485 (define_insn "vctzlsbb"
3486   [(set (match_operand:SI 0 "register_operand" "=r")
3487         (unspec:SI
3488          [(match_operand:V16QI 1 "altivec_register_operand" "v")]
3489          UNSPEC_VCTZLSBB))]
3490   "TARGET_P9_VECTOR"
3491   "vctzlsbb %0,%1"
3492   [(set_attr "type" "vecsimple")])
3494 ;; Vector Extract Unsigned Byte Left-Indexed
3495 (define_insn "vextublx"
3496   [(set (match_operand:SI 0 "register_operand" "=r")
3497         (unspec:SI
3498          [(match_operand:SI 1 "register_operand" "r")
3499           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3500          UNSPEC_VEXTUBLX))]
3501   "TARGET_P9_VECTOR"
3502   "vextublx %0,%1,%2"
3503   [(set_attr "type" "vecsimple")])
3505 ;; Vector Extract Unsigned Byte Right-Indexed
3506 (define_insn "vextubrx"
3507   [(set (match_operand:SI 0 "register_operand" "=r")
3508         (unspec:SI
3509          [(match_operand:SI 1 "register_operand" "r")
3510           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3511          UNSPEC_VEXTUBRX))]
3512   "TARGET_P9_VECTOR"
3513   "vextubrx %0,%1,%2"
3514   [(set_attr "type" "vecsimple")])
3516 ;; Vector Extract Unsigned Half Word Left-Indexed
3517 (define_insn "vextuhlx"
3518   [(set (match_operand:SI 0 "register_operand" "=r")
3519         (unspec:SI
3520          [(match_operand:SI 1 "register_operand" "r")
3521           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3522          UNSPEC_VEXTUHLX))]
3523   "TARGET_P9_VECTOR"
3524   "vextuhlx %0,%1,%2"
3525   [(set_attr "type" "vecsimple")])
3527 ;; Vector Extract Unsigned Half Word Right-Indexed
3528 (define_insn "vextuhrx"
3529   [(set (match_operand:SI 0 "register_operand" "=r")
3530         (unspec:SI
3531          [(match_operand:SI 1 "register_operand" "r")
3532           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3533          UNSPEC_VEXTUHRX))]
3534   "TARGET_P9_VECTOR"
3535   "vextuhrx %0,%1,%2"
3536   [(set_attr "type" "vecsimple")])
3538 ;; Vector Extract Unsigned Word Left-Indexed
3539 (define_insn "vextuwlx"
3540   [(set (match_operand:SI 0 "register_operand" "=r")
3541         (unspec:SI
3542          [(match_operand:SI 1 "register_operand" "r")
3543           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3544          UNSPEC_VEXTUWLX))]
3545   "TARGET_P9_VECTOR"
3546   "vextuwlx %0,%1,%2"
3547   [(set_attr "type" "vecsimple")])
3549 ;; Vector Extract Unsigned Word Right-Indexed
3550 (define_insn "vextuwrx"
3551   [(set (match_operand:SI 0 "register_operand" "=r")
3552         (unspec:SI
3553          [(match_operand:SI 1 "register_operand" "r")
3554           (match_operand:V16QI 2 "altivec_register_operand" "v")]
3555          UNSPEC_VEXTUWRX))]
3556   "TARGET_P9_VECTOR"
3557   "vextuwrx %0,%1,%2"
3558   [(set_attr "type" "vecsimple")])