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