2 ;; Copyright (C)
2009-
2023 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 ;; Mode attribute for vector floate and floato conversions
25 (define_mode_attr VF_sxddp [(V2DI "sxd") (V2DF "dp")])
27 ;; Iterator for both scalar and vector floating point types supported by VSX
28 (define_mode_iterator VSX_B [DF V4SF V2DF])
30 ;; Iterator for the
2 64-bit vector types
31 (define_mode_iterator VSX_D [V2DF V2DI])
33 ;; Mode iterator to handle swapping words on little endian for the
128-bit
34 ;; types that goes in a single vector register.
35 (define_mode_iterator VSX_LE_128 [(KF "FLOAT128_VECTOR_P (KFmode)")
36 (TF "FLOAT128_VECTOR_P (TFmode)")
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
58 (KF "FLOAT128_VECTOR_P (KFmode)")
59 (TF "FLOAT128_VECTOR_P (TFmode)")])
61 ;; Iterator for memory moves.
62 (define_mode_iterator VSX_M [V16QI
69 (KF "FLOAT128_VECTOR_P (KFmode)")
70 (TF "FLOAT128_VECTOR_P (TFmode)")
73 (define_mode_attr VSX_XXBR [(V8HI "h")
80 ;; Map into the appropriate load/store name based on the type
81 (define_mode_attr VSm [(V16QI "vw4")
93 ;; Map the register class used
94 (define_mode_attr VSr [(V16QI "v")
108 ;; What value we need in the "isa" field, to make the IEEE QP float work.
109 (define_mode_attr VSisa [(V16QI "*")
123 ;; A mode attribute to disparage use of GPR registers, except for scalar
125 (define_mode_attr ??r [(V16QI "??r")
136 ;; A mode attribute used for
128-bit constant values.
137 (define_mode_attr nW [(V16QI "W")
148 ;; Same size integer type for floating point data
149 (define_mode_attr VSi [(V4SF "v4si")
153 (define_mode_attr VSI [(V4SF "V4SI")
157 ;; Word size for same size conversion
158 (define_mode_attr VSc [(V4SF "w")
162 ;; Map into either s or v, depending on whether this is a scalar or vector
164 (define_mode_attr VSv [(V16QI "v")
174 ;; Appropriate type for add ops (and other simple FP ops)
175 (define_mode_attr VStype_simple [(V2DF "vecdouble")
179 ;; Appropriate type for multiply ops
180 (define_mode_attr VStype_mul [(V2DF "vecdouble")
184 ;; Appropriate type for divide ops.
185 (define_mode_attr VStype_div [(V2DF "vecdiv")
189 ;; Map to a double-sized vector mode
190 (define_mode_attr VS_double [(V4SI "V8SI")
196 ;; Iterators for loading constants with xxspltib
197 (define_mode_iterator VSINT_84 [V4SI V2DI DI SI])
198 (define_mode_iterator VSINT_842 [V8HI V4SI V2DI])
200 ;; Vector reverse byte modes
201 (define_mode_iterator VEC_REVB [V8HI V4SI V2DI V4SF V2DF V1TI])
203 ;; Iterator for ISA
3.0 vector extract/insert of small integer vectors.
204 ;; VSX_EXTRACT_I2 doesn't include V4SImode because SI extracts can be
205 ;; done on ISA
2.07 and not just ISA
3.0.
206 (define_mode_iterator VSX_EXTRACT_I [V16QI V8HI V4SI])
207 (define_mode_iterator VSX_EXTRACT_I2 [V16QI V8HI])
208 (define_mode_iterator VSX_EXTRACT_I4 [V16QI V8HI V4SI V2DI])
210 (define_mode_attr VSX_EXTRACT_WIDTH [(V16QI "b")
214 ;; Mode attribute to give the correct predicate for ISA
3.0 vector extract and
215 ;; insert to validate the operand number.
216 (define_mode_attr VSX_EXTRACT_PREDICATE [(V16QI "const_0_to_15_operand")
217 (V8HI "const_0_to_7_operand")
218 (V4SI "const_0_to_3_operand")])
220 ;; Mode attribute to give the constraint for vector extract and insert
222 (define_mode_attr VSX_EX [(V16QI "v")
226 ;; Mode iterator for binary floating types other than double to
227 ;; optimize convert to that floating point type from an extract
228 ;; of an integer type
229 (define_mode_iterator VSX_EXTRACT_FL [SF
230 (IF "FLOAT128_2REG_P (IFmode)")
231 (KF "TARGET_FLOAT128_HW")
232 (TF "FLOAT128_2REG_P (TFmode)
233 || (FLOAT128_IEEE_P (TFmode)
234 && TARGET_FLOAT128_HW)")])
236 ;; Mode iterator for binary floating types that have a direct conversion
237 ;; from
64-bit integer to floating point
238 (define_mode_iterator FL_CONV [SF
240 (KF "TARGET_FLOAT128_HW")
241 (TF "TARGET_FLOAT128_HW
242 && FLOAT128_IEEE_P (TFmode)")])
244 ;; Iterator for the
2 short vector types to do a splat from an integer
245 (define_mode_iterator VSX_SPLAT_I [V16QI V8HI])
247 ;; Mode attribute to give the count for the splat instruction to splat
248 ;; the value in the
64-bit integer slot
249 (define_mode_attr VSX_SPLAT_COUNT [(V16QI "
7") (V8HI "
3")])
251 ;; Mode attribute to give the suffix for the splat instruction
252 (define_mode_attr VSX_SPLAT_SUFFIX [(V16QI "b") (V8HI "h")])
254 ;; Iterator for the move to mask instructions
255 (define_mode_iterator VSX_MM [V16QI V8HI V4SI V2DI V1TI])
256 (define_mode_iterator VSX_MM4 [V16QI V8HI V4SI V2DI])
258 ;; Longer vec int modes for rotate/mask ops
259 ;; and Vector Integer Multiply/Divide/Modulo Instructions
260 (define_mode_iterator VIlong [V2DI V4SI])
262 ;; Constants for creating unspecs
263 (define_c_enum "unspec"
276 UNSPEC_VSX_UNS_FLOAT2
278 UNSPEC_VSX_UNS_FLOATE
280 UNSPEC_VSX_UNS_FLOATO
300 UNSPEC_VSX_SIGN_EXTEND
301 UNSPEC_VSX_XVCVBF16SPN
302 UNSPEC_VSX_XVCVSPBF16
303 UNSPEC_VSX_XVCVSPSXDS
314 UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTH
315 UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTL
347 UNSPEC_VSX_FIRST_MATCH_INDEX
348 UNSPEC_VSX_FIRST_MATCH_EOS_INDEX
349 UNSPEC_VSX_FIRST_MISMATCH_INDEX
350 UNSPEC_VSX_FIRST_MISMATCH_EOS_INDEX
374 (define_int_iterator XVCVBF16 [UNSPEC_VSX_XVCVSPBF16
375 UNSPEC_VSX_XVCVBF16SPN])
377 (define_int_attr xvcvbf16 [(UNSPEC_VSX_XVCVSPBF16 "xvcvspbf16")
378 (UNSPEC_VSX_XVCVBF16SPN "xvcvbf16spn")])
380 ;; Like VI, defined in vector.md, but add ISA
2.07 integer vector ops
381 (define_mode_iterator VI2 [V4SI V8HI V16QI V2DI])
383 ;; Vector extract_elt iterator/attr for
32-bit and
64-bit elements
384 (define_mode_iterator REPLACE_ELT [V4SI V4SF V2DI V2DF])
385 (define_mode_attr REPLACE_ELT_char [(V4SI "w") (V4SF "w")
386 (V2DI "d") (V2DF "d")])
387 (define_mode_attr REPLACE_ELT_sh [(V4SI "
2") (V4SF "
2")
388 (V2DI "
3") (V2DF "
3")])
389 (define_mode_attr REPLACE_ELT_max [(V4SI "
12") (V4SF "
12")
390 (V2DI "
8") (V2DF "
8")])
392 ;; Like VM2 in altivec.md, just do char, short, int, long, float and double
393 (define_mode_iterator VM3 [V4SI
400 (define_mode_attr VM3_char [(V2DI "d")
410 ;; The patterns for LE permuted loads and stores come before the general
411 ;; VSX moves so they match first.
412 (define_insn_and_split "*vsx_le_perm_load_<mode>"
413 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
414 (match_operand:VSX_D
1 "indexed_or_indirect_operand" "Z"))]
415 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
421 (parallel [(const_int
1) (const_int
0)])))
425 (parallel [(const_int
1) (const_int
0)])))]
427 rtx mem = operands[
1];
429 /* Don't apply the swap optimization if we've already performed register
430 allocation and the hard register destination is not in the altivec
432 if ((MEM_ALIGN (mem) >=
128)
433 && (!HARD_REGISTER_NUM_P (reg_or_subregno (operands[
0]))
434 || ALTIVEC_REGNO_P (reg_or_subregno (operands[
0]))))
436 rtx mem_address = XEXP (mem,
0);
437 enum machine_mode mode = GET_MODE (mem);
439 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
441 /* Replace the source memory address with masked address. */
442 rtx lvx_set_expr = rs6000_gen_lvx (mode, operands[
0], mem);
443 emit_insn (lvx_set_expr);
446 else if (rs6000_quadword_masked_address_p (mem_address))
448 /* This rtl is already in the form that matches lvx
449 instruction, so leave it alone. */
452 /* Otherwise, fall through to transform into a swapping load. */
454 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
0])
457 [(set_attr "type" "vecload")
458 (set_attr "length" "
8")])
460 (define_insn_and_split "*vsx_le_perm_load_<mode>"
461 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
462 (match_operand:VSX_W
1 "indexed_or_indirect_operand" "Z"))]
463 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
469 (parallel [(const_int
2) (const_int
3)
470 (const_int
0) (const_int
1)])))
474 (parallel [(const_int
2) (const_int
3)
475 (const_int
0) (const_int
1)])))]
477 rtx mem = operands[
1];
479 /* Don't apply the swap optimization if we've already performed register
480 allocation and the hard register destination is not in the altivec
482 if ((MEM_ALIGN (mem) >=
128)
483 && (!HARD_REGISTER_P (operands[
0])
484 || ALTIVEC_REGNO_P (REGNO(operands[
0]))))
486 rtx mem_address = XEXP (mem,
0);
487 enum machine_mode mode = GET_MODE (mem);
489 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
491 /* Replace the source memory address with masked address. */
492 rtx lvx_set_expr = rs6000_gen_lvx (mode, operands[
0], mem);
493 emit_insn (lvx_set_expr);
496 else if (rs6000_quadword_masked_address_p (mem_address))
498 /* This rtl is already in the form that matches lvx
499 instruction, so leave it alone. */
502 /* Otherwise, fall through to transform into a swapping load. */
504 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
0])
507 [(set_attr "type" "vecload")
508 (set_attr "length" "
8")])
510 (define_insn_and_split "*vsx_le_perm_load_v8hi"
511 [(set (match_operand:V8HI
0 "vsx_register_operand" "=wa")
512 (match_operand:V8HI
1 "indexed_or_indirect_operand" "Z"))]
513 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
519 (parallel [(const_int
4) (const_int
5)
520 (const_int
6) (const_int
7)
521 (const_int
0) (const_int
1)
522 (const_int
2) (const_int
3)])))
526 (parallel [(const_int
4) (const_int
5)
527 (const_int
6) (const_int
7)
528 (const_int
0) (const_int
1)
529 (const_int
2) (const_int
3)])))]
531 rtx mem = operands[
1];
533 /* Don't apply the swap optimization if we've already performed register
534 allocation and the hard register destination is not in the altivec
536 if ((MEM_ALIGN (mem) >=
128)
537 && (!HARD_REGISTER_P (operands[
0])
538 || ALTIVEC_REGNO_P (REGNO(operands[
0]))))
540 rtx mem_address = XEXP (mem,
0);
541 enum machine_mode mode = GET_MODE (mem);
543 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
545 /* Replace the source memory address with masked address. */
546 rtx lvx_set_expr = rs6000_gen_lvx (mode, operands[
0], mem);
547 emit_insn (lvx_set_expr);
550 else if (rs6000_quadword_masked_address_p (mem_address))
552 /* This rtl is already in the form that matches lvx
553 instruction, so leave it alone. */
556 /* Otherwise, fall through to transform into a swapping load. */
558 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
0])
561 [(set_attr "type" "vecload")
562 (set_attr "length" "
8")])
564 (define_insn_and_split "*vsx_le_perm_load_v16qi"
565 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
566 (match_operand:V16QI
1 "indexed_or_indirect_operand" "Z"))]
567 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
573 (parallel [(const_int
8) (const_int
9)
574 (const_int
10) (const_int
11)
575 (const_int
12) (const_int
13)
576 (const_int
14) (const_int
15)
577 (const_int
0) (const_int
1)
578 (const_int
2) (const_int
3)
579 (const_int
4) (const_int
5)
580 (const_int
6) (const_int
7)])))
584 (parallel [(const_int
8) (const_int
9)
585 (const_int
10) (const_int
11)
586 (const_int
12) (const_int
13)
587 (const_int
14) (const_int
15)
588 (const_int
0) (const_int
1)
589 (const_int
2) (const_int
3)
590 (const_int
4) (const_int
5)
591 (const_int
6) (const_int
7)])))]
593 rtx mem = operands[
1];
595 /* Don't apply the swap optimization if we've already performed register
596 allocation and the hard register destination is not in the altivec
598 if ((MEM_ALIGN (mem) >=
128)
599 && (!HARD_REGISTER_P (operands[
0])
600 || ALTIVEC_REGNO_P (REGNO(operands[
0]))))
602 rtx mem_address = XEXP (mem,
0);
603 enum machine_mode mode = GET_MODE (mem);
605 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
607 /* Replace the source memory address with masked address. */
608 rtx lvx_set_expr = rs6000_gen_lvx (mode, operands[
0], mem);
609 emit_insn (lvx_set_expr);
612 else if (rs6000_quadword_masked_address_p (mem_address))
614 /* This rtl is already in the form that matches lvx
615 instruction, so leave it alone. */
618 /* Otherwise, fall through to transform into a swapping load. */
620 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
0])
623 [(set_attr "type" "vecload")
624 (set_attr "length" "
8")])
626 (define_insn "*vsx_le_perm_store_<mode>"
627 [(set (match_operand:VSX_D
0 "indexed_or_indirect_operand" "=Z")
628 (match_operand:VSX_D
1 "vsx_register_operand" "+wa"))]
629 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
631 [(set_attr "type" "vecstore")
632 (set_attr "length" "
12")])
635 [(set (match_operand:VSX_D
0 "indexed_or_indirect_operand")
636 (match_operand:VSX_D
1 "vsx_register_operand"))]
637 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
641 (parallel [(const_int
1) (const_int
0)])))
645 (parallel [(const_int
1) (const_int
0)])))]
647 rtx mem = operands[
0];
649 /* Don't apply the swap optimization if we've already performed register
650 allocation and the hard register source is not in the altivec range. */
651 if ((MEM_ALIGN (mem) >=
128)
652 && (!HARD_REGISTER_NUM_P (reg_or_subregno (operands[
1]))
653 || ALTIVEC_REGNO_P (reg_or_subregno (operands[
1]))))
655 rtx mem_address = XEXP (mem,
0);
656 enum machine_mode mode = GET_MODE (mem);
657 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
659 rtx stvx_set_expr = rs6000_gen_stvx (mode, mem, operands[
1]);
660 emit_insn (stvx_set_expr);
663 else if (rs6000_quadword_masked_address_p (mem_address))
665 /* This rtl is already in the form that matches stvx instruction,
666 so leave it alone. */
669 /* Otherwise, fall through to transform into a swapping store. */
672 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
1])
676 ;; The post-reload split requires that we re-permute the source
677 ;; register in case it is still live.
679 [(set (match_operand:VSX_D
0 "indexed_or_indirect_operand")
680 (match_operand:VSX_D
1 "vsx_register_operand"))]
681 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
685 (parallel [(const_int
1) (const_int
0)])))
689 (parallel [(const_int
1) (const_int
0)])))
693 (parallel [(const_int
1) (const_int
0)])))]
696 (define_insn "*vsx_le_perm_store_<mode>"
697 [(set (match_operand:VSX_W
0 "indexed_or_indirect_operand" "=Z")
698 (match_operand:VSX_W
1 "vsx_register_operand" "+wa"))]
699 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
701 [(set_attr "type" "vecstore")
702 (set_attr "length" "
12")])
705 [(set (match_operand:VSX_W
0 "indexed_or_indirect_operand")
706 (match_operand:VSX_W
1 "vsx_register_operand"))]
707 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
711 (parallel [(const_int
2) (const_int
3)
712 (const_int
0) (const_int
1)])))
716 (parallel [(const_int
2) (const_int
3)
717 (const_int
0) (const_int
1)])))]
719 rtx mem = operands[
0];
721 /* Don't apply the swap optimization if we've already performed register
722 allocation and the hard register source is not in the altivec range. */
723 if ((MEM_ALIGN (mem) >=
128)
724 && (!HARD_REGISTER_NUM_P (reg_or_subregno (operands[
1]))
725 || ALTIVEC_REGNO_P (reg_or_subregno (operands[
1]))))
727 rtx mem_address = XEXP (mem,
0);
728 enum machine_mode mode = GET_MODE (mem);
729 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
731 rtx stvx_set_expr = rs6000_gen_stvx (mode, mem, operands[
1]);
732 emit_insn (stvx_set_expr);
735 else if (rs6000_quadword_masked_address_p (mem_address))
737 /* This rtl is already in the form that matches stvx instruction,
738 so leave it alone. */
741 /* Otherwise, fall through to transform into a swapping store. */
744 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
1])
748 ;; The post-reload split requires that we re-permute the source
749 ;; register in case it is still live.
751 [(set (match_operand:VSX_W
0 "indexed_or_indirect_operand")
752 (match_operand:VSX_W
1 "vsx_register_operand"))]
753 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
757 (parallel [(const_int
2) (const_int
3)
758 (const_int
0) (const_int
1)])))
762 (parallel [(const_int
2) (const_int
3)
763 (const_int
0) (const_int
1)])))
767 (parallel [(const_int
2) (const_int
3)
768 (const_int
0) (const_int
1)])))]
771 (define_insn "*vsx_le_perm_store_v8hi"
772 [(set (match_operand:V8HI
0 "indexed_or_indirect_operand" "=Z")
773 (match_operand:V8HI
1 "vsx_register_operand" "+wa"))]
774 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
776 [(set_attr "type" "vecstore")
777 (set_attr "length" "
12")])
780 [(set (match_operand:V8HI
0 "indexed_or_indirect_operand")
781 (match_operand:V8HI
1 "vsx_register_operand"))]
782 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
786 (parallel [(const_int
4) (const_int
5)
787 (const_int
6) (const_int
7)
788 (const_int
0) (const_int
1)
789 (const_int
2) (const_int
3)])))
793 (parallel [(const_int
4) (const_int
5)
794 (const_int
6) (const_int
7)
795 (const_int
0) (const_int
1)
796 (const_int
2) (const_int
3)])))]
798 rtx mem = operands[
0];
800 /* Don't apply the swap optimization if we've already performed register
801 allocation and the hard register source is not in the altivec range. */
802 if ((MEM_ALIGN (mem) >=
128)
803 && (!HARD_REGISTER_NUM_P (reg_or_subregno (operands[
1]))
804 || ALTIVEC_REGNO_P (reg_or_subregno (operands[
1]))))
806 rtx mem_address = XEXP (mem,
0);
807 enum machine_mode mode = GET_MODE (mem);
808 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
810 rtx stvx_set_expr = rs6000_gen_stvx (mode, mem, operands[
1]);
811 emit_insn (stvx_set_expr);
814 else if (rs6000_quadword_masked_address_p (mem_address))
816 /* This rtl is already in the form that matches stvx instruction,
817 so leave it alone. */
820 /* Otherwise, fall through to transform into a swapping store. */
823 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
1])
827 ;; The post-reload split requires that we re-permute the source
828 ;; register in case it is still live.
830 [(set (match_operand:V8HI
0 "indexed_or_indirect_operand")
831 (match_operand:V8HI
1 "vsx_register_operand"))]
832 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
836 (parallel [(const_int
4) (const_int
5)
837 (const_int
6) (const_int
7)
838 (const_int
0) (const_int
1)
839 (const_int
2) (const_int
3)])))
843 (parallel [(const_int
4) (const_int
5)
844 (const_int
6) (const_int
7)
845 (const_int
0) (const_int
1)
846 (const_int
2) (const_int
3)])))
850 (parallel [(const_int
4) (const_int
5)
851 (const_int
6) (const_int
7)
852 (const_int
0) (const_int
1)
853 (const_int
2) (const_int
3)])))]
856 (define_insn "*vsx_le_perm_store_v16qi"
857 [(set (match_operand:V16QI
0 "indexed_or_indirect_operand" "=Z")
858 (match_operand:V16QI
1 "vsx_register_operand" "+wa"))]
859 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
861 [(set_attr "type" "vecstore")
862 (set_attr "length" "
12")])
865 [(set (match_operand:V16QI
0 "indexed_or_indirect_operand")
866 (match_operand:V16QI
1 "vsx_register_operand"))]
867 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
871 (parallel [(const_int
8) (const_int
9)
872 (const_int
10) (const_int
11)
873 (const_int
12) (const_int
13)
874 (const_int
14) (const_int
15)
875 (const_int
0) (const_int
1)
876 (const_int
2) (const_int
3)
877 (const_int
4) (const_int
5)
878 (const_int
6) (const_int
7)])))
882 (parallel [(const_int
8) (const_int
9)
883 (const_int
10) (const_int
11)
884 (const_int
12) (const_int
13)
885 (const_int
14) (const_int
15)
886 (const_int
0) (const_int
1)
887 (const_int
2) (const_int
3)
888 (const_int
4) (const_int
5)
889 (const_int
6) (const_int
7)])))]
891 rtx mem = operands[
0];
893 /* Don't apply the swap optimization if we've already performed register
894 allocation and the hard register source is not in the altivec range. */
895 if ((MEM_ALIGN (mem) >=
128)
896 && (!HARD_REGISTER_NUM_P (reg_or_subregno (operands[
1]))
897 || ALTIVEC_REGNO_P (reg_or_subregno (operands[
1]))))
899 rtx mem_address = XEXP (mem,
0);
900 enum machine_mode mode = GET_MODE (mem);
901 if (REG_P (mem_address) || rs6000_sum_of_two_registers_p (mem_address))
903 rtx stvx_set_expr = rs6000_gen_stvx (mode, mem, operands[
1]);
904 emit_insn (stvx_set_expr);
907 else if (rs6000_quadword_masked_address_p (mem_address))
909 /* This rtl is already in the form that matches stvx instruction,
910 so leave it alone. */
913 /* Otherwise, fall through to transform into a swapping store. */
916 operands[
2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[
1])
920 ;; The post-reload split requires that we re-permute the source
921 ;; register in case it is still live.
923 [(set (match_operand:V16QI
0 "indexed_or_indirect_operand")
924 (match_operand:V16QI
1 "vsx_register_operand"))]
925 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
929 (parallel [(const_int
8) (const_int
9)
930 (const_int
10) (const_int
11)
931 (const_int
12) (const_int
13)
932 (const_int
14) (const_int
15)
933 (const_int
0) (const_int
1)
934 (const_int
2) (const_int
3)
935 (const_int
4) (const_int
5)
936 (const_int
6) (const_int
7)])))
940 (parallel [(const_int
8) (const_int
9)
941 (const_int
10) (const_int
11)
942 (const_int
12) (const_int
13)
943 (const_int
14) (const_int
15)
944 (const_int
0) (const_int
1)
945 (const_int
2) (const_int
3)
946 (const_int
4) (const_int
5)
947 (const_int
6) (const_int
7)])))
951 (parallel [(const_int
8) (const_int
9)
952 (const_int
10) (const_int
11)
953 (const_int
12) (const_int
13)
954 (const_int
14) (const_int
15)
955 (const_int
0) (const_int
1)
956 (const_int
2) (const_int
3)
957 (const_int
4) (const_int
5)
958 (const_int
6) (const_int
7)])))]
961 ;; Little endian word swapping for
128-bit types that are either scalars or the
962 ;; special V1TI container class, which it is not appropriate to use vec_select
964 (define_insn "*vsx_le_permute_<mode>"
965 [(set (match_operand:VEC_TI
0 "nonimmediate_operand" "=wa,wa,Z,&r,&r,Q")
967 (match_operand:VEC_TI
1 "input_operand" "wa,Z,wa,r,Q,r")
969 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
971 xxpermdi %x0,%x1,%x1,
2
975 ld%U1%X1 %
0,%L1\;ld%U1%X1 %L0,%
1
976 std%U0%X0 %L1,%
0\;std%U0%X0 %
1,%L0"
977 [(set_attr "length" "*,*,*,
8,
8,
8")
978 (set_attr "type" "vecperm,vecload,vecstore,*,load,store")])
980 (define_insn_and_split "*vsx_le_undo_permute_<mode>"
981 [(set (match_operand:VEC_TI
0 "vsx_register_operand" "=wa,wa")
984 (match_operand:VEC_TI
1 "vsx_register_operand" "
0,wa")
987 "!BYTES_BIG_ENDIAN && TARGET_VSX"
992 [(set (match_dup
0) (match_dup
1))]
994 if (reload_completed && REGNO (operands[
0]) == REGNO (operands[
1]))
996 emit_note (NOTE_INSN_DELETED);
1000 [(set_attr "length" "
0,
4")
1001 (set_attr "type" "veclogical")])
1003 (define_insn_and_split "*vsx_le_perm_load_<mode>"
1004 [(set (match_operand:VSX_LE_128
0 "vsx_register_operand" "=wa,r")
1005 (match_operand:VSX_LE_128
1 "memory_operand" "Z,Q"))]
1006 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
1007 && !altivec_indexed_or_indirect_operand (operands[
1], <MODE>mode)"
1011 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
1012 && !altivec_indexed_or_indirect_operand (operands[
1], <MODE>mode)"
1015 rtx tmp = (can_create_pseudo_p ()
1016 ? gen_reg_rtx_and_attrs (operands[
0])
1018 rs6000_emit_le_vsx_permute (tmp, operands[
1], <MODE>mode);
1019 rs6000_emit_le_vsx_permute (operands[
0], tmp, <MODE>mode);
1022 [(set_attr "type" "vecload,load")
1023 (set_attr "length" "
8,
8")
1024 (set_attr "isa" "<VSisa>,*")])
1026 (define_insn "*vsx_le_perm_store_<mode>"
1027 [(set (match_operand:VSX_LE_128
0 "memory_operand" "=Z,Q")
1028 (match_operand:VSX_LE_128
1 "vsx_register_operand" "+wa,r"))]
1029 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
1030 && !altivec_indexed_or_indirect_operand (operands[
0], <MODE>mode)"
1034 [(set_attr "type" "vecstore,store")
1035 (set_attr "length" "
12,
8")
1036 (set_attr "isa" "<VSisa>,*")])
1039 [(set (match_operand:VSX_LE_128
0 "memory_operand")
1040 (match_operand:VSX_LE_128
1 "vsx_register_operand"))]
1041 "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed && !TARGET_P9_VECTOR
1042 && !altivec_indexed_or_indirect_operand (operands[
0], <MODE>mode)"
1045 rtx tmp = (can_create_pseudo_p ()
1046 ? gen_reg_rtx_and_attrs (operands[
0])
1048 rs6000_emit_le_vsx_permute (tmp, operands[
1], <MODE>mode);
1049 rs6000_emit_le_vsx_permute (operands[
0], tmp, <MODE>mode);
1053 ;; Peepholes to catch loads and stores for TImode if TImode landed in
1054 ;; GPR registers on a little endian system.
1056 [(set (match_operand:VEC_TI
0 "int_reg_operand")
1057 (rotate:VEC_TI (match_operand:VEC_TI
1 "memory_operand")
1059 (set (match_operand:VEC_TI
2 "int_reg_operand")
1060 (rotate:VEC_TI (match_dup
0)
1062 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
1063 && (rtx_equal_p (operands[
0], operands[
2])
1064 || peep2_reg_dead_p (
2, operands[
0]))"
1065 [(set (match_dup
2) (match_dup
1))])
1068 [(set (match_operand:VEC_TI
0 "int_reg_operand")
1069 (rotate:VEC_TI (match_operand:VEC_TI
1 "int_reg_operand")
1071 (set (match_operand:VEC_TI
2 "memory_operand")
1072 (rotate:VEC_TI (match_dup
0)
1074 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
1075 && peep2_reg_dead_p (
2, operands[
0])"
1076 [(set (match_dup
2) (match_dup
1))])
1078 ;; Peephole to catch memory to memory transfers for TImode if TImode landed in
1079 ;; VSX registers on a little endian system. The vector types and IEEE
128-bit
1080 ;; floating point are handled by the more generic swap elimination pass.
1082 [(set (match_operand:TI
0 "vsx_register_operand")
1083 (rotate:TI (match_operand:TI
1 "vsx_register_operand")
1085 (set (match_operand:TI
2 "vsx_register_operand")
1086 (rotate:TI (match_dup
0)
1088 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
1089 && (rtx_equal_p (operands[
0], operands[
2])
1090 || peep2_reg_dead_p (
2, operands[
0]))"
1091 [(set (match_dup
2) (match_dup
1))])
1093 ;; The post-reload split requires that we re-permute the source
1094 ;; register in case it is still live.
1096 [(set (match_operand:VSX_LE_128
0 "memory_operand")
1097 (match_operand:VSX_LE_128
1 "vsx_register_operand"))]
1098 "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed && !TARGET_P9_VECTOR
1099 && !altivec_indexed_or_indirect_operand (operands[
0], <MODE>mode)"
1102 rs6000_emit_le_vsx_permute (operands[
1], operands[
1], <MODE>mode);
1103 rs6000_emit_le_vsx_permute (operands[
0], operands[
1], <MODE>mode);
1104 rs6000_emit_le_vsx_permute (operands[
1], operands[
1], <MODE>mode);
1108 ;; Vector constants that can be generated with XXSPLTIB that was added in ISA
1109 ;;
3.0. Both (const_vector [..]) and (vec_duplicate ...) forms are recognized.
1110 (define_insn "xxspltib_v16qi"
1111 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
1112 (vec_duplicate:V16QI (match_operand:SI
1 "s8bit_cint_operand" "n")))]
1115 operands[
2] = GEN_INT (INTVAL (operands[
1]) &
0xff);
1116 return "xxspltib %x0,%
2";
1118 [(set_attr "type" "vecperm")])
1120 (define_insn "xxspltib_<mode>_nosplit"
1121 [(set (match_operand:VSINT_842
0 "vsx_register_operand" "=wa,wa")
1122 (match_operand:VSINT_842
1 "xxspltib_constant_nosplit" "jwM,wE"))]
1125 rtx op1 = operands[
1];
1129 if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
1133 operands[
2] = GEN_INT (value &
0xff);
1134 return "xxspltib %x0,%
2";
1136 [(set_attr "type" "vecperm")])
1138 (define_insn_and_split "*xxspltib_<mode>_split"
1139 [(set (match_operand:VSINT_842
0 "altivec_register_operand" "=v")
1140 (match_operand:VSINT_842
1 "xxspltib_constant_split" "wS"))]
1148 rtx op0 = operands[
0];
1149 rtx op1 = operands[
1];
1150 rtx tmp = ((can_create_pseudo_p ())
1151 ? gen_reg_rtx (V16QImode)
1152 : gen_lowpart (V16QImode, op0));
1154 if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
1158 emit_insn (gen_xxspltib_v16qi (tmp, GEN_INT (value)));
1160 if (<MODE>mode == V2DImode)
1161 emit_insn (gen_vsx_sign_extend_v16qi_v2di (op0, tmp));
1163 else if (<MODE>mode == V4SImode)
1164 emit_insn (gen_vsx_sign_extend_v16qi_v4si (op0, tmp));
1166 else if (<MODE>mode == V8HImode)
1167 emit_insn (gen_altivec_vupkhsb (op0, tmp));
1174 [(set_attr "type" "vecperm")
1175 (set_attr "length" "
8")])
1178 ;; Prefer using vector registers over GPRs. Prefer using ISA
3.0's XXSPLTISB
1179 ;; or Altivec VSPLITW
0/-
1 over XXLXOR/XXLORC to set a register to all
0's or
1180 ;; all
1's, since the machine does not have to wait for the previous
1181 ;; instruction using the register being set (such as a store waiting on a slow
1182 ;; instruction). But generate XXLXOR/XXLORC if it will avoid a register move.
1184 ;; VSX store VSX load VSX move VSX->GPR GPR->VSX LQ (GPR)
1185 ;; STQ (GPR) GPR load GPR store GPR move XXSPLTIB VSPLTISW
1187 ;; VSX
0/-
1 VMX const GPR const LVX (VMX) STVX (VMX)
1188 (define_insn "vsx_mov<mode>_64bit"
1189 [(set (match_operand:VSX_M
0 "nonimmediate_operand"
1190 "=ZwO, wa, wa, r, we, ?wQ,
1191 ?&r, ??r, ??Y, <??r>, wa, v,
1193 ?wa, v, <??r>, wZ, v")
1195 (match_operand:VSX_M
1 "input_operand"
1196 "wa, ZwO, wa, we, r, r,
1197 wQ, Y, r, r, wE, jwM,
1199 ?jwM, W, <nW>, v, wZ"))]
1201 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1202 && (register_operand (operands[
0], <MODE>mode)
1203 || register_operand (operands[
1], <MODE>mode))"
1205 return rs6000_output_move_128bit (operands);
1208 "vecstore, vecload, vecsimple, mtvsr, mfvsr, load,
1209 store, load, store, *, vecsimple, vecsimple,
1211 vecsimple, *, *, vecstore, vecload")
1212 (set_attr "num_insns"
1217 (set_attr "max_prefixed_insns"
1228 "<VSisa>, <VSisa>, <VSisa>, *, *, *,
1231 <VSisa>, *, *, *, *")
1232 (set_attr "prefixed"
1238 ;; VSX store VSX load VSX move GPR load GPR store GPR move
1240 ;; XXSPLTIB VSPLTISW VSX
0/-
1 VMX const GPR const
1241 ;; LVX (VMX) STVX (VMX)
1242 (define_insn "*vsx_mov<mode>_32bit"
1243 [(set (match_operand:VSX_M
0 "nonimmediate_operand"
1244 "=ZwO, wa, wa, ??r, ??Y, <??r>,
1246 wa, v, ?wa, v, <??r>,
1249 (match_operand:VSX_M
1 "input_operand"
1250 "wa, ZwO, wa, Y, r, r,
1252 wE, jwM, ?jwM, W, <nW>,
1255 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
1256 && (register_operand (operands[
0], <MODE>mode)
1257 || register_operand (operands[
1], <MODE>mode))"
1259 return rs6000_output_move_128bit (operands);
1262 "vecstore, vecload, vecsimple, load, store, *,
1264 vecsimple, vecsimple, vecsimple, *, *,
1267 "*, *, *,
16,
16,
16,
1272 "<VSisa>, <VSisa>, <VSisa>, *, *, *,
1274 p9v, *, <VSisa>, *, *,
1276 (set_attr "prefixed"
1282 ;; Explicit load/store expanders for the builtin functions
1283 (define_expand "vsx_load_<mode>"
1284 [(set (match_operand:VSX_M
0 "vsx_register_operand")
1285 (match_operand:VSX_M
1 "memory_operand"))]
1286 "VECTOR_MEM_VSX_P (<MODE>mode)"
1288 /* Expand to swaps if needed, prior to swap optimization. */
1289 if (!BYTES_BIG_ENDIAN && !TARGET_P9_VECTOR
1290 && !altivec_indexed_or_indirect_operand(operands[
1], <MODE>mode))
1292 rs6000_emit_le_vsx_move (operands[
0], operands[
1], <MODE>mode);
1297 (define_expand "vsx_store_<mode>"
1298 [(set (match_operand:VSX_M
0 "memory_operand")
1299 (match_operand:VSX_M
1 "vsx_register_operand"))]
1300 "VECTOR_MEM_VSX_P (<MODE>mode)"
1302 /* Expand to swaps if needed, prior to swap optimization. */
1303 if (!BYTES_BIG_ENDIAN && !TARGET_P9_VECTOR
1304 && !altivec_indexed_or_indirect_operand(operands[
0], <MODE>mode))
1306 rs6000_emit_le_vsx_move (operands[
0], operands[
1], <MODE>mode);
1311 ;; Load rightmost element from load_data
1312 ;; using lxvrbx, lxvrhx, lxvrwx, lxvrdx.
1313 (define_insn "vsx_lxvr<wd>x"
1314 [(set (match_operand:TI
0 "vsx_register_operand" "=wa")
1315 (zero_extend:TI (match_operand:INT_ISA3
1 "memory_operand" "Z")))]
1318 [(set_attr "type" "vecload")])
1320 ;; Store rightmost element into store_data
1321 ;; using stxvrbx, stxvrhx, strvxwx, strvxdx.
1322 (define_insn "vsx_stxvr<wd>x"
1323 [(set (match_operand:INT_ISA3
0 "memory_operand" "=Z")
1324 (truncate:INT_ISA3 (match_operand:TI
1 "vsx_register_operand" "wa")))]
1326 "stxvr<wd>x %x1,%y0"
1327 [(set_attr "type" "vecstore")])
1329 ;; Explicit load/store expanders for the builtin functions for lxvd2x, etc.,
1330 ;; when you really want their element-reversing behavior.
1331 (define_insn "vsx_ld_elemrev_v2di"
1332 [(set (match_operand:V2DI
0 "vsx_register_operand" "=wa")
1334 (match_operand:V2DI
1 "memory_operand" "Z")
1335 (parallel [(const_int
1) (const_int
0)])))]
1336 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1338 [(set_attr "type" "vecload")])
1340 (define_insn "vsx_ld_elemrev_v1ti"
1341 [(set (match_operand:V1TI
0 "vsx_register_operand" "=wa")
1343 (match_operand:V1TI
1 "memory_operand" "Z")
1344 (parallel [(const_int
0)])))]
1345 "VECTOR_MEM_VSX_P (V1TImode) && !BYTES_BIG_ENDIAN"
1347 return "lxvd2x %x0,%y1\;xxpermdi %x0,%x0,%x0,
2";
1349 [(set_attr "type" "vecload")])
1351 (define_insn "vsx_ld_elemrev_v2df"
1352 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa")
1354 (match_operand:V2DF
1 "memory_operand" "Z")
1355 (parallel [(const_int
1) (const_int
0)])))]
1356 "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1358 [(set_attr "type" "vecload")])
1360 (define_insn "vsx_ld_elemrev_v4si"
1361 [(set (match_operand:V4SI
0 "vsx_register_operand" "=wa")
1363 (match_operand:V4SI
1 "memory_operand" "Z")
1364 (parallel [(const_int
3) (const_int
2)
1365 (const_int
1) (const_int
0)])))]
1366 "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1368 [(set_attr "type" "vecload")])
1370 (define_insn "vsx_ld_elemrev_v4sf"
1371 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
1373 (match_operand:V4SF
1 "memory_operand" "Z")
1374 (parallel [(const_int
3) (const_int
2)
1375 (const_int
1) (const_int
0)])))]
1376 "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1378 [(set_attr "type" "vecload")])
1380 (define_expand "vsx_ld_elemrev_v8hi"
1381 [(set (match_operand:V8HI
0 "vsx_register_operand" "=wa")
1383 (match_operand:V8HI
1 "memory_operand" "Z")
1384 (parallel [(const_int
7) (const_int
6)
1385 (const_int
5) (const_int
4)
1386 (const_int
3) (const_int
2)
1387 (const_int
1) (const_int
0)])))]
1388 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN"
1390 if (!TARGET_P9_VECTOR)
1392 rtx tmp = gen_reg_rtx (V4SImode);
1393 rtx subreg, subreg2, perm[
16], pcv;
1394 /*
2 is leftmost element in register */
1395 unsigned int reorder[
16] = {
13,
12,
15,
14,
9,
8,
11,
10,
5,
4,
7,
6,
1,
0,
3,
2};
1398 subreg = simplify_gen_subreg (V4SImode, operands[
1], V8HImode,
0);
1399 emit_insn (gen_vsx_ld_elemrev_v4si (tmp, subreg));
1400 subreg2 = simplify_gen_subreg (V8HImode, tmp, V4SImode,
0);
1402 for (i =
0; i <
16; ++i)
1403 perm[i] = GEN_INT (reorder[i]);
1405 pcv = force_reg (V16QImode,
1406 gen_rtx_CONST_VECTOR (V16QImode,
1407 gen_rtvec_v (
16, perm)));
1408 emit_insn (gen_altivec_vperm_v8hi_direct (operands[
0], subreg2,
1414 (define_insn "*vsx_ld_elemrev_v8hi_internal"
1415 [(set (match_operand:V8HI
0 "vsx_register_operand" "=wa")
1417 (match_operand:V8HI
1 "memory_operand" "Z")
1418 (parallel [(const_int
7) (const_int
6)
1419 (const_int
5) (const_int
4)
1420 (const_int
3) (const_int
2)
1421 (const_int
1) (const_int
0)])))]
1422 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1424 [(set_attr "type" "vecload")])
1426 (define_expand "vsx_ld_elemrev_v16qi"
1427 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
1429 (match_operand:V16QI
1 "memory_operand" "Z")
1430 (parallel [(const_int
15) (const_int
14)
1431 (const_int
13) (const_int
12)
1432 (const_int
11) (const_int
10)
1433 (const_int
9) (const_int
8)
1434 (const_int
7) (const_int
6)
1435 (const_int
5) (const_int
4)
1436 (const_int
3) (const_int
2)
1437 (const_int
1) (const_int
0)])))]
1438 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN"
1440 if (!TARGET_P9_VECTOR)
1442 rtx tmp = gen_reg_rtx (V4SImode);
1443 rtx subreg, subreg2, perm[
16], pcv;
1444 /*
3 is leftmost element in register */
1445 unsigned int reorder[
16] = {
12,
13,
14,
15,
8,
9,
10,
11,
4,
5,
6,
7,
0,
1,
2,
3};
1448 subreg = simplify_gen_subreg (V4SImode, operands[
1], V16QImode,
0);
1449 emit_insn (gen_vsx_ld_elemrev_v4si (tmp, subreg));
1450 subreg2 = simplify_gen_subreg (V16QImode, tmp, V4SImode,
0);
1452 for (i =
0; i <
16; ++i)
1453 perm[i] = GEN_INT (reorder[i]);
1455 pcv = force_reg (V16QImode,
1456 gen_rtx_CONST_VECTOR (V16QImode,
1457 gen_rtvec_v (
16, perm)));
1458 emit_insn (gen_altivec_vperm_v16qi_direct (operands[
0], subreg2,
1464 (define_insn "vsx_ld_elemrev_v16qi_internal"
1465 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
1467 (match_operand:V16QI
1 "memory_operand" "Z")
1468 (parallel [(const_int
15) (const_int
14)
1469 (const_int
13) (const_int
12)
1470 (const_int
11) (const_int
10)
1471 (const_int
9) (const_int
8)
1472 (const_int
7) (const_int
6)
1473 (const_int
5) (const_int
4)
1474 (const_int
3) (const_int
2)
1475 (const_int
1) (const_int
0)])))]
1476 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1478 [(set_attr "type" "vecload")])
1480 (define_insn "vsx_st_elemrev_v1ti"
1481 [(set (match_operand:V1TI
0 "memory_operand" "=Z")
1483 (match_operand:V1TI
1 "vsx_register_operand" "+wa")
1484 (parallel [(const_int
0)])))
1485 (clobber (match_dup
1))]
1486 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1488 return "xxpermdi %x1,%x1,%x1,
2\;stxvd2x %x1,%y0";
1490 [(set_attr "type" "vecstore")])
1492 (define_insn "vsx_st_elemrev_v2df"
1493 [(set (match_operand:V2DF
0 "memory_operand" "=Z")
1495 (match_operand:V2DF
1 "vsx_register_operand" "wa")
1496 (parallel [(const_int
1) (const_int
0)])))]
1497 "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1499 [(set_attr "type" "vecstore")])
1501 (define_insn "vsx_st_elemrev_v2di"
1502 [(set (match_operand:V2DI
0 "memory_operand" "=Z")
1504 (match_operand:V2DI
1 "vsx_register_operand" "wa")
1505 (parallel [(const_int
1) (const_int
0)])))]
1506 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1508 [(set_attr "type" "vecstore")])
1510 (define_insn "vsx_st_elemrev_v4sf"
1511 [(set (match_operand:V4SF
0 "memory_operand" "=Z")
1513 (match_operand:V4SF
1 "vsx_register_operand" "wa")
1514 (parallel [(const_int
3) (const_int
2)
1515 (const_int
1) (const_int
0)])))]
1516 "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1518 [(set_attr "type" "vecstore")])
1520 (define_insn "vsx_st_elemrev_v4si"
1521 [(set (match_operand:V4SI
0 "memory_operand" "=Z")
1523 (match_operand:V4SI
1 "vsx_register_operand" "wa")
1524 (parallel [(const_int
3) (const_int
2)
1525 (const_int
1) (const_int
0)])))]
1526 "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1528 [(set_attr "type" "vecstore")])
1530 (define_expand "vsx_st_elemrev_v8hi"
1531 [(set (match_operand:V8HI
0 "memory_operand" "=Z")
1533 (match_operand:V8HI
1 "vsx_register_operand" "wa")
1534 (parallel [(const_int
7) (const_int
6)
1535 (const_int
5) (const_int
4)
1536 (const_int
3) (const_int
2)
1537 (const_int
1) (const_int
0)])))]
1538 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN"
1540 if (!TARGET_P9_VECTOR)
1542 rtx mem_subreg, subreg, perm[
16], pcv;
1543 rtx tmp = gen_reg_rtx (V8HImode);
1544 /*
2 is leftmost element in register */
1545 unsigned int reorder[
16] = {
13,
12,
15,
14,
9,
8,
11,
10,
5,
4,
7,
6,
1,
0,
3,
2};
1548 for (i =
0; i <
16; ++i)
1549 perm[i] = GEN_INT (reorder[i]);
1551 pcv = force_reg (V16QImode,
1552 gen_rtx_CONST_VECTOR (V16QImode,
1553 gen_rtvec_v (
16, perm)));
1554 emit_insn (gen_altivec_vperm_v8hi_direct (tmp, operands[
1],
1556 subreg = simplify_gen_subreg (V4SImode, tmp, V8HImode,
0);
1557 mem_subreg = simplify_gen_subreg (V4SImode, operands[
0], V8HImode,
0);
1558 emit_insn (gen_vsx_st_elemrev_v4si (mem_subreg, subreg));
1563 (define_insn "*vsx_st_elemrev_v2di_internal"
1564 [(set (match_operand:V2DI
0 "memory_operand" "=Z")
1566 (match_operand:V2DI
1 "vsx_register_operand" "wa")
1567 (parallel [(const_int
1) (const_int
0)])))]
1568 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1570 [(set_attr "type" "vecstore")])
1572 (define_insn "*vsx_st_elemrev_v8hi_internal"
1573 [(set (match_operand:V8HI
0 "memory_operand" "=Z")
1575 (match_operand:V8HI
1 "vsx_register_operand" "wa")
1576 (parallel [(const_int
7) (const_int
6)
1577 (const_int
5) (const_int
4)
1578 (const_int
3) (const_int
2)
1579 (const_int
1) (const_int
0)])))]
1580 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1582 [(set_attr "type" "vecstore")])
1584 (define_expand "vsx_st_elemrev_v16qi"
1585 [(set (match_operand:V16QI
0 "memory_operand" "=Z")
1587 (match_operand:V16QI
1 "vsx_register_operand" "wa")
1588 (parallel [(const_int
15) (const_int
14)
1589 (const_int
13) (const_int
12)
1590 (const_int
11) (const_int
10)
1591 (const_int
9) (const_int
8)
1592 (const_int
7) (const_int
6)
1593 (const_int
5) (const_int
4)
1594 (const_int
3) (const_int
2)
1595 (const_int
1) (const_int
0)])))]
1596 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN"
1598 if (!TARGET_P9_VECTOR)
1600 rtx mem_subreg, subreg, perm[
16], pcv;
1601 rtx tmp = gen_reg_rtx (V16QImode);
1602 /*
3 is leftmost element in register */
1603 unsigned int reorder[
16] = {
12,
13,
14,
15,
8,
9,
10,
11,
4,
5,
6,
7,
0,
1,
2,
3};
1606 for (i =
0; i <
16; ++i)
1607 perm[i] = GEN_INT (reorder[i]);
1609 pcv = force_reg (V16QImode,
1610 gen_rtx_CONST_VECTOR (V16QImode,
1611 gen_rtvec_v (
16, perm)));
1612 emit_insn (gen_altivec_vperm_v16qi_direct (tmp, operands[
1],
1614 subreg = simplify_gen_subreg (V4SImode, tmp, V16QImode,
0);
1615 mem_subreg = simplify_gen_subreg (V4SImode, operands[
0], V16QImode,
0);
1616 emit_insn (gen_vsx_st_elemrev_v4si (mem_subreg, subreg));
1621 (define_insn "*vsx_st_elemrev_v16qi_internal"
1622 [(set (match_operand:V16QI
0 "memory_operand" "=Z")
1624 (match_operand:V16QI
1 "vsx_register_operand" "wa")
1625 (parallel [(const_int
15) (const_int
14)
1626 (const_int
13) (const_int
12)
1627 (const_int
11) (const_int
10)
1628 (const_int
9) (const_int
8)
1629 (const_int
7) (const_int
6)
1630 (const_int
5) (const_int
4)
1631 (const_int
3) (const_int
2)
1632 (const_int
1) (const_int
0)])))]
1633 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1635 [(set_attr "type" "vecstore")])
1638 ;; VSX vector floating point arithmetic instructions. The VSX scalar
1639 ;; instructions are now combined with the insn for the traditional floating
1641 (define_insn "*vsx_add<mode>
3"
1642 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1643 (plus:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
1644 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
1645 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1646 "xvadd<sd>p %x0,%x1,%x2"
1647 [(set_attr "type" "<VStype_simple>")])
1649 (define_insn "*vsx_sub<mode>
3"
1650 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa>")
1651 (minus:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
1652 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
1653 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1654 "xvsub<sd>p %x0,%x1,%x2"
1655 [(set_attr "type" "<VStype_simple>")])
1657 (define_insn "*vsx_mul<mode>
3"
1658 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1659 (mult:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
1660 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
1661 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1662 "xvmul<sd>p %x0,%x1,%x2"
1663 [(set_attr "type" "<VStype_simple>")])
1665 ; Emulate vector with scalar for vec_mul in V2DImode
1666 (define_insn_and_split "vsx_mul_v2di"
1667 [(set (match_operand:V2DI
0 "vsx_register_operand" "=wa")
1668 (unspec:V2DI [(match_operand:V2DI
1 "vsx_register_operand" "wa")
1669 (match_operand:V2DI
2 "vsx_register_operand" "wa")]
1671 "VECTOR_MEM_VSX_P (V2DImode)"
1673 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed"
1676 rtx op0 = operands[
0];
1677 rtx op1 = operands[
1];
1678 rtx op2 = operands[
2];
1681 emit_insn (gen_mulv2di3 (op0, op1, op2) );
1685 rtx op3 = gen_reg_rtx (DImode);
1686 rtx op4 = gen_reg_rtx (DImode);
1687 rtx op5 = gen_reg_rtx (DImode);
1688 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (
0)));
1689 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (
0)));
1690 if (TARGET_POWERPC64)
1691 emit_insn (gen_muldi3 (op5, op3, op4));
1694 rtx ret = expand_mult (DImode, op3, op4, NULL,
0, false);
1695 emit_move_insn (op5, ret);
1697 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (
1)));
1698 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (
1)));
1699 if (TARGET_POWERPC64)
1700 emit_insn (gen_muldi3 (op3, op3, op4));
1703 rtx ret = expand_mult (DImode, op3, op4, NULL,
0, false);
1704 emit_move_insn (op3, ret);
1706 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1710 [(set_attr "type" "mul")])
1712 (define_insn "*vsx_div<mode>
3"
1713 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1714 (div:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
1715 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
1716 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1717 "xvdiv<sd>p %x0,%x1,%x2"
1718 [(set_attr "type" "<VStype_div>")])
1720 ; Emulate vector with scalar for vec_div in V2DImode
1721 (define_insn_and_split "vsx_div_v2di"
1722 [(set (match_operand:V2DI
0 "vsx_register_operand" "=wa")
1723 (unspec:V2DI [(match_operand:V2DI
1 "vsx_register_operand" "wa")
1724 (match_operand:V2DI
2 "vsx_register_operand" "wa")]
1726 "VECTOR_MEM_VSX_P (V2DImode)"
1728 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed"
1731 rtx op0 = operands[
0];
1732 rtx op1 = operands[
1];
1733 rtx op2 = operands[
2];
1734 rtx op3 = gen_reg_rtx (DImode);
1735 rtx op4 = gen_reg_rtx (DImode);
1736 rtx op5 = gen_reg_rtx (DImode);
1737 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (
0)));
1738 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (
0)));
1739 if (TARGET_POWERPC64)
1740 emit_insn (gen_divdi3 (op5, op3, op4));
1743 rtx libfunc = optab_libfunc (sdiv_optab, DImode);
1744 rtx target = emit_library_call_value (libfunc,
1745 op5, LCT_NORMAL, DImode,
1748 emit_move_insn (op5, target);
1750 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (
1)));
1751 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (
1)));
1752 if (TARGET_POWERPC64)
1753 emit_insn (gen_divdi3 (op3, op3, op4));
1756 rtx libfunc = optab_libfunc (sdiv_optab, DImode);
1757 rtx target = emit_library_call_value (libfunc,
1758 op3, LCT_NORMAL, DImode,
1761 emit_move_insn (op3, target);
1763 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1766 [(set_attr "type" "div")])
1768 (define_insn_and_split "vsx_udiv_v2di"
1769 [(set (match_operand:V2DI
0 "vsx_register_operand" "=wa")
1770 (unspec:V2DI [(match_operand:V2DI
1 "vsx_register_operand" "wa")
1771 (match_operand:V2DI
2 "vsx_register_operand" "wa")]
1773 "VECTOR_MEM_VSX_P (V2DImode)"
1775 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed"
1778 rtx op0 = operands[
0];
1779 rtx op1 = operands[
1];
1780 rtx op2 = operands[
2];
1783 emit_insn (gen_udivv2di3 (op0, op1, op2) );
1786 rtx op3 = gen_reg_rtx (DImode);
1787 rtx op4 = gen_reg_rtx (DImode);
1788 rtx op5 = gen_reg_rtx (DImode);
1790 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (
0)));
1791 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (
0)));
1793 if (TARGET_POWERPC64)
1794 emit_insn (gen_udivdi3 (op5, op3, op4));
1797 rtx libfunc = optab_libfunc (udiv_optab, DImode);
1798 rtx target = emit_library_call_value (libfunc,
1799 op5, LCT_NORMAL, DImode,
1802 emit_move_insn (op5, target);
1804 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (
1)));
1805 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (
1)));
1807 if (TARGET_POWERPC64)
1808 emit_insn (gen_udivdi3 (op3, op3, op4));
1811 rtx libfunc = optab_libfunc (udiv_optab, DImode);
1812 rtx target = emit_library_call_value (libfunc,
1813 op3, LCT_NORMAL, DImode,
1816 emit_move_insn (op3, target);
1818 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1822 [(set_attr "type" "div")])
1824 ;; Vector integer signed/unsigned divide
1825 (define_insn "vsx_div_v1ti"
1826 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
1827 (unspec:V1TI [(match_operand:V1TI
1 "vsx_register_operand" "v")
1828 (match_operand:V1TI
2 "vsx_register_operand" "v")]
1832 [(set_attr "type" "div")])
1834 (define_insn "vsx_udiv_v1ti"
1835 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
1836 (unspec:V1TI [(match_operand:V1TI
1 "vsx_register_operand" "v")
1837 (match_operand:V1TI
2 "vsx_register_operand" "v")]
1841 [(set_attr "type" "div")])
1843 (define_insn "vsx_dives_v1ti"
1844 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
1845 (unspec:V1TI [(match_operand:V1TI
1 "vsx_register_operand" "v")
1846 (match_operand:V1TI
2 "vsx_register_operand" "v")]
1847 UNSPEC_VSX_DIVESQ))]
1850 [(set_attr "type" "div")])
1852 (define_insn "vsx_diveu_v1ti"
1853 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
1854 (unspec:V1TI [(match_operand:V1TI
1 "vsx_register_operand" "v")
1855 (match_operand:V1TI
2 "vsx_register_operand" "v")]
1856 UNSPEC_VSX_DIVEUQ))]
1859 [(set_attr "type" "div")])
1861 (define_insn "vsx_mods_v1ti"
1862 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
1863 (unspec:V1TI [(match_operand:V1TI
1 "vsx_register_operand" "v")
1864 (match_operand:V1TI
2 "vsx_register_operand" "v")]
1868 [(set_attr "type" "div")])
1870 (define_insn "vsx_modu_v1ti"
1871 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
1872 (unspec:V1TI [(match_operand:V1TI
1 "vsx_register_operand" "v")
1873 (match_operand:V1TI
2 "vsx_register_operand" "v")]
1877 [(set_attr "type" "div")])
1879 ;; *tdiv* instruction returning the FG flag
1880 (define_expand "vsx_tdiv<mode>
3_fg"
1882 (unspec:CCFP [(match_operand:VSX_B
1 "vsx_register_operand")
1883 (match_operand:VSX_B
2 "vsx_register_operand")]
1885 (set (match_operand:SI
0 "gpc_reg_operand")
1886 (gt:SI (match_dup
3)
1888 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1890 operands[
3] = gen_reg_rtx (CCFPmode);
1893 ;; *tdiv* instruction returning the FE flag
1894 (define_expand "vsx_tdiv<mode>
3_fe"
1896 (unspec:CCFP [(match_operand:VSX_B
1 "vsx_register_operand")
1897 (match_operand:VSX_B
2 "vsx_register_operand")]
1899 (set (match_operand:SI
0 "gpc_reg_operand")
1900 (eq:SI (match_dup
3)
1902 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1904 operands[
3] = gen_reg_rtx (CCFPmode);
1907 (define_insn "*vsx_tdiv<mode>
3_internal"
1908 [(set (match_operand:CCFP
0 "cc_reg_operand" "=x")
1909 (unspec:CCFP [(match_operand:VSX_B
1 "vsx_register_operand" "wa")
1910 (match_operand:VSX_B
2 "vsx_register_operand" "wa")]
1912 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1913 "x<VSv>tdiv<sd>p %
0,%x1,%x2"
1914 [(set_attr "type" "<VStype_simple>")])
1916 (define_insn "vsx_fre<mode>
2"
1917 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1918 (unspec:VSX_F [(match_operand:VSX_F
1 "vsx_register_operand" "wa")]
1920 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1922 [(set_attr "type" "<VStype_simple>")])
1924 (define_insn "*vsx_neg<mode>
2"
1925 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1926 (neg:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")))]
1927 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1928 "xvneg<sd>p %x0,%x1"
1929 [(set_attr "type" "<VStype_simple>")])
1931 (define_insn "*vsx_abs<mode>
2"
1932 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1933 (abs:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")))]
1934 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1935 "xvabs<sd>p %x0,%x1"
1936 [(set_attr "type" "<VStype_simple>")])
1938 (define_insn "vsx_nabs<mode>
2"
1939 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1942 (match_operand:VSX_F
1 "vsx_register_operand" "wa"))))]
1943 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1944 "xvnabs<sd>p %x0,%x1"
1945 [(set_attr "type" "<VStype_simple>")])
1947 (define_insn "vsx_smax<mode>
3"
1948 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1949 (smax:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
1950 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
1951 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1952 "xvmax<sd>p %x0,%x1,%x2"
1953 [(set_attr "type" "<VStype_simple>")])
1955 (define_insn "*vsx_smin<mode>
3"
1956 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1957 (smin:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
1958 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
1959 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1960 "xvmin<sd>p %x0,%x1,%x2"
1961 [(set_attr "type" "<VStype_simple>")])
1963 (define_insn "*vsx_sqrt<mode>
2"
1964 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1965 (sqrt:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")))]
1966 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1967 "xvsqrt<sd>p %x0,%x1"
1968 [(set_attr "type" "<sd>sqrt")])
1970 (define_insn "*vsx_rsqrte<mode>
2"
1971 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
1972 (unspec:VSX_F [(match_operand:VSX_F
1 "vsx_register_operand" "wa")]
1974 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1975 "xvrsqrte<sd>p %x0,%x1"
1976 [(set_attr "type" "<VStype_simple>")])
1978 ;; *tsqrt* returning the fg flag
1979 (define_expand "vsx_tsqrt<mode>
2_fg"
1981 (unspec:CCFP [(match_operand:VSX_B
1 "vsx_register_operand")]
1983 (set (match_operand:SI
0 "gpc_reg_operand")
1984 (gt:SI (match_dup
2)
1986 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1988 operands[
2] = gen_reg_rtx (CCFPmode);
1991 ;; *tsqrt* returning the fe flag
1992 (define_expand "vsx_tsqrt<mode>
2_fe"
1994 (unspec:CCFP [(match_operand:VSX_B
1 "vsx_register_operand")]
1996 (set (match_operand:SI
0 "gpc_reg_operand")
1997 (eq:SI (match_dup
2)
1999 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2001 operands[
2] = gen_reg_rtx (CCFPmode);
2004 (define_insn "*vsx_tsqrt<mode>
2_internal"
2005 [(set (match_operand:CCFP
0 "cc_reg_operand" "=x")
2006 (unspec:CCFP [(match_operand:VSX_B
1 "vsx_register_operand" "wa")]
2008 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2009 "x<VSv>tsqrt<sd>p %
0,%x1"
2010 [(set_attr "type" "<VStype_simple>")])
2012 ;; Fused vector multiply/add instructions. Do not generate the Altivec versions
2013 ;; of fma (vmaddfp and vnmsubfp). These instructions allows the target to be a
2014 ;; separate register from the
3 inputs, which can possibly save an extra move
2015 ;; being generated (assuming all registers are AltiVec registers). However,
2016 ;; vmaddfp and vnmsubfp can have different behaviors than the VSX instructions
2017 ;; in some corner cases due to VSCR[NJ] being set or if the addend is +
0.0
2019 (define_insn "*vsx_fmav4sf4"
2020 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa,wa")
2022 (match_operand:V4SF
1 "vsx_register_operand" "%wa,wa")
2023 (match_operand:V4SF
2 "vsx_register_operand" "wa,
0")
2024 (match_operand:V4SF
3 "vsx_register_operand" "
0,wa")))]
2025 "VECTOR_UNIT_VSX_P (V4SFmode)"
2027 xvmaddasp %x0,%x1,%x2
2028 xvmaddmsp %x0,%x1,%x3"
2029 [(set_attr "type" "vecfloat")])
2031 (define_insn "*vsx_fmav2df4"
2032 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa,wa")
2034 (match_operand:V2DF
1 "vsx_register_operand" "%wa,wa")
2035 (match_operand:V2DF
2 "vsx_register_operand" "wa,
0")
2036 (match_operand:V2DF
3 "vsx_register_operand" "
0,wa")))]
2037 "VECTOR_UNIT_VSX_P (V2DFmode)"
2039 xvmaddadp %x0,%x1,%x2
2040 xvmaddmdp %x0,%x1,%x3"
2041 [(set_attr "type" "vecdouble")])
2043 (define_insn "*vsx_fms<mode>
4"
2044 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa,wa")
2046 (match_operand:VSX_F
1 "vsx_register_operand" "%wa,wa")
2047 (match_operand:VSX_F
2 "vsx_register_operand" "wa,
0")
2049 (match_operand:VSX_F
3 "vsx_register_operand" "
0,wa"))))]
2050 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2052 xvmsuba<sd>p %x0,%x1,%x2
2053 xvmsubm<sd>p %x0,%x1,%x3"
2054 [(set_attr "type" "<VStype_mul>")])
2056 (define_insn "*vsx_nfma<mode>
4"
2057 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa,wa")
2060 (match_operand:VSX_F
1 "vsx_register_operand" "wa,wa")
2061 (match_operand:VSX_F
2 "vsx_register_operand" "wa,
0")
2062 (match_operand:VSX_F
3 "vsx_register_operand" "
0,wa"))))]
2063 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2065 xvnmadda<sd>p %x0,%x1,%x2
2066 xvnmaddm<sd>p %x0,%x1,%x3"
2067 [(set_attr "type" "<VStype_mul>")])
2069 (define_insn "*vsx_nfmsv4sf4"
2070 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa,wa")
2073 (match_operand:V4SF
1 "vsx_register_operand" "%wa,wa")
2074 (match_operand:V4SF
2 "vsx_register_operand" "wa,
0")
2076 (match_operand:V4SF
3 "vsx_register_operand" "
0,wa")))))]
2077 "VECTOR_UNIT_VSX_P (V4SFmode)"
2079 xvnmsubasp %x0,%x1,%x2
2080 xvnmsubmsp %x0,%x1,%x3"
2081 [(set_attr "type" "vecfloat")])
2083 (define_insn "*vsx_nfmsv2df4"
2084 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa,wa")
2087 (match_operand:V2DF
1 "vsx_register_operand" "%wa,wa")
2088 (match_operand:V2DF
2 "vsx_register_operand" "wa,
0")
2090 (match_operand:V2DF
3 "vsx_register_operand" "
0,wa")))))]
2091 "VECTOR_UNIT_VSX_P (V2DFmode)"
2093 xvnmsubadp %x0,%x1,%x2
2094 xvnmsubmdp %x0,%x1,%x3"
2095 [(set_attr "type" "vecdouble")])
2097 ;; Vector conditional expressions (no scalar version for these instructions)
2098 (define_insn "vsx_eq<mode>"
2099 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2100 (eq:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
2101 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
2102 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2103 "xvcmpeq<sd>p %x0,%x1,%x2"
2104 [(set_attr "type" "<VStype_simple>")])
2106 (define_insn "vsx_gt<mode>"
2107 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2108 (gt:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
2109 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
2110 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2111 "xvcmpgt<sd>p %x0,%x1,%x2"
2112 [(set_attr "type" "<VStype_simple>")])
2114 (define_insn "*vsx_ge<mode>"
2115 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2116 (ge:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")
2117 (match_operand:VSX_F
2 "vsx_register_operand" "wa")))]
2118 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2119 "xvcmpge<sd>p %x0,%x1,%x2"
2120 [(set_attr "type" "<VStype_simple>")])
2122 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
2123 ;; indicate a combined status
2124 (define_insn "*vsx_eq_<mode>_p"
2125 [(set (reg:CC CR6_REGNO)
2127 [(eq:CC (match_operand:VSX_F
1 "vsx_register_operand" "wa")
2128 (match_operand:VSX_F
2 "vsx_register_operand" "wa"))]
2130 (set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2131 (eq:VSX_F (match_dup
1)
2133 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2134 "xvcmpeq<sd>p. %x0,%x1,%x2"
2135 [(set_attr "type" "<VStype_simple>")])
2137 (define_insn "*vsx_gt_<mode>_p"
2138 [(set (reg:CC CR6_REGNO)
2140 [(gt:CC (match_operand:VSX_F
1 "vsx_register_operand" "wa")
2141 (match_operand:VSX_F
2 "vsx_register_operand" "wa"))]
2143 (set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2144 (gt:VSX_F (match_dup
1)
2146 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2147 "xvcmpgt<sd>p. %x0,%x1,%x2"
2148 [(set_attr "type" "<VStype_simple>")])
2151 ;; Set the CR field BF to indicate if the lowest bit (bit
7) of every byte
2152 ;; element in VSR[XB] is equal to
1 (ALL_TRUE) or equal to
0 (ALL_FALSE).
2153 (define_insn "*xvtlsbb_internal"
2154 [(set (match_operand:CC
0 "cc_reg_operand" "=y")
2155 (unspec:CC [(match_operand:V16QI
1 "vsx_register_operand" "wa")]
2159 [(set_attr "type" "logical")])
2161 ;; Vector Test Least Significant Bit by Byte
2162 ;; for the implementation of the builtin
2163 ;; __builtin_vec_test_lsbb_all_ones
2164 ;; int vec_test_lsbb_all_ones (vector unsigned char);
2166 ;; __builtin_vec_test_lsbb_all_zeros
2167 ;; int vec_test_lsbb_all_zeros (vector unsigned char);
2168 (define_expand "xvtlsbbo"
2170 (unspec:CC [(match_operand:V16QI
1 "vsx_register_operand" "v")]
2172 (set (match_operand:SI
0 "gpc_reg_operand" "=r")
2173 (lt:SI (match_dup
2) (const_int
0)))]
2176 operands[
2] = gen_reg_rtx (CCmode);
2178 (define_expand "xvtlsbbz"
2180 (unspec:CC [(match_operand:V16QI
1 "vsx_register_operand" "v")]
2182 (set (match_operand:SI
0 "gpc_reg_operand" "=r")
2183 (eq:SI (match_dup
2) (const_int
0)))]
2186 operands[
2] = gen_reg_rtx (CCmode);
2189 (define_insn "*vsx_ge_<mode>_p"
2190 [(set (reg:CC CR6_REGNO)
2192 [(ge:CC (match_operand:VSX_F
1 "vsx_register_operand" "wa")
2193 (match_operand:VSX_F
2 "vsx_register_operand" "wa"))]
2195 (set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2196 (ge:VSX_F (match_dup
1)
2198 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2199 "xvcmpge<sd>p. %x0,%x1,%x2"
2200 [(set_attr "type" "<VStype_simple>")])
2203 (define_insn "vsx_copysign<mode>
3"
2204 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2206 [(match_operand:VSX_F
1 "vsx_register_operand" "wa")
2207 (match_operand:VSX_F
2 "vsx_register_operand" "wa")]
2209 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2210 "xvcpsgn<sd>p %x0,%x2,%x1"
2211 [(set_attr "type" "<VStype_simple>")])
2213 ;; For the conversions, limit the register class for the integer value to be
2214 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
2215 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
2216 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
2217 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md
2218 ;; in allowing virtual registers.
2219 (define_insn "vsx_float<VSi><mode>
2"
2220 [(set (match_operand:VSX_F
0 "gpc_reg_operand" "=wa")
2221 (float:VSX_F (match_operand:<VSI>
1 "gpc_reg_operand" "wa")))]
2222 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2223 "xvcvsx<VSc><sd>p %x0,%x1"
2224 [(set_attr "type" "<VStype_simple>")])
2226 (define_insn "vsx_floatuns<VSi><mode>
2"
2227 [(set (match_operand:VSX_F
0 "gpc_reg_operand" "=wa")
2228 (unsigned_float:VSX_F (match_operand:<VSI>
1 "gpc_reg_operand" "wa")))]
2229 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2230 "xvcvux<VSc><sd>p %x0,%x1"
2231 [(set_attr "type" "<VStype_simple>")])
2233 (define_insn "vsx_fix_trunc<mode><VSi>
2"
2234 [(set (match_operand:<VSI>
0 "gpc_reg_operand" "=wa")
2235 (fix:<VSI> (match_operand:VSX_F
1 "gpc_reg_operand" "wa")))]
2236 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2237 "x<VSv>cv<sd>psx<VSc>s %x0,%x1"
2238 [(set_attr "type" "<VStype_simple>")])
2240 (define_insn "vsx_fixuns_trunc<mode><VSi>
2"
2241 [(set (match_operand:<VSI>
0 "gpc_reg_operand" "=wa")
2242 (unsigned_fix:<VSI> (match_operand:VSX_F
1 "gpc_reg_operand" "wa")))]
2243 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2244 "x<VSv>cv<sd>pux<VSc>s %x0,%x1"
2245 [(set_attr "type" "<VStype_simple>")])
2247 ;; Math rounding functions
2248 (define_insn "vsx_x<VSv>r<sd>pi"
2249 [(set (match_operand:VSX_B
0 "vsx_register_operand" "=wa")
2250 (unspec:VSX_B [(match_operand:VSX_B
1 "vsx_register_operand" "wa")]
2251 UNSPEC_VSX_ROUND_I))]
2252 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2253 "x<VSv>r<sd>pi %x0,%x1"
2254 [(set_attr "type" "<VStype_simple>")])
2256 (define_insn "vsx_x<VSv>r<sd>pic"
2257 [(set (match_operand:VSX_B
0 "vsx_register_operand" "=wa")
2258 (unspec:VSX_B [(match_operand:VSX_B
1 "vsx_register_operand" "wa")]
2259 UNSPEC_VSX_ROUND_IC))]
2260 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2261 "x<VSv>r<sd>pic %x0,%x1"
2262 [(set_attr "type" "<VStype_simple>")])
2264 (define_insn "vsx_btrunc<mode>
2"
2265 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2266 (fix:VSX_F (match_operand:VSX_F
1 "vsx_register_operand" "wa")))]
2267 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2268 "xvr<sd>piz %x0,%x1"
2269 [(set_attr "type" "<VStype_simple>")])
2271 (define_insn "*vsx_b2trunc<mode>
2"
2272 [(set (match_operand:VSX_B
0 "vsx_register_operand" "=wa")
2273 (unspec:VSX_B [(match_operand:VSX_B
1 "vsx_register_operand" "wa")]
2275 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2276 "x<VSv>r<sd>piz %x0,%x1"
2277 [(set_attr "type" "<VStype_simple>")])
2279 (define_insn "vsx_floor<mode>
2"
2280 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2281 (unspec:VSX_F [(match_operand:VSX_F
1 "vsx_register_operand" "wa")]
2283 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2284 "xvr<sd>pim %x0,%x1"
2285 [(set_attr "type" "<VStype_simple>")])
2287 (define_insn "vsx_ceil<mode>
2"
2288 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
2289 (unspec:VSX_F [(match_operand:VSX_F
1 "vsx_register_operand" "wa")]
2291 "VECTOR_UNIT_VSX_P (<MODE>mode)"
2292 "xvr<sd>pip %x0,%x1"
2293 [(set_attr "type" "<VStype_simple>")])
2296 ;; VSX convert to/from double vector
2298 ;; Convert between single and double precision
2299 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
2300 ;; scalar single precision instructions internally use the double format.
2301 ;; Prefer the altivec registers, since we likely will need to do a vperm
2302 (define_insn "vsx_xscvdpsp"
2303 [(set (match_operand:V4SF
0 "vsx_register_operand" "=f,?wa")
2304 (unspec:V4SF [(match_operand:DF
1 "vsx_register_operand" "f,wa")]
2305 UNSPEC_VSX_CVSPDP))]
2306 "VECTOR_UNIT_VSX_P (DFmode)"
2308 [(set_attr "type" "fp")])
2310 (define_insn "vsx_xvcvspdp_be"
2311 [(set (match_operand:V2DF
0 "vsx_register_operand" "=v,?wa")
2313 (vec_select:V2SF (match_operand:V4SF
1 "vsx_register_operand" "wa,wa")
2314 (parallel [(const_int
0) (const_int
2)]))))]
2315 "VECTOR_UNIT_VSX_P (V4SFmode) && BYTES_BIG_ENDIAN"
2317 [(set_attr "type" "vecdouble")])
2319 (define_insn "vsx_xvcvspdp_le"
2320 [(set (match_operand:V2DF
0 "vsx_register_operand" "=v,?wa")
2322 (vec_select:V2SF (match_operand:V4SF
1 "vsx_register_operand" "wa,wa")
2323 (parallel [(const_int
1) (const_int
3)]))))]
2324 "VECTOR_UNIT_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
2326 [(set_attr "type" "vecdouble")])
2328 (define_expand "vsx_xvcvspdp"
2329 [(match_operand:V2DF
0 "vsx_register_operand")
2330 (match_operand:V4SF
1 "vsx_register_operand")]
2331 "VECTOR_UNIT_VSX_P (V4SFmode)"
2333 if (BYTES_BIG_ENDIAN)
2334 emit_insn (gen_vsx_xvcvspdp_be (operands[
0], operands[
1]));
2336 emit_insn (gen_vsx_xvcvspdp_le (operands[
0], operands[
1]));
2340 (define_insn "vsx_xvcvdpsp"
2341 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa,?wa")
2342 (unspec:V4SF [(match_operand:V2DF
1 "vsx_register_operand" "v,wa")]
2343 UNSPEC_VSX_CVSPDP))]
2344 "VECTOR_UNIT_VSX_P (V2DFmode)"
2346 [(set_attr "type" "vecdouble")])
2348 ;; xscvspdp, represent the scalar SF type as V4SF
2349 (define_insn "vsx_xscvspdp"
2350 [(set (match_operand:DF
0 "vsx_register_operand" "=wa")
2351 (unspec:DF [(match_operand:V4SF
1 "vsx_register_operand" "wa")]
2352 UNSPEC_VSX_CVSPDP))]
2353 "VECTOR_UNIT_VSX_P (V4SFmode)"
2355 [(set_attr "type" "fp")])
2357 ;; Same as vsx_xscvspdp, but use SF as the type
2358 (define_insn "vsx_xscvspdp_scalar2"
2359 [(set (match_operand:SF
0 "vsx_register_operand" "=wa")
2360 (unspec:SF [(match_operand:V4SF
1 "vsx_register_operand" "wa")]
2361 UNSPEC_VSX_CVSPDP))]
2362 "VECTOR_UNIT_VSX_P (V4SFmode)"
2364 [(set_attr "type" "fp")])
2366 ;; Generate xvcvhpsp instruction
2367 (define_insn "vsx_xvcvhpsp"
2368 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2369 (unspec:V4SF [(match_operand: V16QI
1 "vsx_register_operand" "wa")]
2370 UNSPEC_VSX_CVHPSP))]
2373 [(set_attr "type" "vecfloat")])
2375 ;; Generate xvcvsphp
2376 (define_insn "vsx_xvcvsphp"
2377 [(set (match_operand:V4SI
0 "register_operand" "=wa")
2378 (unspec:V4SI [(match_operand:V4SF
1 "vsx_register_operand" "wa")]
2379 UNSPEC_VSX_XVCVSPHP))]
2382 [(set_attr "type" "vecfloat")])
2384 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
2385 ;; format of scalars is actually DF.
2386 (define_insn "vsx_xscvdpsp_scalar"
2387 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2388 (unspec:V4SF [(match_operand:SF
1 "vsx_register_operand" "wa")]
2389 UNSPEC_VSX_CVSPDP))]
2390 "VECTOR_UNIT_VSX_P (V4SFmode)"
2392 [(set_attr "type" "fp")])
2394 ;; ISA
2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
2395 (define_insn "vsx_xscvdpspn"
2396 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2397 (unspec:V4SF [(match_operand:DF
1 "vsx_register_operand" "wa")]
2398 UNSPEC_VSX_CVDPSPN))]
2401 [(set_attr "type" "fp")])
2403 (define_insn "vsx_xscvspdpn"
2404 [(set (match_operand:DF
0 "vsx_register_operand" "=wa")
2405 (unspec:DF [(match_operand:V4SF
1 "vsx_register_operand" "wa")]
2406 UNSPEC_VSX_CVSPDPN))]
2409 [(set_attr "type" "fp")])
2411 (define_insn "vsx_xscvdpspn_scalar"
2412 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2413 (unspec:V4SF [(match_operand:SF
1 "vsx_register_operand" "wa")]
2414 UNSPEC_VSX_CVDPSPN))]
2417 [(set_attr "type" "fp")])
2419 ;; Used by direct move to move a SFmode value from GPR to VSX register
2420 (define_insn "vsx_xscvspdpn_directmove"
2421 [(set (match_operand:SF
0 "vsx_register_operand" "=wa")
2422 (unspec:SF [(match_operand:SF
1 "vsx_register_operand" "wa")]
2423 UNSPEC_VSX_CVSPDPN))]
2426 [(set_attr "type" "fp")])
2428 ;; Convert and scale (used by vec_ctf, vec_cts, vec_ctu for double/long long)
2430 (define_insn "vsx_xvcv<su>xwsp"
2431 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2432 (any_float:V4SF (match_operand:V4SI
1 "vsx_register_operand" "wa")))]
2433 "VECTOR_UNIT_VSX_P (V4SFmode)"
2434 "xvcv<su>xwsp %x0,%x1"
2435 [(set_attr "type" "vecfloat")])
2437 (define_insn "vsx_xvcv<su>xddp"
2438 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa")
2439 (any_float:V2DF (match_operand:V2DI
1 "vsx_register_operand" "wa")))]
2440 "VECTOR_UNIT_VSX_P (V2DFmode)"
2441 "xvcv<su>xddp %x0,%x1"
2442 [(set_attr "type" "vecdouble")])
2444 (define_insn "vsx_xvcvsp<su>xws"
2445 [(set (match_operand:V4SI
0 "vsx_register_operand" "=wa")
2446 (any_fix:V4SI (match_operand:V4SF
1 "vsx_register_operand" "wa")))]
2447 "VECTOR_UNIT_VSX_P (V4SFmode)"
2448 "xvcvsp<su>xws %x0,%x1"
2449 [(set_attr "type" "vecfloat")])
2451 (define_insn "vsx_xvcvdp<su>xds"
2452 [(set (match_operand:V2DI
0 "vsx_register_operand" "=wa")
2453 (any_fix:V2DI (match_operand:V2DF
1 "vsx_register_operand" "wa")))]
2454 "VECTOR_UNIT_VSX_P (V2DFmode)"
2455 "xvcvdp<su>xds %x0,%x1"
2456 [(set_attr "type" "vecdouble")])
2458 (define_expand "vsx_xvcvsxddp_scale"
2459 [(match_operand:V2DF
0 "vsx_register_operand")
2460 (match_operand:V2DI
1 "vsx_register_operand")
2461 (match_operand:QI
2 "immediate_operand")]
2462 "VECTOR_UNIT_VSX_P (V2DFmode)"
2464 rtx op0 = operands[
0];
2465 rtx op1 = operands[
1];
2466 int scale = INTVAL(operands[
2]);
2467 emit_insn (gen_vsx_xvcvsxddp (op0, op1));
2469 rs6000_scale_v2df (op0, op0, -scale);
2473 (define_expand "vsx_xvcvuxddp_scale"
2474 [(match_operand:V2DF
0 "vsx_register_operand")
2475 (match_operand:V2DI
1 "vsx_register_operand")
2476 (match_operand:QI
2 "immediate_operand")]
2477 "VECTOR_UNIT_VSX_P (V2DFmode)"
2479 rtx op0 = operands[
0];
2480 rtx op1 = operands[
1];
2481 int scale = INTVAL(operands[
2]);
2482 emit_insn (gen_vsx_xvcvuxddp (op0, op1));
2484 rs6000_scale_v2df (op0, op0, -scale);
2488 (define_expand "vsx_xvcvdpsxds_scale"
2489 [(match_operand:V2DI
0 "vsx_register_operand")
2490 (match_operand:V2DF
1 "vsx_register_operand")
2491 (match_operand:QI
2 "immediate_operand")]
2492 "VECTOR_UNIT_VSX_P (V2DFmode)"
2494 rtx op0 = operands[
0];
2495 rtx op1 = operands[
1];
2497 int scale = INTVAL (operands[
2]);
2502 tmp = gen_reg_rtx (V2DFmode);
2503 rs6000_scale_v2df (tmp, op1, scale);
2505 emit_insn (gen_vsx_xvcvdpsxds (op0, tmp));
2509 ;; convert vector of
64-bit floating point numbers to vector of
2510 ;;
64-bit unsigned integer
2511 (define_expand "vsx_xvcvdpuxds_scale"
2512 [(match_operand:V2DI
0 "vsx_register_operand")
2513 (match_operand:V2DF
1 "vsx_register_operand")
2514 (match_operand:QI
2 "immediate_operand")]
2515 "VECTOR_UNIT_VSX_P (V2DFmode)"
2517 rtx op0 = operands[
0];
2518 rtx op1 = operands[
1];
2520 int scale = INTVAL (operands[
2]);
2525 tmp = gen_reg_rtx (V2DFmode);
2526 rs6000_scale_v2df (tmp, op1, scale);
2528 emit_insn (gen_vsx_xvcvdpuxds (op0, tmp));
2532 ;; Convert from
64-bit to
32-bit types
2533 ;; Note, favor the Altivec registers since the usual use of these instructions
2534 ;; is in vector converts and we need to use the Altivec vperm instruction.
2536 (define_insn "vsx_xvcvdpsxws"
2537 [(set (match_operand:V4SI
0 "vsx_register_operand" "=v,?wa")
2538 (unspec:V4SI [(match_operand:V2DF
1 "vsx_register_operand" "wa,wa")]
2539 UNSPEC_VSX_CVDPSXWS))]
2540 "VECTOR_UNIT_VSX_P (V2DFmode)"
2541 "xvcvdpsxws %x0,%x1"
2542 [(set_attr "type" "vecdouble")])
2544 (define_insn "vsx_xvcvdpuxws"
2545 [(set (match_operand:V4SI
0 "vsx_register_operand" "=v,?wa")
2546 (unspec:V4SI [(match_operand:V2DF
1 "vsx_register_operand" "wa,wa")]
2547 UNSPEC_VSX_CVDPUXWS))]
2548 "VECTOR_UNIT_VSX_P (V2DFmode)"
2549 "xvcvdpuxws %x0,%x1"
2550 [(set_attr "type" "vecdouble")])
2552 (define_insn "vsx_xvcvsxdsp"
2553 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2554 (unspec:V4SF [(match_operand:V2DI
1 "vsx_register_operand" "wa")]
2555 UNSPEC_VSX_CVSXDSP))]
2556 "VECTOR_UNIT_VSX_P (V2DFmode)"
2558 [(set_attr "type" "vecfloat")])
2560 (define_insn "vsx_xvcvuxdsp"
2561 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa")
2562 (unspec:V4SF [(match_operand:V2DI
1 "vsx_register_operand" "wa")]
2563 UNSPEC_VSX_CVUXDSP))]
2564 "VECTOR_UNIT_VSX_P (V2DFmode)"
2566 [(set_attr "type" "vecdouble")])
2568 ;; Convert vector of
32-bit signed/unsigned integers to vector of
2569 ;;
64-bit floating point numbers.
2570 (define_insn "vsx_xvcv<su>xwdp_be"
2571 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa")
2573 (vec_select:V2SI (match_operand:V4SI
1 "vsx_register_operand" "wa")
2574 (parallel [(const_int
0) (const_int
2)]))))]
2575 "VECTOR_UNIT_VSX_P (V2DFmode) && BYTES_BIG_ENDIAN"
2576 "xvcv<su>xwdp %x0,%x1"
2577 [(set_attr "type" "vecdouble")])
2579 (define_insn "vsx_xvcv<su>xwdp_le"
2580 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa")
2582 (vec_select:V2SI (match_operand:V4SI
1 "vsx_register_operand" "wa")
2583 (parallel [(const_int
1) (const_int
3)]))))]
2584 "VECTOR_UNIT_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
2585 "xvcv<su>xwdp %x0,%x1"
2586 [(set_attr "type" "vecdouble")])
2588 (define_expand "vsx_xvcv<su>xwdp"
2589 [(match_operand:V2DF
0 "vsx_register_operand")
2590 (match_operand:V4SI
1 "vsx_register_operand")
2592 "VECTOR_UNIT_VSX_P (V2DFmode)"
2594 if (BYTES_BIG_ENDIAN)
2595 emit_insn (gen_vsx_xvcv<su>xwdp_be (operands[
0], operands[
1]));
2597 emit_insn (gen_vsx_xvcv<su>xwdp_le (operands[
0], operands[
1]));
2601 (define_insn "vsx_xvcvsxwdp_df"
2602 [(set (match_operand:DF
0 "vsx_register_operand" "=wa")
2603 (unspec:DF [(match_operand:V4SI
1 "vsx_register_operand" "wa")]
2604 UNSPEC_VSX_CVSXWDP))]
2607 [(set_attr "type" "vecdouble")])
2609 (define_insn "vsx_xvcvuxwdp_df"
2610 [(set (match_operand:DF
0 "vsx_register_operand" "=wa")
2611 (unspec:DF [(match_operand:V4SI
1 "vsx_register_operand" "wa")]
2612 UNSPEC_VSX_CVUXWDP))]
2615 [(set_attr "type" "vecdouble")])
2617 ;; Convert vector of
32-bit floating point numbers to vector of
2618 ;;
64-bit signed/unsigned integers.
2619 (define_insn "vsx_xvcvsp<su>xds_be"
2620 [(set (match_operand:V2DI
0 "vsx_register_operand" "=v,?wa")
2622 (vec_select:V2SF (match_operand:V4SF
1 "vsx_register_operand" "wa,wa")
2623 (parallel [(const_int
0) (const_int
2)]))))]
2624 "VECTOR_UNIT_VSX_P (V2DFmode) && BYTES_BIG_ENDIAN"
2625 "xvcvsp<su>xds %x0,%x1"
2626 [(set_attr "type" "vecdouble")])
2628 (define_insn "vsx_xvcvsp<su>xds_le"
2629 [(set (match_operand:V2DI
0 "vsx_register_operand" "=v,?wa")
2631 (vec_select:V2SF (match_operand:V4SF
1 "vsx_register_operand" "wa,wa")
2632 (parallel [(const_int
1) (const_int
3)]))))]
2633 "VECTOR_UNIT_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
2634 "xvcvsp<su>xds %x0,%x1"
2635 [(set_attr "type" "vecdouble")])
2637 (define_expand "vsx_xvcvsp<su>xds"
2638 [(match_operand:V2DI
0 "vsx_register_operand")
2639 (match_operand:V4SF
1 "vsx_register_operand")
2641 "VECTOR_UNIT_VSX_P (V2DFmode)"
2643 if (BYTES_BIG_ENDIAN)
2644 emit_insn (gen_vsx_xvcvsp<su>xds_be (operands[
0], operands[
1]));
2646 emit_insn (gen_vsx_xvcvsp<su>xds_le (operands[
0], operands[
1]));
2650 ;; Generate float2 double
2651 ;; convert two double to float
2652 (define_expand "float2_v2df"
2653 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2654 (use (match_operand:V2DF
1 "register_operand" "wa"))
2655 (use (match_operand:V2DF
2 "register_operand" "wa"))]
2656 "VECTOR_UNIT_VSX_P (V4SFmode)"
2658 rtx rtx_src1, rtx_src2, rtx_dst;
2660 rtx_dst = operands[
0];
2661 rtx_src1 = operands[
1];
2662 rtx_src2 = operands[
2];
2664 rs6000_generate_float2_double_code (rtx_dst, rtx_src1, rtx_src2);
2669 ;; convert two long long signed ints to float
2670 (define_expand "float2_v2di"
2671 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2672 (use (match_operand:V2DI
1 "register_operand" "wa"))
2673 (use (match_operand:V2DI
2 "register_operand" "wa"))]
2674 "VECTOR_UNIT_VSX_P (V4SFmode)"
2676 rtx rtx_src1, rtx_src2, rtx_dst;
2678 rtx_dst = operands[
0];
2679 rtx_src1 = operands[
1];
2680 rtx_src2 = operands[
2];
2682 rs6000_generate_float2_code (true, rtx_dst, rtx_src1, rtx_src2);
2686 ;; Generate uns_float2
2687 ;; convert two long long unsigned ints to float
2688 (define_expand "uns_float2_v2di"
2689 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2690 (use (match_operand:V2DI
1 "register_operand" "wa"))
2691 (use (match_operand:V2DI
2 "register_operand" "wa"))]
2692 "VECTOR_UNIT_VSX_P (V4SFmode)"
2694 rtx rtx_src1, rtx_src2, rtx_dst;
2696 rtx_dst = operands[
0];
2697 rtx_src1 = operands[
1];
2698 rtx_src2 = operands[
2];
2700 rs6000_generate_float2_code (true, rtx_dst, rtx_src1, rtx_src2);
2705 ;; convert double or long long signed to float
2706 ;; (Only even words are valid, BE numbering)
2707 (define_expand "floate<mode>"
2708 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2709 (use (match_operand:VSX_D
1 "register_operand" "wa"))]
2710 "VECTOR_UNIT_VSX_P (V4SFmode)"
2712 if (BYTES_BIG_ENDIAN)
2714 /* Shift left one word to put even word correct location */
2716 rtx rtx_val = GEN_INT (
4);
2718 rtx_tmp = gen_reg_rtx (V4SFmode);
2719 emit_insn (gen_vsx_xvcv<VF_sxddp>sp (rtx_tmp, operands[
1]));
2720 emit_insn (gen_altivec_vsldoi_v4sf (operands[
0],
2721 rtx_tmp, rtx_tmp, rtx_val));
2724 emit_insn (gen_vsx_xvcv<VF_sxddp>sp (operands[
0], operands[
1]));
2729 ;; Generate uns_floate
2730 ;; convert long long unsigned to float
2731 ;; (Only even words are valid, BE numbering)
2732 (define_expand "unsfloatev2di"
2733 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2734 (use (match_operand:V2DI
1 "register_operand" "wa"))]
2735 "VECTOR_UNIT_VSX_P (V4SFmode)"
2737 if (BYTES_BIG_ENDIAN)
2739 /* Shift left one word to put even word correct location */
2741 rtx rtx_val = GEN_INT (
4);
2743 rtx_tmp = gen_reg_rtx (V4SFmode);
2744 emit_insn (gen_vsx_xvcvuxdsp (rtx_tmp, operands[
1]));
2745 emit_insn (gen_altivec_vsldoi_v4sf (operands[
0],
2746 rtx_tmp, rtx_tmp, rtx_val));
2749 emit_insn (gen_vsx_xvcvuxdsp (operands[
0], operands[
1]));
2755 ;; convert double or long long signed to float
2756 ;; Only odd words are valid, BE numbering)
2757 (define_expand "floato<mode>"
2758 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2759 (use (match_operand:VSX_D
1 "register_operand" "wa"))]
2760 "VECTOR_UNIT_VSX_P (V4SFmode)"
2762 if (BYTES_BIG_ENDIAN)
2763 emit_insn (gen_vsx_xvcv<VF_sxddp>sp (operands[
0], operands[
1]));
2766 /* Shift left one word to put odd word correct location */
2768 rtx rtx_val = GEN_INT (
4);
2770 rtx_tmp = gen_reg_rtx (V4SFmode);
2771 emit_insn (gen_vsx_xvcv<VF_sxddp>sp (rtx_tmp, operands[
1]));
2772 emit_insn (gen_altivec_vsldoi_v4sf (operands[
0],
2773 rtx_tmp, rtx_tmp, rtx_val));
2778 ;; Generate uns_floato
2779 ;; convert long long unsigned to float
2780 ;; (Only odd words are valid, BE numbering)
2781 (define_expand "unsfloatov2di"
2782 [(use (match_operand:V4SF
0 "register_operand" "=wa"))
2783 (use (match_operand:V2DI
1 "register_operand" "wa"))]
2784 "VECTOR_UNIT_VSX_P (V4SFmode)"
2786 if (BYTES_BIG_ENDIAN)
2787 emit_insn (gen_vsx_xvcvuxdsp (operands[
0], operands[
1]));
2790 /* Shift left one word to put odd word correct location */
2792 rtx rtx_val = GEN_INT (
4);
2794 rtx_tmp = gen_reg_rtx (V4SFmode);
2795 emit_insn (gen_vsx_xvcvuxdsp (rtx_tmp, operands[
1]));
2796 emit_insn (gen_altivec_vsldoi_v4sf (operands[
0],
2797 rtx_tmp, rtx_tmp, rtx_val));
2802 ;; Generate vsigned2
2803 ;; convert two double float vectors to a vector of single precision ints
2804 (define_expand "vsigned2_v2df"
2805 [(match_operand:V4SI
0 "register_operand" "=wa")
2806 (unspec:V4SI [(match_operand:V2DF
1 "register_operand" "wa")
2807 (match_operand:V2DF
2 "register_operand" "wa")]
2808 UNSPEC_VSX_VSIGNED2)]
2811 rtx rtx_src1, rtx_src2, rtx_dst;
2812 bool signed_convert=true;
2814 rtx_dst = operands[
0];
2815 rtx_src1 = operands[
1];
2816 rtx_src2 = operands[
2];
2818 rs6000_generate_vsigned2_code (signed_convert, rtx_dst, rtx_src1, rtx_src2);
2822 ;; Generate vsignedo_v2df
2823 ;; signed double float to int convert odd word
2824 (define_expand "vsignedo_v2df"
2825 [(set (match_operand:V4SI
0 "register_operand" "=wa")
2826 (match_operand:V2DF
1 "register_operand" "wa"))]
2829 if (BYTES_BIG_ENDIAN)
2832 rtx rtx_val = GEN_INT (
12);
2833 rtx_tmp = gen_reg_rtx (V4SImode);
2835 emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp, operands[
1]));
2837 /* Big endian word numbering for words in operand is
0 1 2 3.
2838 take (operand[
1] operand[
1]) and shift left one word
2839 0 1 2 3 0 1 2 3 =>
1 2 3 0
2840 Words
1 and
3 are now are now where they need to be for result. */
2842 emit_insn (gen_altivec_vsldoi_v4si (operands[
0], rtx_tmp,
2846 /* Little endian word numbering for operand is
3 2 1 0.
2847 Result words
3 and
1 are where they need to be. */
2848 emit_insn (gen_vsx_xvcvdpsxws (operands[
0], operands[
1]));
2852 [(set_attr "type" "veccomplex")])
2854 ;; Generate vsignede_v2df
2855 ;; signed double float to int even word
2856 (define_expand "vsignede_v2df"
2857 [(set (match_operand:V4SI
0 "register_operand" "=v")
2858 (match_operand:V2DF
1 "register_operand" "v"))]
2861 if (BYTES_BIG_ENDIAN)
2862 /* Big endian word numbering for words in operand is
0 1
2863 Result words
0 is where they need to be. */
2864 emit_insn (gen_vsx_xvcvdpsxws (operands[
0], operands[
1]));
2869 rtx rtx_val = GEN_INT (
12);
2870 rtx_tmp = gen_reg_rtx (V4SImode);
2872 emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp, operands[
1]));
2874 /* Little endian word numbering for operand is
3 2 1 0.
2875 take (operand[
1] operand[
1]) and shift left three words
2876 0 1 2 3 0 1 2 3 =>
3 0 1 2
2877 Words
0 and
2 are now where they need to be for the result. */
2878 emit_insn (gen_altivec_vsldoi_v4si (operands[
0], rtx_tmp,
2883 [(set_attr "type" "veccomplex")])
2885 ;; Generate unsigned2
2886 ;; convert two double float vectors to a vector of single precision
2888 (define_expand "vunsigned2_v2df"
2889 [(match_operand:V4SI
0 "register_operand" "=v")
2890 (unspec:V4SI [(match_operand:V2DF
1 "register_operand" "v")
2891 (match_operand:V2DF
2 "register_operand" "v")]
2892 UNSPEC_VSX_VSIGNED2)]
2895 rtx rtx_src1, rtx_src2, rtx_dst;
2896 bool signed_convert=false;
2898 rtx_dst = operands[
0];
2899 rtx_src1 = operands[
1];
2900 rtx_src2 = operands[
2];
2902 rs6000_generate_vsigned2_code (signed_convert, rtx_dst, rtx_src1, rtx_src2);
2906 ;; Generate vunsignedo_v2df
2907 ;; unsigned double float to int convert odd word
2908 (define_expand "vunsignedo_v2df"
2909 [(set (match_operand:V4SI
0 "register_operand" "=v")
2910 (match_operand:V2DF
1 "register_operand" "v"))]
2913 if (BYTES_BIG_ENDIAN)
2916 rtx rtx_val = GEN_INT (
12);
2917 rtx_tmp = gen_reg_rtx (V4SImode);
2919 emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp, operands[
1]));
2921 /* Big endian word numbering for words in operand is
0 1 2 3.
2922 take (operand[
1] operand[
1]) and shift left one word
2923 0 1 2 3 0 1 2 3 =>
1 2 3 0
2924 Words
1 and
3 are now are now where they need to be for result. */
2926 emit_insn (gen_altivec_vsldoi_v4si (operands[
0], rtx_tmp,
2930 /* Little endian word numbering for operand is
3 2 1 0.
2931 Result words
3 and
1 are where they need to be. */
2932 emit_insn (gen_vsx_xvcvdpuxws (operands[
0], operands[
1]));
2936 [(set_attr "type" "veccomplex")])
2938 ;; Generate vunsignede_v2df
2939 ;; unsigned double float to int even word
2940 (define_expand "vunsignede_v2df"
2941 [(set (match_operand:V4SI
0 "register_operand" "=v")
2942 (match_operand:V2DF
1 "register_operand" "v"))]
2945 if (BYTES_BIG_ENDIAN)
2946 /* Big endian word numbering for words in operand is
0 1
2947 Result words
0 is where they need to be. */
2948 emit_insn (gen_vsx_xvcvdpuxws (operands[
0], operands[
1]));
2953 rtx rtx_val = GEN_INT (
12);
2954 rtx_tmp = gen_reg_rtx (V4SImode);
2956 emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp, operands[
1]));
2958 /* Little endian word numbering for operand is
3 2 1 0.
2959 take (operand[
1] operand[
1]) and shift left three words
2960 0 1 2 3 0 1 2 3 =>
3 0 1 2
2961 Words
0 and
2 are now where they need to be for the result. */
2962 emit_insn (gen_altivec_vsldoi_v4si (operands[
0], rtx_tmp,
2967 [(set_attr "type" "veccomplex")])
2969 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
2970 ;; since the xvrdpiz instruction does not truncate the value if the floating
2971 ;; point value is < LONG_MIN or > LONG_MAX.
2972 (define_insn "*vsx_float_fix_v2df2"
2973 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa,?wa")
2976 (match_operand:V2DF
1 "vsx_register_operand" "wa,?wa"))))]
2978 && VECTOR_UNIT_VSX_P (V2DFmode) && flag_unsafe_math_optimizations
2979 && !flag_trapping_math && TARGET_FRIZ"
2981 [(set_attr "type" "vecdouble")])
2984 ;; Permute operations
2986 ;; Build a V2DF/V2DI vector from two scalars
2987 (define_insn "vsx_concat_<mode>"
2988 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa,we")
2990 (match_operand:<VEC_base>
1 "gpc_reg_operand" "wa,b")
2991 (match_operand:<VEC_base>
2 "gpc_reg_operand" "wa,b")))]
2992 "VECTOR_MEM_VSX_P (<MODE>mode)"
2994 if (which_alternative ==
0)
2995 return (BYTES_BIG_ENDIAN
2996 ? "xxpermdi %x0,%x1,%x2,
0"
2997 : "xxpermdi %x0,%x2,%x1,
0");
2999 else if (which_alternative ==
1)
3000 return (BYTES_BIG_ENDIAN
3001 ? "mtvsrdd %x0,%
1,%
2"
3002 : "mtvsrdd %x0,%
2,%
1");
3007 [(set_attr "type" "vecperm,vecmove")])
3009 ;; Combiner patterns to allow creating XXPERMDI's to access either double
3010 ;; word element in a vector register.
3011 (define_insn "*vsx_concat_<mode>_1"
3012 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3014 (vec_select:<VEC_base>
3015 (match_operand:VSX_D
1 "gpc_reg_operand" "wa")
3016 (parallel [(match_operand:QI
2 "const_0_to_1_operand" "n")]))
3017 (match_operand:<VEC_base>
3 "gpc_reg_operand" "wa")))]
3018 "VECTOR_MEM_VSX_P (<MODE>mode)"
3020 HOST_WIDE_INT dword = INTVAL (operands[
2]);
3021 if (BYTES_BIG_ENDIAN)
3023 operands[
4] = GEN_INT (
2*dword);
3024 return "xxpermdi %x0,%x1,%x3,%
4";
3028 operands[
4] = GEN_INT (!dword);
3029 return "xxpermdi %x0,%x3,%x1,%
4";
3032 [(set_attr "type" "vecperm")])
3034 (define_insn "*vsx_concat_<mode>_2"
3035 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3037 (match_operand:<VEC_base>
1 "gpc_reg_operand" "wa")
3038 (vec_select:<VEC_base>
3039 (match_operand:VSX_D
2 "gpc_reg_operand" "wa")
3040 (parallel [(match_operand:QI
3 "const_0_to_1_operand" "n")]))))]
3041 "VECTOR_MEM_VSX_P (<MODE>mode)"
3043 HOST_WIDE_INT dword = INTVAL (operands[
3]);
3044 if (BYTES_BIG_ENDIAN)
3046 operands[
4] = GEN_INT (dword);
3047 return "xxpermdi %x0,%x1,%x2,%
4";
3051 operands[
4] = GEN_INT (
2 * !dword);
3052 return "xxpermdi %x0,%x2,%x1,%
4";
3055 [(set_attr "type" "vecperm")])
3057 (define_insn "*vsx_concat_<mode>_3"
3058 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3060 (vec_select:<VEC_base>
3061 (match_operand:VSX_D
1 "gpc_reg_operand" "wa")
3062 (parallel [(match_operand:QI
2 "const_0_to_1_operand" "n")]))
3063 (vec_select:<VEC_base>
3064 (match_operand:VSX_D
3 "gpc_reg_operand" "wa")
3065 (parallel [(match_operand:QI
4 "const_0_to_1_operand" "n")]))))]
3066 "VECTOR_MEM_VSX_P (<MODE>mode)"
3068 HOST_WIDE_INT dword1 = INTVAL (operands[
2]);
3069 HOST_WIDE_INT dword2 = INTVAL (operands[
4]);
3070 if (BYTES_BIG_ENDIAN)
3072 operands[
5] = GEN_INT ((
2 * dword1) + dword2);
3073 return "xxpermdi %x0,%x1,%x3,%
5";
3077 operands[
5] = GEN_INT ((
2 * !dword2) + !dword1);
3078 return "xxpermdi %x0,%x3,%x1,%
5";
3081 [(set_attr "type" "vecperm")])
3083 ;; Special purpose concat using xxpermdi to glue two single precision values
3084 ;; together, relying on the fact that internally scalar floats are represented
3085 ;; as doubles. This is used to initialize a V4SF vector with
4 floats
3086 (define_insn "vsx_concat_v2sf"
3087 [(set (match_operand:V2DF
0 "vsx_register_operand" "=wa")
3089 [(match_operand:SF
1 "vsx_register_operand" "wa")
3090 (match_operand:SF
2 "vsx_register_operand" "wa")]
3091 UNSPEC_VSX_CONCAT))]
3092 "VECTOR_MEM_VSX_P (V2DFmode)"
3094 if (BYTES_BIG_ENDIAN)
3095 return "xxpermdi %x0,%x1,%x2,
0";
3097 return "xxpermdi %x0,%x2,%x1,
0";
3099 [(set_attr "type" "vecperm")])
3101 ;; Concatenate
4 SImode elements into a V4SImode reg.
3102 (define_expand "vsx_init_v4si"
3103 [(use (match_operand:V4SI
0 "gpc_reg_operand"))
3104 (use (match_operand:SI
1 "gpc_reg_operand"))
3105 (use (match_operand:SI
2 "gpc_reg_operand"))
3106 (use (match_operand:SI
3 "gpc_reg_operand"))
3107 (use (match_operand:SI
4 "gpc_reg_operand"))]
3108 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
3110 rtx a = gen_lowpart_SUBREG (DImode, operands[
1]);
3111 rtx b = gen_lowpart_SUBREG (DImode, operands[
2]);
3112 rtx c = gen_lowpart_SUBREG (DImode, operands[
3]);
3113 rtx d = gen_lowpart_SUBREG (DImode, operands[
4]);
3114 if (!BYTES_BIG_ENDIAN)
3120 rtx ab = gen_reg_rtx (DImode);
3121 rtx cd = gen_reg_rtx (DImode);
3122 emit_insn (gen_rotldi3_insert_3 (ab, a, GEN_INT (
32), b,
3123 GEN_INT (
0xffffffff)));
3124 emit_insn (gen_rotldi3_insert_3 (cd, c, GEN_INT (
32), d,
3125 GEN_INT (
0xffffffff)));
3127 rtx abcd = gen_reg_rtx (V2DImode);
3128 emit_insn (gen_vsx_concat_v2di (abcd, ab, cd));
3129 emit_move_insn (operands[
0], gen_lowpart (V4SImode, abcd));
3133 ;; xxpermdi for little endian loads and stores. We need several of
3134 ;; these since the form of the PARALLEL differs by mode.
3135 (define_insn "*vsx_xxpermdi2_le_<mode>"
3136 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3138 (match_operand:VSX_D
1 "vsx_register_operand" "wa")
3139 (parallel [(const_int
1) (const_int
0)])))]
3140 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
3141 "xxpermdi %x0,%x1,%x1,
2"
3142 [(set_attr "type" "vecperm")])
3144 (define_insn "xxswapd_v16qi"
3145 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
3147 (match_operand:V16QI
1 "vsx_register_operand" "wa")
3148 (parallel [(const_int
8) (const_int
9)
3149 (const_int
10) (const_int
11)
3150 (const_int
12) (const_int
13)
3151 (const_int
14) (const_int
15)
3152 (const_int
0) (const_int
1)
3153 (const_int
2) (const_int
3)
3154 (const_int
4) (const_int
5)
3155 (const_int
6) (const_int
7)])))]
3157 ;; AIX does not support the extended mnemonic xxswapd. Use the basic
3158 ;; mnemonic xxpermdi instead.
3159 "xxpermdi %x0,%x1,%x1,
2"
3160 [(set_attr "type" "vecperm")])
3162 (define_insn "xxswapd_v8hi"
3163 [(set (match_operand:V8HI
0 "vsx_register_operand" "=wa")
3165 (match_operand:V8HI
1 "vsx_register_operand" "wa")
3166 (parallel [(const_int
4) (const_int
5)
3167 (const_int
6) (const_int
7)
3168 (const_int
0) (const_int
1)
3169 (const_int
2) (const_int
3)])))]
3171 ;; AIX does not support the extended mnemonic xxswapd. Use the basic
3172 ;; mnemonic xxpermdi instead.
3173 "xxpermdi %x0,%x1,%x1,
2"
3174 [(set_attr "type" "vecperm")])
3176 (define_insn "xxswapd_<mode>"
3177 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
3179 (match_operand:VSX_W
1 "vsx_register_operand" "wa")
3180 (parallel [(const_int
2) (const_int
3)
3181 (const_int
0) (const_int
1)])))]
3183 ;; AIX does not support extended mnemonic xxswapd. Use the basic
3184 ;; mnemonic xxpermdi instead.
3185 "xxpermdi %x0,%x1,%x1,
2"
3186 [(set_attr "type" "vecperm")])
3188 (define_insn "xxswapd_<mode>"
3189 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3191 (match_operand:VSX_D
1 "vsx_register_operand" "wa")
3192 (parallel [(const_int
1) (const_int
0)])))]
3194 ;; AIX does not support extended mnemonic xxswapd. Use the basic
3195 ;; mnemonic xxpermdi instead.
3196 "xxpermdi %x0,%x1,%x1,
2"
3197 [(set_attr "type" "vecperm")])
3199 ;; Swap upper/lower
64-bit values in a
128-bit vector
3200 (define_insn "xxswapd_v1ti"
3201 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
3205 (match_operand:V1TI
1 "vsx_register_operand" "v")
0 )
3206 (parallel [(const_int
1)(const_int
0)]))
3209 ;; AIX does not support extended mnemonic xxswapd. Use the basic
3210 ;; mnemonic xxpermdi instead.
3211 "xxpermdi %x0,%x1,%x1,
2"
3212 [(set_attr "type" "vecperm")])
3214 (define_insn "xxgenpcvm_<mode>_internal"
3215 [(set (match_operand:VSX_EXTRACT_I4
0 "altivec_register_operand" "=wa")
3216 (unspec:VSX_EXTRACT_I4
3217 [(match_operand:VSX_EXTRACT_I4
1 "altivec_register_operand" "v")
3218 (match_operand:QI
2 "const_0_to_3_operand" "n")]
3221 "xxgenpcv<wd>m %x0,%
1,%
2"
3222 [(set_attr "type" "vecsimple")])
3224 (define_expand "xxgenpcvm_<mode>"
3225 [(use (match_operand:VSX_EXTRACT_I4
0 "register_operand"))
3226 (use (match_operand:VSX_EXTRACT_I4
1 "register_operand"))
3227 (use (match_operand:QI
2 "immediate_operand"))]
3230 if (!BYTES_BIG_ENDIAN)
3232 /* gen_xxgenpcvm assumes Big Endian order. If LE,
3233 change swap upper and lower double words. */
3234 rtx tmp = gen_reg_rtx (<MODE>mode);
3236 emit_insn (gen_xxswapd_<mode> (tmp, operands[
1]));
3239 emit_insn (gen_xxgenpcvm_<mode>_internal (operands[
0], operands[
1],
3244 ;; lxvd2x for little endian loads. We need several of
3245 ;; these since the form of the PARALLEL differs by mode.
3246 (define_insn "*vsx_lxvd2x2_le_<mode>"
3247 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3249 (match_operand:VSX_D
1 "memory_operand" "Z")
3250 (parallel [(const_int
1) (const_int
0)])))]
3251 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
3253 [(set_attr "type" "vecload")])
3255 (define_insn "*vsx_lxvd2x4_le_<mode>"
3256 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
3258 (match_operand:VSX_W
1 "memory_operand" "Z")
3259 (parallel [(const_int
2) (const_int
3)
3260 (const_int
0) (const_int
1)])))]
3261 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
3263 [(set_attr "type" "vecload")])
3265 (define_insn "*vsx_lxvd2x8_le_V8HI"
3266 [(set (match_operand:V8HI
0 "vsx_register_operand" "=wa")
3268 (match_operand:V8HI
1 "memory_operand" "Z")
3269 (parallel [(const_int
4) (const_int
5)
3270 (const_int
6) (const_int
7)
3271 (const_int
0) (const_int
1)
3272 (const_int
2) (const_int
3)])))]
3273 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
3275 [(set_attr "type" "vecload")])
3277 (define_insn "*vsx_lxvd2x16_le_V16QI"
3278 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
3280 (match_operand:V16QI
1 "memory_operand" "Z")
3281 (parallel [(const_int
8) (const_int
9)
3282 (const_int
10) (const_int
11)
3283 (const_int
12) (const_int
13)
3284 (const_int
14) (const_int
15)
3285 (const_int
0) (const_int
1)
3286 (const_int
2) (const_int
3)
3287 (const_int
4) (const_int
5)
3288 (const_int
6) (const_int
7)])))]
3289 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
3291 [(set_attr "type" "vecload")])
3293 ;; stxvd2x for little endian stores. We need several of
3294 ;; these since the form of the PARALLEL differs by mode.
3295 (define_insn "*vsx_stxvd2x2_le_<mode>"
3296 [(set (match_operand:VSX_D
0 "memory_operand" "=Z")
3298 (match_operand:VSX_D
1 "vsx_register_operand" "wa")
3299 (parallel [(const_int
1) (const_int
0)])))]
3300 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
3302 [(set_attr "type" "vecstore")])
3304 (define_insn "*vsx_stxvd2x4_le_<mode>"
3305 [(set (match_operand:VSX_W
0 "memory_operand" "=Z")
3307 (match_operand:VSX_W
1 "vsx_register_operand" "wa")
3308 (parallel [(const_int
2) (const_int
3)
3309 (const_int
0) (const_int
1)])))]
3310 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
3312 [(set_attr "type" "vecstore")])
3314 (define_insn "*vsx_stxvd2x8_le_V8HI"
3315 [(set (match_operand:V8HI
0 "memory_operand" "=Z")
3317 (match_operand:V8HI
1 "vsx_register_operand" "wa")
3318 (parallel [(const_int
4) (const_int
5)
3319 (const_int
6) (const_int
7)
3320 (const_int
0) (const_int
1)
3321 (const_int
2) (const_int
3)])))]
3322 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
3324 [(set_attr "type" "vecstore")])
3326 (define_insn "*vsx_stxvd2x16_le_V16QI"
3327 [(set (match_operand:V16QI
0 "memory_operand" "=Z")
3329 (match_operand:V16QI
1 "vsx_register_operand" "wa")
3330 (parallel [(const_int
8) (const_int
9)
3331 (const_int
10) (const_int
11)
3332 (const_int
12) (const_int
13)
3333 (const_int
14) (const_int
15)
3334 (const_int
0) (const_int
1)
3335 (const_int
2) (const_int
3)
3336 (const_int
4) (const_int
5)
3337 (const_int
6) (const_int
7)])))]
3338 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
3340 [(set_attr "type" "vecstore")])
3342 ;; Convert a TImode value into V1TImode
3343 (define_expand "vsx_set_v1ti"
3344 [(match_operand:V1TI
0 "nonimmediate_operand")
3345 (match_operand:V1TI
1 "nonimmediate_operand")
3346 (match_operand:TI
2 "input_operand")
3347 (match_operand:QI
3 "u5bit_cint_operand")]
3348 "VECTOR_MEM_VSX_P (V1TImode)"
3350 if (operands[
3] != const0_rtx)
3353 emit_move_insn (operands[
0], gen_lowpart (V1TImode, operands[
1]));
3357 ;; Rewrite V2DF/V2DI set in terms of VEC_CONCAT
3358 (define_expand "vsx_set_<mode>"
3359 [(use (match_operand:VSX_D
0 "vsx_register_operand"))
3360 (use (match_operand:VSX_D
1 "vsx_register_operand"))
3361 (use (match_operand:<VEC_base>
2 "gpc_reg_operand"))
3362 (use (match_operand:QI
3 "const_0_to_1_operand"))]
3363 "VECTOR_MEM_VSX_P (<MODE>mode)"
3365 rtx dest = operands[
0];
3366 rtx vec_reg = operands[
1];
3367 rtx value = operands[
2];
3368 rtx ele = operands[
3];
3369 rtx tmp = gen_reg_rtx (<VEC_base>mode);
3371 if (ele == const0_rtx)
3373 emit_insn (gen_vsx_extract_<mode> (tmp, vec_reg, const1_rtx));
3374 emit_insn (gen_vsx_concat_<mode> (dest, value, tmp));
3377 else if (ele == const1_rtx)
3379 emit_insn (gen_vsx_extract_<mode> (tmp, vec_reg, const0_rtx));
3380 emit_insn (gen_vsx_concat_<mode> (dest, tmp, value));
3387 ;; Extract a DF/DI element from V2DF/V2DI
3388 ;; Optimize cases were we can do a simple or direct move.
3389 ;; Or see if we can avoid doing the move at all
3391 (define_expand "vsx_extract_<mode>"
3392 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand")
3393 (vec_select:<VEC_base>
3394 (match_operand:VSX_D
1 "gpc_reg_operand")
3396 [(match_operand:QI
2 "const_0_to_1_operand")])))]
3397 "VECTOR_MEM_VSX_P (<MODE>mode)"
3400 (define_insn "*vsx_extract_<mode>_0"
3401 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=wa,wa,wr")
3402 (vec_select:<VEC_base>
3403 (match_operand:VSX_D
1 "gpc_reg_operand" "
0,wa,wa")
3405 [(match_operand:QI
2 "const_0_to_1_operand" "n,n,n")])))]
3406 "VECTOR_MEM_VSX_P (<MODE>mode)
3407 && INTVAL (operands[
2]) == (BYTES_BIG_ENDIAN ?
0 :
1)"
3409 if (which_alternative ==
0)
3410 return ASM_COMMENT_START " vec_extract to same register";
3412 if (which_alternative ==
2)
3413 return "mfvsrd %
0,%x1";
3415 return "xxlor %x0,%x1,%x1";
3417 [(set_attr "type" "*,veclogical,mfvsr")
3418 (set_attr "isa" "*,*,p8v")
3419 (set_attr "length" "
0,*,*")])
3421 (define_insn "*vsx_extract_<mode>_1"
3422 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=wa,wr")
3423 (vec_select:<VEC_base>
3424 (match_operand:VSX_D
1 "gpc_reg_operand" "wa,wa")
3426 [(match_operand:QI
2 "const_0_to_1_operand" "n,n")])))]
3427 "VECTOR_MEM_VSX_P (<MODE>mode)
3428 && INTVAL (operands[
2]) == (BYTES_BIG_ENDIAN ?
1 :
0)"
3430 if (which_alternative ==
1)
3431 return "mfvsrld %
0,%x1";
3433 operands[
3] = GEN_INT (BYTES_BIG_ENDIAN ?
2 :
3);
3434 return "xxpermdi %x0,%x1,%x1,%
3";
3436 [(set_attr "type" "mfvsr,vecperm")
3437 (set_attr "isa" "*,p9v")])
3439 ;; Optimize extracting a single scalar element from memory.
3440 (define_insn_and_split "*vsx_extract_<P:mode>_<VSX_D:mode>_load"
3441 [(set (match_operand:<VEC_base>
0 "register_operand" "=wa,wr")
3442 (vec_select:<VSX_D:VEC_base>
3443 (match_operand:VSX_D
1 "memory_operand" "m,m")
3444 (parallel [(match_operand:QI
2 "const_0_to_1_operand" "n,n")])))
3445 (clobber (match_scratch:P
3 "=&b,&b"))]
3446 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<VSX_D:MODE>mode)"
3448 "&& reload_completed"
3449 [(set (match_dup
0) (match_dup
4))]
3451 operands[
4] = rs6000_adjust_vec_address (operands[
0], operands[
1], operands[
2],
3452 operands[
3], <VSX_D:VEC_base>mode);
3454 [(set_attr "type" "fpload,load")
3455 (set_attr "length" "
8")])
3457 ;; Optimize storing a single scalar element that is the right location to
3459 (define_insn "*vsx_extract_<mode>_store"
3460 [(set (match_operand:<VEC_base>
0 "memory_operand" "=m,Z,wY")
3461 (vec_select:<VEC_base>
3462 (match_operand:VSX_D
1 "register_operand" "d,v,v")
3463 (parallel [(match_operand:QI
2 "vsx_scalar_64bit" "n,n,n")])))]
3464 "VECTOR_MEM_VSX_P (<MODE>mode)
3465 && INTVAL (operands[
2]) == (BYTES_BIG_ENDIAN ?
0 :
1)"
3470 [(set_attr "type" "fpstore")
3471 (set_attr "isa" "*,p7v,p9v")])
3473 ;; Variable V2DI/V2DF extract shift
3474 (define_insn "vsx_vslo_<mode>"
3475 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=v")
3476 (unspec:<VEC_base> [(match_operand:VSX_D
1 "gpc_reg_operand" "v")
3477 (match_operand:V2DI
2 "gpc_reg_operand" "v")]
3479 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3481 [(set_attr "type" "vecperm")])
3483 ;; Variable V2DI/V2DF extract from a register
3484 (define_insn_and_split "vsx_extract_<mode>_var"
3485 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=v")
3486 (unspec:<VEC_base> [(match_operand:VSX_D
1 "gpc_reg_operand" "v")
3487 (match_operand:DI
2 "gpc_reg_operand" "r")]
3488 UNSPEC_VSX_EXTRACT))
3489 (clobber (match_scratch:DI
3 "=r"))
3490 (clobber (match_scratch:V2DI
4 "=&v"))]
3491 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3493 "&& reload_completed"
3496 rs6000_split_vec_extract_var (operands[
0], operands[
1], operands[
2],
3497 operands[
3], operands[
4]);
3501 ;; Variable V2DI/V2DF extract from memory
3502 (define_insn_and_split "*vsx_extract_<mode>_var_load"
3503 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=wa,r")
3504 (unspec:<VEC_base> [(match_operand:VSX_D
1 "memory_operand" "Q,Q")
3505 (match_operand:DI
2 "gpc_reg_operand" "r,r")]
3506 UNSPEC_VSX_EXTRACT))
3507 (clobber (match_scratch:DI
3 "=&b,&b"))]
3508 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3510 "&& reload_completed"
3511 [(set (match_dup
0) (match_dup
4))]
3513 operands[
4] = rs6000_adjust_vec_address (operands[
0], operands[
1], operands[
2],
3514 operands[
3], <VEC_base>mode);
3516 [(set_attr "type" "fpload,load")])
3518 ;; Extract a SF element from V4SF
3519 (define_insn_and_split "vsx_extract_v4sf"
3520 [(set (match_operand:SF
0 "vsx_register_operand" "=wa")
3522 (match_operand:V4SF
1 "vsx_register_operand" "wa")
3523 (parallel [(match_operand:QI
2 "u5bit_cint_operand" "n")])))
3524 (clobber (match_scratch:V4SF
3 "=
0"))]
3525 "VECTOR_UNIT_VSX_P (V4SFmode)"
3530 rtx op0 = operands[
0];
3531 rtx op1 = operands[
1];
3532 rtx op2 = operands[
2];
3533 rtx op3 = operands[
3];
3535 HOST_WIDE_INT ele = BYTES_BIG_ENDIAN ? INTVAL (op2) :
3 - INTVAL (op2);
3541 if (GET_CODE (op3) == SCRATCH)
3542 op3 = gen_reg_rtx (V4SFmode);
3543 emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, GEN_INT (ele)));
3546 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
3549 [(set_attr "length" "
8")
3550 (set_attr "type" "fp")])
3552 (define_insn_and_split "*vsx_extract_v4sf_load"
3553 [(set (match_operand:SF
0 "register_operand" "=f,v,v,?r")
3555 (match_operand:V4SF
1 "memory_operand" "m,Z,m,m")
3556 (parallel [(match_operand:QI
2 "const_0_to_3_operand" "n,n,n,n")])))
3557 (clobber (match_scratch:P
3 "=&b,&b,&b,&b"))]
3558 "VECTOR_MEM_VSX_P (V4SFmode)"
3560 "&& reload_completed"
3561 [(set (match_dup
0) (match_dup
4))]
3563 operands[
4] = rs6000_adjust_vec_address (operands[
0], operands[
1], operands[
2],
3564 operands[
3], SFmode);
3566 [(set_attr "type" "fpload,fpload,fpload,load")
3567 (set_attr "length" "
8")
3568 (set_attr "isa" "*,p7v,p9v,*")])
3570 ;; Variable V4SF extract from a register
3571 (define_insn_and_split "vsx_extract_v4sf_var"
3572 [(set (match_operand:SF
0 "gpc_reg_operand" "=wa")
3573 (unspec:SF [(match_operand:V4SF
1 "gpc_reg_operand" "v")
3574 (match_operand:DI
2 "gpc_reg_operand" "r")]
3575 UNSPEC_VSX_EXTRACT))
3576 (clobber (match_scratch:DI
3 "=r"))
3577 (clobber (match_scratch:V2DI
4 "=&v"))]
3578 "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT"
3580 "&& reload_completed"
3583 rs6000_split_vec_extract_var (operands[
0], operands[
1], operands[
2],
3584 operands[
3], operands[
4]);
3588 ;; Variable V4SF extract from memory
3589 (define_insn_and_split "*vsx_extract_v4sf_var_load"
3590 [(set (match_operand:SF
0 "gpc_reg_operand" "=wa,?r")
3591 (unspec:SF [(match_operand:V4SF
1 "memory_operand" "Q,Q")
3592 (match_operand:DI
2 "gpc_reg_operand" "r,r")]
3593 UNSPEC_VSX_EXTRACT))
3594 (clobber (match_scratch:DI
3 "=&b,&b"))]
3595 "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT"
3597 "&& reload_completed"
3598 [(set (match_dup
0) (match_dup
4))]
3600 operands[
4] = rs6000_adjust_vec_address (operands[
0], operands[
1], operands[
2],
3601 operands[
3], SFmode);
3603 [(set_attr "type" "fpload,load")])
3605 ;; Expand the builtin form of xxpermdi to canonical rtl.
3606 (define_expand "vsx_xxpermdi_<mode>"
3607 [(match_operand:VSX_L
0 "vsx_register_operand")
3608 (match_operand:VSX_L
1 "vsx_register_operand")
3609 (match_operand:VSX_L
2 "vsx_register_operand")
3610 (match_operand:QI
3 "u5bit_cint_operand")]
3611 "VECTOR_MEM_VSX_P (<MODE>mode)"
3613 rtx target = operands[
0];
3614 rtx op0 = operands[
1];
3615 rtx op1 = operands[
2];
3616 int mask = INTVAL (operands[
3]);
3617 rtx perm0 = GEN_INT ((mask >>
1) &
1);
3618 rtx perm1 = GEN_INT ((mask &
1) +
2);
3619 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
3621 if (<MODE>mode == V2DFmode)
3622 gen = gen_vsx_xxpermdi2_v2df_1;
3625 gen = gen_vsx_xxpermdi2_v2di_1;
3626 if (<MODE>mode != V2DImode)
3628 target = gen_lowpart (V2DImode, target);
3629 op0 = gen_lowpart (V2DImode, op0);
3630 op1 = gen_lowpart (V2DImode, op1);
3633 emit_insn (gen (target, op0, op1, perm0, perm1));
3637 ;; Special version of xxpermdi that retains big-endian semantics.
3638 (define_expand "vsx_xxpermdi_<mode>_be"
3639 [(match_operand:VSX_L
0 "vsx_register_operand")
3640 (match_operand:VSX_L
1 "vsx_register_operand")
3641 (match_operand:VSX_L
2 "vsx_register_operand")
3642 (match_operand:QI
3 "u5bit_cint_operand")]
3643 "VECTOR_MEM_VSX_P (<MODE>mode)"
3645 rtx target = operands[
0];
3646 rtx op0 = operands[
1];
3647 rtx op1 = operands[
2];
3648 int mask = INTVAL (operands[
3]);
3649 rtx perm0 = GEN_INT ((mask >>
1) &
1);
3650 rtx perm1 = GEN_INT ((mask &
1) +
2);
3651 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
3653 if (<MODE>mode == V2DFmode)
3654 gen = gen_vsx_xxpermdi2_v2df_1;
3657 gen = gen_vsx_xxpermdi2_v2di_1;
3658 if (<MODE>mode != V2DImode)
3660 target = gen_lowpart (V2DImode, target);
3661 op0 = gen_lowpart (V2DImode, op0);
3662 op1 = gen_lowpart (V2DImode, op1);
3665 /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
3666 transformation we don't want; it is necessary for
3667 rs6000_expand_vec_perm_const_1 but not for this use. So we
3668 prepare for that by reversing the transformation here. */
3669 if (BYTES_BIG_ENDIAN)
3670 emit_insn (gen (target, op0, op1, perm0, perm1));
3673 rtx p0 = GEN_INT (
3 - INTVAL (perm1));
3674 rtx p1 = GEN_INT (
3 - INTVAL (perm0));
3675 emit_insn (gen (target, op1, op0, p0, p1));
3680 (define_insn "vsx_xxpermdi2_<mode>_1"
3681 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
3683 (vec_concat:<VS_double>
3684 (match_operand:VSX_D
1 "vsx_register_operand" "wa")
3685 (match_operand:VSX_D
2 "vsx_register_operand" "wa"))
3686 (parallel [(match_operand
3 "const_0_to_1_operand" "")
3687 (match_operand
4 "const_2_to_3_operand" "")])))]
3688 "VECTOR_MEM_VSX_P (<MODE>mode)"
3692 /* For little endian, swap operands and invert/swap selectors
3693 to get the correct xxpermdi. The operand swap sets up the
3694 inputs as a little endian array. The selectors are swapped
3695 because they are defined to use big endian ordering. The
3696 selectors are inverted to get the correct doublewords for
3697 little endian ordering. */
3698 if (BYTES_BIG_ENDIAN)
3700 op3 = INTVAL (operands[
3]);
3701 op4 = INTVAL (operands[
4]);
3705 op3 =
3 - INTVAL (operands[
4]);
3706 op4 =
3 - INTVAL (operands[
3]);
3709 mask = (op3 <<
1) | (op4 -
2);
3710 operands[
3] = GEN_INT (mask);
3712 if (BYTES_BIG_ENDIAN)
3713 return "xxpermdi %x0,%x1,%x2,%
3";
3715 return "xxpermdi %x0,%x2,%x1,%
3";
3717 [(set_attr "type" "vecperm")])
3719 ;; Extraction of a single element in a small integer vector. Until ISA
3.0,
3720 ;; none of the small types were allowed in a vector register, so we had to
3721 ;; extract to a DImode and either do a direct move or store.
3722 (define_expand "vsx_extract_<mode>"
3723 [(parallel [(set (match_operand:<VEC_base>
0 "gpc_reg_operand")
3724 (vec_select:<VEC_base>
3725 (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand")
3726 (parallel [(match_operand:QI
2 "const_int_operand")])))
3727 (clobber (match_scratch:VSX_EXTRACT_I
3))])]
3728 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3730 /* If we have ISA
3.0, we can do a xxextractuw/vextractu{b,h}. */
3731 if (TARGET_P9_VECTOR)
3733 emit_insn (gen_vsx_extract_<mode>_p9 (operands[
0], operands[
1],
3739 (define_insn "vsx_extract_<mode>_p9"
3740 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=r,<VSX_EX>")
3741 (vec_select:<VEC_base>
3742 (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "v,<VSX_EX>")
3743 (parallel [(match_operand:QI
2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
3744 (clobber (match_scratch:SI
3 "=r,X"))]
3745 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
3747 if (which_alternative ==
0)
3752 HOST_WIDE_INT elt = INTVAL (operands[
2]);
3753 HOST_WIDE_INT elt_adj = (!BYTES_BIG_ENDIAN
3754 ? GET_MODE_NUNITS (<MODE>mode) -
1 - elt
3757 HOST_WIDE_INT unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
3758 HOST_WIDE_INT offset = unit_size * elt_adj;
3760 operands[
2] = GEN_INT (offset);
3762 return "xxextractuw %x0,%x1,%
2";
3764 return "vextractu<wd> %
0,%
1,%
2";
3767 [(set_attr "type" "vecsimple")
3768 (set_attr "isa" "p9v,*")])
3771 [(set (match_operand:<VEC_base>
0 "int_reg_operand")
3772 (vec_select:<VEC_base>
3773 (match_operand:VSX_EXTRACT_I
1 "altivec_register_operand")
3774 (parallel [(match_operand:QI
2 "const_int_operand")])))
3775 (clobber (match_operand:SI
3 "int_reg_operand"))]
3776 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB && reload_completed"
3779 rtx op0_si = gen_rtx_REG (SImode, REGNO (operands[
0]));
3780 rtx op1 = operands[
1];
3781 rtx op2 = operands[
2];
3782 rtx op3 = operands[
3];
3783 HOST_WIDE_INT offset = INTVAL (op2) * GET_MODE_UNIT_SIZE (<MODE>mode);
3785 emit_move_insn (op3, GEN_INT (offset));
3786 if (BYTES_BIG_ENDIAN)
3787 emit_insn (gen_vextu<wd>lx (op0_si, op3, op1));
3789 emit_insn (gen_vextu<wd>rx (op0_si, op3, op1));
3793 ;; Optimize zero extracts to eliminate the AND after the extract.
3794 (define_insn_and_split "*vsx_extract_<mode>_di_p9"
3795 [(set (match_operand:DI
0 "gpc_reg_operand" "=r,<VSX_EX>")
3797 (vec_select:<VEC_base>
3798 (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "v,<VSX_EX>")
3799 (parallel [(match_operand:QI
2 "const_int_operand" "n,n")]))))
3800 (clobber (match_scratch:SI
3 "=r,X"))]
3801 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
3803 "&& reload_completed"
3804 [(parallel [(set (match_dup
4)
3805 (vec_select:<VEC_base>
3807 (parallel [(match_dup
2)])))
3808 (clobber (match_dup
3))])]
3810 operands[
4] = gen_rtx_REG (<VEC_base>mode, REGNO (operands[
0]));
3812 [(set_attr "isa" "p9v,*")])
3814 ;; Optimize stores to use the ISA
3.0 scalar store instructions
3815 (define_insn_and_split "*vsx_extract_<mode>_store_p9"
3816 [(set (match_operand:<VEC_base>
0 "memory_operand" "=Z,m")
3817 (vec_select:<VEC_base>
3818 (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "<VSX_EX>,v")
3819 (parallel [(match_operand:QI
2 "const_int_operand" "n,n")])))
3820 (clobber (match_scratch:<VEC_base>
3 "=<VSX_EX>,&*r"))
3821 (clobber (match_scratch:SI
4 "=X,&r"))]
3822 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
3824 "&& reload_completed"
3825 [(parallel [(set (match_dup
3)
3826 (vec_select:<VEC_base>
3828 (parallel [(match_dup
2)])))
3829 (clobber (match_dup
4))])
3833 (define_insn_and_split "*vsx_extract_si"
3834 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,wa,Z")
3836 (match_operand:V4SI
1 "gpc_reg_operand" "v,v,v")
3837 (parallel [(match_operand:QI
2 "const_0_to_3_operand" "n,n,n")])))
3838 (clobber (match_scratch:V4SI
3 "=v,v,v"))]
3839 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT && !TARGET_P9_VECTOR"
3841 "&& reload_completed"
3844 rtx dest = operands[
0];
3845 rtx src = operands[
1];
3846 rtx element = operands[
2];
3847 rtx vec_tmp = operands[
3];
3850 /* Adjust index for LE element ordering, the below minuend
3 is computed by
3851 GET_MODE_NUNITS (V4SImode) -
1. */
3852 if (!BYTES_BIG_ENDIAN)
3853 element = GEN_INT (
3 - INTVAL (element));
3855 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
3857 value = INTVAL (element);
3859 emit_insn (gen_altivec_vspltw_direct (vec_tmp, src, element));
3863 if (MEM_P (operands[
0]))
3865 if (can_create_pseudo_p ())
3866 dest = rs6000_force_indexed_or_indirect_mem (dest);
3868 if (TARGET_P8_VECTOR)
3869 emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
3871 emit_insn (gen_stfiwx (dest, gen_rtx_REG (DImode, REGNO (vec_tmp))));
3874 else if (TARGET_P8_VECTOR)
3875 emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
3877 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
3878 gen_rtx_REG (DImode, REGNO (vec_tmp)));
3882 [(set_attr "type" "mfvsr,vecperm,fpstore")
3883 (set_attr "length" "
8")
3884 (set_attr "isa" "*,p8v,*")])
3886 (define_insn_and_split "*vsx_extract_<mode>_p8"
3887 [(set (match_operand:<VEC_base>
0 "nonimmediate_operand" "=r")
3888 (vec_select:<VEC_base>
3889 (match_operand:VSX_EXTRACT_I2
1 "gpc_reg_operand" "v")
3890 (parallel [(match_operand:QI
2 "<VSX_EXTRACT_PREDICATE>" "n")])))
3891 (clobber (match_scratch:VSX_EXTRACT_I2
3 "=v"))]
3892 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT
3893 && !TARGET_P9_VECTOR"
3895 "&& reload_completed"
3898 rtx dest = operands[
0];
3899 rtx src = operands[
1];
3900 rtx element = operands[
2];
3901 rtx vec_tmp = operands[
3];
3904 if (!BYTES_BIG_ENDIAN)
3905 element = GEN_INT (GET_MODE_NUNITS (<MODE>mode) -
1 - INTVAL (element));
3907 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
3909 value = INTVAL (element);
3910 if (<MODE>mode == V16QImode)
3913 emit_insn (gen_altivec_vspltb_direct (vec_tmp, src, element));
3917 else if (<MODE>mode == V8HImode)
3920 emit_insn (gen_altivec_vsplth_direct (vec_tmp, src, element));
3927 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
3928 gen_rtx_REG (DImode, REGNO (vec_tmp)));
3931 [(set_attr "type" "mfvsr")])
3933 ;; Optimize extracting a single scalar element from memory.
3934 (define_insn_and_split "*vsx_extract_<mode>_load"
3935 [(set (match_operand:<VEC_base>
0 "register_operand" "=r")
3936 (vec_select:<VEC_base>
3937 (match_operand:VSX_EXTRACT_I
1 "memory_operand" "m")
3938 (parallel [(match_operand:QI
2 "<VSX_EXTRACT_PREDICATE>" "n")])))
3939 (clobber (match_scratch:DI
3 "=&b"))]
3940 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3942 "&& reload_completed"
3943 [(set (match_dup
0) (match_dup
4))]
3945 operands[
4] = rs6000_adjust_vec_address (operands[
0], operands[
1], operands[
2],
3946 operands[
3], <VEC_base>mode);
3948 [(set_attr "type" "load")
3949 (set_attr "length" "
8")])
3951 ;; Variable V16QI/V8HI/V4SI extract from a register
3952 (define_insn_and_split "vsx_extract_<mode>_var"
3953 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=r,r")
3955 [(match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "v,v")
3956 (match_operand:DI
2 "gpc_reg_operand" "r,r")]
3957 UNSPEC_VSX_EXTRACT))
3958 (clobber (match_scratch:DI
3 "=r,r"))
3959 (clobber (match_scratch:V2DI
4 "=X,&v"))]
3960 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3962 "&& reload_completed"
3965 rs6000_split_vec_extract_var (operands[
0], operands[
1], operands[
2],
3966 operands[
3], operands[
4]);
3969 [(set_attr "isa" "p9v,*")])
3971 ;; Variable V16QI/V8HI/V4SI extract from memory
3972 (define_insn_and_split "*vsx_extract_<mode>_var_load"
3973 [(set (match_operand:<VEC_base>
0 "gpc_reg_operand" "=r")
3975 [(match_operand:VSX_EXTRACT_I
1 "memory_operand" "Q")
3976 (match_operand:DI
2 "gpc_reg_operand" "r")]
3977 UNSPEC_VSX_EXTRACT))
3978 (clobber (match_scratch:DI
3 "=&b"))]
3979 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3981 "&& reload_completed"
3982 [(set (match_dup
0) (match_dup
4))]
3984 operands[
4] = rs6000_adjust_vec_address (operands[
0], operands[
1], operands[
2],
3985 operands[
3], <VEC_base>mode);
3987 [(set_attr "type" "load")])
3990 (define_expand "vextractl<mode>"
3991 [(set (match_operand:V2DI
0 "altivec_register_operand")
3992 (unspec:V2DI [(match_operand:VI2
1 "altivec_register_operand")
3993 (match_operand:VI2
2 "altivec_register_operand")
3994 (match_operand:SI
3 "register_operand")]
3998 if (BYTES_BIG_ENDIAN)
4000 emit_insn (gen_vextractl<mode>_internal (operands[
0], operands[
1],
4001 operands[
2], operands[
3]));
4002 emit_insn (gen_xxswapd_v2di (operands[
0], operands[
0]));
4005 emit_insn (gen_vextractr<mode>_internal (operands[
0], operands[
2],
4006 operands[
1], operands[
3]));
4010 (define_insn "vextractl<mode>_internal"
4011 [(set (match_operand:V2DI
0 "altivec_register_operand" "=v")
4012 (unspec:V2DI [(match_operand:VEC_I
1 "altivec_register_operand" "v")
4013 (match_operand:VEC_I
2 "altivec_register_operand" "v")
4014 (match_operand:SI
3 "register_operand" "r")]
4017 "vext<du_or_d><wd>vlx %
0,%
1,%
2,%
3"
4018 [(set_attr "type" "vecsimple")])
4020 (define_expand "vextractr<mode>"
4021 [(set (match_operand:V2DI
0 "altivec_register_operand")
4022 (unspec:V2DI [(match_operand:VI2
1 "altivec_register_operand")
4023 (match_operand:VI2
2 "altivec_register_operand")
4024 (match_operand:SI
3 "register_operand")]
4028 if (BYTES_BIG_ENDIAN)
4030 emit_insn (gen_vextractr<mode>_internal (operands[
0], operands[
1],
4031 operands[
2], operands[
3]));
4032 emit_insn (gen_xxswapd_v2di (operands[
0], operands[
0]));
4035 emit_insn (gen_vextractl<mode>_internal (operands[
0], operands[
2],
4036 operands[
1], operands[
3]));
4040 (define_insn "vextractr<mode>_internal"
4041 [(set (match_operand:V2DI
0 "altivec_register_operand" "=v")
4042 (unspec:V2DI [(match_operand:VEC_I
1 "altivec_register_operand" "v")
4043 (match_operand:VEC_I
2 "altivec_register_operand" "v")
4044 (match_operand:SI
3 "register_operand" "r")]
4047 "vext<du_or_d><wd>vrx %
0,%
1,%
2,%
3"
4048 [(set_attr "type" "vecsimple")])
4050 (define_expand "vinsertvl_<mode>"
4051 [(set (match_operand:VI2
0 "altivec_register_operand")
4052 (unspec:VI2 [(match_operand:VI2
1 "altivec_register_operand")
4053 (match_operand:VI2
2 "altivec_register_operand")
4054 (match_operand:SI
3 "register_operand" "r")]
4058 if (BYTES_BIG_ENDIAN)
4059 emit_insn (gen_vinsertvl_internal_<mode> (operands[
0], operands[
3],
4060 operands[
1], operands[
2]));
4062 emit_insn (gen_vinsertvr_internal_<mode> (operands[
0], operands[
3],
4063 operands[
1], operands[
2]));
4067 (define_insn "vinsertvl_internal_<mode>"
4068 [(set (match_operand:VEC_I
0 "altivec_register_operand" "=v")
4069 (unspec:VEC_I [(match_operand:SI
1 "register_operand" "r")
4070 (match_operand:VEC_I
2 "altivec_register_operand" "v")
4071 (match_operand:VEC_I
3 "altivec_register_operand" "
0")]
4074 "vins<wd>vlx %
0,%
1,%
2"
4075 [(set_attr "type" "vecsimple")])
4077 (define_expand "vinsertvr_<mode>"
4078 [(set (match_operand:VI2
0 "altivec_register_operand")
4079 (unspec:VI2 [(match_operand:VI2
1 "altivec_register_operand")
4080 (match_operand:VI2
2 "altivec_register_operand")
4081 (match_operand:SI
3 "register_operand" "r")]
4085 if (BYTES_BIG_ENDIAN)
4086 emit_insn (gen_vinsertvr_internal_<mode> (operands[
0], operands[
3],
4087 operands[
1], operands[
2]));
4089 emit_insn (gen_vinsertvl_internal_<mode> (operands[
0], operands[
3],
4090 operands[
1], operands[
2]));
4094 (define_insn "vinsertvr_internal_<mode>"
4095 [(set (match_operand:VEC_I
0 "altivec_register_operand" "=v")
4096 (unspec:VEC_I [(match_operand:SI
1 "register_operand" "r")
4097 (match_operand:VEC_I
2 "altivec_register_operand" "v")
4098 (match_operand:VEC_I
3 "altivec_register_operand" "
0")]
4101 "vins<wd>vrx %
0,%
1,%
2"
4102 [(set_attr "type" "vecsimple")])
4104 (define_expand "vinsertgl_<mode>"
4105 [(set (match_operand:VI2
0 "altivec_register_operand")
4106 (unspec:VI2 [(match_operand:SI
1 "register_operand")
4107 (match_operand:VI2
2 "altivec_register_operand")
4108 (match_operand:SI
3 "register_operand")]
4112 if (BYTES_BIG_ENDIAN)
4113 emit_insn (gen_vinsertgl_internal_<mode> (operands[
0], operands[
3],
4114 operands[
1], operands[
2]));
4116 emit_insn (gen_vinsertgr_internal_<mode> (operands[
0], operands[
3],
4117 operands[
1], operands[
2]));
4121 (define_insn "vinsertgl_internal_<mode>"
4122 [(set (match_operand:VEC_I
0 "altivec_register_operand" "=v")
4123 (unspec:VEC_I [(match_operand:SI
1 "register_operand" "r")
4124 (match_operand:SI
2 "register_operand" "r")
4125 (match_operand:VEC_I
3 "altivec_register_operand" "
0")]
4128 "vins<wd>lx %
0,%
1,%
2"
4129 [(set_attr "type" "vecsimple")])
4131 (define_expand "vinsertgr_<mode>"
4132 [(set (match_operand:VI2
0 "altivec_register_operand")
4133 (unspec:VI2 [(match_operand:SI
1 "register_operand")
4134 (match_operand:VI2
2 "altivec_register_operand")
4135 (match_operand:SI
3 "register_operand")]
4139 if (BYTES_BIG_ENDIAN)
4140 emit_insn (gen_vinsertgr_internal_<mode> (operands[
0], operands[
3],
4141 operands[
1], operands[
2]));
4143 emit_insn (gen_vinsertgl_internal_<mode> (operands[
0], operands[
3],
4144 operands[
1], operands[
2]));
4148 (define_insn "vinsertgr_internal_<mode>"
4149 [(set (match_operand:VEC_I
0 "altivec_register_operand" "=v")
4150 (unspec:VEC_I [(match_operand:SI
1 "register_operand" "r")
4151 (match_operand:SI
2 "register_operand" "r")
4152 (match_operand:VEC_I
3 "altivec_register_operand" "
0")]
4155 "vins<wd>rx %
0,%
1,%
2"
4156 [(set_attr "type" "vecsimple")])
4158 (define_expand "vreplace_elt_<mode>"
4159 [(set (match_operand:REPLACE_ELT
0 "register_operand")
4160 (unspec:REPLACE_ELT [(match_operand:REPLACE_ELT
1 "register_operand")
4161 (match_operand:<VEC_base>
2 "register_operand")
4162 (match_operand:QI
3 "const_0_to_3_operand")]
4163 UNSPEC_REPLACE_ELT))]
4167 /* Immediate value is the word index, convert to byte index and adjust for
4168 Endianness if needed. */
4169 if (BYTES_BIG_ENDIAN)
4170 index = INTVAL (operands[
3]) << <REPLACE_ELT_sh>;
4173 index = <REPLACE_ELT_max> - (INTVAL (operands[
3]) << <REPLACE_ELT_sh>);
4175 emit_insn (gen_vreplace_elt_<mode>_inst (operands[
0], operands[
1],
4180 [(set_attr "type" "vecsimple")])
4182 (define_insn "vreplace_elt_<mode>_inst"
4183 [(set (match_operand:REPLACE_ELT
0 "register_operand" "=v")
4184 (unspec:REPLACE_ELT [(match_operand:REPLACE_ELT
1 "register_operand" "
0")
4185 (match_operand:<VEC_base>
2 "register_operand" "r")
4186 (match_operand:QI
3 "const_0_to_12_operand" "n")]
4187 UNSPEC_REPLACE_ELT))]
4189 "vins<REPLACE_ELT_char> %
0,%
2,%
3"
4190 [(set_attr "type" "vecsimple")])
4192 (define_insn "vreplace_un_<mode>"
4193 [(set (match_operand:V16QI
0 "register_operand" "=v")
4194 (unspec:V16QI [(match_operand:REPLACE_ELT
1 "register_operand" "
0")
4195 (match_operand:<VEC_base>
2 "register_operand" "r")
4196 (match_operand:QI
3 "const_0_to_12_operand" "n")]
4197 UNSPEC_REPLACE_UN))]
4199 "vins<REPLACE_ELT_char> %
0,%
2,%
3"
4200 [(set_attr "type" "vecsimple")])
4202 ;; VSX_EXTRACT optimizations
4203 ;; Optimize double d = (double) vec_extract (vi, <n>)
4204 ;; Get the element into the top position and use XVCVSWDP/XVCVUWDP
4205 (define_insn_and_split "*vsx_extract_si_<uns>float_df"
4206 [(set (match_operand:DF
0 "gpc_reg_operand" "=wa")
4209 (match_operand:V4SI
1 "gpc_reg_operand" "v")
4210 (parallel [(match_operand:QI
2 "const_0_to_3_operand" "n")]))))
4211 (clobber (match_scratch:V4SI
3 "=v"))]
4212 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
4217 rtx dest = operands[
0];
4218 rtx src = operands[
1];
4219 rtx element = operands[
2];
4220 rtx v4si_tmp = operands[
3];
4223 /* Adjust index for LE element ordering, the below minuend
3 is computed by
4224 GET_MODE_NUNITS (V4SImode) -
1. */
4225 if (!BYTES_BIG_ENDIAN)
4226 element = GEN_INT (
3 - INTVAL (element));
4228 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
4230 value = INTVAL (element);
4233 if (GET_CODE (v4si_tmp) == SCRATCH)
4234 v4si_tmp = gen_reg_rtx (V4SImode);
4235 emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
4240 emit_insn (gen_vsx_xvcv<su>xwdp_df (dest, v4si_tmp));
4244 ;; Optimize <type> f = (<type>) vec_extract (vi, <n>)
4245 ;; where <type> is a floating point type that supported by the hardware that is
4246 ;; not double. First convert the value to double, and then to the desired
4248 (define_insn_and_split "*vsx_extract_si_<uns>float_<mode>"
4249 [(set (match_operand:VSX_EXTRACT_FL
0 "gpc_reg_operand" "=wa")
4250 (any_float:VSX_EXTRACT_FL
4252 (match_operand:V4SI
1 "gpc_reg_operand" "v")
4253 (parallel [(match_operand:QI
2 "const_0_to_3_operand" "n")]))))
4254 (clobber (match_scratch:V4SI
3 "=v"))
4255 (clobber (match_scratch:DF
4 "=wa"))]
4256 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
4261 rtx dest = operands[
0];
4262 rtx src = operands[
1];
4263 rtx element = operands[
2];
4264 rtx v4si_tmp = operands[
3];
4265 rtx df_tmp = operands[
4];
4268 /* Adjust index for LE element ordering, the below minuend
3 is computed by
4269 GET_MODE_NUNITS (V4SImode) -
1. */
4270 if (!BYTES_BIG_ENDIAN)
4271 element = GEN_INT (
3 - INTVAL (element));
4273 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
4275 value = INTVAL (element);
4278 if (GET_CODE (v4si_tmp) == SCRATCH)
4279 v4si_tmp = gen_reg_rtx (V4SImode);
4280 emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
4285 if (GET_CODE (df_tmp) == SCRATCH)
4286 df_tmp = gen_reg_rtx (DFmode);
4288 emit_insn (gen_vsx_xvcv<su>xwdp_df (df_tmp, v4si_tmp));
4290 if (<MODE>mode == SFmode)
4291 emit_insn (gen_truncdfsf2 (dest, df_tmp));
4292 else if (<MODE>mode == TFmode && FLOAT128_IBM_P (TFmode))
4293 emit_insn (gen_extenddftf2_vsx (dest, df_tmp));
4294 else if (<MODE>mode == TFmode && FLOAT128_IEEE_P (TFmode)
4295 && TARGET_FLOAT128_HW)
4296 emit_insn (gen_extenddftf2_hw (dest, df_tmp));
4297 else if (<MODE>mode == IFmode && FLOAT128_IBM_P (IFmode))
4298 emit_insn (gen_extenddfif2 (dest, df_tmp));
4299 else if (<MODE>mode == KFmode && TARGET_FLOAT128_HW)
4300 emit_insn (gen_extenddfkf2_hw (dest, df_tmp));
4307 ;; Optimize <type> f = (<ftype>) vec_extract (<vtype>, <n>)
4308 ;; Where <ftype> is SFmode, DFmode (and KFmode/TFmode if those types are IEEE
4309 ;;
128-bit hardware types) and <vtype> is vector char, vector unsigned char,
4310 ;; vector short or vector unsigned short.
4311 (define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VEC_base>_fl_<FL_CONV:mode>"
4312 [(set (match_operand:FL_CONV
0 "gpc_reg_operand" "=wa")
4314 (vec_select:<VSX_EXTRACT_I:VEC_base>
4315 (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "v")
4316 (parallel [(match_operand:QI
2 "const_int_operand" "n")]))))
4317 (clobber (match_scratch:<VSX_EXTRACT_I:VEC_base>
3 "=v"))]
4318 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
4319 && TARGET_P9_VECTOR"
4321 "&& reload_completed"
4322 [(parallel [(set (match_dup
3)
4323 (vec_select:<VSX_EXTRACT_I:VEC_base>
4325 (parallel [(match_dup
2)])))
4326 (clobber (scratch:SI))])
4328 (sign_extend:DI (match_dup
3)))
4330 (float:<FL_CONV:MODE> (match_dup
4)))]
4332 operands[
4] = gen_rtx_REG (DImode, REGNO (operands[
3]));
4334 [(set_attr "isa" "<FL_CONV:VSisa>")])
4336 (define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VEC_base>_ufl_<FL_CONV:mode>"
4337 [(set (match_operand:FL_CONV
0 "gpc_reg_operand" "=wa")
4338 (unsigned_float:FL_CONV
4339 (vec_select:<VSX_EXTRACT_I:VEC_base>
4340 (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "v")
4341 (parallel [(match_operand:QI
2 "const_int_operand" "n")]))))
4342 (clobber (match_scratch:<VSX_EXTRACT_I:VEC_base>
3 "=v"))]
4343 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
4344 && TARGET_P9_VECTOR"
4346 "&& reload_completed"
4347 [(parallel [(set (match_dup
3)
4348 (vec_select:<VSX_EXTRACT_I:VEC_base>
4350 (parallel [(match_dup
2)])))
4351 (clobber (scratch:SI))])
4353 (float:<FL_CONV:MODE> (match_dup
4)))]
4355 operands[
4] = gen_rtx_REG (DImode, REGNO (operands[
3]));
4357 [(set_attr "isa" "<FL_CONV:VSisa>")])
4359 ;; V4SI/V8HI/V16QI set operation on ISA
3.0
4360 (define_insn "vsx_set_<mode>_p9"
4361 [(set (match_operand:VSX_EXTRACT_I
0 "gpc_reg_operand" "=<VSX_EX>")
4362 (unspec:VSX_EXTRACT_I
4363 [(match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "
0")
4364 (match_operand:<VEC_base>
2 "gpc_reg_operand" "<VSX_EX>")
4365 (match_operand:QI
3 "<VSX_EXTRACT_PREDICATE>" "n")]
4367 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
4369 int ele = INTVAL (operands[
3]);
4370 int nunits = GET_MODE_NUNITS (<MODE>mode);
4372 if (!BYTES_BIG_ENDIAN)
4373 ele = nunits -
1 - ele;
4375 operands[
3] = GEN_INT (GET_MODE_SIZE (<VEC_base>mode) * ele);
4376 if (<MODE>mode == V4SImode)
4377 return "xxinsertw %x0,%x2,%
3";
4379 return "vinsert<wd> %
0,%
2,%
3";
4381 [(set_attr "type" "vecperm")])
4383 (define_insn_and_split "vsx_set_v4sf_p9"
4384 [(set (match_operand:V4SF
0 "gpc_reg_operand" "=wa")
4386 [(match_operand:V4SF
1 "gpc_reg_operand" "
0")
4387 (match_operand:SF
2 "gpc_reg_operand" "wa")
4388 (match_operand:QI
3 "const_0_to_3_operand" "n")]
4390 (clobber (match_scratch:SI
4 "=&wa"))]
4391 "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
4393 "&& reload_completed"
4395 (unspec:V4SF [(match_dup
2)]
4396 UNSPEC_VSX_CVDPSPN))
4397 (parallel [(set (match_dup
4)
4398 (vec_select:SI (match_dup
6)
4399 (parallel [(match_dup
7)])))
4400 (clobber (scratch:SI))])
4402 (unspec:V4SI [(match_dup
8)
4407 unsigned int tmp_regno = reg_or_subregno (operands[
4]);
4409 operands[
5] = gen_rtx_REG (V4SFmode, tmp_regno);
4410 operands[
6] = gen_rtx_REG (V4SImode, tmp_regno);
4411 operands[
7] = GEN_INT (BYTES_BIG_ENDIAN ?
0 :
3);
4412 operands[
8] = gen_rtx_REG (V4SImode, reg_or_subregno (operands[
0]));
4414 [(set_attr "type" "vecperm")
4415 (set_attr "length" "
12")
4416 (set_attr "isa" "p9v")])
4418 ;; Special case setting
0.0f to a V4SF element
4419 (define_insn_and_split "*vsx_set_v4sf_p9_zero"
4420 [(set (match_operand:V4SF
0 "gpc_reg_operand" "=wa")
4422 [(match_operand:V4SF
1 "gpc_reg_operand" "
0")
4423 (match_operand:SF
2 "zero_fp_constant" "j")
4424 (match_operand:QI
3 "const_0_to_3_operand" "n")]
4426 (clobber (match_scratch:SI
4 "=&wa"))]
4427 "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
4429 "&& reload_completed"
4433 (unspec:V4SI [(match_dup
5)
4438 operands[
5] = gen_rtx_REG (V4SImode, reg_or_subregno (operands[
0]));
4440 [(set_attr "type" "vecperm")
4441 (set_attr "length" "
8")
4442 (set_attr "isa" "p9v")])
4444 ;; Optimize x = vec_insert (vec_extract (v2, n), v1, m) if n is the element
4445 ;; that is in the default scalar position (
1 for big endian,
2 for little
4446 ;; endian). We just need to do an xxinsertw since the element is in the
4447 ;; correct location.
4449 (define_insn "*vsx_insert_extract_v4sf_p9"
4450 [(set (match_operand:V4SF
0 "gpc_reg_operand" "=wa")
4452 [(match_operand:V4SF
1 "gpc_reg_operand" "
0")
4453 (vec_select:SF (match_operand:V4SF
2 "gpc_reg_operand" "wa")
4455 [(match_operand:QI
3 "const_0_to_3_operand" "n")]))
4456 (match_operand:QI
4 "const_0_to_3_operand" "n")]
4458 "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64
4459 && (INTVAL (operands[
3]) == (BYTES_BIG_ENDIAN ?
1 :
2))"
4461 int ele = INTVAL (operands[
4]);
4463 /* Adjust index for LE element ordering, the below minuend
3 is computed by
4464 GET_MODE_NUNITS (V4SFmode) -
1. */
4465 if (!BYTES_BIG_ENDIAN)
4468 operands[
4] = GEN_INT (GET_MODE_SIZE (SFmode) * ele);
4469 return "xxinsertw %x0,%x2,%
4";
4471 [(set_attr "type" "vecperm")])
4473 ;; Optimize x = vec_insert (vec_extract (v2, n), v1, m) if n is not the element
4474 ;; that is in the default scalar position (
1 for big endian,
2 for little
4475 ;; endian). Convert the insert/extract to int and avoid doing the conversion.
4477 (define_insn_and_split "*vsx_insert_extract_v4sf_p9_2"
4478 [(set (match_operand:V4SF
0 "gpc_reg_operand" "=wa")
4480 [(match_operand:V4SF
1 "gpc_reg_operand" "
0")
4481 (vec_select:SF (match_operand:V4SF
2 "gpc_reg_operand" "wa")
4483 [(match_operand:QI
3 "const_0_to_3_operand" "n")]))
4484 (match_operand:QI
4 "const_0_to_3_operand" "n")]
4486 (clobber (match_scratch:SI
5 "=&wa"))]
4487 "VECTOR_MEM_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SImode)
4488 && TARGET_P9_VECTOR && TARGET_POWERPC64
4489 && (INTVAL (operands[
3]) != (BYTES_BIG_ENDIAN ?
1 :
2))"
4492 [(parallel [(set (match_dup
5)
4493 (vec_select:SI (match_dup
6)
4494 (parallel [(match_dup
3)])))
4495 (clobber (scratch:SI))])
4497 (unspec:V4SI [(match_dup
8)
4502 if (GET_CODE (operands[
5]) == SCRATCH)
4503 operands[
5] = gen_reg_rtx (SImode);
4505 operands[
6] = gen_lowpart (V4SImode, operands[
2]);
4506 operands[
7] = gen_lowpart (V4SImode, operands[
0]);
4507 operands[
8] = gen_lowpart (V4SImode, operands[
1]);
4509 [(set_attr "type" "vecperm")
4510 (set_attr "isa" "p9v")])
4512 ;; Expanders for builtins
4513 (define_expand "vsx_mergel_<mode>"
4514 [(use (match_operand:VSX_D
0 "vsx_register_operand"))
4515 (use (match_operand:VSX_D
1 "vsx_register_operand"))
4516 (use (match_operand:VSX_D
2 "vsx_register_operand"))]
4517 "VECTOR_MEM_VSX_P (<MODE>mode)"
4519 rtvec v = gen_rtvec (
2, GEN_INT (
1), GEN_INT (
3));
4520 rtx x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[
1], operands[
2]);
4521 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
4522 emit_insn (gen_rtx_SET (operands[
0], x));
4526 (define_expand "vsx_mergeh_<mode>"
4527 [(use (match_operand:VSX_D
0 "vsx_register_operand"))
4528 (use (match_operand:VSX_D
1 "vsx_register_operand"))
4529 (use (match_operand:VSX_D
2 "vsx_register_operand"))]
4530 "VECTOR_MEM_VSX_P (<MODE>mode)"
4532 rtvec v = gen_rtvec (
2, GEN_INT (
0), GEN_INT (
2));
4533 rtx x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[
1], operands[
2]);
4534 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
4535 emit_insn (gen_rtx_SET (operands[
0], x));
4540 ;; We separate the register splat insn from the memory splat insn to force the
4541 ;; register allocator to generate the indexed form of the SPLAT when it is
4542 ;; given an offsettable memory reference. Otherwise, if the register and
4543 ;; memory insns were combined into a single insn, the register allocator will
4544 ;; load the value into a register, and then do a double word permute.
4545 (define_expand "vsx_splat_<mode>"
4546 [(set (match_operand:VSX_D
0 "vsx_register_operand")
4547 (vec_duplicate:VSX_D
4548 (match_operand:<VEC_base>
1 "input_operand")))]
4549 "VECTOR_MEM_VSX_P (<MODE>mode)"
4551 rtx op1 = operands[
1];
4553 operands[
1] = rs6000_force_indexed_or_indirect_mem (op1);
4554 else if (!REG_P (op1))
4555 op1 = force_reg (<VSX_D:VEC_base>mode, op1);
4558 (define_insn "vsx_splat_<mode>_reg"
4559 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa,we")
4560 (vec_duplicate:VSX_D
4561 (match_operand:<VEC_base>
1 "gpc_reg_operand" "wa,b")))]
4562 "VECTOR_MEM_VSX_P (<MODE>mode)"
4564 xxpermdi %x0,%x1,%x1,
0
4566 [(set_attr "type" "vecperm,vecmove")])
4568 (define_insn "vsx_splat_<mode>_mem"
4569 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
4570 (vec_duplicate:VSX_D
4571 (match_operand:<VSX_D:VEC_base>
1 "memory_operand" "Z")))]
4572 "VECTOR_MEM_VSX_P (<MODE>mode)"
4574 [(set_attr "type" "vecload")])
4576 ;; Optimize SPLAT of an extract from a V2DF/V2DI vector with a constant element
4577 (define_insn "*vsx_splat_extract_<mode>"
4578 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
4579 (vec_duplicate:VSX_D
4580 (vec_select:<VEC_base>
4581 (match_operand:VSX_D
1 "vsx_register_operand" "wa")
4582 (parallel [(match_operand
2 "const_0_to_1_operand" "n")]))))]
4583 "VECTOR_MEM_VSX_P (<MODE>mode)"
4585 int which_word = INTVAL (operands[
2]);
4586 if (!BYTES_BIG_ENDIAN)
4587 which_word =
1 - which_word;
4589 operands[
3] = GEN_INT (which_word ?
3 :
0);
4590 return "xxpermdi %x0,%x1,%x1,%
3";
4592 [(set_attr "type" "vecperm")])
4594 ;; V4SI splat support
4595 (define_insn "vsx_splat_v4si"
4596 [(set (match_operand:V4SI
0 "vsx_register_operand" "=wa,wa")
4598 (match_operand:SI
1 "splat_input_operand" "r,Z")))]
4603 [(set_attr "type" "vecperm,vecload")])
4605 ;; SImode is not currently allowed in vector registers. This pattern
4606 ;; allows us to use direct move to get the value in a vector register
4607 ;; so that we can use XXSPLTW
4608 (define_insn "vsx_splat_v4si_di"
4609 [(set (match_operand:V4SI
0 "vsx_register_operand" "=wa,we")
4612 (match_operand:DI
1 "gpc_reg_operand" "wa,r"))))]
4613 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
4617 [(set_attr "type" "vecperm")
4618 (set_attr "isa" "p8v,*")])
4620 ;; V4SF splat (ISA
3.0)
4621 (define_insn_and_split "vsx_splat_v4sf"
4622 [(set (match_operand:V4SF
0 "vsx_register_operand" "=wa,wa,wa")
4624 (match_operand:SF
1 "splat_input_operand" "Z,wa,r")))]
4630 "&& reload_completed && vsx_register_operand (operands[
1], SFmode)"
4632 (unspec:V4SF [(match_dup
1)] UNSPEC_VSX_CVDPSPN))
4634 (unspec:V4SF [(match_dup
0)
4635 (const_int
0)] UNSPEC_VSX_XXSPLTW))]
4637 [(set_attr "type" "vecload,vecperm,vecperm")
4638 (set_attr "length" "*,
8,*")
4639 (set_attr "isa" "*,p8v,*")])
4641 ;; V4SF/V4SI splat from a vector element
4642 (define_insn "vsx_xxspltw_<mode>"
4643 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
4644 (vec_duplicate:VSX_W
4645 (vec_select:<VEC_base>
4646 (match_operand:VSX_W
1 "vsx_register_operand" "wa")
4648 [(match_operand:QI
2 "u5bit_cint_operand" "n")]))))]
4649 "VECTOR_MEM_VSX_P (<MODE>mode)"
4651 if (!BYTES_BIG_ENDIAN)
4652 operands[
2] = GEN_INT (
3 - INTVAL (operands[
2]));
4654 return "xxspltw %x0,%x1,%
2";
4656 [(set_attr "type" "vecperm")])
4658 (define_insn "vsx_xxspltw_<mode>_direct"
4659 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
4660 (unspec:VSX_W [(match_operand:VSX_W
1 "vsx_register_operand" "wa")
4661 (match_operand:QI
2 "u5bit_cint_operand" "i")]
4662 UNSPEC_VSX_XXSPLTW))]
4663 "VECTOR_MEM_VSX_P (<MODE>mode)"
4664 "xxspltw %x0,%x1,%
2"
4665 [(set_attr "type" "vecperm")])
4667 ;; V16QI/V8HI splat support on ISA
2.07
4668 (define_insn "vsx_vsplt<VSX_SPLAT_SUFFIX>_di"
4669 [(set (match_operand:VSX_SPLAT_I
0 "altivec_register_operand" "=v")
4670 (vec_duplicate:VSX_SPLAT_I
4671 (truncate:<VEC_base>
4672 (match_operand:DI
1 "altivec_register_operand" "v"))))]
4673 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
4674 "vsplt<VSX_SPLAT_SUFFIX> %
0,%
1,<VSX_SPLAT_COUNT>"
4675 [(set_attr "type" "vecperm")])
4677 ;; V2DF/V2DI splat for use by vec_splat builtin
4678 (define_insn "vsx_xxspltd_<mode>"
4679 [(set (match_operand:VSX_D
0 "vsx_register_operand" "=wa")
4680 (unspec:VSX_D [(match_operand:VSX_D
1 "vsx_register_operand" "wa")
4681 (match_operand:QI
2 "u5bit_cint_operand" "i")]
4682 UNSPEC_VSX_XXSPLTD))]
4683 "VECTOR_MEM_VSX_P (<MODE>mode)"
4685 if ((BYTES_BIG_ENDIAN && INTVAL (operands[
2]) ==
0)
4686 || (!BYTES_BIG_ENDIAN && INTVAL (operands[
2]) ==
1))
4687 return "xxpermdi %x0,%x1,%x1,
0";
4689 return "xxpermdi %x0,%x1,%x1,
3";
4691 [(set_attr "type" "vecperm")])
4693 ;; V4SF/V4SI interleave
4694 (define_expand "vsx_xxmrghw_<mode>"
4695 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
4697 (vec_concat:<VS_double>
4698 (match_operand:VSX_W
1 "vsx_register_operand" "wa")
4699 (match_operand:VSX_W
2 "vsx_register_operand" "wa"))
4700 (parallel [(const_int
0) (const_int
4)
4701 (const_int
1) (const_int
5)])))]
4702 "VECTOR_MEM_VSX_P (<MODE>mode)"
4704 rtx (*fun) (rtx, rtx, rtx);
4705 fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_<mode>
4706 : gen_altivec_vmrglw_direct_<mode>;
4707 if (!BYTES_BIG_ENDIAN)
4708 std::swap (operands[
1], operands[
2]);
4709 emit_insn (fun (operands[
0], operands[
1], operands[
2]));
4712 [(set_attr "type" "vecperm")])
4714 (define_expand "vsx_xxmrglw_<mode>"
4715 [(set (match_operand:VSX_W
0 "vsx_register_operand" "=wa")
4717 (vec_concat:<VS_double>
4718 (match_operand:VSX_W
1 "vsx_register_operand" "wa")
4719 (match_operand:VSX_W
2 "vsx_register_operand" "wa"))
4720 (parallel [(const_int
2) (const_int
6)
4721 (const_int
3) (const_int
7)])))]
4722 "VECTOR_MEM_VSX_P (<MODE>mode)"
4724 rtx (*fun) (rtx, rtx, rtx);
4725 fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_<mode>
4726 : gen_altivec_vmrghw_direct_<mode>;
4727 if (!BYTES_BIG_ENDIAN)
4728 std::swap (operands[
1], operands[
2]);
4729 emit_insn (fun (operands[
0], operands[
1], operands[
2]));
4732 [(set_attr "type" "vecperm")])
4734 ;; Shift left double by word immediate
4735 (define_insn "vsx_xxsldwi_<mode>"
4736 [(set (match_operand:VSX_L
0 "vsx_register_operand" "=wa")
4737 (unspec:VSX_L [(match_operand:VSX_L
1 "vsx_register_operand" "wa")
4738 (match_operand:VSX_L
2 "vsx_register_operand" "wa")
4739 (match_operand:QI
3 "u5bit_cint_operand" "i")]
4741 "VECTOR_MEM_VSX_P (<MODE>mode)"
4742 "xxsldwi %x0,%x1,%x2,%
3"
4743 [(set_attr "type" "vecperm")
4744 (set_attr "isa" "<VSisa>")])
4747 ;; Vector reduction insns and splitters
4749 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
4750 [(set (match_operand:V2DF
0 "vfloat_operand" "=&wa,wa")
4754 (match_operand:V2DF
1 "vfloat_operand" "wa,wa")
4755 (parallel [(const_int
1)]))
4758 (parallel [(const_int
0)])))
4760 (clobber (match_scratch:V2DF
2 "=
0,&wa"))]
4761 "VECTOR_UNIT_VSX_P (V2DFmode)"
4766 rtx tmp = (GET_CODE (operands[
2]) == SCRATCH)
4767 ? gen_reg_rtx (V2DFmode)
4769 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[
1], operands[
1], const2_rtx));
4770 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[
0], tmp, operands[
1]));
4773 [(set_attr "length" "
8")
4774 (set_attr "type" "veccomplex")])
4776 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
4777 [(set (match_operand:V4SF
0 "vfloat_operand" "=wa")
4779 (unspec:V4SF [(const_int
0)] UNSPEC_REDUC)
4780 (match_operand:V4SF
1 "vfloat_operand" "wa")))
4781 (clobber (match_scratch:V4SF
2 "=&wa"))
4782 (clobber (match_scratch:V4SF
3 "=&wa"))]
4783 "VECTOR_UNIT_VSX_P (V4SFmode)"
4788 rtx op0 = operands[
0];
4789 rtx op1 = operands[
1];
4790 rtx tmp2, tmp3, tmp4;
4792 if (can_create_pseudo_p ())
4794 tmp2 = gen_reg_rtx (V4SFmode);
4795 tmp3 = gen_reg_rtx (V4SFmode);
4796 tmp4 = gen_reg_rtx (V4SFmode);
4805 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
4806 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
4807 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (
3)));
4808 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
4811 [(set_attr "length" "
16")
4812 (set_attr "type" "veccomplex")])
4814 ;; Combiner patterns with the vector reduction patterns that knows we can get
4815 ;; to the top element of the V2DF array without doing an extract.
4817 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
4818 [(set (match_operand:DF
0 "vfloat_operand" "=&wa,wa")
4823 (match_operand:V2DF
1 "vfloat_operand" "wa,wa")
4824 (parallel [(const_int
1)]))
4827 (parallel [(const_int
0)])))
4829 (parallel [(const_int
1)])))
4830 (clobber (match_scratch:DF
2 "=
0,&wa"))]
4831 "BYTES_BIG_ENDIAN && VECTOR_UNIT_VSX_P (V2DFmode)"
4836 rtx hi = gen_highpart (DFmode, operands[
1]);
4837 rtx lo = (GET_CODE (operands[
2]) == SCRATCH)
4838 ? gen_reg_rtx (DFmode)
4841 emit_insn (gen_vsx_extract_v2df (lo, operands[
1], const1_rtx));
4842 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[
0], hi, lo));
4845 [(set_attr "length" "
8")
4846 (set_attr "type" "veccomplex")])
4848 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
4849 [(set (match_operand:SF
0 "vfloat_operand" "=f")
4852 (unspec:V4SF [(const_int
0)] UNSPEC_REDUC)
4853 (match_operand:V4SF
1 "vfloat_operand" "wa"))
4854 (parallel [(const_int
3)])))
4855 (clobber (match_scratch:V4SF
2 "=&wa"))
4856 (clobber (match_scratch:V4SF
3 "=&wa"))
4857 (clobber (match_scratch:V4SF
4 "=
0"))]
4858 "BYTES_BIG_ENDIAN && VECTOR_UNIT_VSX_P (V4SFmode)"
4863 rtx op0 = operands[
0];
4864 rtx op1 = operands[
1];
4865 rtx tmp2, tmp3, tmp4, tmp5;
4867 if (can_create_pseudo_p ())
4869 tmp2 = gen_reg_rtx (V4SFmode);
4870 tmp3 = gen_reg_rtx (V4SFmode);
4871 tmp4 = gen_reg_rtx (V4SFmode);
4872 tmp5 = gen_reg_rtx (V4SFmode);
4882 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
4883 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
4884 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (
3)));
4885 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
4886 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
4889 [(set_attr "length" "
20")
4890 (set_attr "type" "veccomplex")])
4893 ;; Power8 Vector fusion. The fused ops must be physically adjacent.
4895 [(set (match_operand:P
0 "base_reg_operand")
4896 (match_operand:P
1 "short_cint_operand"))
4897 (set (match_operand:VSX_M
2 "vsx_register_operand")
4898 (mem:VSX_M (plus:P (match_dup
0)
4899 (match_operand:P
3 "int_reg_operand"))))]
4900 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
4901 "li %
0,%
1\;lx<VSX_M:VSm>x %x2,%
0,%
3\t\t\t# vector load fusion"
4902 [(set_attr "length" "
8")
4903 (set_attr "type" "vecload")])
4906 [(set (match_operand:P
0 "base_reg_operand")
4907 (match_operand:P
1 "short_cint_operand"))
4908 (set (match_operand:VSX_M
2 "vsx_register_operand")
4909 (mem:VSX_M (plus:P (match_operand:P
3 "int_reg_operand")
4911 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
4912 "li %
0,%
1\;lx<VSX_M:VSm>x %x2,%
0,%
3\t\t\t# vector load fusion"
4913 [(set_attr "length" "
8")
4914 (set_attr "type" "vecload")])
4917 ;; ISA
3.1 vector extend sign support
4918 (define_insn "vsx_sign_extend_v2di_v1ti"
4919 [(set (match_operand:V1TI
0 "vsx_register_operand" "=v")
4920 (unspec:V1TI [(match_operand:V2DI
1 "vsx_register_operand" "v")]
4921 UNSPEC_VSX_SIGN_EXTEND))]
4924 [(set_attr "type" "vecexts")])
4926 ;; ISA
3.0 vector extend sign support
4928 (define_insn "vsx_sign_extend_v16qi_<mode>"
4929 [(set (match_operand:VSINT_84
0 "vsx_register_operand" "=v")
4931 [(match_operand:V16QI
1 "vsx_register_operand" "v")]
4932 UNSPEC_VSX_SIGN_EXTEND))]
4935 [(set_attr "type" "vecexts")])
4937 (define_insn "vsx_sign_extend_v8hi_<mode>"
4938 [(set (match_operand:VSINT_84
0 "vsx_register_operand" "=v")
4940 [(match_operand:V8HI
1 "vsx_register_operand" "v")]
4941 UNSPEC_VSX_SIGN_EXTEND))]
4944 [(set_attr "type" "vecexts")])
4946 (define_insn "vsx_sign_extend_v4si_v2di"
4947 [(set (match_operand:V2DI
0 "vsx_register_operand" "=v")
4948 (unspec:V2DI [(match_operand:V4SI
1 "vsx_register_operand" "v")]
4949 UNSPEC_VSX_SIGN_EXTEND))]
4952 [(set_attr "type" "vecexts")])
4954 ;; Sign extend DI to TI. We provide both GPR targets and Altivec targets on
4955 ;; power10. On earlier systems, the machine independent code will generate a
4956 ;; shift left to sign extend the
64-bit value to
128-bit.
4958 ;; If the register allocator prefers to use GPR registers, we will use a shift
4959 ;; left instruction to sign extend the
64-bit value to
128-bit.
4961 ;; If the register allocator prefers to use Altivec registers on power10,
4962 ;; generate the vextsd2q instruction.
4963 (define_insn_and_split "extendditi2"
4964 [(set (match_operand:TI
0 "register_operand" "=r,r,v,v,v")
4965 (sign_extend:TI (match_operand:DI
1 "input_operand" "r,m,b,wa,Z")))
4966 (clobber (reg:DI CA_REGNO))]
4967 "TARGET_POWERPC64 && TARGET_POWER10"
4969 "&& reload_completed"
4972 rtx dest = operands[
0];
4973 rtx src = operands[
1];
4974 int dest_regno = reg_or_subregno (dest);
4976 /* Handle conversion to GPR registers. Load up the low part and then do
4977 a sign extension to the upper part. */
4978 if (INT_REGNO_P (dest_regno))
4980 rtx dest_hi = gen_highpart (DImode, dest);
4981 rtx dest_lo = gen_lowpart (DImode, dest);
4983 emit_move_insn (dest_lo, src);
4984 /* In case src is a MEM, we have to use the destination, which is a
4985 register, instead of re-using the source. */
4986 rtx src2 = (REG_P (src) || SUBREG_P (src)) ? src : dest_lo;
4987 emit_insn (gen_ashrdi3 (dest_hi, src2, GEN_INT (
63)));
4991 /* For conversion to an Altivec register, generate either a splat operation
4992 or a load rightmost double word instruction. Both instructions gets the
4993 DImode value into the lower
64 bits, and then do the vextsd2q
4996 else if (ALTIVEC_REGNO_P (dest_regno))
4999 emit_insn (gen_vsx_lxvrdx (dest, src));
5002 rtx dest_v2di = gen_rtx_REG (V2DImode, dest_regno);
5003 emit_insn (gen_vsx_splat_v2di (dest_v2di, src));
5006 emit_insn (gen_extendditi2_vector (dest, dest));
5013 [(set_attr "length" "
8")
5014 (set_attr "type" "shift,load,vecmove,vecperm,load")])
5016 ;; Sign extend
64-bit value in TI reg, word
1, to
128-bit value in TI reg
5017 (define_insn "extendditi2_vector"
5018 [(set (match_operand:TI
0 "gpc_reg_operand" "=v")
5019 (unspec:TI [(match_operand:TI
1 "gpc_reg_operand" "v")]
5020 UNSPEC_EXTENDDITI2))]
5023 [(set_attr "type" "vecexts")])
5026 ;; ISA
3.0 Binary Floating-Point Support
5028 ;; VSX Scalar Extract Exponent Quad-Precision
5029 (define_insn "xsxexpqp_<mode>"
5030 [(set (match_operand:DI
0 "altivec_register_operand" "=v")
5031 (unspec:DI [(match_operand:IEEE128
1 "altivec_register_operand" "v")]
5032 UNSPEC_VSX_SXEXPDP))]
5035 [(set_attr "type" "vecmove")])
5037 ;; VSX Scalar Extract Exponent Double-Precision
5038 (define_insn "xsxexpdp"
5039 [(set (match_operand:DI
0 "register_operand" "=r")
5040 (unspec:DI [(match_operand:DF
1 "vsx_register_operand" "wa")]
5041 UNSPEC_VSX_SXEXPDP))]
5042 "TARGET_P9_VECTOR && TARGET_64BIT"
5044 [(set_attr "type" "integer")])
5046 ;; VSX Scalar Extract Significand Quad-Precision
5047 (define_insn "xsxsigqp_<mode>"
5048 [(set (match_operand:TI
0 "altivec_register_operand" "=v")
5049 (unspec:TI [(match_operand:IEEE128
1 "altivec_register_operand" "v")]
5053 [(set_attr "type" "vecmove")])
5055 ;; VSX Scalar Extract Significand Double-Precision
5056 (define_insn "xsxsigdp"
5057 [(set (match_operand:DI
0 "register_operand" "=r")
5058 (unspec:DI [(match_operand:DF
1 "vsx_register_operand" "wa")]
5060 "TARGET_P9_VECTOR && TARGET_64BIT"
5062 [(set_attr "type" "integer")])
5064 ;; VSX Scalar Insert Exponent Quad-Precision Floating Point Argument
5065 (define_insn "xsiexpqpf_<mode>"
5066 [(set (match_operand:IEEE128
0 "altivec_register_operand" "=v")
5068 [(match_operand:IEEE128
1 "altivec_register_operand" "v")
5069 (match_operand:DI
2 "altivec_register_operand" "v")]
5070 UNSPEC_VSX_SIEXPQP))]
5073 [(set_attr "type" "vecmove")])
5075 ;; VSX Scalar Insert Exponent Quad-Precision
5076 (define_insn "xsiexpqp_<mode>"
5077 [(set (match_operand:IEEE128
0 "altivec_register_operand" "=v")
5078 (unspec:IEEE128 [(match_operand:TI
1 "altivec_register_operand" "v")
5079 (match_operand:DI
2 "altivec_register_operand" "v")]
5080 UNSPEC_VSX_SIEXPQP))]
5083 [(set_attr "type" "vecmove")])
5085 ;; VSX Scalar Insert Exponent Double-Precision
5086 (define_insn "xsiexpdp"
5087 [(set (match_operand:DF
0 "vsx_register_operand" "=wa")
5088 (unspec:DF [(match_operand:DI
1 "register_operand" "r")
5089 (match_operand:DI
2 "register_operand" "r")]
5090 UNSPEC_VSX_SIEXPDP))]
5091 "TARGET_P9_VECTOR && TARGET_64BIT"
5092 "xsiexpdp %x0,%
1,%
2"
5093 [(set_attr "type" "fpsimple")])
5095 ;; VSX Scalar Insert Exponent Double-Precision Floating Point Argument
5096 (define_insn "xsiexpdpf"
5097 [(set (match_operand:DF
0 "vsx_register_operand" "=wa")
5098 (unspec:DF [(match_operand:DF
1 "register_operand" "r")
5099 (match_operand:DI
2 "register_operand" "r")]
5100 UNSPEC_VSX_SIEXPDP))]
5101 "TARGET_P9_VECTOR && TARGET_64BIT"
5102 "xsiexpdp %x0,%
1,%
2"
5103 [(set_attr "type" "fpsimple")])
5105 ;; VSX Scalar Compare Exponents Double-Precision
5106 (define_expand "xscmpexpdp_<code>"
5110 [(match_operand:DF
1 "vsx_register_operand" "wa")
5111 (match_operand:DF
2 "vsx_register_operand" "wa")]
5112 UNSPEC_VSX_SCMPEXPDP)
5114 (set (match_operand:SI
0 "register_operand" "=r")
5115 (CMP_TEST:SI (match_dup
3)
5119 if (<CODE> == UNORDERED && !HONOR_NANS (DFmode))
5121 emit_move_insn (operands[
0], const0_rtx);
5125 operands[
3] = gen_reg_rtx (CCFPmode);
5128 (define_insn "*xscmpexpdp"
5129 [(set (match_operand:CCFP
0 "cc_reg_operand" "=y")
5131 (unspec:DF [(match_operand:DF
1 "vsx_register_operand" "wa")
5132 (match_operand:DF
2 "vsx_register_operand" "wa")]
5133 UNSPEC_VSX_SCMPEXPDP)
5134 (match_operand:SI
3 "zero_constant" "j")))]
5136 "xscmpexpdp %
0,%x1,%x2"
5137 [(set_attr "type" "fpcompare")])
5139 ;; VSX Scalar Compare Exponents Quad-Precision
5140 (define_expand "xscmpexpqp_<code>_<mode>"
5144 [(match_operand:IEEE128
1 "vsx_register_operand" "v")
5145 (match_operand:IEEE128
2 "vsx_register_operand" "v")]
5146 UNSPEC_VSX_SCMPEXPQP)
5148 (set (match_operand:SI
0 "register_operand" "=r")
5149 (CMP_TEST:SI (match_dup
3)
5153 if (<CODE> == UNORDERED && !HONOR_NANS (<MODE>mode))
5155 emit_move_insn (operands[
0], const0_rtx);
5159 operands[
3] = gen_reg_rtx (CCFPmode);
5162 (define_insn "*xscmpexpqp"
5163 [(set (match_operand:CCFP
0 "cc_reg_operand" "=y")
5165 (unspec:IEEE128 [(match_operand:IEEE128
1 "altivec_register_operand" "v")
5166 (match_operand:IEEE128
2 "altivec_register_operand" "v")]
5167 UNSPEC_VSX_SCMPEXPQP)
5168 (match_operand:SI
3 "zero_constant" "j")))]
5170 "xscmpexpqp %
0,%
1,%
2"
5171 [(set_attr "type" "fpcompare")])
5173 ;; VSX Scalar Test Data Class Quad-Precision
5174 ;; (Expansion for scalar_test_data_class (__ieee128, int))
5175 ;; (Has side effect of setting the lt bit if operand
1 is negative,
5176 ;; setting the eq bit if any of the conditions tested by operand
2
5177 ;; are satisfied, and clearing the gt and undordered bits to zero.)
5178 (define_expand "xststdcqp_<mode>"
5182 [(match_operand:IEEE128
1 "altivec_register_operand" "v")
5183 (match_operand:SI
2 "u7bit_cint_operand" "n")]
5186 (set (match_operand:SI
0 "register_operand" "=r")
5187 (eq:SI (match_dup
3)
5191 operands[
3] = gen_reg_rtx (CCFPmode);
5194 ;; VSX Scalar Test Data Class Double- and Single-Precision
5195 ;; (The lt bit is set if operand
1 is negative. The eq bit is set
5196 ;; if any of the conditions tested by operand
2 are satisfied.
5197 ;; The gt and unordered bits are cleared to zero.)
5198 (define_expand "xststdc<sd>p"
5202 [(match_operand:SFDF
1 "vsx_register_operand" "wa")
5203 (match_operand:SI
2 "u7bit_cint_operand" "n")]
5206 (set (match_operand:SI
0 "register_operand" "=r")
5207 (eq:SI (match_dup
3)
5211 operands[
3] = gen_reg_rtx (CCFPmode);
5212 operands[
4] = CONST0_RTX (SImode);
5215 ;; The VSX Scalar Test Negative Quad-Precision
5216 (define_expand "xststdcnegqp_<mode>"
5220 [(match_operand:IEEE128
1 "altivec_register_operand" "v")
5224 (set (match_operand:SI
0 "register_operand" "=r")
5225 (lt:SI (match_dup
2)
5229 operands[
2] = gen_reg_rtx (CCFPmode);
5232 ;; The VSX Scalar Test Negative Double- and Single-Precision
5233 (define_expand "xststdcneg<sd>p"
5237 [(match_operand:SFDF
1 "vsx_register_operand" "wa")
5241 (set (match_operand:SI
0 "register_operand" "=r")
5242 (lt:SI (match_dup
2)
5246 operands[
2] = gen_reg_rtx (CCFPmode);
5247 operands[
3] = CONST0_RTX (SImode);
5250 (define_insn "*xststdcqp_<mode>"
5251 [(set (match_operand:CCFP
0 "" "=y")
5254 [(match_operand:IEEE128
1 "altivec_register_operand" "v")
5255 (match_operand:SI
2 "u7bit_cint_operand" "n")]
5259 "xststdcqp %
0,%
1,%
2"
5260 [(set_attr "type" "fpcompare")])
5262 (define_insn "*xststdc<sd>p"
5263 [(set (match_operand:CCFP
0 "" "=y")
5265 (unspec:SFDF [(match_operand:SFDF
1 "vsx_register_operand" "wa")
5266 (match_operand:SI
2 "u7bit_cint_operand" "n")]
5268 (match_operand:SI
3 "zero_constant" "j")))]
5270 "xststdc<sd>p %
0,%x1,%
2"
5271 [(set_attr "type" "fpcompare")])
5273 ;; VSX Vector Extract Exponent Double and Single Precision
5274 (define_insn "xvxexp<sd>p"
5275 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
5277 [(match_operand:VSX_F
1 "vsx_register_operand" "wa")]
5280 "xvxexp<sd>p %x0,%x1"
5281 [(set_attr "type" "vecsimple")])
5283 ;; VSX Vector Extract Significand Double and Single Precision
5284 (define_insn "xvxsig<sd>p"
5285 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
5287 [(match_operand:VSX_F
1 "vsx_register_operand" "wa")]
5290 "xvxsig<sd>p %x0,%x1"
5291 [(set_attr "type" "vecsimple")])
5293 ;; VSX Vector Insert Exponent Double and Single Precision
5294 (define_insn "xviexp<sd>p"
5295 [(set (match_operand:VSX_F
0 "vsx_register_operand" "=wa")
5297 [(match_operand:VSX_F
1 "vsx_register_operand" "wa")
5298 (match_operand:VSX_F
2 "vsx_register_operand" "wa")]
5301 "xviexp<sd>p %x0,%x1,%x2"
5302 [(set_attr "type" "vecsimple")])
5304 ;; VSX Vector Test Data Class Double and Single Precision
5305 ;; The corresponding elements of the result vector are all ones
5306 ;; if any of the conditions tested by operand
3 are satisfied.
5307 (define_insn "xvtstdc<sd>p"
5308 [(set (match_operand:<VSI>
0 "vsx_register_operand" "=wa")
5310 [(match_operand:VSX_F
1 "vsx_register_operand" "wa")
5311 (match_operand:SI
2 "u7bit_cint_operand" "n")]
5312 UNSPEC_VSX_VTSTDC))]
5314 "xvtstdc<sd>p %x0,%x1,%
2"
5315 [(set_attr "type" "vecsimple")])
5317 ;; ISA
3.0 String Operations Support
5319 ;; Compare vectors producing a vector result and a predicate, setting CR6
5320 ;; to indicate a combined status. This pattern matches v16qi, v8hi, and
5321 ;; v4si modes. It does not match v2df, v4sf, or v2di modes. There's no
5322 ;; need to match v4sf, v2df, or v2di modes because those are expanded
5323 ;; to use Power8 instructions.
5324 (define_insn "*vsx_ne_<mode>_p"
5325 [(set (reg:CC CR6_REGNO)
5327 [(ne:CC (match_operand:VSX_EXTRACT_I
1 "gpc_reg_operand" "v")
5328 (match_operand:VSX_EXTRACT_I
2 "gpc_reg_operand" "v"))]
5330 (set (match_operand:VSX_EXTRACT_I
0 "gpc_reg_operand" "=v")
5331 (ne:VSX_EXTRACT_I (match_dup
1)
5334 "vcmpne<VSX_EXTRACT_WIDTH>. %
0,%
1,%
2"
5335 [(set_attr "type" "vecsimple")])
5337 (define_insn "*vector_nez_<mode>_p"
5338 [(set (reg:CC CR6_REGNO)
5339 (unspec:CC [(unspec:VI
5340 [(match_operand:VI
1 "gpc_reg_operand" "v")
5341 (match_operand:VI
2 "gpc_reg_operand" "v")]
5344 (set (match_operand:VI
0 "gpc_reg_operand" "=v")
5345 (unspec:VI [(match_dup
1)
5349 "vcmpnez<VSX_EXTRACT_WIDTH>. %
0,%
1,%
2"
5350 [(set_attr "type" "vecsimple")])
5352 ;; Return first position of match between vectors using natural order
5353 ;; for both LE and BE execution modes.
5354 (define_expand "first_match_index_<mode>"
5355 [(match_operand:SI
0 "register_operand")
5356 (unspec:SI [(match_operand:VSX_EXTRACT_I
1 "register_operand")
5357 (match_operand:VSX_EXTRACT_I
2 "register_operand")]
5358 UNSPEC_VSX_FIRST_MATCH_INDEX)]
5363 rtx cmp_result = gen_reg_rtx (<MODE>mode);
5364 rtx not_result = gen_reg_rtx (<MODE>mode);
5366 emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmp_result, operands[
1],
5368 emit_insn (gen_one_cmpl<mode>
2 (not_result, cmp_result));
5370 sh = GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) /
2;
5372 if (<MODE>mode == V16QImode)
5374 if (!BYTES_BIG_ENDIAN)
5375 emit_insn (gen_vctzlsbb_<mode> (operands[
0], not_result));
5377 emit_insn (gen_vclzlsbb_<mode> (operands[
0], not_result));
5381 rtx tmp = gen_reg_rtx (SImode);
5382 if (!BYTES_BIG_ENDIAN)
5383 emit_insn (gen_vctzlsbb_<mode> (tmp, not_result));
5385 emit_insn (gen_vclzlsbb_<mode> (tmp, not_result));
5386 emit_insn (gen_lshrsi3 (operands[
0], tmp, GEN_INT (sh)));
5391 ;; Return first position of match between vectors or end of string (EOS) using
5392 ;; natural element order for both LE and BE execution modes.
5393 (define_expand "first_match_or_eos_index_<mode>"
5394 [(match_operand:SI
0 "register_operand")
5395 (unspec: SI [(match_operand:VSX_EXTRACT_I
1 "register_operand")
5396 (match_operand:VSX_EXTRACT_I
2 "register_operand")]
5397 UNSPEC_VSX_FIRST_MATCH_EOS_INDEX)]
5401 rtx cmpz1_result = gen_reg_rtx (<MODE>mode);
5402 rtx cmpz2_result = gen_reg_rtx (<MODE>mode);
5403 rtx cmpz_result = gen_reg_rtx (<MODE>mode);
5404 rtx and_result = gen_reg_rtx (<MODE>mode);
5405 rtx result = gen_reg_rtx (<MODE>mode);
5406 rtx vzero = gen_reg_rtx (<MODE>mode);
5408 /* Vector with zeros in elements that correspond to zeros in operands. */
5409 emit_move_insn (vzero, CONST0_RTX (<MODE>mode));
5410 emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmpz1_result, operands[
1], vzero));
5411 emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmpz2_result, operands[
2], vzero));
5412 emit_insn (gen_and<mode>
3 (and_result, cmpz1_result, cmpz2_result));
5414 /* Vector with ones in elments that do not match. */
5415 emit_insn (gen_vcmpnez<VSX_EXTRACT_WIDTH> (cmpz_result, operands[
1],
5418 /* Create vector with ones in elements where there was a zero in one of
5419 the source elements or the elements that match. */
5420 emit_insn (gen_nand<mode>
3 (result, and_result, cmpz_result));
5421 sh = GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) /
2;
5423 if (<MODE>mode == V16QImode)
5425 if (!BYTES_BIG_ENDIAN)
5426 emit_insn (gen_vctzlsbb_<mode> (operands[
0], result));
5428 emit_insn (gen_vclzlsbb_<mode> (operands[
0], result));
5432 rtx tmp = gen_reg_rtx (SImode);
5433 if (!BYTES_BIG_ENDIAN)
5434 emit_insn (gen_vctzlsbb_<mode> (tmp, result));
5436 emit_insn (gen_vclzlsbb_<mode> (tmp, result));
5437 emit_insn (gen_lshrsi3 (operands[
0], tmp, GEN_INT (sh)));
5442 ;; Return first position of mismatch between vectors using natural
5443 ;; element order for both LE and BE execution modes.
5444 (define_expand "first_mismatch_index_<mode>"
5445 [(match_operand:SI
0 "register_operand")
5446 (unspec: SI [(match_operand:VSX_EXTRACT_I
1 "register_operand")
5447 (match_operand:VSX_EXTRACT_I
2 "register_operand")]
5448 UNSPEC_VSX_FIRST_MISMATCH_INDEX)]
5452 rtx cmp_result = gen_reg_rtx (<MODE>mode);
5454 emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmp_result, operands[
1],
5456 sh = GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) /
2;
5458 if (<MODE>mode == V16QImode)
5460 if (!BYTES_BIG_ENDIAN)
5461 emit_insn (gen_vctzlsbb_<mode> (operands[
0], cmp_result));
5463 emit_insn (gen_vclzlsbb_<mode> (operands[
0], cmp_result));
5467 rtx tmp = gen_reg_rtx (SImode);
5468 if (!BYTES_BIG_ENDIAN)
5469 emit_insn (gen_vctzlsbb_<mode> (tmp, cmp_result));
5471 emit_insn (gen_vclzlsbb_<mode> (tmp, cmp_result));
5472 emit_insn (gen_lshrsi3 (operands[
0], tmp, GEN_INT (sh)));
5477 ;; Return first position of mismatch between vectors or end of string (EOS)
5478 ;; using natural element order for both LE and BE execution modes.
5479 (define_expand "first_mismatch_or_eos_index_<mode>"
5480 [(match_operand:SI
0 "register_operand")
5481 (unspec: SI [(match_operand:VSX_EXTRACT_I
1 "register_operand")
5482 (match_operand:VSX_EXTRACT_I
2 "register_operand")]
5483 UNSPEC_VSX_FIRST_MISMATCH_EOS_INDEX)]
5487 rtx cmpz1_result = gen_reg_rtx (<MODE>mode);
5488 rtx cmpz2_result = gen_reg_rtx (<MODE>mode);
5489 rtx cmpz_result = gen_reg_rtx (<MODE>mode);
5490 rtx not_cmpz_result = gen_reg_rtx (<MODE>mode);
5491 rtx and_result = gen_reg_rtx (<MODE>mode);
5492 rtx result = gen_reg_rtx (<MODE>mode);
5493 rtx vzero = gen_reg_rtx (<MODE>mode);
5495 /* Vector with zeros in elements that correspond to zeros in operands. */
5496 emit_move_insn (vzero, CONST0_RTX (<MODE>mode));
5498 emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmpz1_result, operands[
1], vzero));
5499 emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmpz2_result, operands[
2], vzero));
5500 emit_insn (gen_and<mode>
3 (and_result, cmpz1_result, cmpz2_result));
5502 /* Vector with ones in elments that match. */
5503 emit_insn (gen_vcmpnez<VSX_EXTRACT_WIDTH> (cmpz_result, operands[
1],
5505 emit_insn (gen_one_cmpl<mode>
2 (not_cmpz_result, cmpz_result));
5507 /* Create vector with ones in elements where there was a zero in one of
5508 the source elements or the elements did not match. */
5509 emit_insn (gen_nand<mode>
3 (result, and_result, not_cmpz_result));
5510 sh = GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) /
2;
5512 if (<MODE>mode == V16QImode)
5514 if (!BYTES_BIG_ENDIAN)
5515 emit_insn (gen_vctzlsbb_<mode> (operands[
0], result));
5517 emit_insn (gen_vclzlsbb_<mode> (operands[
0], result));
5521 rtx tmp = gen_reg_rtx (SImode);
5522 if (!BYTES_BIG_ENDIAN)
5523 emit_insn (gen_vctzlsbb_<mode> (tmp, result));
5525 emit_insn (gen_vclzlsbb_<mode> (tmp, result));
5526 emit_insn (gen_lshrsi3 (operands[
0], tmp, GEN_INT (sh)));
5531 ;; Load VSX Vector with Length
5532 (define_expand "lxvl"
5534 (ashift:DI (match_operand:DI
2 "register_operand")
5536 (set (match_operand:V16QI
0 "vsx_register_operand")
5538 [(match_operand:DI
1 "gpc_reg_operand")
5539 (mem:V16QI (match_dup
1))
5542 "TARGET_P9_VECTOR && TARGET_64BIT"
5544 operands[
3] = gen_reg_rtx (DImode);
5547 (define_insn "*lxvl"
5548 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
5550 [(match_operand:DI
1 "gpc_reg_operand" "b")
5551 (mem:V16QI (match_dup
1))
5552 (match_operand:DI
2 "register_operand" "r")]
5554 "TARGET_P9_VECTOR && TARGET_64BIT"
5556 [(set_attr "type" "vecload")])
5558 (define_insn "lxvll"
5559 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
5560 (unspec:V16QI [(match_operand:DI
1 "gpc_reg_operand" "b")
5561 (mem:V16QI (match_dup
1))
5562 (match_operand:DI
2 "register_operand" "r")]
5566 [(set_attr "type" "vecload")])
5568 ;; Expand for builtin xl_len_r
5569 (define_expand "xl_len_r"
5570 [(match_operand:V16QI
0 "vsx_register_operand")
5571 (match_operand:DI
1 "register_operand")
5572 (match_operand:DI
2 "register_operand")]
5575 rtx shift_mask = gen_reg_rtx (V16QImode);
5576 rtx rtx_vtmp = gen_reg_rtx (V16QImode);
5577 rtx tmp = gen_reg_rtx (DImode);
5579 emit_insn (gen_altivec_lvsl_reg_di (shift_mask, operands[
2]));
5580 emit_insn (gen_ashldi3 (tmp, operands[
2], GEN_INT (
56)));
5581 emit_insn (gen_lxvll (rtx_vtmp, operands[
1], tmp));
5582 emit_insn (gen_altivec_vperm_v8hiv16qi (operands[
0], rtx_vtmp, rtx_vtmp,
5587 (define_insn "stxvll"
5588 [(set (mem:V16QI (match_operand:DI
1 "gpc_reg_operand" "b"))
5589 (unspec:V16QI [(match_operand:V16QI
0 "vsx_register_operand" "wa")
5590 (mem:V16QI (match_dup
1))
5591 (match_operand:DI
2 "register_operand" "r")]
5595 [(set_attr "type" "vecstore")])
5597 ;; Store VSX Vector with Length
5598 (define_expand "stxvl"
5600 (ashift:DI (match_operand:DI
2 "register_operand")
5602 (set (mem:V16QI (match_operand:DI
1 "gpc_reg_operand"))
5604 [(match_operand:V16QI
0 "vsx_register_operand")
5605 (mem:V16QI (match_dup
1))
5608 "TARGET_P9_VECTOR && TARGET_64BIT"
5610 operands[
3] = gen_reg_rtx (DImode);
5613 ;; Define optab for vector access with length vectorization exploitation.
5614 (define_expand "len_load_v16qi"
5615 [(match_operand:V16QI
0 "vlogical_operand")
5616 (match_operand:V16QI
1 "memory_operand")
5617 (match_operand:QI
2 "gpc_reg_operand")
5618 (match_operand:QI
3 "zero_constant")]
5619 "TARGET_P9_VECTOR && TARGET_64BIT"
5621 rtx mem = XEXP (operands[
1],
0);
5622 mem = force_reg (DImode, mem);
5623 rtx len = gen_lowpart (DImode, operands[
2]);
5624 emit_insn (gen_lxvl (operands[
0], mem, len));
5628 (define_expand "len_store_v16qi"
5629 [(match_operand:V16QI
0 "memory_operand")
5630 (match_operand:V16QI
1 "vlogical_operand")
5631 (match_operand:QI
2 "gpc_reg_operand")
5632 (match_operand:QI
3 "zero_constant")
5634 "TARGET_P9_VECTOR && TARGET_64BIT"
5636 rtx mem = XEXP (operands[
0],
0);
5637 mem = force_reg (DImode, mem);
5638 rtx len = gen_lowpart (DImode, operands[
2]);
5639 emit_insn (gen_stxvl (operands[
1], mem, len));
5643 (define_insn "*stxvl"
5644 [(set (mem:V16QI (match_operand:DI
1 "gpc_reg_operand" "b"))
5646 [(match_operand:V16QI
0 "vsx_register_operand" "wa")
5647 (mem:V16QI (match_dup
1))
5648 (match_operand:DI
2 "register_operand" "r")]
5650 "TARGET_P9_VECTOR && TARGET_64BIT"
5652 [(set_attr "type" "vecstore")])
5654 ;; Expand for builtin xst_len_r
5655 (define_expand "xst_len_r"
5656 [(match_operand:V16QI
0 "vsx_register_operand" "=wa")
5657 (match_operand:DI
1 "register_operand" "b")
5658 (match_operand:DI
2 "register_operand" "r")]
5661 rtx shift_mask = gen_reg_rtx (V16QImode);
5662 rtx rtx_vtmp = gen_reg_rtx (V16QImode);
5663 rtx tmp = gen_reg_rtx (DImode);
5665 emit_insn (gen_altivec_lvsr_reg_di (shift_mask, operands[
2]));
5666 emit_insn (gen_altivec_vperm_v8hiv16qi (rtx_vtmp, operands[
0], operands[
0],
5668 emit_insn (gen_ashldi3 (tmp, operands[
2], GEN_INT (
56)));
5669 emit_insn (gen_stxvll (rtx_vtmp, operands[
1], tmp));
5673 ;; Vector Compare Not Equal Byte (specified/not+eq:)
5674 (define_insn "vcmpneb"
5675 [(set (match_operand:V16QI
0 "altivec_register_operand" "=v")
5677 (eq:V16QI (match_operand:V16QI
1 "altivec_register_operand" "v")
5678 (match_operand:V16QI
2 "altivec_register_operand" "v"))))]
5681 [(set_attr "type" "vecsimple")])
5683 ;; Vector Compare Not Equal v1ti (specified/not+eq:)
5684 (define_expand "vcmpnet"
5685 [(set (match_operand:V1TI
0 "altivec_register_operand")
5687 (eq:V1TI (match_operand:V1TI
1 "altivec_register_operand")
5688 (match_operand:V1TI
2 "altivec_register_operand"))))]
5691 emit_insn (gen_eqvv1ti3 (operands[
0], operands[
1], operands[
2]));
5692 emit_insn (gen_one_cmplv1ti2 (operands[
0], operands[
0]));
5696 ;; Vector Compare Not Equal or Zero Byte
5697 (define_insn "vcmpnezb"
5698 [(set (match_operand:V16QI
0 "altivec_register_operand" "=v")
5700 [(match_operand:V16QI
1 "altivec_register_operand" "v")
5701 (match_operand:V16QI
2 "altivec_register_operand" "v")]
5705 [(set_attr "type" "vecsimple")])
5707 ;; Vector Compare Not Equal or Zero Byte predicate or record-form
5708 (define_insn "vcmpnezb_p"
5709 [(set (reg:CC CR6_REGNO)
5711 [(match_operand:V16QI
1 "altivec_register_operand" "v")
5712 (match_operand:V16QI
2 "altivec_register_operand" "v")]
5714 (set (match_operand:V16QI
0 "altivec_register_operand" "=v")
5720 "vcmpnezb. %
0,%
1,%
2"
5721 [(set_attr "type" "vecsimple")])
5723 ;; Vector Compare Not Equal Half Word (specified/not+eq:)
5724 (define_insn "vcmpneh"
5725 [(set (match_operand:V8HI
0 "altivec_register_operand" "=v")
5727 (eq:V8HI (match_operand:V8HI
1 "altivec_register_operand" "v")
5728 (match_operand:V8HI
2 "altivec_register_operand" "v"))))]
5731 [(set_attr "type" "vecsimple")])
5733 ;; Vector Compare Not Equal or Zero Half Word
5734 (define_insn "vcmpnezh"
5735 [(set (match_operand:V8HI
0 "altivec_register_operand" "=v")
5736 (unspec:V8HI [(match_operand:V8HI
1 "altivec_register_operand" "v")
5737 (match_operand:V8HI
2 "altivec_register_operand" "v")]
5741 [(set_attr "type" "vecsimple")])
5743 ;; Vector Compare Not Equal Word (specified/not+eq:)
5744 (define_insn "vcmpnew"
5745 [(set (match_operand:V4SI
0 "altivec_register_operand" "=v")
5747 (eq:V4SI (match_operand:V4SI
1 "altivec_register_operand" "v")
5748 (match_operand:V4SI
2 "altivec_register_operand" "v"))))]
5751 [(set_attr "type" "vecsimple")])
5753 ;; Vector Compare Not Equal or Zero Word
5754 (define_insn "vcmpnezw"
5755 [(set (match_operand:V4SI
0 "altivec_register_operand" "=v")
5756 (unspec:V4SI [(match_operand:V4SI
1 "altivec_register_operand" "v")
5757 (match_operand:V4SI
2 "altivec_register_operand" "v")]
5761 [(set_attr "type" "vecsimple")])
5763 ;; Vector Count Leading Zero Least-Significant Bits Byte
5764 (define_insn "vclzlsbb_<mode>"
5765 [(set (match_operand:SI
0 "register_operand" "=r")
5767 [(match_operand:VSX_EXTRACT_I
1 "altivec_register_operand" "v")]
5771 [(set_attr "type" "vecsimple")])
5773 ;; Vector Count Trailing Zero Least-Significant Bits Byte
5774 (define_insn "vctzlsbb_<mode>"
5775 [(set (match_operand:SI
0 "register_operand" "=r")
5777 [(match_operand:VSX_EXTRACT_I
1 "altivec_register_operand" "v")]
5781 [(set_attr "type" "vecsimple")])
5783 ;; Vector Extract Unsigned Byte Left-Indexed
5784 (define_insn "vextublx"
5785 [(set (match_operand:SI
0 "register_operand" "=r")
5787 [(match_operand:SI
1 "register_operand" "r")
5788 (match_operand:V16QI
2 "altivec_register_operand" "v")]
5792 [(set_attr "type" "vecsimple")])
5794 ;; Vector Extract Unsigned Byte Right-Indexed
5795 (define_insn "vextubrx"
5796 [(set (match_operand:SI
0 "register_operand" "=r")
5798 [(match_operand:SI
1 "register_operand" "r")
5799 (match_operand:V16QI
2 "altivec_register_operand" "v")]
5803 [(set_attr "type" "vecsimple")])
5805 ;; Vector Extract Unsigned Half Word Left-Indexed
5806 (define_insn "vextuhlx"
5807 [(set (match_operand:SI
0 "register_operand" "=r")
5809 [(match_operand:SI
1 "register_operand" "r")
5810 (match_operand:V8HI
2 "altivec_register_operand" "v")]
5814 [(set_attr "type" "vecsimple")])
5816 ;; Vector Extract Unsigned Half Word Right-Indexed
5817 (define_insn "vextuhrx"
5818 [(set (match_operand:SI
0 "register_operand" "=r")
5820 [(match_operand:SI
1 "register_operand" "r")
5821 (match_operand:V8HI
2 "altivec_register_operand" "v")]
5825 [(set_attr "type" "vecsimple")])
5827 ;; Vector Extract Unsigned Word Left-Indexed
5828 (define_insn "vextuwlx"
5829 [(set (match_operand:SI
0 "register_operand" "=r")
5831 [(match_operand:SI
1 "register_operand" "r")
5832 (match_operand:V4SI
2 "altivec_register_operand" "v")]
5836 [(set_attr "type" "vecsimple")])
5838 ;; Vector Extract Unsigned Word Right-Indexed
5839 (define_insn "vextuwrx"
5840 [(set (match_operand:SI
0 "register_operand" "=r")
5842 [(match_operand:SI
1 "register_operand" "r")
5843 (match_operand:V4SI
2 "altivec_register_operand" "v")]
5847 [(set_attr "type" "vecsimple")])
5849 ;; Vector insert/extract word at arbitrary byte values. Note, the little
5850 ;; endian version needs to adjust the byte number, and the V4SI element in
5852 (define_insn "extract4b"
5853 [(set (match_operand:V2DI
0 "vsx_register_operand")
5854 (unspec:V2DI [(match_operand:V16QI
1 "vsx_register_operand" "wa")
5855 (match_operand:QI
2 "const_0_to_12_operand" "n")]
5856 UNSPEC_XXEXTRACTUW))]
5859 if (!BYTES_BIG_ENDIAN)
5860 operands[
2] = GEN_INT (
12 - INTVAL (operands[
2]));
5862 return "xxextractuw %x0,%x1,%
2";
5865 (define_expand "insert4b"
5866 [(set (match_operand:V16QI
0 "vsx_register_operand")
5867 (unspec:V16QI [(match_operand:V4SI
1 "vsx_register_operand")
5868 (match_operand:V16QI
2 "vsx_register_operand")
5869 (match_operand:QI
3 "const_0_to_12_operand")]
5873 if (!BYTES_BIG_ENDIAN)
5875 rtx op1 = operands[
1];
5876 rtx v4si_tmp = gen_reg_rtx (V4SImode);
5877 emit_insn (gen_vsx_xxpermdi_v4si_be (v4si_tmp, op1, op1, const1_rtx));
5878 operands[
1] = v4si_tmp;
5879 operands[
3] = GEN_INT (
12 - INTVAL (operands[
3]));
5883 (define_insn "*insert4b_internal"
5884 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
5885 (unspec:V16QI [(match_operand:V4SI
1 "vsx_register_operand" "wa")
5886 (match_operand:V16QI
2 "vsx_register_operand" "
0")
5887 (match_operand:QI
3 "const_0_to_12_operand" "n")]
5890 "xxinsertw %x0,%x1,%
3"
5891 [(set_attr "type" "vecperm")])
5894 ;; Generate vector extract four float
32 values from left four elements
5895 ;; of eight element vector of float
16 values.
5896 (define_expand "vextract_fp_from_shorth"
5897 [(set (match_operand:V4SF
0 "register_operand" "=wa")
5898 (unspec:V4SF [(match_operand:V8HI
1 "register_operand" "wa")]
5899 UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTH))]
5903 int vals_le[
16] = {
15,
14,
0,
0,
13,
12,
0,
0,
11,
10,
0,
0,
9,
8,
0,
0};
5904 int vals_be[
16] = {
0,
0,
0,
1,
0,
0,
2,
3,
0,
0,
4,
5,
0,
0,
6,
7};
5907 rtx mask = gen_reg_rtx (V16QImode);
5908 rtx tmp = gen_reg_rtx (V16QImode);
5911 for (i =
0; i <
16; i++)
5912 if (!BYTES_BIG_ENDIAN)
5913 rvals[i] = GEN_INT (vals_le[i]);
5915 rvals[i] = GEN_INT (vals_be[i]);
5917 /* xvcvhpsp - vector convert F16 to vector F32 requires the four F16
5918 inputs in half words
1,
3,
5,
7 (IBM numbering). Use xxperm to move
5919 src half words
0,
1,
2,
3 (LE), src half words
4,
5,
6,
7 (BE) for the
5920 conversion instruction. */
5921 v = gen_rtvec_v (
16, rvals);
5922 emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
5923 emit_insn (gen_altivec_vperm_v8hiv16qi (tmp, operands[
1],
5924 operands[
1], mask));
5925 emit_insn (gen_vsx_xvcvhpsp (operands[
0], tmp));
5929 ;; Generate vector extract four float
32 values from right four elements
5930 ;; of eight element vector of float
16 values.
5931 (define_expand "vextract_fp_from_shortl"
5932 [(set (match_operand:V4SF
0 "register_operand" "=wa")
5933 (unspec:V4SF [(match_operand:V8HI
1 "register_operand" "wa")]
5934 UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTL))]
5937 int vals_le[
16] = {
7,
6,
0,
0,
5,
4,
0,
0,
3,
2,
0,
0,
1,
0,
0,
0};
5938 int vals_be[
16] = {
0,
0,
8,
9,
0,
0,
10,
11,
0,
0,
12,
13,
0,
0,
14,
15};
5942 rtx mask = gen_reg_rtx (V16QImode);
5943 rtx tmp = gen_reg_rtx (V16QImode);
5946 for (i =
0; i <
16; i++)
5947 if (!BYTES_BIG_ENDIAN)
5948 rvals[i] = GEN_INT (vals_le[i]);
5950 rvals[i] = GEN_INT (vals_be[i]);
5952 /* xvcvhpsp - vector convert F16 to vector F32 requires the four F16
5953 inputs in half words
1,
3,
5,
7 (IBM numbering). Use xxperm to move
5954 src half words
4,
5,
6,
7 (LE), src half words
0,
1,
2,
3 (BE) for the
5955 conversion instruction. */
5956 v = gen_rtvec_v (
16, rvals);
5957 emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v)));
5958 emit_insn (gen_altivec_vperm_v8hiv16qi (tmp, operands[
1],
5959 operands[
1], mask));
5960 emit_insn (gen_vsx_xvcvhpsp (operands[
0], tmp));
5964 ;; Support for ISA
3.0 vector byte reverse
5966 ;; Swap all bytes with in a vector
5967 (define_insn "p9_xxbrq_v1ti"
5968 [(set (match_operand:V1TI
0 "vsx_register_operand" "=wa")
5969 (bswap:V1TI (match_operand:V1TI
1 "vsx_register_operand" "wa")))]
5972 [(set_attr "type" "vecperm")])
5974 (define_expand "p9_xxbrq_v16qi"
5975 [(use (match_operand:V16QI
0 "vsx_register_operand" "=wa"))
5976 (use (match_operand:V16QI
1 "vsx_register_operand" "wa"))]
5979 rtx op0 = gen_reg_rtx (V1TImode);
5980 rtx op1 = gen_lowpart (V1TImode, operands[
1]);
5981 emit_insn (gen_p9_xxbrq_v1ti (op0, op1));
5982 emit_move_insn (operands[
0], gen_lowpart (V16QImode, op0));
5986 ;; Swap all bytes in each
64-bit element
5987 (define_insn "p9_xxbrd_v2di"
5988 [(set (match_operand:V2DI
0 "vsx_register_operand" "=wa")
5989 (bswap:V2DI (match_operand:V2DI
1 "vsx_register_operand" "wa")))]
5992 [(set_attr "type" "vecperm")])
5994 (define_expand "p9_xxbrd_v2df"
5995 [(use (match_operand:V2DF
0 "vsx_register_operand" "=wa"))
5996 (use (match_operand:V2DF
1 "vsx_register_operand" "wa"))]
5999 rtx op0 = gen_reg_rtx (V2DImode);
6000 rtx op1 = gen_lowpart (V2DImode, operands[
1]);
6001 emit_insn (gen_p9_xxbrd_v2di (op0, op1));
6002 emit_move_insn (operands[
0], gen_lowpart (V2DFmode, op0));
6006 ;; Swap all bytes in each
32-bit element
6007 (define_insn "p9_xxbrw_v4si"
6008 [(set (match_operand:V4SI
0 "vsx_register_operand" "=wa")
6009 (bswap:V4SI (match_operand:V4SI
1 "vsx_register_operand" "wa")))]
6012 [(set_attr "type" "vecperm")])
6014 (define_expand "p9_xxbrw_v4sf"
6015 [(use (match_operand:V4SF
0 "vsx_register_operand" "=wa"))
6016 (use (match_operand:V4SF
1 "vsx_register_operand" "wa"))]
6019 rtx op0 = gen_reg_rtx (V4SImode);
6020 rtx op1 = gen_lowpart (V4SImode, operands[
1]);
6021 emit_insn (gen_p9_xxbrw_v4si (op0, op1));
6022 emit_move_insn (operands[
0], gen_lowpart (V4SFmode, op0));
6026 ;; Swap all bytes in each element of vector
6027 (define_expand "revb_<mode>"
6028 [(use (match_operand:VEC_REVB
0 "vsx_register_operand"))
6029 (use (match_operand:VEC_REVB
1 "vsx_register_operand"))]
6032 if (TARGET_P9_VECTOR)
6033 emit_insn (gen_p9_xxbr<VSX_XXBR>_<mode> (operands[
0], operands[
1]));
6036 if (<MODE>mode == V8HImode)
6038 rtx splt = gen_reg_rtx (V8HImode);
6039 emit_insn (gen_altivec_vspltish (splt, GEN_INT (
8)));
6040 emit_insn (gen_altivec_vrlh (operands[
0], operands[
1], splt));
6044 /* Want to have the elements in reverse order relative
6045 to the endian mode in use, i.e. in LE mode, put elements
6047 rtx sel = swap_endian_selector_for_mode (<MODE>mode);
6048 emit_insn (gen_altivec_vperm_<mode>_direct (operands[
0], operands[
1],
6056 ;; Reversing bytes in vector char is just a NOP.
6057 (define_expand "revb_v16qi"
6058 [(set (match_operand:V16QI
0 "vsx_register_operand")
6059 (bswap:V16QI (match_operand:V16QI
1 "vsx_register_operand")))]
6062 emit_move_insn (operands[
0], operands[
1]);
6066 ;; Swap all bytes in each
16-bit element
6067 (define_insn "p9_xxbrh_v8hi"
6068 [(set (match_operand:V8HI
0 "vsx_register_operand" "=wa")
6069 (bswap:V8HI (match_operand:V8HI
1 "vsx_register_operand" "wa")))]
6072 [(set_attr "type" "vecperm")])
6075 ;; Operand numbers for the following peephole2
6077 [(SFBOOL_TMP_GPR
0) ;; GPR temporary
6078 (SFBOOL_TMP_VSX
1) ;; vector temporary
6079 (SFBOOL_MFVSR_D
2) ;; move to gpr dest
6080 (SFBOOL_MFVSR_A
3) ;; move to gpr src
6081 (SFBOOL_BOOL_D
4) ;; and/ior/xor dest
6082 (SFBOOL_BOOL_A1
5) ;; and/ior/xor arg1
6083 (SFBOOL_BOOL_A2
6) ;; and/ior/xor arg1
6084 (SFBOOL_SHL_D
7) ;; shift left dest
6085 (SFBOOL_SHL_A
8) ;; shift left arg
6086 (SFBOOL_MTVSR_D
9) ;; move to vecter dest
6087 (SFBOOL_MFVSR_A_V4SF
10) ;; SFBOOL_MFVSR_A as V4SFmode
6088 (SFBOOL_BOOL_A_DI
11) ;; SFBOOL_BOOL_A1/A2 as DImode
6089 (SFBOOL_TMP_VSX_DI
12) ;; SFBOOL_TMP_VSX as DImode
6090 (SFBOOL_MTVSR_D_V4SF
13)]) ;; SFBOOL_MTVSRD_D as V4SFmode
6092 ;; Attempt to optimize some common GLIBC operations using logical operations to
6093 ;; pick apart SFmode operations. For example, there is code from e_powf.c
6094 ;; after macro expansion that looks like:
6099 ;; } ieee_float_shape_type;
6105 ;; ieee_float_shape_type gf_u;
6106 ;; gf_u.value = (t1);
6107 ;; (is) = gf_u.word;
6111 ;; ieee_float_shape_type sf_u;
6112 ;; sf_u.word = (is &
0xfffff000);
6113 ;; (t1) = sf_u.value;
6117 ;; This would result in two direct move operations (convert to memory format,
6118 ;; direct move to GPR, do the AND operation, direct move to VSX, convert to
6119 ;; scalar format). With this peephole, we eliminate the direct move to the
6120 ;; GPR, and instead move the integer mask value to the vector register after a
6121 ;; shift and do the VSX logical operation.
6123 ;; The insns for dealing with SFmode in GPR registers looks like:
6124 ;; (set (reg:V4SF reg2) (unspec:V4SF [(reg:SF reg1)] UNSPEC_VSX_CVDPSPN))
6126 ;; (set (reg:DI reg3) (unspec:DI [(reg:V4SF reg2)] UNSPEC_P8V_RELOAD_FROM_VSX))
6128 ;; (set (reg:DI reg4) (and:DI (reg:DI reg3) (reg:DI reg3)))
6130 ;; (set (reg:DI reg5) (ashift:DI (reg:DI reg4) (const_int
32)))
6132 ;; (set (reg:SF reg6) (unspec:SF [(reg:DI reg5)] UNSPEC_P8V_MTVSRD))
6134 ;; (set (reg:SF reg6) (unspec:SF [(reg:SF reg6)] UNSPEC_VSX_CVSPDPN))
6137 [(match_scratch:DI SFBOOL_TMP_GPR "r")
6138 (match_scratch:V4SF SFBOOL_TMP_VSX "wa")
6140 ;; MFVSRWZ (aka zero_extend)
6141 (set (match_operand:DI SFBOOL_MFVSR_D "int_reg_operand")
6143 (match_operand:SI SFBOOL_MFVSR_A "vsx_register_operand")))
6145 ;; AND/IOR/XOR operation on int
6146 (set (match_operand:SI SFBOOL_BOOL_D "int_reg_operand")
6147 (and_ior_xor:SI (match_operand:SI SFBOOL_BOOL_A1 "int_reg_operand")
6148 (match_operand:SI SFBOOL_BOOL_A2 "reg_or_cint_operand")))
6151 (set (match_operand:DI SFBOOL_SHL_D "int_reg_operand")
6152 (ashift:DI (match_operand:DI SFBOOL_SHL_A "int_reg_operand")
6156 (set (match_operand:SF SFBOOL_MTVSR_D "vsx_register_operand")
6157 (unspec:SF [(match_dup SFBOOL_SHL_D)] UNSPEC_P8V_MTVSRD))]
6159 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE
6160 /* The REG_P (xxx) tests prevents SUBREG's, which allows us to use REGNO
6161 to compare registers, when the mode is different. */
6162 && REG_P (operands[SFBOOL_MFVSR_D]) && REG_P (operands[SFBOOL_BOOL_D])
6163 && REG_P (operands[SFBOOL_BOOL_A1]) && REG_P (operands[SFBOOL_SHL_D])
6164 && REG_P (operands[SFBOOL_SHL_A]) && REG_P (operands[SFBOOL_MTVSR_D])
6165 && (REG_P (operands[SFBOOL_BOOL_A2])
6166 || CONST_INT_P (operands[SFBOOL_BOOL_A2]))
6167 && (REGNO (operands[SFBOOL_BOOL_D]) == REGNO (operands[SFBOOL_MFVSR_D])
6168 || peep2_reg_dead_p (
2, operands[SFBOOL_MFVSR_D]))
6169 && (REGNO (operands[SFBOOL_MFVSR_D]) == REGNO (operands[SFBOOL_BOOL_A1])
6170 || (REG_P (operands[SFBOOL_BOOL_A2])
6171 && REGNO (operands[SFBOOL_MFVSR_D])
6172 == REGNO (operands[SFBOOL_BOOL_A2])))
6173 && REGNO (operands[SFBOOL_BOOL_D]) == REGNO (operands[SFBOOL_SHL_A])
6174 && (REGNO (operands[SFBOOL_SHL_D]) == REGNO (operands[SFBOOL_BOOL_D])
6175 || peep2_reg_dead_p (
3, operands[SFBOOL_BOOL_D]))
6176 && peep2_reg_dead_p (
4, operands[SFBOOL_SHL_D])"
6177 [(set (match_dup SFBOOL_TMP_GPR)
6178 (ashift:DI (match_dup SFBOOL_BOOL_A_DI)
6181 (set (match_dup SFBOOL_TMP_VSX_DI)
6182 (match_dup SFBOOL_TMP_GPR))
6184 (set (match_dup SFBOOL_MTVSR_D_V4SF)
6185 (and_ior_xor:V4SF (match_dup SFBOOL_MFVSR_A_V4SF)
6186 (match_dup SFBOOL_TMP_VSX)))]
6188 rtx bool_a1 = operands[SFBOOL_BOOL_A1];
6189 rtx bool_a2 = operands[SFBOOL_BOOL_A2];
6190 int regno_mfvsr_d = REGNO (operands[SFBOOL_MFVSR_D]);
6191 int regno_mfvsr_a = REGNO (operands[SFBOOL_MFVSR_A]);
6192 int regno_tmp_vsx = REGNO (operands[SFBOOL_TMP_VSX]);
6193 int regno_mtvsr_d = REGNO (operands[SFBOOL_MTVSR_D]);
6195 if (CONST_INT_P (bool_a2))
6197 rtx tmp_gpr = operands[SFBOOL_TMP_GPR];
6198 emit_move_insn (tmp_gpr, bool_a2);
6199 operands[SFBOOL_BOOL_A_DI] = tmp_gpr;
6203 int regno_bool_a1 = REGNO (bool_a1);
6204 int regno_bool_a2 = REGNO (bool_a2);
6205 int regno_bool_a = (regno_mfvsr_d == regno_bool_a1
6206 ? regno_bool_a2 : regno_bool_a1);
6207 operands[SFBOOL_BOOL_A_DI] = gen_rtx_REG (DImode, regno_bool_a);
6210 operands[SFBOOL_MFVSR_A_V4SF] = gen_rtx_REG (V4SFmode, regno_mfvsr_a);
6211 operands[SFBOOL_TMP_VSX_DI] = gen_rtx_REG (DImode, regno_tmp_vsx);
6212 operands[SFBOOL_MTVSR_D_V4SF] = gen_rtx_REG (V4SFmode, regno_mtvsr_d);
6215 ;; Support signed/unsigned long long to float conversion vectorization.
6216 ;; Note that any_float (pc) here is just for code attribute <su>.
6217 (define_expand "vec_pack<su>_float_v2di"
6218 [(match_operand:V4SF
0 "vfloat_operand")
6219 (match_operand:V2DI
1 "vint_operand")
6220 (match_operand:V2DI
2 "vint_operand")
6224 rtx r1 = gen_reg_rtx (V4SFmode);
6225 rtx r2 = gen_reg_rtx (V4SFmode);
6226 emit_insn (gen_vsx_xvcv<su>xdsp (r1, operands[
1]));
6227 emit_insn (gen_vsx_xvcv<su>xdsp (r2, operands[
2]));
6228 rs6000_expand_extract_even (operands[
0], r1, r2);
6232 ;; Support float to signed/unsigned long long conversion vectorization.
6233 ;; Note that any_fix (pc) here is just for code attribute <su>.
6234 (define_expand "vec_unpack_<su>fix_trunc_hi_v4sf"
6235 [(match_operand:V2DI
0 "vint_operand")
6236 (match_operand:V4SF
1 "vfloat_operand")
6240 rtx reg = gen_reg_rtx (V4SFmode);
6241 rs6000_expand_interleave (reg, operands[
1], operands[
1], BYTES_BIG_ENDIAN);
6242 emit_insn (gen_vsx_xvcvsp<su>xds (operands[
0], reg));
6246 ;; Note that any_fix (pc) here is just for code attribute <su>.
6247 (define_expand "vec_unpack_<su>fix_trunc_lo_v4sf"
6248 [(match_operand:V2DI
0 "vint_operand")
6249 (match_operand:V4SF
1 "vfloat_operand")
6253 rtx reg = gen_reg_rtx (V4SFmode);
6254 rs6000_expand_interleave (reg, operands[
1], operands[
1], !BYTES_BIG_ENDIAN);
6255 emit_insn (gen_vsx_xvcvsp<su>xds (operands[
0], reg));
6259 (define_insn "vsx_<xvcvbf16>"
6260 [(set (match_operand:V16QI
0 "vsx_register_operand" "=wa")
6261 (unspec:V16QI [(match_operand:V16QI
1 "vsx_register_operand" "wa")]
6264 "<xvcvbf16> %x0,%x1"
6265 [(set_attr "type" "vecfloat")])
6267 (define_insn "vec_mtvsrbmi"
6268 [(set (match_operand:V16QI
0 "altivec_register_operand" "=v")
6269 (unspec:V16QI [(match_operand:QI
1 "u6bit_cint_operand" "n")]
6275 (define_insn "vec_mtvsr_<mode>"
6276 [(set (match_operand:VSX_MM
0 "altivec_register_operand" "=v")
6277 (unspec:VSX_MM [(match_operand:DI
1 "gpc_reg_operand" "r")]
6281 [(set_attr "type" "vecsimple")])
6283 (define_insn "vec_cntmb_<mode>"
6284 [(set (match_operand:DI
0 "gpc_reg_operand" "=r")
6285 (unspec:DI [(match_operand:VSX_MM4
1 "altivec_register_operand" "v")
6286 (match_operand:QI
2 "const_0_to_1_operand" "n")]
6289 "vcntmb<wd> %
0,%
1,%
2"
6290 [(set_attr "type" "vecsimple")])
6292 (define_insn "vec_extract_<mode>"
6293 [(set (match_operand:SI
0 "register_operand" "=r")
6294 (unspec:SI [(match_operand:VSX_MM
1 "altivec_register_operand" "v")]
6297 "vextract<wd>m %
0,%
1"
6298 [(set_attr "type" "vecsimple")])
6300 (define_insn "vec_expand_<mode>"
6301 [(set (match_operand:VSX_MM
0 "vsx_register_operand" "=v")
6302 (unspec:VSX_MM [(match_operand:VSX_MM
1 "vsx_register_operand" "v")]
6305 "vexpand<wd>m %
0,%
1"
6306 [(set_attr "type" "vecsimple")])
6308 (define_insn "dives_<mode>"
6309 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6310 (unspec:VIlong [(match_operand:VIlong
1 "vsx_register_operand" "v")
6311 (match_operand:VIlong
2 "vsx_register_operand" "v")]
6314 "vdives<wd> %
0,%
1,%
2"
6315 [(set_attr "type" "vecdiv")
6316 (set_attr "size" "<bits>")])
6318 (define_insn "diveu_<mode>"
6319 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6320 (unspec:VIlong [(match_operand:VIlong
1 "vsx_register_operand" "v")
6321 (match_operand:VIlong
2 "vsx_register_operand" "v")]
6324 "vdiveu<wd> %
0,%
1,%
2"
6325 [(set_attr "type" "vecdiv")
6326 (set_attr "size" "<bits>")])
6328 (define_insn "div<mode>
3"
6329 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6330 (div:VIlong (match_operand:VIlong
1 "vsx_register_operand" "v")
6331 (match_operand:VIlong
2 "vsx_register_operand" "v")))]
6333 "vdivs<wd> %
0,%
1,%
2"
6334 [(set_attr "type" "vecdiv")
6335 (set_attr "size" "<bits>")])
6337 (define_insn "udiv<mode>
3"
6338 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6339 (udiv:VIlong (match_operand:VIlong
1 "vsx_register_operand" "v")
6340 (match_operand:VIlong
2 "vsx_register_operand" "v")))]
6342 "vdivu<wd> %
0,%
1,%
2"
6343 [(set_attr "type" "vecdiv")
6344 (set_attr "size" "<bits>")])
6346 (define_insn "mod<mode>
3"
6347 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6348 (mod:VIlong (match_operand:VIlong
1 "vsx_register_operand" "v")
6349 (match_operand:VIlong
2 "vsx_register_operand" "v")))]
6351 "vmods<wd> %
0,%
1,%
2"
6352 [(set_attr "type" "vecdiv")
6353 (set_attr "size" "<bits>")])
6355 (define_insn "umod<mode>
3"
6356 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6357 (umod:VIlong (match_operand:VIlong
1 "vsx_register_operand" "v")
6358 (match_operand:VIlong
2 "vsx_register_operand" "v")))]
6360 "vmodu<wd> %
0,%
1,%
2"
6361 [(set_attr "type" "vecdiv")
6362 (set_attr "size" "<bits>")])
6364 (define_insn "smul<mode>
3_highpart"
6365 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6366 (mult:VIlong (ashiftrt
6367 (match_operand:VIlong
1 "vsx_register_operand" "v")
6370 (match_operand:VIlong
2 "vsx_register_operand" "v")
6373 "vmulhs<wd> %
0,%
1,%
2"
6374 [(set_attr "type" "veccomplex")])
6376 (define_insn "umul<mode>
3_highpart"
6377 [(set (match_operand:VIlong
0 "vsx_register_operand" "=v")
6378 (us_mult:VIlong (ashiftrt
6379 (match_operand:VIlong
1 "vsx_register_operand" "v")
6382 (match_operand:VIlong
2 "vsx_register_operand" "v")
6385 "vmulhu<wd> %
0,%
1,%
2"
6386 [(set_attr "type" "veccomplex")])
6388 ;; Vector multiply low double word
6389 (define_insn "mulv2di3"
6390 [(set (match_operand:V2DI
0 "vsx_register_operand" "=v")
6391 (mult:V2DI (match_operand:V2DI
1 "vsx_register_operand" "v")
6392 (match_operand:V2DI
2 "vsx_register_operand" "v")))]
6395 [(set_attr "type" "veccomplex")])
6398 ;; XXSPLTIW built-in function support
6399 (define_insn "xxspltiw_v4si"
6400 [(set (match_operand:V4SI
0 "register_operand" "=wa")
6401 (unspec:V4SI [(match_operand:SI
1 "s32bit_cint_operand" "n")]
6405 [(set_attr "type" "vecperm")
6406 (set_attr "prefixed" "yes")])
6408 (define_expand "xxspltiw_v4sf"
6409 [(set (match_operand:V4SF
0 "register_operand" "=wa")
6410 (unspec:V4SF [(match_operand:SF
1 "const_double_operand" "n")]
6414 long value = rs6000_const_f32_to_i32 (operands[
1]);
6415 emit_insn (gen_xxspltiw_v4sf_inst (operands[
0], GEN_INT (value)));
6419 (define_insn "xxspltiw_v4sf_inst"
6420 [(set (match_operand:V4SF
0 "register_operand" "=wa")
6421 (unspec:V4SF [(match_operand:SI
1 "c32bit_cint_operand" "n")]
6425 [(set_attr "type" "vecperm")
6426 (set_attr "prefixed" "yes")])
6428 ;; XXSPLTIDP built-in function support
6429 (define_expand "xxspltidp_v2df"
6430 [(set (match_operand:V2DF
0 "register_operand" )
6431 (unspec:V2DF [(match_operand:SF
1 "const_double_operand")]
6435 long value = rs6000_const_f32_to_i32 (operands[
1]);
6436 rs6000_emit_xxspltidp_v2df (operands[
0], value);
6440 (define_insn "xxspltidp_v2df_inst"
6441 [(set (match_operand:V2DF
0 "register_operand" "=wa")
6442 (unspec:V2DF [(match_operand:SI
1 "c32bit_cint_operand" "n")]
6446 [(set_attr "type" "vecperm")
6447 (set_attr "prefixed" "yes")])
6449 ;; XXSPLTI32DX built-in function support
6450 (define_expand "xxsplti32dx_v4si"
6451 [(set (match_operand:V4SI
0 "register_operand" "=wa")
6452 (unspec:V4SI [(match_operand:V4SI
1 "register_operand" "
0")
6453 (match_operand:QI
2 "u1bit_cint_operand" "n")
6454 (match_operand:SI
3 "s32bit_cint_operand" "n")]
6455 UNSPEC_XXSPLTI32DX))]
6458 int index = INTVAL (operands[
2]);
6460 if (!BYTES_BIG_ENDIAN)
6463 emit_insn (gen_xxsplti32dx_v4si_inst (operands[
0], operands[
1],
6464 GEN_INT (index), operands[
3]));
6467 [(set_attr "type" "vecperm")])
6469 (define_insn "xxsplti32dx_v4si_inst"
6470 [(set (match_operand:V4SI
0 "register_operand" "=wa")
6471 (unspec:V4SI [(match_operand:V4SI
1 "register_operand" "
0")
6472 (match_operand:QI
2 "u1bit_cint_operand" "n")
6473 (match_operand:SI
3 "s32bit_cint_operand" "n")]
6474 UNSPEC_XXSPLTI32DX))]
6476 "xxsplti32dx %x0,%
2,%
3"
6477 [(set_attr "type" "vecperm")
6478 (set_attr "prefixed" "yes")])
6480 (define_expand "xxsplti32dx_v4sf"
6481 [(set (match_operand:V4SF
0 "register_operand" "=wa")
6482 (unspec:V4SF [(match_operand:V4SF
1 "register_operand" "
0")
6483 (match_operand:QI
2 "u1bit_cint_operand" "n")
6484 (match_operand:SF
3 "const_double_operand" "n")]
6485 UNSPEC_XXSPLTI32DX))]
6488 int index = INTVAL (operands[
2]);
6489 long value = rs6000_const_f32_to_i32 (operands[
3]);
6490 if (!BYTES_BIG_ENDIAN)
6493 emit_insn (gen_xxsplti32dx_v4sf_inst (operands[
0], operands[
1],
6494 GEN_INT (index), GEN_INT (value)));
6498 (define_insn "xxsplti32dx_v4sf_inst"
6499 [(set (match_operand:V4SF
0 "register_operand" "=wa")
6500 (unspec:V4SF [(match_operand:V4SF
1 "register_operand" "
0")
6501 (match_operand:QI
2 "u1bit_cint_operand" "n")
6502 (match_operand:SI
3 "s32bit_cint_operand" "n")]
6503 UNSPEC_XXSPLTI32DX))]
6505 "xxsplti32dx %x0,%
2,%
3"
6506 [(set_attr "type" "vecperm")
6507 (set_attr "prefixed" "yes")])
6509 ;; XXBLEND built-in function support
6510 (define_insn "xxblend_<mode>"
6511 [(set (match_operand:VM3
0 "register_operand" "=wa")
6512 (unspec:VM3 [(match_operand:VM3
1 "register_operand" "wa")
6513 (match_operand:VM3
2 "register_operand" "wa")
6514 (match_operand:VM3
3 "register_operand" "wa")]
6517 "xxblendv<VM3_char> %x0,%x1,%x2,%x3"
6518 [(set_attr "type" "vecperm")
6519 (set_attr "prefixed" "yes")])
6521 ;; XXPERMX built-in function support
6522 (define_expand "xxpermx"
6523 [(set (match_operand:V2DI
0 "register_operand" "+wa")
6524 (unspec:V2DI [(match_operand:V2DI
1 "register_operand" "wa")
6525 (match_operand:V2DI
2 "register_operand" "wa")
6526 (match_operand:V16QI
3 "register_operand" "wa")
6527 (match_operand:QI
4 "u8bit_cint_operand" "n")]
6531 if (BYTES_BIG_ENDIAN)
6532 emit_insn (gen_xxpermx_inst (operands[
0], operands[
1],
6533 operands[
2], operands[
3],
6537 /* Reverse value of byte element indexes by XORing with
0xFF.
6538 Reverse the
32-byte section identifier match by subracting bits [
0:
2]
6539 of elemet from
7. */
6540 int value = INTVAL (operands[
4]);
6541 rtx vreg = gen_reg_rtx (V16QImode);
6543 emit_insn (gen_xxspltib_v16qi (vreg, GEN_INT (-
1)));
6544 emit_insn (gen_xorv16qi3 (operands[
3], operands[
3], vreg));
6546 emit_insn (gen_xxpermx_inst (operands[
0], operands[
2],
6547 operands[
1], operands[
3],
6553 [(set_attr "type" "vecperm")])
6555 (define_insn "xxpermx_inst"
6556 [(set (match_operand:V2DI
0 "register_operand" "+v")
6557 (unspec:V2DI [(match_operand:V2DI
1 "register_operand" "v")
6558 (match_operand:V2DI
2 "register_operand" "v")
6559 (match_operand:V16QI
3 "register_operand" "v")
6560 (match_operand:QI
4 "u3bit_cint_operand" "n")]
6563 "xxpermx %x0,%x1,%x2,%x3,%
4"
6564 [(set_attr "type" "vecperm")
6565 (set_attr "prefixed" "yes")])
6567 ;; XXEVAL built-in function support
6568 (define_insn "xxeval"
6569 [(set (match_operand:V2DI
0 "register_operand" "=wa")
6570 (unspec:V2DI [(match_operand:V2DI
1 "register_operand" "wa")
6571 (match_operand:V2DI
2 "register_operand" "wa")
6572 (match_operand:V2DI
3 "register_operand" "wa")
6573 (match_operand:QI
4 "u8bit_cint_operand" "n")]
6576 "xxeval %
0,%
1,%
2,%
3,%
4"
6577 [(set_attr "type" "vecperm")
6578 (set_attr "prefixed" "yes")])
6580 ;; Construct V1TI by vsx_concat_v2di
6582 [(set (match_operand:V1TI
0 "vsx_register_operand")
6584 (match_operand:TI
1 "int_reg_operand")
0 ))]
6585 "TARGET_P9_VECTOR && !reload_completed"
6588 rtx tmp1 = simplify_gen_subreg (DImode, operands[
1], TImode,
0);
6589 rtx tmp2 = simplify_gen_subreg (DImode, operands[
1], TImode,
8);
6590 rtx tmp3 = gen_reg_rtx (V2DImode);
6591 emit_insn (gen_vsx_concat_v2di (tmp3, tmp1, tmp2));
6592 rtx tmp4 = simplify_gen_subreg (V1TImode, tmp3, V2DImode,
0);
6593 emit_move_insn (operands[
0], tmp4);
6598 (define_insn "vmsumcud"
6599 [(set (match_operand:V1TI
0 "register_operand" "+v")
6600 (unspec:V1TI [(match_operand:V2DI
1 "register_operand" "v")
6601 (match_operand:V2DI
2 "register_operand" "v")
6602 (match_operand:V1TI
3 "register_operand" "v")]
6605 "vmsumcud %
0,%
1,%
2,%
3"
6606 [(set_attr "type" "veccomplex")]