2 ;; Copyright (C) 2009-2018 Free Software Foundation, Inc.
3 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 ;; License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Iterator for comparison types
22 (define_code_iterator CMP_TEST [eq lt gt unordered])
24 ;; Iterator for both scalar and vector floating point types supported by VSX
25 (define_mode_iterator VSX_B [DF V4SF V2DF])
27 ;; Iterator for the 2 64-bit vector types
28 (define_mode_iterator VSX_D [V2DF V2DI])
30 ;; Mode iterator to handle swapping words on little endian for the 128-bit
31 ;; types that goes in a single vector register.
32 (define_mode_iterator VSX_LE_128 [(KF "FLOAT128_VECTOR_P (KFmode)")
33 (TF "FLOAT128_VECTOR_P (TFmode)")
34 (TI "TARGET_VSX_TIMODE")
37 ;; Iterator for the 2 32-bit vector types
38 (define_mode_iterator VSX_W [V4SF V4SI])
40 ;; Iterator for the DF types
41 (define_mode_iterator VSX_DF [V2DF DF])
43 ;; Iterator for vector floating point types supported by VSX
44 (define_mode_iterator VSX_F [V4SF V2DF])
46 ;; Iterator for logical types supported by VSX
47 (define_mode_iterator VSX_L [V16QI
55 (KF "FLOAT128_VECTOR_P (KFmode)")
56 (TF "FLOAT128_VECTOR_P (TFmode)")])
58 ;; Iterator for memory moves.
59 (define_mode_iterator VSX_M [V16QI
66 (KF "FLOAT128_VECTOR_P (KFmode)")
67 (TF "FLOAT128_VECTOR_P (TFmode)")
68 (TI "TARGET_VSX_TIMODE")])
70 ;; Map into the appropriate load/store name based on the type
71 (define_mode_attr VSm [(V16QI "vw4")
83 ;; Map into the appropriate suffix based on the type
84 (define_mode_attr VSs [(V16QI "sp")
97 ;; Map the register class used
98 (define_mode_attr VSr [(V16QI "v")
112 ;; Map the register class used for float<->int conversions (floating point side)
113 ;; VSr2 is the preferred register class, VSr3 is any register class that will
115 (define_mode_attr VSr2 [(V2DF "wd")
123 (define_mode_attr VSr3 [(V2DF "wa")
131 ;; Map the register class for sp<->dp float conversions, destination
132 (define_mode_attr VSr4 [(SF "ws")
137 ;; Map the register class for sp<->dp float conversions, source
138 (define_mode_attr VSr5 [(SF "ws")
143 ;; The VSX register class that a type can occupy, even if it is not the
144 ;; preferred register class (VSr is the preferred register class that will get
146 (define_mode_attr VSa [(V16QI "wa")
160 ;; Same size integer type for floating point data
161 (define_mode_attr VSi [(V4SF "v4si")
165 (define_mode_attr VSI [(V4SF "V4SI")
169 ;; Word size for same size conversion
170 (define_mode_attr VSc [(V4SF "w")
174 ;; Map into either s or v, depending on whether this is a scalar or vector
176 (define_mode_attr VSv [(V16QI "v")
186 ;; Appropriate type for add ops (and other simple FP ops)
187 (define_mode_attr VStype_simple [(V2DF "vecdouble")
191 (define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
195 ;; Appropriate type for multiply ops
196 (define_mode_attr VStype_mul [(V2DF "vecdouble")
200 (define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
204 ;; Appropriate type for divide ops.
205 (define_mode_attr VStype_div [(V2DF "vecdiv")
209 (define_mode_attr VSfptype_div [(V2DF "fp_div_d")
213 ;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
215 (define_mode_attr VStype_sqrt [(V2DF "dsqrt")
219 (define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
223 ;; Iterator and modes for sp<->dp conversions
224 ;; Because scalar SF values are represented internally as double, use the
225 ;; V4SF type to represent this than SF.
226 (define_mode_iterator VSX_SPDP [DF V4SF V2DF])
228 (define_mode_attr VS_spdp_res [(DF "V4SF")
232 (define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
236 (define_mode_attr VS_spdp_type [(DF "fp")
240 ;; Map the scalar mode for a vector type
241 (define_mode_attr VS_scalar [(V1TI "TI")
249 ;; Map to a double-sized vector mode
250 (define_mode_attr VS_double [(V4SI "V8SI")
256 ;; Map register class for 64-bit element in 128-bit vector for direct moves
258 (define_mode_attr VS_64dm [(V2DF "wk")
261 ;; Map register class for 64-bit element in 128-bit vector for normal register
263 (define_mode_attr VS_64reg [(V2DF "ws")
266 ;; Iterators for loading constants with xxspltib
267 (define_mode_iterator VSINT_84 [V4SI V2DI DI SI])
268 (define_mode_iterator VSINT_842 [V8HI V4SI V2DI])
270 ;; Iterator for ISA 3.0 vector extract/insert of small integer vectors.
271 ;; VSX_EXTRACT_I2 doesn't include V4SImode because SI extracts can be
272 ;; done on ISA 2.07 and not just ISA 3.0.
273 (define_mode_iterator VSX_EXTRACT_I [V16QI V8HI V4SI])
274 (define_mode_iterator VSX_EXTRACT_I2 [V16QI V8HI])
276 (define_mode_attr VSX_EXTRACT_WIDTH [(V16QI "b")
280 ;; Mode attribute to give the correct predicate for ISA 3.0 vector extract and
281 ;; insert to validate the operand number.
282 (define_mode_attr VSX_EXTRACT_PREDICATE [(V16QI "const_0_to_15_operand")
283 (V8HI "const_0_to_7_operand")
284 (V4SI "const_0_to_3_operand")])
286 ;; Mode attribute to give the constraint for vector extract and insert
288 (define_mode_attr VSX_EX [(V16QI "v")
292 ;; Mode iterator for binary floating types other than double to
293 ;; optimize convert to that floating point type from an extract
294 ;; of an integer type
295 (define_mode_iterator VSX_EXTRACT_FL [SF
296 (IF "FLOAT128_2REG_P (IFmode)")
297 (KF "TARGET_FLOAT128_HW")
298 (TF "FLOAT128_2REG_P (TFmode)
299 || (FLOAT128_IEEE_P (TFmode)
300 && TARGET_FLOAT128_HW)")])
302 ;; Mode iterator for binary floating types that have a direct conversion
303 ;; from 64-bit integer to floating point
304 (define_mode_iterator FL_CONV [SF
306 (KF "TARGET_FLOAT128_HW")
307 (TF "TARGET_FLOAT128_HW
308 && FLOAT128_IEEE_P (TFmode)")])
310 ;; Iterator for the 2 short vector types to do a splat from an integer
311 (define_mode_iterator VSX_SPLAT_I [V16QI V8HI])
313 ;; Mode attribute to give the count for the splat instruction to splat
314 ;; the value in the 64-bit integer slot
315 (define_mode_attr VSX_SPLAT_COUNT [(V16QI "7") (V8HI "3")])
317 ;; Mode attribute to give the suffix for the splat instruction
318 (define_mode_attr VSX_SPLAT_SUFFIX [(V16QI "b") (V8HI "h")])
320 ;; Constants for creating unspecs
321 (define_c_enum "unspec"
347 UNSPEC_VSX_XVCVDPSXDS
348 UNSPEC_VSX_XVCVDPUXDS
349 UNSPEC_VSX_SIGN_EXTEND
384 ;; The patterns for LE permuted loads and stores come before the general
385 ;; VSX moves so they match first.
386 (define_insn_and_split "*vsx_le_perm_load_<mode>"
387 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
388 (match_operand:VSX_D 1 "memory_operand" "Z"))]
389 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
391 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
395 (parallel [(const_int 1) (const_int 0)])))
399 (parallel [(const_int 1) (const_int 0)])))]
402 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
406 [(set_attr "type" "vecload")
407 (set_attr "length" "8")])
409 (define_insn_and_split "*vsx_le_perm_load_<mode>"
410 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
411 (match_operand:VSX_W 1 "memory_operand" "Z"))]
412 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
414 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
418 (parallel [(const_int 2) (const_int 3)
419 (const_int 0) (const_int 1)])))
423 (parallel [(const_int 2) (const_int 3)
424 (const_int 0) (const_int 1)])))]
427 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
431 [(set_attr "type" "vecload")
432 (set_attr "length" "8")])
434 (define_insn_and_split "*vsx_le_perm_load_v8hi"
435 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
436 (match_operand:V8HI 1 "memory_operand" "Z"))]
437 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
439 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
443 (parallel [(const_int 4) (const_int 5)
444 (const_int 6) (const_int 7)
445 (const_int 0) (const_int 1)
446 (const_int 2) (const_int 3)])))
450 (parallel [(const_int 4) (const_int 5)
451 (const_int 6) (const_int 7)
452 (const_int 0) (const_int 1)
453 (const_int 2) (const_int 3)])))]
456 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
460 [(set_attr "type" "vecload")
461 (set_attr "length" "8")])
463 (define_insn_and_split "*vsx_le_perm_load_v16qi"
464 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
465 (match_operand:V16QI 1 "memory_operand" "Z"))]
466 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
468 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
472 (parallel [(const_int 8) (const_int 9)
473 (const_int 10) (const_int 11)
474 (const_int 12) (const_int 13)
475 (const_int 14) (const_int 15)
476 (const_int 0) (const_int 1)
477 (const_int 2) (const_int 3)
478 (const_int 4) (const_int 5)
479 (const_int 6) (const_int 7)])))
483 (parallel [(const_int 8) (const_int 9)
484 (const_int 10) (const_int 11)
485 (const_int 12) (const_int 13)
486 (const_int 14) (const_int 15)
487 (const_int 0) (const_int 1)
488 (const_int 2) (const_int 3)
489 (const_int 4) (const_int 5)
490 (const_int 6) (const_int 7)])))]
493 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
497 [(set_attr "type" "vecload")
498 (set_attr "length" "8")])
500 (define_insn "*vsx_le_perm_store_<mode>"
501 [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
502 (match_operand:VSX_D 1 "vsx_register_operand" "+<VSa>"))]
503 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
505 [(set_attr "type" "vecstore")
506 (set_attr "length" "12")])
509 [(set (match_operand:VSX_D 0 "memory_operand" "")
510 (match_operand:VSX_D 1 "vsx_register_operand" ""))]
511 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
515 (parallel [(const_int 1) (const_int 0)])))
519 (parallel [(const_int 1) (const_int 0)])))]
521 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
525 ;; The post-reload split requires that we re-permute the source
526 ;; register in case it is still live.
528 [(set (match_operand:VSX_D 0 "memory_operand" "")
529 (match_operand:VSX_D 1 "vsx_register_operand" ""))]
530 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
534 (parallel [(const_int 1) (const_int 0)])))
538 (parallel [(const_int 1) (const_int 0)])))
542 (parallel [(const_int 1) (const_int 0)])))]
545 (define_insn "*vsx_le_perm_store_<mode>"
546 [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
547 (match_operand:VSX_W 1 "vsx_register_operand" "+<VSa>"))]
548 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
550 [(set_attr "type" "vecstore")
551 (set_attr "length" "12")])
554 [(set (match_operand:VSX_W 0 "memory_operand" "")
555 (match_operand:VSX_W 1 "vsx_register_operand" ""))]
556 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
560 (parallel [(const_int 2) (const_int 3)
561 (const_int 0) (const_int 1)])))
565 (parallel [(const_int 2) (const_int 3)
566 (const_int 0) (const_int 1)])))]
568 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
572 ;; The post-reload split requires that we re-permute the source
573 ;; register in case it is still live.
575 [(set (match_operand:VSX_W 0 "memory_operand" "")
576 (match_operand:VSX_W 1 "vsx_register_operand" ""))]
577 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
581 (parallel [(const_int 2) (const_int 3)
582 (const_int 0) (const_int 1)])))
586 (parallel [(const_int 2) (const_int 3)
587 (const_int 0) (const_int 1)])))
591 (parallel [(const_int 2) (const_int 3)
592 (const_int 0) (const_int 1)])))]
595 (define_insn "*vsx_le_perm_store_v8hi"
596 [(set (match_operand:V8HI 0 "memory_operand" "=Z")
597 (match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
598 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
600 [(set_attr "type" "vecstore")
601 (set_attr "length" "12")])
604 [(set (match_operand:V8HI 0 "memory_operand" "")
605 (match_operand:V8HI 1 "vsx_register_operand" ""))]
606 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
610 (parallel [(const_int 4) (const_int 5)
611 (const_int 6) (const_int 7)
612 (const_int 0) (const_int 1)
613 (const_int 2) (const_int 3)])))
617 (parallel [(const_int 4) (const_int 5)
618 (const_int 6) (const_int 7)
619 (const_int 0) (const_int 1)
620 (const_int 2) (const_int 3)])))]
622 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
626 ;; The post-reload split requires that we re-permute the source
627 ;; register in case it is still live.
629 [(set (match_operand:V8HI 0 "memory_operand" "")
630 (match_operand:V8HI 1 "vsx_register_operand" ""))]
631 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
635 (parallel [(const_int 4) (const_int 5)
636 (const_int 6) (const_int 7)
637 (const_int 0) (const_int 1)
638 (const_int 2) (const_int 3)])))
642 (parallel [(const_int 4) (const_int 5)
643 (const_int 6) (const_int 7)
644 (const_int 0) (const_int 1)
645 (const_int 2) (const_int 3)])))
649 (parallel [(const_int 4) (const_int 5)
650 (const_int 6) (const_int 7)
651 (const_int 0) (const_int 1)
652 (const_int 2) (const_int 3)])))]
655 (define_insn "*vsx_le_perm_store_v16qi"
656 [(set (match_operand:V16QI 0 "memory_operand" "=Z")
657 (match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
658 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
660 [(set_attr "type" "vecstore")
661 (set_attr "length" "12")])
664 [(set (match_operand:V16QI 0 "memory_operand" "")
665 (match_operand:V16QI 1 "vsx_register_operand" ""))]
666 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
670 (parallel [(const_int 8) (const_int 9)
671 (const_int 10) (const_int 11)
672 (const_int 12) (const_int 13)
673 (const_int 14) (const_int 15)
674 (const_int 0) (const_int 1)
675 (const_int 2) (const_int 3)
676 (const_int 4) (const_int 5)
677 (const_int 6) (const_int 7)])))
681 (parallel [(const_int 8) (const_int 9)
682 (const_int 10) (const_int 11)
683 (const_int 12) (const_int 13)
684 (const_int 14) (const_int 15)
685 (const_int 0) (const_int 1)
686 (const_int 2) (const_int 3)
687 (const_int 4) (const_int 5)
688 (const_int 6) (const_int 7)])))]
690 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
694 ;; The post-reload split requires that we re-permute the source
695 ;; register in case it is still live.
697 [(set (match_operand:V16QI 0 "memory_operand" "")
698 (match_operand:V16QI 1 "vsx_register_operand" ""))]
699 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
703 (parallel [(const_int 8) (const_int 9)
704 (const_int 10) (const_int 11)
705 (const_int 12) (const_int 13)
706 (const_int 14) (const_int 15)
707 (const_int 0) (const_int 1)
708 (const_int 2) (const_int 3)
709 (const_int 4) (const_int 5)
710 (const_int 6) (const_int 7)])))
714 (parallel [(const_int 8) (const_int 9)
715 (const_int 10) (const_int 11)
716 (const_int 12) (const_int 13)
717 (const_int 14) (const_int 15)
718 (const_int 0) (const_int 1)
719 (const_int 2) (const_int 3)
720 (const_int 4) (const_int 5)
721 (const_int 6) (const_int 7)])))
725 (parallel [(const_int 8) (const_int 9)
726 (const_int 10) (const_int 11)
727 (const_int 12) (const_int 13)
728 (const_int 14) (const_int 15)
729 (const_int 0) (const_int 1)
730 (const_int 2) (const_int 3)
731 (const_int 4) (const_int 5)
732 (const_int 6) (const_int 7)])))]
735 ;; Little endian word swapping for 128-bit types that are either scalars or the
736 ;; special V1TI container class, which it is not appropriate to use vec_select
738 (define_insn "*vsx_le_permute_<mode>"
739 [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
741 (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
743 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
745 xxpermdi %x0,%x1,%x1,2
748 [(set_attr "length" "4")
749 (set_attr "type" "vecperm,vecload,vecstore")])
751 (define_insn_and_split "*vsx_le_undo_permute_<mode>"
752 [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
755 (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
758 "!BYTES_BIG_ENDIAN && TARGET_VSX"
763 [(set (match_dup 0) (match_dup 1))]
765 if (reload_completed && REGNO (operands[0]) == REGNO (operands[1]))
767 emit_note (NOTE_INSN_DELETED);
771 [(set_attr "length" "0,4")
772 (set_attr "type" "veclogical")])
774 (define_insn_and_split "*vsx_le_perm_load_<mode>"
775 [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>")
776 (match_operand:VSX_LE_128 1 "memory_operand" "Z"))]
777 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
779 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
781 (rotate:VSX_LE_128 (match_dup 1)
784 (rotate:VSX_LE_128 (match_dup 2)
788 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
792 [(set_attr "type" "vecload")
793 (set_attr "length" "8")])
795 (define_insn "*vsx_le_perm_store_<mode>"
796 [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z")
797 (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>"))]
798 "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
800 [(set_attr "type" "vecstore")
801 (set_attr "length" "12")])
804 [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
805 (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
806 "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed && !TARGET_P9_VECTOR"
808 (rotate:VSX_LE_128 (match_dup 1)
811 (rotate:VSX_LE_128 (match_dup 2)
814 operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
818 ;; Peephole to catch memory to memory transfers for TImode if TImode landed in
819 ;; VSX registers on a little endian system. The vector types and IEEE 128-bit
820 ;; floating point are handled by the more generic swap elimination pass.
822 [(set (match_operand:TI 0 "vsx_register_operand" "")
823 (rotate:TI (match_operand:TI 1 "vsx_register_operand" "")
825 (set (match_operand:TI 2 "vsx_register_operand" "")
826 (rotate:TI (match_dup 0)
828 "!BYTES_BIG_ENDIAN && TARGET_VSX && TARGET_VSX_TIMODE && !TARGET_P9_VECTOR
829 && (rtx_equal_p (operands[0], operands[2])
830 || peep2_reg_dead_p (2, operands[0]))"
831 [(set (match_dup 2) (match_dup 1))])
833 ;; The post-reload split requires that we re-permute the source
834 ;; register in case it is still live.
836 [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
837 (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
838 "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed && !TARGET_P9_VECTOR"
840 (rotate:VSX_LE_128 (match_dup 1)
843 (rotate:VSX_LE_128 (match_dup 1)
846 (rotate:VSX_LE_128 (match_dup 1)
850 ;; Vector constants that can be generated with XXSPLTIB that was added in ISA
851 ;; 3.0. Both (const_vector [..]) and (vec_duplicate ...) forms are recognized.
852 (define_insn "xxspltib_v16qi"
853 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
854 (vec_duplicate:V16QI (match_operand:SI 1 "s8bit_cint_operand" "n")))]
857 operands[2] = GEN_INT (INTVAL (operands[1]) & 0xff);
858 return "xxspltib %x0,%2";
860 [(set_attr "type" "vecperm")])
862 (define_insn "xxspltib_<mode>_nosplit"
863 [(set (match_operand:VSINT_842 0 "vsx_register_operand" "=wa,wa")
864 (match_operand:VSINT_842 1 "xxspltib_constant_nosplit" "jwM,wE"))]
867 rtx op1 = operands[1];
871 if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
875 operands[2] = GEN_INT (value & 0xff);
876 return "xxspltib %x0,%2";
878 [(set_attr "type" "vecperm")])
880 (define_insn_and_split "*xxspltib_<mode>_split"
881 [(set (match_operand:VSINT_842 0 "altivec_register_operand" "=v")
882 (match_operand:VSINT_842 1 "xxspltib_constant_split" "wS"))]
890 rtx op0 = operands[0];
891 rtx op1 = operands[1];
892 rtx tmp = ((can_create_pseudo_p ())
893 ? gen_reg_rtx (V16QImode)
894 : gen_lowpart (V16QImode, op0));
896 if (!xxspltib_constant_p (op1, <MODE>mode, &num_insns, &value)
900 emit_insn (gen_xxspltib_v16qi (tmp, GEN_INT (value)));
902 if (<MODE>mode == V2DImode)
903 emit_insn (gen_vsx_sign_extend_qi_v2di (op0, tmp));
905 else if (<MODE>mode == V4SImode)
906 emit_insn (gen_vsx_sign_extend_qi_v4si (op0, tmp));
908 else if (<MODE>mode == V8HImode)
909 emit_insn (gen_altivec_vupkhsb (op0, tmp));
916 [(set_attr "type" "vecperm")
917 (set_attr "length" "8")])
920 ;; Prefer using vector registers over GPRs. Prefer using ISA 3.0's XXSPLTISB
921 ;; or Altivec VSPLITW 0/-1 over XXLXOR/XXLORC to set a register to all 0's or
922 ;; all 1's, since the machine does not have to wait for the previous
923 ;; instruction using the register being set (such as a store waiting on a slow
924 ;; instruction). But generate XXLXOR/XXLORC if it will avoid a register move.
926 ;; VSX store VSX load VSX move VSX->GPR GPR->VSX LQ (GPR)
927 ;; STQ (GPR) GPR load GPR store GPR move XXSPLTIB VSPLTISW
928 ;; VSX 0/-1 GPR 0/-1 VMX const GPR const LVX (VMX) STVX (VMX)
929 (define_insn "*vsx_mov<mode>_64bit"
930 [(set (match_operand:VSX_M 0 "nonimmediate_operand"
931 "=ZwO, <VSa>, <VSa>, r, we, ?wQ,
932 ?&r, ??r, ??Y, ??r, wo, v,
933 ?<VSa>, *r, v, ??r, wZ, v")
935 (match_operand:VSX_M 1 "input_operand"
936 "<VSa>, ZwO, <VSa>, we, r, r,
937 wQ, Y, r, r, wE, jwM,
938 ?jwM, jwM, W, W, v, wZ"))]
940 "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
941 && (register_operand (operands[0], <MODE>mode)
942 || register_operand (operands[1], <MODE>mode))"
944 return rs6000_output_move_128bit (operands);
947 "vecstore, vecload, vecsimple, mffgpr, mftgpr, load,
948 store, load, store, *, vecsimple, vecsimple,
949 vecsimple, *, *, *, vecstore, vecload")
954 4, 8, 20, 20, 4, 4")])
956 ;; VSX store VSX load VSX move GPR load GPR store GPR move
957 ;; XXSPLTIB VSPLTISW VSX 0/-1 GPR 0/-1 VMX const GPR const
958 ;; LVX (VMX) STVX (VMX)
959 (define_insn "*vsx_mov<mode>_32bit"
960 [(set (match_operand:VSX_M 0 "nonimmediate_operand"
961 "=ZwO, <VSa>, <VSa>, ??r, ??Y, ??r,
962 wo, v, ?<VSa>, *r, v, ??r,
965 (match_operand:VSX_M 1 "input_operand"
966 "<VSa>, ZwO, <VSa>, Y, r, r,
967 wE, jwM, ?jwM, jwM, W, W,
970 "!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
971 && (register_operand (operands[0], <MODE>mode)
972 || register_operand (operands[1], <MODE>mode))"
974 return rs6000_output_move_128bit (operands);
977 "vecstore, vecload, vecsimple, load, store, *,
978 vecsimple, vecsimple, vecsimple, *, *, *,
982 "4, 4, 4, 16, 16, 16,
986 ;; Explicit load/store expanders for the builtin functions
987 (define_expand "vsx_load_<mode>"
988 [(set (match_operand:VSX_M 0 "vsx_register_operand" "")
989 (match_operand:VSX_M 1 "memory_operand" ""))]
990 "VECTOR_MEM_VSX_P (<MODE>mode)"
992 /* Expand to swaps if needed, prior to swap optimization. */
993 if (!BYTES_BIG_ENDIAN && !TARGET_P9_VECTOR)
995 rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
1000 (define_expand "vsx_store_<mode>"
1001 [(set (match_operand:VSX_M 0 "memory_operand" "")
1002 (match_operand:VSX_M 1 "vsx_register_operand" ""))]
1003 "VECTOR_MEM_VSX_P (<MODE>mode)"
1005 /* Expand to swaps if needed, prior to swap optimization. */
1006 if (!BYTES_BIG_ENDIAN && !TARGET_P9_VECTOR)
1008 rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
1013 ;; Explicit load/store expanders for the builtin functions for lxvd2x, etc.,
1014 ;; when you really want their element-reversing behavior.
1015 (define_insn "vsx_ld_elemrev_v2di"
1016 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1018 (match_operand:V2DI 1 "memory_operand" "Z")
1019 (parallel [(const_int 1) (const_int 0)])))]
1020 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1022 [(set_attr "type" "vecload")])
1024 (define_insn "vsx_ld_elemrev_v2df"
1025 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1027 (match_operand:V2DF 1 "memory_operand" "Z")
1028 (parallel [(const_int 1) (const_int 0)])))]
1029 "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1031 [(set_attr "type" "vecload")])
1033 (define_insn "vsx_ld_elemrev_v4si"
1034 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
1036 (match_operand:V4SI 1 "memory_operand" "Z")
1037 (parallel [(const_int 3) (const_int 2)
1038 (const_int 1) (const_int 0)])))]
1039 "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1041 [(set_attr "type" "vecload")])
1043 (define_insn "vsx_ld_elemrev_v4sf"
1044 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1046 (match_operand:V4SF 1 "memory_operand" "Z")
1047 (parallel [(const_int 3) (const_int 2)
1048 (const_int 1) (const_int 0)])))]
1049 "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1051 [(set_attr "type" "vecload")])
1053 (define_insn "vsx_ld_elemrev_v8hi"
1054 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
1056 (match_operand:V8HI 1 "memory_operand" "Z")
1057 (parallel [(const_int 7) (const_int 6)
1058 (const_int 5) (const_int 4)
1059 (const_int 3) (const_int 2)
1060 (const_int 1) (const_int 0)])))]
1061 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1063 [(set_attr "type" "vecload")])
1065 (define_insn "vsx_ld_elemrev_v16qi"
1066 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
1068 (match_operand:V16QI 1 "memory_operand" "Z")
1069 (parallel [(const_int 15) (const_int 14)
1070 (const_int 13) (const_int 12)
1071 (const_int 11) (const_int 10)
1072 (const_int 9) (const_int 8)
1073 (const_int 7) (const_int 6)
1074 (const_int 5) (const_int 4)
1075 (const_int 3) (const_int 2)
1076 (const_int 1) (const_int 0)])))]
1077 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1079 [(set_attr "type" "vecload")])
1081 (define_insn "vsx_st_elemrev_v2df"
1082 [(set (match_operand:V2DF 0 "memory_operand" "=Z")
1084 (match_operand:V2DF 1 "vsx_register_operand" "wa")
1085 (parallel [(const_int 1) (const_int 0)])))]
1086 "VECTOR_MEM_VSX_P (V2DFmode) && !BYTES_BIG_ENDIAN"
1088 [(set_attr "type" "vecstore")])
1090 (define_insn "vsx_st_elemrev_v2di"
1091 [(set (match_operand:V2DI 0 "memory_operand" "=Z")
1093 (match_operand:V2DI 1 "vsx_register_operand" "wa")
1094 (parallel [(const_int 1) (const_int 0)])))]
1095 "VECTOR_MEM_VSX_P (V2DImode) && !BYTES_BIG_ENDIAN"
1097 [(set_attr "type" "vecstore")])
1099 (define_insn "vsx_st_elemrev_v4sf"
1100 [(set (match_operand:V4SF 0 "memory_operand" "=Z")
1102 (match_operand:V4SF 1 "vsx_register_operand" "wa")
1103 (parallel [(const_int 3) (const_int 2)
1104 (const_int 1) (const_int 0)])))]
1105 "VECTOR_MEM_VSX_P (V4SFmode) && !BYTES_BIG_ENDIAN"
1107 [(set_attr "type" "vecstore")])
1109 (define_insn "vsx_st_elemrev_v4si"
1110 [(set (match_operand:V4SI 0 "memory_operand" "=Z")
1112 (match_operand:V4SI 1 "vsx_register_operand" "wa")
1113 (parallel [(const_int 3) (const_int 2)
1114 (const_int 1) (const_int 0)])))]
1115 "VECTOR_MEM_VSX_P (V4SImode) && !BYTES_BIG_ENDIAN"
1117 [(set_attr "type" "vecstore")])
1119 (define_insn "vsx_st_elemrev_v8hi"
1120 [(set (match_operand:V8HI 0 "memory_operand" "=Z")
1122 (match_operand:V8HI 1 "vsx_register_operand" "wa")
1123 (parallel [(const_int 7) (const_int 6)
1124 (const_int 5) (const_int 4)
1125 (const_int 3) (const_int 2)
1126 (const_int 1) (const_int 0)])))]
1127 "VECTOR_MEM_VSX_P (V8HImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1129 [(set_attr "type" "vecstore")])
1131 (define_insn "vsx_st_elemrev_v16qi"
1132 [(set (match_operand:V16QI 0 "memory_operand" "=Z")
1134 (match_operand:V16QI 1 "vsx_register_operand" "wa")
1135 (parallel [(const_int 15) (const_int 14)
1136 (const_int 13) (const_int 12)
1137 (const_int 11) (const_int 10)
1138 (const_int 9) (const_int 8)
1139 (const_int 7) (const_int 6)
1140 (const_int 5) (const_int 4)
1141 (const_int 3) (const_int 2)
1142 (const_int 1) (const_int 0)])))]
1143 "VECTOR_MEM_VSX_P (V16QImode) && !BYTES_BIG_ENDIAN && TARGET_P9_VECTOR"
1145 [(set_attr "type" "vecstore")])
1148 ;; VSX vector floating point arithmetic instructions. The VSX scalar
1149 ;; instructions are now combined with the insn for the traditional floating
1151 (define_insn "*vsx_add<mode>3"
1152 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1153 (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1154 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1155 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1156 "xvadd<VSs> %x0,%x1,%x2"
1157 [(set_attr "type" "<VStype_simple>")
1158 (set_attr "fp_type" "<VSfptype_simple>")])
1160 (define_insn "*vsx_sub<mode>3"
1161 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1162 (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1163 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1164 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1165 "xvsub<VSs> %x0,%x1,%x2"
1166 [(set_attr "type" "<VStype_simple>")
1167 (set_attr "fp_type" "<VSfptype_simple>")])
1169 (define_insn "*vsx_mul<mode>3"
1170 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1171 (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1172 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1173 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1174 "xvmul<VSs> %x0,%x1,%x2"
1175 [(set_attr "type" "<VStype_simple>")
1176 (set_attr "fp_type" "<VSfptype_mul>")])
1178 ; Emulate vector with scalar for vec_mul in V2DImode
1179 (define_insn_and_split "vsx_mul_v2di"
1180 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1181 (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1182 (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1184 "VECTOR_MEM_VSX_P (V2DImode)"
1186 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1190 rtx op0 = operands[0];
1191 rtx op1 = operands[1];
1192 rtx op2 = operands[2];
1193 rtx op3 = gen_reg_rtx (DImode);
1194 rtx op4 = gen_reg_rtx (DImode);
1195 rtx op5 = gen_reg_rtx (DImode);
1196 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1197 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1198 emit_insn (gen_muldi3 (op5, op3, op4));
1199 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1200 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1201 emit_insn (gen_muldi3 (op3, op3, op4));
1202 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1205 [(set_attr "type" "mul")])
1207 (define_insn "*vsx_div<mode>3"
1208 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1209 (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1210 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1211 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1212 "xvdiv<VSs> %x0,%x1,%x2"
1213 [(set_attr "type" "<VStype_div>")
1214 (set_attr "fp_type" "<VSfptype_div>")])
1216 ; Emulate vector with scalar for vec_div in V2DImode
1217 (define_insn_and_split "vsx_div_v2di"
1218 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1219 (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1220 (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1222 "VECTOR_MEM_VSX_P (V2DImode)"
1224 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1228 rtx op0 = operands[0];
1229 rtx op1 = operands[1];
1230 rtx op2 = operands[2];
1231 rtx op3 = gen_reg_rtx (DImode);
1232 rtx op4 = gen_reg_rtx (DImode);
1233 rtx op5 = gen_reg_rtx (DImode);
1234 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1235 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1236 emit_insn (gen_divdi3 (op5, op3, op4));
1237 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1238 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1239 emit_insn (gen_divdi3 (op3, op3, op4));
1240 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1243 [(set_attr "type" "div")])
1245 (define_insn_and_split "vsx_udiv_v2di"
1246 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1247 (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa")
1248 (match_operand:V2DI 2 "vsx_register_operand" "wa")]
1250 "VECTOR_MEM_VSX_P (V2DImode)"
1252 "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
1256 rtx op0 = operands[0];
1257 rtx op1 = operands[1];
1258 rtx op2 = operands[2];
1259 rtx op3 = gen_reg_rtx (DImode);
1260 rtx op4 = gen_reg_rtx (DImode);
1261 rtx op5 = gen_reg_rtx (DImode);
1262 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0)));
1263 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0)));
1264 emit_insn (gen_udivdi3 (op5, op3, op4));
1265 emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1)));
1266 emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1)));
1267 emit_insn (gen_udivdi3 (op3, op3, op4));
1268 emit_insn (gen_vsx_concat_v2di (op0, op5, op3));
1271 [(set_attr "type" "div")])
1273 ;; *tdiv* instruction returning the FG flag
1274 (define_expand "vsx_tdiv<mode>3_fg"
1276 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1277 (match_operand:VSX_B 2 "vsx_register_operand" "")]
1279 (set (match_operand:SI 0 "gpc_reg_operand" "")
1280 (gt:SI (match_dup 3)
1282 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1284 operands[3] = gen_reg_rtx (CCFPmode);
1287 ;; *tdiv* instruction returning the FE flag
1288 (define_expand "vsx_tdiv<mode>3_fe"
1290 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
1291 (match_operand:VSX_B 2 "vsx_register_operand" "")]
1293 (set (match_operand:SI 0 "gpc_reg_operand" "")
1294 (eq:SI (match_dup 3)
1296 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1298 operands[3] = gen_reg_rtx (CCFPmode);
1301 (define_insn "*vsx_tdiv<mode>3_internal"
1302 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1303 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")
1304 (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,<VSa>")]
1306 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1307 "x<VSv>tdiv<VSs> %0,%x1,%x2"
1308 [(set_attr "type" "<VStype_simple>")
1309 (set_attr "fp_type" "<VSfptype_simple>")])
1311 (define_insn "vsx_fre<mode>2"
1312 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1313 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1315 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1317 [(set_attr "type" "<VStype_simple>")
1318 (set_attr "fp_type" "<VSfptype_simple>")])
1320 (define_insn "*vsx_neg<mode>2"
1321 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1322 (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1323 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1324 "xvneg<VSs> %x0,%x1"
1325 [(set_attr "type" "<VStype_simple>")
1326 (set_attr "fp_type" "<VSfptype_simple>")])
1328 (define_insn "*vsx_abs<mode>2"
1329 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1330 (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1331 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1332 "xvabs<VSs> %x0,%x1"
1333 [(set_attr "type" "<VStype_simple>")
1334 (set_attr "fp_type" "<VSfptype_simple>")])
1336 (define_insn "vsx_nabs<mode>2"
1337 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1340 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>"))))]
1341 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1342 "xvnabs<VSs> %x0,%x1"
1343 [(set_attr "type" "<VStype_simple>")
1344 (set_attr "fp_type" "<VSfptype_simple>")])
1346 (define_insn "vsx_smax<mode>3"
1347 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1348 (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1349 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1350 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1351 "xvmax<VSs> %x0,%x1,%x2"
1352 [(set_attr "type" "<VStype_simple>")
1353 (set_attr "fp_type" "<VSfptype_simple>")])
1355 (define_insn "*vsx_smin<mode>3"
1356 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1357 (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1358 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1359 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1360 "xvmin<VSs> %x0,%x1,%x2"
1361 [(set_attr "type" "<VStype_simple>")
1362 (set_attr "fp_type" "<VSfptype_simple>")])
1364 (define_insn "*vsx_sqrt<mode>2"
1365 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1366 (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1367 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1368 "xvsqrt<VSs> %x0,%x1"
1369 [(set_attr "type" "<VStype_sqrt>")
1370 (set_attr "fp_type" "<VSfptype_sqrt>")])
1372 (define_insn "*vsx_rsqrte<mode>2"
1373 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1374 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1376 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1377 "xvrsqrte<VSs> %x0,%x1"
1378 [(set_attr "type" "<VStype_simple>")
1379 (set_attr "fp_type" "<VSfptype_simple>")])
1381 ;; *tsqrt* returning the fg flag
1382 (define_expand "vsx_tsqrt<mode>2_fg"
1384 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1386 (set (match_operand:SI 0 "gpc_reg_operand" "")
1387 (gt:SI (match_dup 2)
1389 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1391 operands[2] = gen_reg_rtx (CCFPmode);
1394 ;; *tsqrt* returning the fe flag
1395 (define_expand "vsx_tsqrt<mode>2_fe"
1397 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
1399 (set (match_operand:SI 0 "gpc_reg_operand" "")
1400 (eq:SI (match_dup 2)
1402 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1404 operands[2] = gen_reg_rtx (CCFPmode);
1407 (define_insn "*vsx_tsqrt<mode>2_internal"
1408 [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
1409 (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1411 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1412 "x<VSv>tsqrt<VSs> %0,%x1"
1413 [(set_attr "type" "<VStype_simple>")
1414 (set_attr "fp_type" "<VSfptype_simple>")])
1416 ;; Fused vector multiply/add instructions. Support the classical Altivec
1417 ;; versions of fma, which allows the target to be a separate register from the
1418 ;; 3 inputs. Under VSX, the target must be either the addend or the first
1421 (define_insn "*vsx_fmav4sf4"
1422 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1424 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1425 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1426 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))]
1427 "VECTOR_UNIT_VSX_P (V4SFmode)"
1429 xvmaddasp %x0,%x1,%x2
1430 xvmaddmsp %x0,%x1,%x3
1431 xvmaddasp %x0,%x1,%x2
1432 xvmaddmsp %x0,%x1,%x3
1433 vmaddfp %0,%1,%2,%3"
1434 [(set_attr "type" "vecfloat")])
1436 (define_insn "*vsx_fmav2df4"
1437 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1439 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1440 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1441 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))]
1442 "VECTOR_UNIT_VSX_P (V2DFmode)"
1444 xvmaddadp %x0,%x1,%x2
1445 xvmaddmdp %x0,%x1,%x3
1446 xvmaddadp %x0,%x1,%x2
1447 xvmaddmdp %x0,%x1,%x3"
1448 [(set_attr "type" "vecdouble")])
1450 (define_insn "*vsx_fms<mode>4"
1451 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1453 (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,<VSa>,<VSa>")
1454 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1456 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1457 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1459 xvmsuba<VSs> %x0,%x1,%x2
1460 xvmsubm<VSs> %x0,%x1,%x3
1461 xvmsuba<VSs> %x0,%x1,%x2
1462 xvmsubm<VSs> %x0,%x1,%x3"
1463 [(set_attr "type" "<VStype_mul>")])
1465 (define_insn "*vsx_nfma<mode>4"
1466 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
1469 (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,<VSa>,<VSa>")
1470 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
1471 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
1472 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1474 xvnmadda<VSs> %x0,%x1,%x2
1475 xvnmaddm<VSs> %x0,%x1,%x3
1476 xvnmadda<VSs> %x0,%x1,%x2
1477 xvnmaddm<VSs> %x0,%x1,%x3"
1478 [(set_attr "type" "<VStype_mul>")
1479 (set_attr "fp_type" "<VSfptype_mul>")])
1481 (define_insn "*vsx_nfmsv4sf4"
1482 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
1485 (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
1486 (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
1488 (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
1489 "VECTOR_UNIT_VSX_P (V4SFmode)"
1491 xvnmsubasp %x0,%x1,%x2
1492 xvnmsubmsp %x0,%x1,%x3
1493 xvnmsubasp %x0,%x1,%x2
1494 xvnmsubmsp %x0,%x1,%x3
1495 vnmsubfp %0,%1,%2,%3"
1496 [(set_attr "type" "vecfloat")])
1498 (define_insn "*vsx_nfmsv2df4"
1499 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
1502 (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
1503 (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
1505 (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
1506 "VECTOR_UNIT_VSX_P (V2DFmode)"
1508 xvnmsubadp %x0,%x1,%x2
1509 xvnmsubmdp %x0,%x1,%x3
1510 xvnmsubadp %x0,%x1,%x2
1511 xvnmsubmdp %x0,%x1,%x3"
1512 [(set_attr "type" "vecdouble")])
1514 ;; Vector conditional expressions (no scalar version for these instructions)
1515 (define_insn "vsx_eq<mode>"
1516 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1517 (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1518 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1519 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1520 "xvcmpeq<VSs> %x0,%x1,%x2"
1521 [(set_attr "type" "<VStype_simple>")
1522 (set_attr "fp_type" "<VSfptype_simple>")])
1524 (define_insn "vsx_gt<mode>"
1525 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1526 (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1527 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1528 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1529 "xvcmpgt<VSs> %x0,%x1,%x2"
1530 [(set_attr "type" "<VStype_simple>")
1531 (set_attr "fp_type" "<VSfptype_simple>")])
1533 (define_insn "*vsx_ge<mode>"
1534 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1535 (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1536 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
1537 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1538 "xvcmpge<VSs> %x0,%x1,%x2"
1539 [(set_attr "type" "<VStype_simple>")
1540 (set_attr "fp_type" "<VSfptype_simple>")])
1542 ;; Compare vectors producing a vector result and a predicate, setting CR6 to
1543 ;; indicate a combined status
1544 (define_insn "*vsx_eq_<mode>_p"
1545 [(set (reg:CC CR6_REGNO)
1547 [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1548 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1550 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1551 (eq:VSX_F (match_dup 1)
1553 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1554 "xvcmpeq<VSs>. %x0,%x1,%x2"
1555 [(set_attr "type" "<VStype_simple>")])
1557 (define_insn "*vsx_gt_<mode>_p"
1558 [(set (reg:CC CR6_REGNO)
1560 [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1561 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1563 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1564 (gt:VSX_F (match_dup 1)
1566 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1567 "xvcmpgt<VSs>. %x0,%x1,%x2"
1568 [(set_attr "type" "<VStype_simple>")])
1570 (define_insn "*vsx_ge_<mode>_p"
1571 [(set (reg:CC CR6_REGNO)
1573 [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
1574 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
1576 (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1577 (ge:VSX_F (match_dup 1)
1579 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1580 "xvcmpge<VSs>. %x0,%x1,%x2"
1581 [(set_attr "type" "<VStype_simple>")])
1584 (define_insn "*vsx_xxsel<mode>"
1585 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1587 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1588 (match_operand:VSX_L 4 "zero_constant" ""))
1589 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1590 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1591 "VECTOR_MEM_VSX_P (<MODE>mode)"
1592 "xxsel %x0,%x3,%x2,%x1"
1593 [(set_attr "type" "vecmove")])
1595 (define_insn "*vsx_xxsel<mode>_uns"
1596 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1598 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
1599 (match_operand:VSX_L 4 "zero_constant" ""))
1600 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
1601 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
1602 "VECTOR_MEM_VSX_P (<MODE>mode)"
1603 "xxsel %x0,%x3,%x2,%x1"
1604 [(set_attr "type" "vecmove")])
1607 (define_insn "vsx_copysign<mode>3"
1608 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1610 [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
1611 (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")]
1613 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1614 "xvcpsgn<VSs> %x0,%x2,%x1"
1615 [(set_attr "type" "<VStype_simple>")
1616 (set_attr "fp_type" "<VSfptype_simple>")])
1618 ;; For the conversions, limit the register class for the integer value to be
1619 ;; the fprs because we don't want to add the altivec registers to movdi/movsi.
1620 ;; For the unsigned tests, there isn't a generic double -> unsigned conversion
1621 ;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
1622 ;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md
1623 ;; in allowing virtual registers.
1624 (define_insn "vsx_float<VSi><mode>2"
1625 [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1626 (float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1627 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1628 "xvcvsx<VSc><VSs> %x0,%x1"
1629 [(set_attr "type" "<VStype_simple>")
1630 (set_attr "fp_type" "<VSfptype_simple>")])
1632 (define_insn "vsx_floatuns<VSi><mode>2"
1633 [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
1634 (unsigned_float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
1635 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1636 "xvcvux<VSc><VSs> %x0,%x1"
1637 [(set_attr "type" "<VStype_simple>")
1638 (set_attr "fp_type" "<VSfptype_simple>")])
1640 (define_insn "vsx_fix_trunc<mode><VSi>2"
1641 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1642 (fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1643 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1644 "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
1645 [(set_attr "type" "<VStype_simple>")
1646 (set_attr "fp_type" "<VSfptype_simple>")])
1648 (define_insn "vsx_fixuns_trunc<mode><VSi>2"
1649 [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
1650 (unsigned_fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
1651 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1652 "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
1653 [(set_attr "type" "<VStype_simple>")
1654 (set_attr "fp_type" "<VSfptype_simple>")])
1656 ;; Math rounding functions
1657 (define_insn "vsx_x<VSv>r<VSs>i"
1658 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1659 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1660 UNSPEC_VSX_ROUND_I))]
1661 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1662 "x<VSv>r<VSs>i %x0,%x1"
1663 [(set_attr "type" "<VStype_simple>")
1664 (set_attr "fp_type" "<VSfptype_simple>")])
1666 (define_insn "vsx_x<VSv>r<VSs>ic"
1667 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1668 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1669 UNSPEC_VSX_ROUND_IC))]
1670 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1671 "x<VSv>r<VSs>ic %x0,%x1"
1672 [(set_attr "type" "<VStype_simple>")
1673 (set_attr "fp_type" "<VSfptype_simple>")])
1675 (define_insn "vsx_btrunc<mode>2"
1676 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1677 (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
1678 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1679 "xvr<VSs>iz %x0,%x1"
1680 [(set_attr "type" "<VStype_simple>")
1681 (set_attr "fp_type" "<VSfptype_simple>")])
1683 (define_insn "*vsx_b2trunc<mode>2"
1684 [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1685 (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
1687 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1688 "x<VSv>r<VSs>iz %x0,%x1"
1689 [(set_attr "type" "<VStype_simple>")
1690 (set_attr "fp_type" "<VSfptype_simple>")])
1692 (define_insn "vsx_floor<mode>2"
1693 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1694 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1696 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1697 "xvr<VSs>im %x0,%x1"
1698 [(set_attr "type" "<VStype_simple>")
1699 (set_attr "fp_type" "<VSfptype_simple>")])
1701 (define_insn "vsx_ceil<mode>2"
1702 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
1703 (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
1705 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1706 "xvr<VSs>ip %x0,%x1"
1707 [(set_attr "type" "<VStype_simple>")
1708 (set_attr "fp_type" "<VSfptype_simple>")])
1711 ;; VSX convert to/from double vector
1713 ;; Convert between single and double precision
1714 ;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
1715 ;; scalar single precision instructions internally use the double format.
1716 ;; Prefer the altivec registers, since we likely will need to do a vperm
1717 (define_insn "vsx_<VS_spdp_insn>"
1718 [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?<VSa>")
1719 (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,<VSa>")]
1720 UNSPEC_VSX_CVSPDP))]
1721 "VECTOR_UNIT_VSX_P (<MODE>mode)"
1722 "<VS_spdp_insn> %x0,%x1"
1723 [(set_attr "type" "<VS_spdp_type>")])
1725 ;; xscvspdp, represent the scalar SF type as V4SF
1726 (define_insn "vsx_xscvspdp"
1727 [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
1728 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1729 UNSPEC_VSX_CVSPDP))]
1730 "VECTOR_UNIT_VSX_P (V4SFmode)"
1732 [(set_attr "type" "fp")])
1734 ;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
1735 ;; format of scalars is actually DF.
1736 (define_insn "vsx_xscvdpsp_scalar"
1737 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
1738 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
1739 UNSPEC_VSX_CVSPDP))]
1740 "VECTOR_UNIT_VSX_P (V4SFmode)"
1742 [(set_attr "type" "fp")])
1744 ;; Same as vsx_xscvspdp, but use SF as the type
1745 (define_insn "vsx_xscvspdp_scalar2"
1746 [(set (match_operand:SF 0 "vsx_register_operand" "=ww")
1747 (unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
1748 UNSPEC_VSX_CVSPDP))]
1749 "VECTOR_UNIT_VSX_P (V4SFmode)"
1751 [(set_attr "type" "fp")])
1753 ;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
1754 (define_insn "vsx_xscvdpspn"
1755 [(set (match_operand:V4SF 0 "vsx_register_operand" "=ww,?ww")
1756 (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wd,wa")]
1757 UNSPEC_VSX_CVDPSPN))]
1760 [(set_attr "type" "fp")])
1762 (define_insn "vsx_xscvspdpn"
1763 [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?ws")
1764 (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
1765 UNSPEC_VSX_CVSPDPN))]
1768 [(set_attr "type" "fp")])
1770 (define_insn "vsx_xscvdpspn_scalar"
1771 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa")
1772 (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "ww,ww")]
1773 UNSPEC_VSX_CVDPSPN))]
1776 [(set_attr "type" "fp")])
1778 ;; Used by direct move to move a SFmode value from GPR to VSX register
1779 (define_insn "vsx_xscvspdpn_directmove"
1780 [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
1781 (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
1782 UNSPEC_VSX_CVSPDPN))]
1785 [(set_attr "type" "fp")])
1787 ;; Convert and scale (used by vec_ctf, vec_cts, vec_ctu for double/long long)
1789 (define_expand "vsx_xvcvsxddp_scale"
1790 [(match_operand:V2DF 0 "vsx_register_operand" "")
1791 (match_operand:V2DI 1 "vsx_register_operand" "")
1792 (match_operand:QI 2 "immediate_operand" "")]
1793 "VECTOR_UNIT_VSX_P (V2DFmode)"
1795 rtx op0 = operands[0];
1796 rtx op1 = operands[1];
1797 int scale = INTVAL(operands[2]);
1798 emit_insn (gen_vsx_xvcvsxddp (op0, op1));
1800 rs6000_scale_v2df (op0, op0, -scale);
1804 (define_insn "vsx_xvcvsxddp"
1805 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1806 (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1807 UNSPEC_VSX_XVCVSXDDP))]
1808 "VECTOR_UNIT_VSX_P (V2DFmode)"
1810 [(set_attr "type" "vecdouble")])
1812 (define_expand "vsx_xvcvuxddp_scale"
1813 [(match_operand:V2DF 0 "vsx_register_operand" "")
1814 (match_operand:V2DI 1 "vsx_register_operand" "")
1815 (match_operand:QI 2 "immediate_operand" "")]
1816 "VECTOR_UNIT_VSX_P (V2DFmode)"
1818 rtx op0 = operands[0];
1819 rtx op1 = operands[1];
1820 int scale = INTVAL(operands[2]);
1821 emit_insn (gen_vsx_xvcvuxddp (op0, op1));
1823 rs6000_scale_v2df (op0, op0, -scale);
1827 (define_insn "vsx_xvcvuxddp"
1828 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
1829 (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
1830 UNSPEC_VSX_XVCVUXDDP))]
1831 "VECTOR_UNIT_VSX_P (V2DFmode)"
1833 [(set_attr "type" "vecdouble")])
1835 (define_expand "vsx_xvcvdpsxds_scale"
1836 [(match_operand:V2DI 0 "vsx_register_operand" "")
1837 (match_operand:V2DF 1 "vsx_register_operand" "")
1838 (match_operand:QI 2 "immediate_operand" "")]
1839 "VECTOR_UNIT_VSX_P (V2DFmode)"
1841 rtx op0 = operands[0];
1842 rtx op1 = operands[1];
1844 int scale = INTVAL (operands[2]);
1849 tmp = gen_reg_rtx (V2DFmode);
1850 rs6000_scale_v2df (tmp, op1, scale);
1852 emit_insn (gen_vsx_xvcvdpsxds (op0, tmp));
1856 (define_insn "vsx_xvcvdpsxds"
1857 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1858 (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1859 UNSPEC_VSX_XVCVDPSXDS))]
1860 "VECTOR_UNIT_VSX_P (V2DFmode)"
1861 "xvcvdpsxds %x0,%x1"
1862 [(set_attr "type" "vecdouble")])
1864 (define_expand "vsx_xvcvdpuxds_scale"
1865 [(match_operand:V2DI 0 "vsx_register_operand" "")
1866 (match_operand:V2DF 1 "vsx_register_operand" "")
1867 (match_operand:QI 2 "immediate_operand" "")]
1868 "VECTOR_UNIT_VSX_P (V2DFmode)"
1870 rtx op0 = operands[0];
1871 rtx op1 = operands[1];
1873 int scale = INTVAL (operands[2]);
1878 tmp = gen_reg_rtx (V2DFmode);
1879 rs6000_scale_v2df (tmp, op1, scale);
1881 emit_insn (gen_vsx_xvcvdpuxds (op0, tmp));
1885 (define_insn "vsx_xvcvdpuxds"
1886 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
1887 (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
1888 UNSPEC_VSX_XVCVDPUXDS))]
1889 "VECTOR_UNIT_VSX_P (V2DFmode)"
1890 "xvcvdpuxds %x0,%x1"
1891 [(set_attr "type" "vecdouble")])
1893 ;; Convert from 64-bit to 32-bit types
1894 ;; Note, favor the Altivec registers since the usual use of these instructions
1895 ;; is in vector converts and we need to use the Altivec vperm instruction.
1897 (define_insn "vsx_xvcvdpsxws"
1898 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1899 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1900 UNSPEC_VSX_CVDPSXWS))]
1901 "VECTOR_UNIT_VSX_P (V2DFmode)"
1902 "xvcvdpsxws %x0,%x1"
1903 [(set_attr "type" "vecdouble")])
1905 (define_insn "vsx_xvcvdpuxws"
1906 [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
1907 (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
1908 UNSPEC_VSX_CVDPUXWS))]
1909 "VECTOR_UNIT_VSX_P (V2DFmode)"
1910 "xvcvdpuxws %x0,%x1"
1911 [(set_attr "type" "vecdouble")])
1913 (define_insn "vsx_xvcvsxdsp"
1914 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wd,?wa")
1915 (unspec:V4SF [(match_operand:V2DI 1 "vsx_register_operand" "wf,wa")]
1916 UNSPEC_VSX_CVSXDSP))]
1917 "VECTOR_UNIT_VSX_P (V2DFmode)"
1919 [(set_attr "type" "vecfloat")])
1921 (define_insn "vsx_xvcvuxdsp"
1922 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wd,?wa")
1923 (unspec:V4SF [(match_operand:V2DI 1 "vsx_register_operand" "wf,wa")]
1924 UNSPEC_VSX_CVUXDSP))]
1925 "VECTOR_UNIT_VSX_P (V2DFmode)"
1927 [(set_attr "type" "vecdouble")])
1929 ;; Convert from 32-bit to 64-bit types
1930 ;; Provide both vector and scalar targets
1931 (define_insn "vsx_xvcvsxwdp"
1932 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1933 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1934 UNSPEC_VSX_CVSXWDP))]
1935 "VECTOR_UNIT_VSX_P (V2DFmode)"
1937 [(set_attr "type" "vecdouble")])
1939 (define_insn "vsx_xvcvsxwdp_df"
1940 [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
1941 (unspec:DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
1942 UNSPEC_VSX_CVSXWDP))]
1945 [(set_attr "type" "vecdouble")])
1947 (define_insn "vsx_xvcvuxwdp"
1948 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1949 (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
1950 UNSPEC_VSX_CVUXWDP))]
1951 "VECTOR_UNIT_VSX_P (V2DFmode)"
1953 [(set_attr "type" "vecdouble")])
1955 (define_insn "vsx_xvcvuxwdp_df"
1956 [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
1957 (unspec:DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
1958 UNSPEC_VSX_CVUXWDP))]
1961 [(set_attr "type" "vecdouble")])
1963 (define_insn "vsx_xvcvspsxds"
1964 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1965 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1966 UNSPEC_VSX_CVSPSXDS))]
1967 "VECTOR_UNIT_VSX_P (V2DFmode)"
1968 "xvcvspsxds %x0,%x1"
1969 [(set_attr "type" "vecdouble")])
1971 (define_insn "vsx_xvcvspuxds"
1972 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
1973 (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
1974 UNSPEC_VSX_CVSPUXDS))]
1975 "VECTOR_UNIT_VSX_P (V2DFmode)"
1976 "xvcvspuxds %x0,%x1"
1977 [(set_attr "type" "vecdouble")])
1979 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
1980 ;; since the xvrdpiz instruction does not truncate the value if the floating
1981 ;; point value is < LONG_MIN or > LONG_MAX.
1982 (define_insn "*vsx_float_fix_v2df2"
1983 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
1986 (match_operand:V2DF 1 "vsx_register_operand" "wd,?wa"))))]
1987 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
1988 && VECTOR_UNIT_VSX_P (V2DFmode) && flag_unsafe_math_optimizations
1989 && !flag_trapping_math && TARGET_FRIZ"
1991 [(set_attr "type" "vecdouble")
1992 (set_attr "fp_type" "fp_addsub_d")])
1995 ;; Permute operations
1997 ;; Build a V2DF/V2DI vector from two scalars
1998 (define_insn "vsx_concat_<mode>"
1999 [(set (match_operand:VSX_D 0 "gpc_reg_operand" "=<VSa>,we")
2001 (match_operand:<VS_scalar> 1 "gpc_reg_operand" "<VS_64reg>,b")
2002 (match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VS_64reg>,b")))]
2003 "VECTOR_MEM_VSX_P (<MODE>mode)"
2005 if (which_alternative == 0)
2006 return (BYTES_BIG_ENDIAN
2007 ? "xxpermdi %x0,%x1,%x2,0"
2008 : "xxpermdi %x0,%x2,%x1,0");
2010 else if (which_alternative == 1)
2011 return (BYTES_BIG_ENDIAN
2012 ? "mtvsrdd %x0,%1,%2"
2013 : "mtvsrdd %x0,%2,%1");
2018 [(set_attr "type" "vecperm")])
2020 ;; Special purpose concat using xxpermdi to glue two single precision values
2021 ;; together, relying on the fact that internally scalar floats are represented
2022 ;; as doubles. This is used to initialize a V4SF vector with 4 floats
2023 (define_insn "vsx_concat_v2sf"
2024 [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
2026 [(match_operand:SF 1 "vsx_register_operand" "ww")
2027 (match_operand:SF 2 "vsx_register_operand" "ww")]
2028 UNSPEC_VSX_CONCAT))]
2029 "VECTOR_MEM_VSX_P (V2DFmode)"
2031 if (BYTES_BIG_ENDIAN)
2032 return "xxpermdi %x0,%x1,%x2,0";
2034 return "xxpermdi %x0,%x2,%x1,0";
2036 [(set_attr "type" "vecperm")])
2038 ;; V4SImode initialization splitter
2039 (define_insn_and_split "vsx_init_v4si"
2040 [(set (match_operand:V4SI 0 "gpc_reg_operand" "=&r")
2042 [(match_operand:SI 1 "reg_or_cint_operand" "rn")
2043 (match_operand:SI 2 "reg_or_cint_operand" "rn")
2044 (match_operand:SI 3 "reg_or_cint_operand" "rn")
2045 (match_operand:SI 4 "reg_or_cint_operand" "rn")]
2046 UNSPEC_VSX_VEC_INIT))
2047 (clobber (match_scratch:DI 5 "=&r"))
2048 (clobber (match_scratch:DI 6 "=&r"))]
2049 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2051 "&& reload_completed"
2054 rs6000_split_v4si_init (operands);
2058 ;; xxpermdi for little endian loads and stores. We need several of
2059 ;; these since the form of the PARALLEL differs by mode.
2060 (define_insn "*vsx_xxpermdi2_le_<mode>"
2061 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
2063 (match_operand:VSX_D 1 "vsx_register_operand" "<VSa>")
2064 (parallel [(const_int 1) (const_int 0)])))]
2065 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
2066 "xxpermdi %x0,%x1,%x1,2"
2067 [(set_attr "type" "vecperm")])
2069 (define_insn "*vsx_xxpermdi4_le_<mode>"
2070 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
2072 (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2073 (parallel [(const_int 2) (const_int 3)
2074 (const_int 0) (const_int 1)])))]
2075 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
2076 "xxpermdi %x0,%x1,%x1,2"
2077 [(set_attr "type" "vecperm")])
2079 (define_insn "*vsx_xxpermdi8_le_V8HI"
2080 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
2082 (match_operand:V8HI 1 "vsx_register_operand" "wa")
2083 (parallel [(const_int 4) (const_int 5)
2084 (const_int 6) (const_int 7)
2085 (const_int 0) (const_int 1)
2086 (const_int 2) (const_int 3)])))]
2087 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
2088 "xxpermdi %x0,%x1,%x1,2"
2089 [(set_attr "type" "vecperm")])
2091 (define_insn "*vsx_xxpermdi16_le_V16QI"
2092 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
2094 (match_operand:V16QI 1 "vsx_register_operand" "wa")
2095 (parallel [(const_int 8) (const_int 9)
2096 (const_int 10) (const_int 11)
2097 (const_int 12) (const_int 13)
2098 (const_int 14) (const_int 15)
2099 (const_int 0) (const_int 1)
2100 (const_int 2) (const_int 3)
2101 (const_int 4) (const_int 5)
2102 (const_int 6) (const_int 7)])))]
2103 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
2104 "xxpermdi %x0,%x1,%x1,2"
2105 [(set_attr "type" "vecperm")])
2107 ;; lxvd2x for little endian loads. We need several of
2108 ;; these since the form of the PARALLEL differs by mode.
2109 (define_insn "*vsx_lxvd2x2_le_<mode>"
2110 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
2112 (match_operand:VSX_D 1 "memory_operand" "Z")
2113 (parallel [(const_int 1) (const_int 0)])))]
2114 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2116 [(set_attr "type" "vecload")])
2118 (define_insn "*vsx_lxvd2x4_le_<mode>"
2119 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
2121 (match_operand:VSX_W 1 "memory_operand" "Z")
2122 (parallel [(const_int 2) (const_int 3)
2123 (const_int 0) (const_int 1)])))]
2124 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2126 [(set_attr "type" "vecload")])
2128 (define_insn "*vsx_lxvd2x8_le_V8HI"
2129 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
2131 (match_operand:V8HI 1 "memory_operand" "Z")
2132 (parallel [(const_int 4) (const_int 5)
2133 (const_int 6) (const_int 7)
2134 (const_int 0) (const_int 1)
2135 (const_int 2) (const_int 3)])))]
2136 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2138 [(set_attr "type" "vecload")])
2140 (define_insn "*vsx_lxvd2x16_le_V16QI"
2141 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
2143 (match_operand:V16QI 1 "memory_operand" "Z")
2144 (parallel [(const_int 8) (const_int 9)
2145 (const_int 10) (const_int 11)
2146 (const_int 12) (const_int 13)
2147 (const_int 14) (const_int 15)
2148 (const_int 0) (const_int 1)
2149 (const_int 2) (const_int 3)
2150 (const_int 4) (const_int 5)
2151 (const_int 6) (const_int 7)])))]
2152 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2154 [(set_attr "type" "vecload")])
2156 ;; stxvd2x for little endian stores. We need several of
2157 ;; these since the form of the PARALLEL differs by mode.
2158 (define_insn "*vsx_stxvd2x2_le_<mode>"
2159 [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
2161 (match_operand:VSX_D 1 "vsx_register_operand" "<VSa>")
2162 (parallel [(const_int 1) (const_int 0)])))]
2163 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2165 [(set_attr "type" "vecstore")])
2167 (define_insn "*vsx_stxvd2x4_le_<mode>"
2168 [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
2170 (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
2171 (parallel [(const_int 2) (const_int 3)
2172 (const_int 0) (const_int 1)])))]
2173 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
2175 [(set_attr "type" "vecstore")])
2177 (define_insn "*vsx_stxvd2x8_le_V8HI"
2178 [(set (match_operand:V8HI 0 "memory_operand" "=Z")
2180 (match_operand:V8HI 1 "vsx_register_operand" "wa")
2181 (parallel [(const_int 4) (const_int 5)
2182 (const_int 6) (const_int 7)
2183 (const_int 0) (const_int 1)
2184 (const_int 2) (const_int 3)])))]
2185 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode) && !TARGET_P9_VECTOR"
2187 [(set_attr "type" "vecstore")])
2189 (define_insn "*vsx_stxvd2x16_le_V16QI"
2190 [(set (match_operand:V16QI 0 "memory_operand" "=Z")
2192 (match_operand:V16QI 1 "vsx_register_operand" "wa")
2193 (parallel [(const_int 8) (const_int 9)
2194 (const_int 10) (const_int 11)
2195 (const_int 12) (const_int 13)
2196 (const_int 14) (const_int 15)
2197 (const_int 0) (const_int 1)
2198 (const_int 2) (const_int 3)
2199 (const_int 4) (const_int 5)
2200 (const_int 6) (const_int 7)])))]
2201 "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode) && !TARGET_P9_VECTOR"
2203 [(set_attr "type" "vecstore")])
2205 ;; Convert a TImode value into V1TImode
2206 (define_expand "vsx_set_v1ti"
2207 [(match_operand:V1TI 0 "nonimmediate_operand" "")
2208 (match_operand:V1TI 1 "nonimmediate_operand" "")
2209 (match_operand:TI 2 "input_operand" "")
2210 (match_operand:QI 3 "u5bit_cint_operand" "")]
2211 "VECTOR_MEM_VSX_P (V1TImode)"
2213 if (operands[3] != const0_rtx)
2216 emit_move_insn (operands[0], gen_lowpart (V1TImode, operands[1]));
2220 ;; Set the element of a V2DI/VD2F mode
2221 (define_insn "vsx_set_<mode>"
2222 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?<VSa>")
2224 [(match_operand:VSX_D 1 "vsx_register_operand" "wd,<VSa>")
2225 (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")
2226 (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
2228 "VECTOR_MEM_VSX_P (<MODE>mode)"
2230 int idx_first = BYTES_BIG_ENDIAN ? 0 : 1;
2231 if (INTVAL (operands[3]) == idx_first)
2232 return \"xxpermdi %x0,%x2,%x1,1\";
2233 else if (INTVAL (operands[3]) == 1 - idx_first)
2234 return \"xxpermdi %x0,%x1,%x2,0\";
2238 [(set_attr "type" "vecperm")])
2240 ;; Extract a DF/DI element from V2DF/V2DI
2241 ;; Optimize cases were we can do a simple or direct move.
2242 ;; Or see if we can avoid doing the move at all
2244 ;; There are some unresolved problems with reload that show up if an Altivec
2245 ;; register was picked. Limit the scalar value to FPRs for now.
2247 (define_insn "vsx_extract_<mode>"
2248 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=d, d, wr, wr")
2250 (vec_select:<VS_scalar>
2251 (match_operand:VSX_D 1 "gpc_reg_operand" "<VSa>, <VSa>, wm, wo")
2254 [(match_operand:QI 2 "const_0_to_1_operand" "wD, n, wD, n")])))]
2255 "VECTOR_MEM_VSX_P (<MODE>mode)"
2257 int element = INTVAL (operands[2]);
2258 int op0_regno = REGNO (operands[0]);
2259 int op1_regno = REGNO (operands[1]);
2262 gcc_assert (IN_RANGE (element, 0, 1));
2263 gcc_assert (VSX_REGNO_P (op1_regno));
2265 if (element == VECTOR_ELEMENT_SCALAR_64BIT)
2267 if (op0_regno == op1_regno)
2268 return ASM_COMMENT_START " vec_extract to same register";
2270 else if (INT_REGNO_P (op0_regno) && TARGET_DIRECT_MOVE
2271 && TARGET_POWERPC64)
2272 return "mfvsrd %0,%x1";
2274 else if (FP_REGNO_P (op0_regno) && FP_REGNO_P (op1_regno))
2277 else if (VSX_REGNO_P (op0_regno))
2278 return "xxlor %x0,%x1,%x1";
2284 else if (element == VECTOR_ELEMENT_MFVSRLD_64BIT && INT_REGNO_P (op0_regno)
2285 && TARGET_P9_VECTOR && TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
2286 return "mfvsrld %0,%x1";
2288 else if (VSX_REGNO_P (op0_regno))
2290 fldDM = element << 1;
2291 if (!BYTES_BIG_ENDIAN)
2293 operands[3] = GEN_INT (fldDM);
2294 return "xxpermdi %x0,%x1,%x1,%3";
2300 [(set_attr "type" "veclogical,mftgpr,mftgpr,vecperm")])
2302 ;; Optimize extracting a single scalar element from memory.
2303 (define_insn_and_split "*vsx_extract_<P:mode>_<VSX_D:mode>_load"
2304 [(set (match_operand:<VS_scalar> 0 "register_operand" "=<VSX_D:VS_64reg>,wr")
2305 (vec_select:<VSX_D:VS_scalar>
2306 (match_operand:VSX_D 1 "memory_operand" "m,m")
2307 (parallel [(match_operand:QI 2 "const_0_to_1_operand" "n,n")])))
2308 (clobber (match_scratch:P 3 "=&b,&b"))]
2309 "VECTOR_MEM_VSX_P (<VSX_D:MODE>mode)"
2311 "&& reload_completed"
2312 [(set (match_dup 0) (match_dup 4))]
2314 operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2315 operands[3], <VSX_D:VS_scalar>mode);
2317 [(set_attr "type" "fpload,load")
2318 (set_attr "length" "8")])
2320 ;; Optimize storing a single scalar element that is the right location to
2322 (define_insn "*vsx_extract_<mode>_store"
2323 [(set (match_operand:<VS_scalar> 0 "memory_operand" "=m,Z,wY")
2324 (vec_select:<VS_scalar>
2325 (match_operand:VSX_D 1 "register_operand" "d,wv,wb")
2326 (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))]
2327 "VECTOR_MEM_VSX_P (<MODE>mode)"
2332 [(set_attr "type" "fpstore")
2333 (set_attr "length" "4")])
2335 ;; Variable V2DI/V2DF extract shift
2336 (define_insn "vsx_vslo_<mode>"
2337 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v")
2338 (unspec:<VS_scalar> [(match_operand:VSX_D 1 "gpc_reg_operand" "v")
2339 (match_operand:V2DI 2 "gpc_reg_operand" "v")]
2341 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2343 [(set_attr "type" "vecperm")])
2345 ;; Variable V2DI/V2DF extract
2346 (define_insn_and_split "vsx_extract_<mode>_var"
2347 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,<VSa>,r")
2348 (unspec:<VS_scalar> [(match_operand:VSX_D 1 "input_operand" "v,m,m")
2349 (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2350 UNSPEC_VSX_EXTRACT))
2351 (clobber (match_scratch:DI 3 "=r,&b,&b"))
2352 (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
2353 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2355 "&& reload_completed"
2358 rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2359 operands[3], operands[4]);
2363 ;; Extract a SF element from V4SF
2364 (define_insn_and_split "vsx_extract_v4sf"
2365 [(set (match_operand:SF 0 "vsx_register_operand" "=ww")
2367 (match_operand:V4SF 1 "vsx_register_operand" "wa")
2368 (parallel [(match_operand:QI 2 "u5bit_cint_operand" "n")])))
2369 (clobber (match_scratch:V4SF 3 "=0"))]
2370 "VECTOR_UNIT_VSX_P (V4SFmode)"
2375 rtx op0 = operands[0];
2376 rtx op1 = operands[1];
2377 rtx op2 = operands[2];
2378 rtx op3 = operands[3];
2380 HOST_WIDE_INT ele = BYTES_BIG_ENDIAN ? INTVAL (op2) : 3 - INTVAL (op2);
2386 if (GET_CODE (op3) == SCRATCH)
2387 op3 = gen_reg_rtx (V4SFmode);
2388 emit_insn (gen_vsx_xxsldwi_v4sf (op3, op1, op1, GEN_INT (ele)));
2391 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp));
2394 [(set_attr "length" "8")
2395 (set_attr "type" "fp")])
2397 (define_insn_and_split "*vsx_extract_v4sf_<mode>_load"
2398 [(set (match_operand:SF 0 "register_operand" "=f,wv,wb,?r")
2400 (match_operand:V4SF 1 "memory_operand" "m,Z,m,m")
2401 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n,n")])))
2402 (clobber (match_scratch:P 3 "=&b,&b,&b,&b"))]
2403 "VECTOR_MEM_VSX_P (V4SFmode)"
2405 "&& reload_completed"
2406 [(set (match_dup 0) (match_dup 4))]
2408 operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2409 operands[3], SFmode);
2411 [(set_attr "type" "fpload,fpload,fpload,load")
2412 (set_attr "length" "8")])
2414 ;; Variable V4SF extract
2415 (define_insn_and_split "vsx_extract_v4sf_var"
2416 [(set (match_operand:SF 0 "gpc_reg_operand" "=ww,ww,?r")
2417 (unspec:SF [(match_operand:V4SF 1 "input_operand" "v,m,m")
2418 (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2419 UNSPEC_VSX_EXTRACT))
2420 (clobber (match_scratch:DI 3 "=r,&b,&b"))
2421 (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
2422 "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT"
2424 "&& reload_completed"
2427 rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2428 operands[3], operands[4]);
2432 ;; Expand the builtin form of xxpermdi to canonical rtl.
2433 (define_expand "vsx_xxpermdi_<mode>"
2434 [(match_operand:VSX_L 0 "vsx_register_operand")
2435 (match_operand:VSX_L 1 "vsx_register_operand")
2436 (match_operand:VSX_L 2 "vsx_register_operand")
2437 (match_operand:QI 3 "u5bit_cint_operand")]
2438 "VECTOR_MEM_VSX_P (<MODE>mode)"
2440 rtx target = operands[0];
2441 rtx op0 = operands[1];
2442 rtx op1 = operands[2];
2443 int mask = INTVAL (operands[3]);
2444 rtx perm0 = GEN_INT ((mask >> 1) & 1);
2445 rtx perm1 = GEN_INT ((mask & 1) + 2);
2446 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2448 if (<MODE>mode == V2DFmode)
2449 gen = gen_vsx_xxpermdi2_v2df_1;
2452 gen = gen_vsx_xxpermdi2_v2di_1;
2453 if (<MODE>mode != V2DImode)
2455 target = gen_lowpart (V2DImode, target);
2456 op0 = gen_lowpart (V2DImode, op0);
2457 op1 = gen_lowpart (V2DImode, op1);
2460 emit_insn (gen (target, op0, op1, perm0, perm1));
2464 ;; Special version of xxpermdi that retains big-endian semantics.
2465 (define_expand "vsx_xxpermdi_<mode>_be"
2466 [(match_operand:VSX_L 0 "vsx_register_operand")
2467 (match_operand:VSX_L 1 "vsx_register_operand")
2468 (match_operand:VSX_L 2 "vsx_register_operand")
2469 (match_operand:QI 3 "u5bit_cint_operand")]
2470 "VECTOR_MEM_VSX_P (<MODE>mode)"
2472 rtx target = operands[0];
2473 rtx op0 = operands[1];
2474 rtx op1 = operands[2];
2475 int mask = INTVAL (operands[3]);
2476 rtx perm0 = GEN_INT ((mask >> 1) & 1);
2477 rtx perm1 = GEN_INT ((mask & 1) + 2);
2478 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2480 if (<MODE>mode == V2DFmode)
2481 gen = gen_vsx_xxpermdi2_v2df_1;
2484 gen = gen_vsx_xxpermdi2_v2di_1;
2485 if (<MODE>mode != V2DImode)
2487 target = gen_lowpart (V2DImode, target);
2488 op0 = gen_lowpart (V2DImode, op0);
2489 op1 = gen_lowpart (V2DImode, op1);
2492 /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
2493 transformation we don't want; it is necessary for
2494 rs6000_expand_vec_perm_const_1 but not for this use. So we
2495 prepare for that by reversing the transformation here. */
2496 if (BYTES_BIG_ENDIAN)
2497 emit_insn (gen (target, op0, op1, perm0, perm1));
2500 rtx p0 = GEN_INT (3 - INTVAL (perm1));
2501 rtx p1 = GEN_INT (3 - INTVAL (perm0));
2502 emit_insn (gen (target, op1, op0, p0, p1));
2507 (define_insn "vsx_xxpermdi2_<mode>_1"
2508 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
2510 (vec_concat:<VS_double>
2511 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
2512 (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
2513 (parallel [(match_operand 3 "const_0_to_1_operand" "")
2514 (match_operand 4 "const_2_to_3_operand" "")])))]
2515 "VECTOR_MEM_VSX_P (<MODE>mode)"
2519 /* For little endian, swap operands and invert/swap selectors
2520 to get the correct xxpermdi. The operand swap sets up the
2521 inputs as a little endian array. The selectors are swapped
2522 because they are defined to use big endian ordering. The
2523 selectors are inverted to get the correct doublewords for
2524 little endian ordering. */
2525 if (BYTES_BIG_ENDIAN)
2527 op3 = INTVAL (operands[3]);
2528 op4 = INTVAL (operands[4]);
2532 op3 = 3 - INTVAL (operands[4]);
2533 op4 = 3 - INTVAL (operands[3]);
2536 mask = (op3 << 1) | (op4 - 2);
2537 operands[3] = GEN_INT (mask);
2539 if (BYTES_BIG_ENDIAN)
2540 return "xxpermdi %x0,%x1,%x2,%3";
2542 return "xxpermdi %x0,%x2,%x1,%3";
2544 [(set_attr "type" "vecperm")])
2546 ;; Extraction of a single element in a small integer vector. Until ISA 3.0,
2547 ;; none of the small types were allowed in a vector register, so we had to
2548 ;; extract to a DImode and either do a direct move or store.
2549 (define_expand "vsx_extract_<mode>"
2550 [(parallel [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand")
2551 (vec_select:<VS_scalar>
2552 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand")
2553 (parallel [(match_operand:QI 2 "const_int_operand")])))
2554 (clobber (match_scratch:VSX_EXTRACT_I 3))])]
2555 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2557 /* If we have ISA 3.0, we can do a xxextractuw/vextractu{b,h}. */
2558 if (TARGET_VSX_SMALL_INTEGER && TARGET_P9_VECTOR)
2560 emit_insn (gen_vsx_extract_<mode>_p9 (operands[0], operands[1],
2566 (define_insn "vsx_extract_<mode>_p9"
2567 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,<VSX_EX>")
2568 (vec_select:<VS_scalar>
2569 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
2570 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
2571 (clobber (match_scratch:SI 3 "=r,X"))]
2572 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2573 && TARGET_VSX_SMALL_INTEGER"
2575 if (which_alternative == 0)
2580 HOST_WIDE_INT elt = INTVAL (operands[2]);
2581 HOST_WIDE_INT elt_adj = (!VECTOR_ELT_ORDER_BIG
2582 ? GET_MODE_NUNITS (<MODE>mode) - 1 - elt
2585 HOST_WIDE_INT unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
2586 HOST_WIDE_INT offset = unit_size * elt_adj;
2588 operands[2] = GEN_INT (offset);
2590 return "xxextractuw %x0,%x1,%2";
2592 return "vextractu<wd> %0,%1,%2";
2595 [(set_attr "type" "vecsimple")])
2598 [(set (match_operand:<VS_scalar> 0 "int_reg_operand")
2599 (vec_select:<VS_scalar>
2600 (match_operand:VSX_EXTRACT_I 1 "altivec_register_operand")
2601 (parallel [(match_operand:QI 2 "const_int_operand")])))
2602 (clobber (match_operand:SI 3 "int_reg_operand"))]
2603 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2604 && TARGET_VSX_SMALL_INTEGER && reload_completed"
2607 rtx op0_si = gen_rtx_REG (SImode, REGNO (operands[0]));
2608 rtx op1 = operands[1];
2609 rtx op2 = operands[2];
2610 rtx op3 = operands[3];
2611 HOST_WIDE_INT offset = INTVAL (op2) * GET_MODE_UNIT_SIZE (<MODE>mode);
2613 emit_move_insn (op3, GEN_INT (offset));
2614 if (VECTOR_ELT_ORDER_BIG)
2615 emit_insn (gen_vextu<wd>lx (op0_si, op3, op1));
2617 emit_insn (gen_vextu<wd>rx (op0_si, op3, op1));
2621 ;; Optimize zero extracts to eliminate the AND after the extract.
2622 (define_insn_and_split "*vsx_extract_<mode>_di_p9"
2623 [(set (match_operand:DI 0 "gpc_reg_operand" "=r,<VSX_EX>")
2625 (vec_select:<VS_scalar>
2626 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
2627 (parallel [(match_operand:QI 2 "const_int_operand" "n,n")]))))
2628 (clobber (match_scratch:SI 3 "=r,X"))]
2629 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2630 && TARGET_VSX_SMALL_INTEGER"
2632 "&& reload_completed"
2633 [(parallel [(set (match_dup 4)
2634 (vec_select:<VS_scalar>
2636 (parallel [(match_dup 2)])))
2637 (clobber (match_dup 3))])]
2639 operands[4] = gen_rtx_REG (<VS_scalar>mode, REGNO (operands[0]));
2642 ;; Optimize stores to use the ISA 3.0 scalar store instructions
2643 (define_insn_and_split "*vsx_extract_<mode>_store_p9"
2644 [(set (match_operand:<VS_scalar> 0 "memory_operand" "=Z,m")
2645 (vec_select:<VS_scalar>
2646 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>,v")
2647 (parallel [(match_operand:QI 2 "const_int_operand" "n,n")])))
2648 (clobber (match_scratch:<VS_scalar> 3 "=<VSX_EX>,&r"))
2649 (clobber (match_scratch:SI 4 "=X,&r"))]
2650 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2651 && TARGET_VSX_SMALL_INTEGER"
2653 "&& reload_completed"
2654 [(parallel [(set (match_dup 3)
2655 (vec_select:<VS_scalar>
2657 (parallel [(match_dup 2)])))
2658 (clobber (match_dup 4))])
2662 (define_insn_and_split "*vsx_extract_si"
2663 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,wHwI,Z")
2665 (match_operand:V4SI 1 "gpc_reg_operand" "wJv,wJv,wJv")
2666 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n")])))
2667 (clobber (match_scratch:V4SI 3 "=wJv,wJv,wJv"))]
2668 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT
2669 && (!TARGET_P9_VECTOR || !TARGET_VSX_SMALL_INTEGER)"
2671 "&& reload_completed"
2674 rtx dest = operands[0];
2675 rtx src = operands[1];
2676 rtx element = operands[2];
2677 rtx vec_tmp = operands[3];
2680 if (!VECTOR_ELT_ORDER_BIG)
2681 element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2683 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2685 value = INTVAL (element);
2688 if (TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER)
2690 rtx si_tmp = gen_rtx_REG (SImode, REGNO (vec_tmp));
2691 emit_insn (gen_vsx_extract_v4si_p9 (si_tmp,src, element));
2694 emit_insn (gen_altivec_vspltw_direct (vec_tmp, src, element));
2699 if (MEM_P (operands[0]))
2701 if (can_create_pseudo_p ())
2702 dest = rs6000_address_for_fpconvert (dest);
2704 if (TARGET_VSX_SMALL_INTEGER)
2705 emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
2707 emit_insn (gen_stfiwx (dest, gen_rtx_REG (DImode, REGNO (vec_tmp))));
2710 else if (TARGET_VSX_SMALL_INTEGER)
2711 emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
2713 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
2714 gen_rtx_REG (DImode, REGNO (vec_tmp)));
2718 [(set_attr "type" "mftgpr,vecperm,fpstore")
2719 (set_attr "length" "8")])
2721 (define_insn_and_split "*vsx_extract_<mode>_p8"
2722 [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r")
2723 (vec_select:<VS_scalar>
2724 (match_operand:VSX_EXTRACT_I2 1 "gpc_reg_operand" "v")
2725 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
2726 (clobber (match_scratch:VSX_EXTRACT_I2 3 "=v"))]
2727 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT
2728 && (!TARGET_P9_VECTOR || !TARGET_VSX_SMALL_INTEGER)"
2730 "&& reload_completed"
2733 rtx dest = operands[0];
2734 rtx src = operands[1];
2735 rtx element = operands[2];
2736 rtx vec_tmp = operands[3];
2739 if (!VECTOR_ELT_ORDER_BIG)
2740 element = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1 - INTVAL (element));
2742 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2744 value = INTVAL (element);
2745 if (<MODE>mode == V16QImode)
2748 emit_insn (gen_altivec_vspltb_direct (vec_tmp, src, element));
2752 else if (<MODE>mode == V8HImode)
2755 emit_insn (gen_altivec_vsplth_direct (vec_tmp, src, element));
2762 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
2763 gen_rtx_REG (DImode, REGNO (vec_tmp)));
2766 [(set_attr "type" "mftgpr")])
2768 ;; Optimize extracting a single scalar element from memory.
2769 (define_insn_and_split "*vsx_extract_<mode>_load"
2770 [(set (match_operand:<VS_scalar> 0 "register_operand" "=r")
2771 (vec_select:<VS_scalar>
2772 (match_operand:VSX_EXTRACT_I 1 "memory_operand" "m")
2773 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
2774 (clobber (match_scratch:DI 3 "=&b"))]
2775 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2777 "&& reload_completed"
2778 [(set (match_dup 0) (match_dup 4))]
2780 operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2781 operands[3], <VS_scalar>mode);
2783 [(set_attr "type" "load")
2784 (set_attr "length" "8")])
2786 ;; Variable V16QI/V8HI/V4SI extract
2787 (define_insn_and_split "vsx_extract_<mode>_var"
2788 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r")
2790 [(match_operand:VSX_EXTRACT_I 1 "input_operand" "wK,v,m")
2791 (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2792 UNSPEC_VSX_EXTRACT))
2793 (clobber (match_scratch:DI 3 "=r,r,&b"))
2794 (clobber (match_scratch:V2DI 4 "=X,&v,X"))]
2795 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2797 "&& reload_completed"
2800 rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2801 operands[3], operands[4]);
2805 (define_insn_and_split "*vsx_extract_<VSX_EXTRACT_I:mode>_<SDI:mode>_var"
2806 [(set (match_operand:SDI 0 "gpc_reg_operand" "=r,r,r")
2808 (unspec:<VSX_EXTRACT_I:VS_scalar>
2809 [(match_operand:VSX_EXTRACT_I 1 "input_operand" "wK,v,m")
2810 (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2811 UNSPEC_VSX_EXTRACT)))
2812 (clobber (match_scratch:DI 3 "=r,r,&b"))
2813 (clobber (match_scratch:V2DI 4 "=X,&v,X"))]
2814 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2816 "&& reload_completed"
2819 machine_mode smode = <VSX_EXTRACT_I:MODE>mode;
2820 rs6000_split_vec_extract_var (gen_rtx_REG (smode, REGNO (operands[0])),
2821 operands[1], operands[2],
2822 operands[3], operands[4]);
2826 ;; VSX_EXTRACT optimizations
2827 ;; Optimize double d = (double) vec_extract (vi, <n>)
2828 ;; Get the element into the top position and use XVCVSWDP/XVCVUWDP
2829 (define_insn_and_split "*vsx_extract_si_<uns>float_df"
2830 [(set (match_operand:DF 0 "gpc_reg_operand" "=ws")
2833 (match_operand:V4SI 1 "gpc_reg_operand" "v")
2834 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
2835 (clobber (match_scratch:V4SI 3 "=v"))]
2836 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2841 rtx dest = operands[0];
2842 rtx src = operands[1];
2843 rtx element = operands[2];
2844 rtx v4si_tmp = operands[3];
2847 if (!VECTOR_ELT_ORDER_BIG)
2848 element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2850 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2852 value = INTVAL (element);
2855 if (GET_CODE (v4si_tmp) == SCRATCH)
2856 v4si_tmp = gen_reg_rtx (V4SImode);
2857 emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
2862 emit_insn (gen_vsx_xvcv<su>xwdp_df (dest, v4si_tmp));
2866 ;; Optimize <type> f = (<type>) vec_extract (vi, <n>)
2867 ;; where <type> is a floating point type that supported by the hardware that is
2868 ;; not double. First convert the value to double, and then to the desired
2870 (define_insn_and_split "*vsx_extract_si_<uns>float_<mode>"
2871 [(set (match_operand:VSX_EXTRACT_FL 0 "gpc_reg_operand" "=ww")
2872 (any_float:VSX_EXTRACT_FL
2874 (match_operand:V4SI 1 "gpc_reg_operand" "v")
2875 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
2876 (clobber (match_scratch:V4SI 3 "=v"))
2877 (clobber (match_scratch:DF 4 "=ws"))]
2878 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2883 rtx dest = operands[0];
2884 rtx src = operands[1];
2885 rtx element = operands[2];
2886 rtx v4si_tmp = operands[3];
2887 rtx df_tmp = operands[4];
2890 if (!VECTOR_ELT_ORDER_BIG)
2891 element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2893 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2895 value = INTVAL (element);
2898 if (GET_CODE (v4si_tmp) == SCRATCH)
2899 v4si_tmp = gen_reg_rtx (V4SImode);
2900 emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
2905 if (GET_CODE (df_tmp) == SCRATCH)
2906 df_tmp = gen_reg_rtx (DFmode);
2908 emit_insn (gen_vsx_xvcv<su>xwdp_df (df_tmp, v4si_tmp));
2910 if (<MODE>mode == SFmode)
2911 emit_insn (gen_truncdfsf2 (dest, df_tmp));
2912 else if (<MODE>mode == TFmode && FLOAT128_IBM_P (TFmode))
2913 emit_insn (gen_extenddftf2_vsx (dest, df_tmp));
2914 else if (<MODE>mode == TFmode && FLOAT128_IEEE_P (TFmode)
2915 && TARGET_FLOAT128_HW)
2916 emit_insn (gen_extenddftf2_hw (dest, df_tmp));
2917 else if (<MODE>mode == IFmode && FLOAT128_IBM_P (IFmode))
2918 emit_insn (gen_extenddfif2 (dest, df_tmp));
2919 else if (<MODE>mode == KFmode && TARGET_FLOAT128_HW)
2920 emit_insn (gen_extenddfkf2_hw (dest, df_tmp));
2927 ;; Optimize <type> f = (<ftype>) vec_extract (<vtype>, <n>)
2928 ;; Where <ftype> is SFmode, DFmode (and KFmode/TFmode if those types are IEEE
2929 ;; 128-bit hardware types) and <vtype> is vector char, vector unsigned char,
2930 ;; vector short or vector unsigned short.
2931 (define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VS_scalar>_fl_<FL_CONV:mode>"
2932 [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=<FL_CONV:VSr3>")
2934 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2935 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
2936 (parallel [(match_operand:QI 2 "const_int_operand" "n")]))))
2937 (clobber (match_scratch:<VSX_EXTRACT_I:VS_scalar> 3 "=v"))]
2938 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
2939 && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER"
2941 "&& reload_completed"
2942 [(parallel [(set (match_dup 3)
2943 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2945 (parallel [(match_dup 2)])))
2946 (clobber (scratch:SI))])
2948 (sign_extend:DI (match_dup 3)))
2950 (float:<FL_CONV:MODE> (match_dup 4)))]
2952 operands[4] = gen_rtx_REG (DImode, REGNO (operands[3]));
2955 (define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VS_scalar>_ufl_<FL_CONV:mode>"
2956 [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=<FL_CONV:VSr3>")
2957 (unsigned_float:FL_CONV
2958 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2959 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
2960 (parallel [(match_operand:QI 2 "const_int_operand" "n")]))))
2961 (clobber (match_scratch:<VSX_EXTRACT_I:VS_scalar> 3 "=v"))]
2962 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
2963 && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER"
2965 "&& reload_completed"
2966 [(parallel [(set (match_dup 3)
2967 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2969 (parallel [(match_dup 2)])))
2970 (clobber (scratch:SI))])
2972 (float:<FL_CONV:MODE> (match_dup 4)))]
2974 operands[4] = gen_rtx_REG (DImode, REGNO (operands[3]));
2977 ;; V4SI/V8HI/V16QI set operation on ISA 3.0
2978 (define_insn "vsx_set_<mode>_p9"
2979 [(set (match_operand:VSX_EXTRACT_I 0 "gpc_reg_operand" "=<VSX_EX>")
2980 (unspec:VSX_EXTRACT_I
2981 [(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "0")
2982 (match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VSX_EX>")
2983 (match_operand:QI 3 "<VSX_EXTRACT_PREDICATE>" "n")]
2985 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
2986 && TARGET_UPPER_REGS_DI && TARGET_POWERPC64"
2988 int ele = INTVAL (operands[3]);
2989 int nunits = GET_MODE_NUNITS (<MODE>mode);
2991 if (!VECTOR_ELT_ORDER_BIG)
2992 ele = nunits - 1 - ele;
2994 operands[3] = GEN_INT (GET_MODE_SIZE (<VS_scalar>mode) * ele);
2995 if (<MODE>mode == V4SImode)
2996 return "xxinsertw %x0,%x2,%3";
2998 return "vinsert<wd> %0,%2,%3";
3000 [(set_attr "type" "vecperm")])
3002 ;; Expanders for builtins
3003 (define_expand "vsx_mergel_<mode>"
3004 [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
3005 (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
3006 (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
3007 "VECTOR_MEM_VSX_P (<MODE>mode)"
3012 /* Special handling for LE with -maltivec=be. */
3013 if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
3015 v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
3016 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
3020 v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
3021 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
3024 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
3025 emit_insn (gen_rtx_SET (operands[0], x));
3029 (define_expand "vsx_mergeh_<mode>"
3030 [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
3031 (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
3032 (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
3033 "VECTOR_MEM_VSX_P (<MODE>mode)"
3038 /* Special handling for LE with -maltivec=be. */
3039 if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
3041 v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
3042 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
3046 v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
3047 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
3050 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
3051 emit_insn (gen_rtx_SET (operands[0], x));
3056 ;; We separate the register splat insn from the memory splat insn to force the
3057 ;; register allocator to generate the indexed form of the SPLAT when it is
3058 ;; given an offsettable memory reference. Otherwise, if the register and
3059 ;; memory insns were combined into a single insn, the register allocator will
3060 ;; load the value into a register, and then do a double word permute.
3061 (define_expand "vsx_splat_<mode>"
3062 [(set (match_operand:VSX_D 0 "vsx_register_operand")
3063 (vec_duplicate:VSX_D
3064 (match_operand:<VS_scalar> 1 "input_operand")))]
3065 "VECTOR_MEM_VSX_P (<MODE>mode)"
3067 rtx op1 = operands[1];
3069 operands[1] = rs6000_address_for_fpconvert (op1);
3070 else if (!REG_P (op1))
3071 op1 = force_reg (<VSX_D:VS_scalar>mode, op1);
3074 (define_insn "vsx_splat_<mode>_reg"
3075 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSX_D:VSa>,?we")
3076 (vec_duplicate:VSX_D
3077 (match_operand:<VS_scalar> 1 "gpc_reg_operand" "<VSX_D:VS_64reg>,b")))]
3078 "VECTOR_MEM_VSX_P (<MODE>mode)"
3080 xxpermdi %x0,%x1,%x1,0
3082 [(set_attr "type" "vecperm")])
3084 (define_insn "vsx_splat_<VSX_D:mode>_mem"
3085 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSX_D:VSa>")
3086 (vec_duplicate:VSX_D
3087 (match_operand:<VSX_D:VS_scalar> 1 "memory_operand" "Z")))]
3088 "VECTOR_MEM_VSX_P (<MODE>mode)"
3090 [(set_attr "type" "vecload")])
3092 ;; V4SI splat support
3093 (define_insn "vsx_splat_v4si"
3094 [(set (match_operand:V4SI 0 "vsx_register_operand" "=we,we")
3096 (match_operand:SI 1 "splat_input_operand" "r,Z")))]
3101 [(set_attr "type" "vecperm,vecload")])
3103 ;; SImode is not currently allowed in vector registers. This pattern
3104 ;; allows us to use direct move to get the value in a vector register
3105 ;; so that we can use XXSPLTW
3106 (define_insn "vsx_splat_v4si_di"
3107 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,we")
3110 (match_operand:DI 1 "gpc_reg_operand" "wj,r"))))]
3111 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
3115 [(set_attr "type" "vecperm")])
3117 ;; V4SF splat (ISA 3.0)
3118 (define_insn_and_split "vsx_splat_v4sf"
3119 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,wa")
3121 (match_operand:SF 1 "splat_input_operand" "Z,wy,r")))]
3127 "&& reload_completed && vsx_register_operand (operands[1], SFmode)"
3129 (unspec:V4SF [(match_dup 1)] UNSPEC_VSX_CVDPSPN))
3131 (unspec:V4SF [(match_dup 0)
3132 (const_int 0)] UNSPEC_VSX_XXSPLTW))]
3134 [(set_attr "type" "vecload,vecperm,mftgpr")
3135 (set_attr "length" "4,8,4")])
3137 ;; V4SF/V4SI splat from a vector element
3138 (define_insn "vsx_xxspltw_<mode>"
3139 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
3140 (vec_duplicate:VSX_W
3141 (vec_select:<VS_scalar>
3142 (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
3144 [(match_operand:QI 2 "u5bit_cint_operand" "n")]))))]
3145 "VECTOR_MEM_VSX_P (<MODE>mode)"
3147 if (!BYTES_BIG_ENDIAN)
3148 operands[2] = GEN_INT (3 - INTVAL (operands[2]));
3150 return "xxspltw %x0,%x1,%2";
3152 [(set_attr "type" "vecperm")])
3154 (define_insn "vsx_xxspltw_<mode>_direct"
3155 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
3156 (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
3157 (match_operand:QI 2 "u5bit_cint_operand" "i")]
3158 UNSPEC_VSX_XXSPLTW))]
3159 "VECTOR_MEM_VSX_P (<MODE>mode)"
3160 "xxspltw %x0,%x1,%2"
3161 [(set_attr "type" "vecperm")])
3163 ;; V16QI/V8HI splat support on ISA 2.07
3164 (define_insn "vsx_vsplt<VSX_SPLAT_SUFFIX>_di"
3165 [(set (match_operand:VSX_SPLAT_I 0 "altivec_register_operand" "=v")
3166 (vec_duplicate:VSX_SPLAT_I
3167 (truncate:<VS_scalar>
3168 (match_operand:DI 1 "altivec_register_operand" "v"))))]
3169 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3170 "vsplt<VSX_SPLAT_SUFFIX> %0,%1,<VSX_SPLAT_COUNT>"
3171 [(set_attr "type" "vecperm")])
3173 ;; V2DF/V2DI splat for use by vec_splat builtin
3174 (define_insn "vsx_xxspltd_<mode>"
3175 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
3176 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa")
3177 (match_operand:QI 2 "u5bit_cint_operand" "i")]
3178 UNSPEC_VSX_XXSPLTD))]
3179 "VECTOR_MEM_VSX_P (<MODE>mode)"
3181 if ((VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 0)
3182 || (!VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 1))
3183 return "xxpermdi %x0,%x1,%x1,0";
3185 return "xxpermdi %x0,%x1,%x1,3";
3187 [(set_attr "type" "vecperm")])
3189 ;; V4SF/V4SI interleave
3190 (define_insn "vsx_xxmrghw_<mode>"
3191 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
3193 (vec_concat:<VS_double>
3194 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
3195 (match_operand:VSX_W 2 "vsx_register_operand" "wf,<VSa>"))
3196 (parallel [(const_int 0) (const_int 4)
3197 (const_int 1) (const_int 5)])))]
3198 "VECTOR_MEM_VSX_P (<MODE>mode)"
3200 if (BYTES_BIG_ENDIAN)
3201 return "xxmrghw %x0,%x1,%x2";
3203 return "xxmrglw %x0,%x2,%x1";
3205 [(set_attr "type" "vecperm")])
3207 (define_insn "vsx_xxmrglw_<mode>"
3208 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
3210 (vec_concat:<VS_double>
3211 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
3212 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?<VSa>"))
3213 (parallel [(const_int 2) (const_int 6)
3214 (const_int 3) (const_int 7)])))]
3215 "VECTOR_MEM_VSX_P (<MODE>mode)"
3217 if (BYTES_BIG_ENDIAN)
3218 return "xxmrglw %x0,%x1,%x2";
3220 return "xxmrghw %x0,%x2,%x1";
3222 [(set_attr "type" "vecperm")])
3224 ;; Shift left double by word immediate
3225 (define_insn "vsx_xxsldwi_<mode>"
3226 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSa>")
3227 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "<VSa>")
3228 (match_operand:VSX_L 2 "vsx_register_operand" "<VSa>")
3229 (match_operand:QI 3 "u5bit_cint_operand" "i")]
3231 "VECTOR_MEM_VSX_P (<MODE>mode)"
3232 "xxsldwi %x0,%x1,%x2,%3"
3233 [(set_attr "type" "vecperm")])
3236 ;; Vector reduction insns and splitters
3238 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
3239 [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
3243 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
3244 (parallel [(const_int 1)]))
3247 (parallel [(const_int 0)])))
3249 (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
3250 "VECTOR_UNIT_VSX_P (V2DFmode)"
3256 rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
3257 ? gen_reg_rtx (V2DFmode)
3259 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
3260 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
3263 [(set_attr "length" "8")
3264 (set_attr "type" "veccomplex")])
3266 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
3267 [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
3269 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
3270 (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
3271 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
3272 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
3273 "VECTOR_UNIT_VSX_P (V4SFmode)"
3279 rtx op0 = operands[0];
3280 rtx op1 = operands[1];
3281 rtx tmp2, tmp3, tmp4;
3283 if (can_create_pseudo_p ())
3285 tmp2 = gen_reg_rtx (V4SFmode);
3286 tmp3 = gen_reg_rtx (V4SFmode);
3287 tmp4 = gen_reg_rtx (V4SFmode);
3296 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
3297 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
3298 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
3299 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
3302 [(set_attr "length" "16")
3303 (set_attr "type" "veccomplex")])
3305 ;; Combiner patterns with the vector reduction patterns that knows we can get
3306 ;; to the top element of the V2DF array without doing an extract.
3308 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
3309 [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws")
3314 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
3315 (parallel [(const_int 1)]))
3318 (parallel [(const_int 0)])))
3320 (parallel [(const_int 1)])))
3321 (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
3322 "VECTOR_UNIT_VSX_P (V2DFmode)"
3328 rtx hi = gen_highpart (DFmode, operands[1]);
3329 rtx lo = (GET_CODE (operands[2]) == SCRATCH)
3330 ? gen_reg_rtx (DFmode)
3333 emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
3334 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
3337 [(set_attr "length" "8")
3338 (set_attr "type" "veccomplex")])
3340 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
3341 [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
3344 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
3345 (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
3346 (parallel [(const_int 3)])))
3347 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
3348 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
3349 (clobber (match_scratch:V4SF 4 "=0,0"))]
3350 "VECTOR_UNIT_VSX_P (V4SFmode)"
3356 rtx op0 = operands[0];
3357 rtx op1 = operands[1];
3358 rtx tmp2, tmp3, tmp4, tmp5;
3360 if (can_create_pseudo_p ())
3362 tmp2 = gen_reg_rtx (V4SFmode);
3363 tmp3 = gen_reg_rtx (V4SFmode);
3364 tmp4 = gen_reg_rtx (V4SFmode);
3365 tmp5 = gen_reg_rtx (V4SFmode);
3375 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
3376 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
3377 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
3378 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
3379 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
3382 [(set_attr "length" "20")
3383 (set_attr "type" "veccomplex")])
3386 ;; Power8 Vector fusion. The fused ops must be physically adjacent.
3388 [(set (match_operand:P 0 "base_reg_operand" "")
3389 (match_operand:P 1 "short_cint_operand" ""))
3390 (set (match_operand:VSX_M 2 "vsx_register_operand" "")
3391 (mem:VSX_M (plus:P (match_dup 0)
3392 (match_operand:P 3 "int_reg_operand" ""))))]
3393 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
3394 "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"
3395 [(set_attr "length" "8")
3396 (set_attr "type" "vecload")])
3399 [(set (match_operand:P 0 "base_reg_operand" "")
3400 (match_operand:P 1 "short_cint_operand" ""))
3401 (set (match_operand:VSX_M 2 "vsx_register_operand" "")
3402 (mem:VSX_M (plus:P (match_operand:P 3 "int_reg_operand" "")
3404 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
3405 "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"
3406 [(set_attr "length" "8")
3407 (set_attr "type" "vecload")])
3410 ;; ISA 3.0 vector extend sign support
3412 (define_insn "vsx_sign_extend_qi_<mode>"
3413 [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
3415 [(match_operand:V16QI 1 "vsx_register_operand" "v")]
3416 UNSPEC_VSX_SIGN_EXTEND))]
3419 [(set_attr "type" "vecexts")])
3421 (define_insn "vsx_sign_extend_hi_<mode>"
3422 [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
3424 [(match_operand:V8HI 1 "vsx_register_operand" "v")]
3425 UNSPEC_VSX_SIGN_EXTEND))]
3428 [(set_attr "type" "vecexts")])
3430 (define_insn "*vsx_sign_extend_si_v2di"
3431 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v")
3432 (unspec:V2DI [(match_operand:V4SI 1 "vsx_register_operand" "v")]
3433 UNSPEC_VSX_SIGN_EXTEND))]
3436 [(set_attr "type" "vecexts")])
3439 ;; ISA 3.0 Binary Floating-Point Support
3441 ;; VSX Scalar Extract Exponent Double-Precision
3442 (define_insn "xsxexpdp"
3443 [(set (match_operand:DI 0 "register_operand" "=r")
3444 (unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
3445 UNSPEC_VSX_SXEXPDP))]
3446 "TARGET_P9_VECTOR && TARGET_64BIT"
3448 [(set_attr "type" "integer")])
3450 ;; VSX Scalar Extract Significand Double-Precision
3451 (define_insn "xsxsigdp"
3452 [(set (match_operand:DI 0 "register_operand" "=r")
3453 (unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
3454 UNSPEC_VSX_SXSIGDP))]
3455 "TARGET_P9_VECTOR && TARGET_64BIT"
3457 [(set_attr "type" "integer")])
3459 ;; VSX Scalar Insert Exponent Double-Precision
3460 (define_insn "xsiexpdp"
3461 [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
3462 (unspec:DF [(match_operand:DI 1 "register_operand" "r")
3463 (match_operand:DI 2 "register_operand" "r")]
3464 UNSPEC_VSX_SIEXPDP))]
3465 "TARGET_P9_VECTOR && TARGET_64BIT"
3466 "xsiexpdp %x0,%1,%2"
3467 [(set_attr "type" "fpsimple")])
3469 ;; VSX Scalar Insert Exponent Double-Precision Floating Point Argument
3470 (define_insn "xsiexpdpf"
3471 [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
3472 (unspec:DF [(match_operand:DF 1 "register_operand" "r")
3473 (match_operand:DI 2 "register_operand" "r")]
3474 UNSPEC_VSX_SIEXPDP))]
3475 "TARGET_P9_VECTOR && TARGET_64BIT"
3476 "xsiexpdp %x0,%1,%2"
3477 [(set_attr "type" "fpsimple")])
3479 ;; VSX Scalar Compare Exponents Double-Precision
3480 (define_expand "xscmpexpdp_<code>"
3484 [(match_operand:DF 1 "vsx_register_operand" "wa")
3485 (match_operand:DF 2 "vsx_register_operand" "wa")]
3486 UNSPEC_VSX_SCMPEXPDP)
3488 (set (match_operand:SI 0 "register_operand" "=r")
3489 (CMP_TEST:SI (match_dup 3)
3493 operands[3] = gen_reg_rtx (CCFPmode);
3496 (define_insn "*xscmpexpdp"
3497 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
3499 (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "wa")
3500 (match_operand:DF 2 "vsx_register_operand" "wa")]
3501 UNSPEC_VSX_SCMPEXPDP)
3502 (match_operand:SI 3 "zero_constant" "j")))]
3504 "xscmpexpdp %0,%x1,%x2"
3505 [(set_attr "type" "fpcompare")])
3507 ;; VSX Scalar Test Data Class Double- and Single-Precision
3508 ;; (The lt bit is set if operand 1 is negative. The eq bit is set
3509 ;; if any of the conditions tested by operand 2 are satisfied.
3510 ;; The gt and unordered bits are cleared to zero.)
3511 (define_expand "xststdc<Fvsx>"
3515 [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3516 (match_operand:SI 2 "u7bit_cint_operand" "n")]
3519 (set (match_operand:SI 0 "register_operand" "=r")
3520 (eq:SI (match_dup 3)
3524 operands[3] = gen_reg_rtx (CCFPmode);
3525 operands[4] = CONST0_RTX (SImode);
3528 ;; The VSX Scalar Test Data Class Double- and Single-Precision
3529 ;; instruction may also be used to test for negative value.
3530 (define_expand "xststdcneg<Fvsx>"
3534 [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3538 (set (match_operand:SI 0 "register_operand" "=r")
3539 (lt:SI (match_dup 2)
3543 operands[2] = gen_reg_rtx (CCFPmode);
3544 operands[3] = CONST0_RTX (SImode);
3547 (define_insn "*xststdc<Fvsx>"
3548 [(set (match_operand:CCFP 0 "" "=y")
3550 (unspec:SFDF [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3551 (match_operand:SI 2 "u7bit_cint_operand" "n")]
3553 (match_operand:SI 3 "zero_constant" "j")))]
3555 "xststdc<Fvsx> %0,%x1,%2"
3556 [(set_attr "type" "fpcompare")])
3558 ;; VSX Vector Extract Exponent Double and Single Precision
3559 (define_insn "xvxexp<VSs>"
3560 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3562 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
3565 "xvxexp<VSs> %x0,%x1"
3566 [(set_attr "type" "vecsimple")])
3568 ;; VSX Vector Extract Significand Double and Single Precision
3569 (define_insn "xvxsig<VSs>"
3570 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3572 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
3575 "xvxsig<VSs> %x0,%x1"
3576 [(set_attr "type" "vecsimple")])
3578 ;; VSX Vector Insert Exponent Double and Single Precision
3579 (define_insn "xviexp<VSs>"
3580 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3582 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3583 (match_operand:VSX_F 2 "vsx_register_operand" "wa")]
3586 "xviexp<VSs> %x0,%x1,%x2"
3587 [(set_attr "type" "vecsimple")])
3589 ;; VSX Vector Test Data Class Double and Single Precision
3590 ;; The corresponding elements of the result vector are all ones
3591 ;; if any of the conditions tested by operand 3 are satisfied.
3592 (define_insn "xvtstdc<VSs>"
3593 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=wa")
3595 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3596 (match_operand:SI 2 "u7bit_cint_operand" "n")]
3597 UNSPEC_VSX_VTSTDC))]
3599 "xvtstdc<VSs> %x0,%x1,%2"
3600 [(set_attr "type" "vecsimple")])
3602 ;; ISA 3.0 String Operations Support
3604 ;; Compare vectors producing a vector result and a predicate, setting CR6
3605 ;; to indicate a combined status. This pattern matches v16qi, v8hi, and
3606 ;; v4si modes. It does not match v2df, v4sf, or v2di modes. There's no
3607 ;; need to match v4sf, v2df, or v2di modes because those are expanded
3608 ;; to use Power8 instructions.
3609 (define_insn "*vsx_ne_<mode>_p"
3610 [(set (reg:CC CR6_REGNO)
3612 [(ne:CC (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
3613 (match_operand:VSX_EXTRACT_I 2 "gpc_reg_operand" "v"))]
3615 (set (match_operand:VSX_EXTRACT_I 0 "gpc_reg_operand" "=v")
3616 (ne:VSX_EXTRACT_I (match_dup 1)
3619 "vcmpne<VSX_EXTRACT_WIDTH>. %0,%1,%2"
3620 [(set_attr "type" "vecsimple")])
3622 (define_insn "*vector_nez_<mode>_p"
3623 [(set (reg:CC CR6_REGNO)
3624 (unspec:CC [(unspec:VI
3625 [(match_operand:VI 1 "gpc_reg_operand" "v")
3626 (match_operand:VI 2 "gpc_reg_operand" "v")]
3629 (set (match_operand:VI 0 "gpc_reg_operand" "=v")
3630 (unspec:VI [(match_dup 1)
3634 "vcmpnez<VSX_EXTRACT_WIDTH>. %0,%1,%2"
3635 [(set_attr "type" "vecsimple")])
3637 ;; Load VSX Vector with Length
3638 (define_expand "lxvl"
3640 (match_operand:DI 2 "register_operand"))
3641 (set (match_operand:V16QI 0 "vsx_register_operand")
3643 [(match_operand:DI 1 "gpc_reg_operand")
3646 "TARGET_P9_VECTOR && TARGET_64BIT"
3648 operands[3] = gen_reg_rtx (DImode);
3651 (define_insn "*lxvl"
3652 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3654 [(match_operand:DI 1 "gpc_reg_operand" "b")
3655 (match_operand:DI 2 "register_operand" "+r")]
3657 "TARGET_P9_VECTOR && TARGET_64BIT"
3658 "sldi %2,%2, 56\; lxvl %x0,%1,%2"
3659 [(set_attr "length" "8")
3660 (set_attr "type" "vecload")])
3662 ;; Store VSX Vector with Length
3663 (define_expand "stxvl"
3665 (match_operand:DI 2 "register_operand"))
3666 (set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand"))
3668 [(match_operand:V16QI 0 "vsx_register_operand")
3671 "TARGET_P9_VECTOR && TARGET_64BIT"
3673 operands[3] = gen_reg_rtx (DImode);
3676 (define_insn "*stxvl"
3677 [(set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand" "b"))
3679 [(match_operand:V16QI 0 "vsx_register_operand" "wa")
3680 (match_operand:DI 2 "register_operand" "+r")]
3682 "TARGET_P9_VECTOR && TARGET_64BIT"
3683 "sldi %2,%2\;stxvl %x0,%1,%2"
3684 [(set_attr "length" "8")
3685 (set_attr "type" "vecstore")])
3687 ;; Vector Compare Not Equal Byte
3688 (define_insn "vcmpneb"
3689 [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
3690 (unspec:V16QI [(match_operand:V16QI 1 "altivec_register_operand" "v")
3691 (match_operand:V16QI 2 "altivec_register_operand" "v")]
3695 [(set_attr "type" "vecsimple")])
3697 ;; Vector Compare Not Equal or Zero Byte
3698 (define_insn "vcmpnezb"
3699 [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
3701 [(match_operand:V16QI 1 "altivec_register_operand" "v")
3702 (match_operand:V16QI 2 "altivec_register_operand" "v")]
3706 [(set_attr "type" "vecsimple")])
3708 ;; Vector Compare Not Equal Half Word
3709 (define_insn "vcmpneh"
3710 [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
3711 (unspec:V8HI [(match_operand:V8HI 1 "altivec_register_operand" "v")
3712 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3716 [(set_attr "type" "vecsimple")])
3718 ;; Vector Compare Not Equal or Zero Half Word
3719 (define_insn "vcmpnezh"
3720 [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
3721 (unspec:V8HI [(match_operand:V8HI 1 "altivec_register_operand" "v")
3722 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3726 [(set_attr "type" "vecsimple")])
3728 ;; Vector Compare Not Equal Word
3729 (define_insn "vcmpnew"
3730 [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
3732 [(match_operand:V4SI 1 "altivec_register_operand" "v")
3733 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3737 [(set_attr "type" "vecsimple")])
3739 ;; Vector Compare Not Equal or Zero Word
3740 (define_insn "vcmpnezw"
3741 [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
3742 (unspec:V4SI [(match_operand:V4SI 1 "altivec_register_operand" "v")
3743 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3747 [(set_attr "type" "vecsimple")])
3749 ;; Vector Count Leading Zero Least-Significant Bits Byte
3750 (define_insn "vclzlsbb"
3751 [(set (match_operand:SI 0 "register_operand" "=r")
3753 [(match_operand:V16QI 1 "altivec_register_operand" "v")]
3757 [(set_attr "type" "vecsimple")])
3759 ;; Vector Count Trailing Zero Least-Significant Bits Byte
3760 (define_insn "vctzlsbb"
3761 [(set (match_operand:SI 0 "register_operand" "=r")
3763 [(match_operand:V16QI 1 "altivec_register_operand" "v")]
3767 [(set_attr "type" "vecsimple")])
3769 ;; Vector Extract Unsigned Byte Left-Indexed
3770 (define_insn "vextublx"
3771 [(set (match_operand:SI 0 "register_operand" "=r")
3773 [(match_operand:SI 1 "register_operand" "r")
3774 (match_operand:V16QI 2 "altivec_register_operand" "v")]
3778 [(set_attr "type" "vecsimple")])
3780 ;; Vector Extract Unsigned Byte Right-Indexed
3781 (define_insn "vextubrx"
3782 [(set (match_operand:SI 0 "register_operand" "=r")
3784 [(match_operand:SI 1 "register_operand" "r")
3785 (match_operand:V16QI 2 "altivec_register_operand" "v")]
3789 [(set_attr "type" "vecsimple")])
3791 ;; Vector Extract Unsigned Half Word Left-Indexed
3792 (define_insn "vextuhlx"
3793 [(set (match_operand:SI 0 "register_operand" "=r")
3795 [(match_operand:SI 1 "register_operand" "r")
3796 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3800 [(set_attr "type" "vecsimple")])
3802 ;; Vector Extract Unsigned Half Word Right-Indexed
3803 (define_insn "vextuhrx"
3804 [(set (match_operand:SI 0 "register_operand" "=r")
3806 [(match_operand:SI 1 "register_operand" "r")
3807 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3811 [(set_attr "type" "vecsimple")])
3813 ;; Vector Extract Unsigned Word Left-Indexed
3814 (define_insn "vextuwlx"
3815 [(set (match_operand:SI 0 "register_operand" "=r")
3817 [(match_operand:SI 1 "register_operand" "r")
3818 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3822 [(set_attr "type" "vecsimple")])
3824 ;; Vector Extract Unsigned Word Right-Indexed
3825 (define_insn "vextuwrx"
3826 [(set (match_operand:SI 0 "register_operand" "=r")
3828 [(match_operand:SI 1 "register_operand" "r")
3829 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3833 [(set_attr "type" "vecsimple")])
3835 ;; Vector insert/extract word at arbitrary byte values. Note, the little
3836 ;; endian version needs to adjust the byte number, and the V4SI element in
3838 (define_expand "vextract4b"
3839 [(set (match_operand:DI 0 "gpc_reg_operand")
3840 (unspec:DI [(match_operand:V16QI 1 "vsx_register_operand")
3841 (match_operand:QI 2 "const_0_to_12_operand")]
3842 UNSPEC_XXEXTRACTUW))]
3845 if (!VECTOR_ELT_ORDER_BIG)
3846 operands[2] = GEN_INT (12 - INTVAL (operands[2]));
3849 (define_insn_and_split "*vextract4b_internal"
3850 [(set (match_operand:DI 0 "gpc_reg_operand" "=wj,r")
3851 (unspec:DI [(match_operand:V16QI 1 "vsx_register_operand" "wa,v")
3852 (match_operand:QI 2 "const_0_to_12_operand" "n,n")]
3853 UNSPEC_XXEXTRACTUW))]
3856 xxextractuw %x0,%x1,%2
3858 "&& reload_completed && int_reg_operand (operands[0], DImode)"
3861 rtx op0 = operands[0];
3862 rtx op1 = operands[1];
3863 rtx op2 = operands[2];
3864 rtx op0_si = gen_rtx_REG (SImode, REGNO (op0));
3865 rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (op1));
3867 emit_move_insn (op0, op2);
3868 if (VECTOR_ELT_ORDER_BIG)
3869 emit_insn (gen_vextuwlx (op0_si, op0_si, op1_v4si));
3871 emit_insn (gen_vextuwrx (op0_si, op0_si, op1_v4si));
3874 [(set_attr "type" "vecperm")])
3876 (define_expand "vinsert4b"
3877 [(set (match_operand:V16QI 0 "vsx_register_operand")
3878 (unspec:V16QI [(match_operand:V4SI 1 "vsx_register_operand")
3879 (match_operand:V16QI 2 "vsx_register_operand")
3880 (match_operand:QI 3 "const_0_to_12_operand")]
3884 if (!VECTOR_ELT_ORDER_BIG)
3886 rtx op1 = operands[1];
3887 rtx v4si_tmp = gen_reg_rtx (V4SImode);
3888 emit_insn (gen_vsx_xxpermdi_v4si_be (v4si_tmp, op1, op1, const1_rtx));
3889 operands[1] = v4si_tmp;
3890 operands[3] = GEN_INT (12 - INTVAL (operands[3]));
3894 (define_insn "*vinsert4b_internal"
3895 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3896 (unspec:V16QI [(match_operand:V4SI 1 "vsx_register_operand" "wa")
3897 (match_operand:V16QI 2 "vsx_register_operand" "0")
3898 (match_operand:QI 3 "const_0_to_12_operand" "n")]
3901 "xxinsertw %x0,%x1,%3"
3902 [(set_attr "type" "vecperm")])
3904 (define_expand "vinsert4b_di"
3905 [(set (match_operand:V16QI 0 "vsx_register_operand")
3906 (unspec:V16QI [(match_operand:DI 1 "vsx_register_operand")
3907 (match_operand:V16QI 2 "vsx_register_operand")
3908 (match_operand:QI 3 "const_0_to_12_operand")]
3912 if (!VECTOR_ELT_ORDER_BIG)
3913 operands[3] = GEN_INT (12 - INTVAL (operands[3]));
3916 (define_insn "*vinsert4b_di_internal"
3917 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3918 (unspec:V16QI [(match_operand:DI 1 "vsx_register_operand" "wj")
3919 (match_operand:V16QI 2 "vsx_register_operand" "0")
3920 (match_operand:QI 3 "const_0_to_12_operand" "n")]
3923 "xxinsertw %x0,%x1,%3"
3924 [(set_attr "type" "vecperm")])
3927 ;; Support for ISA 3.0 vector byte reverse
3929 ;; Swap all bytes with in a vector
3930 (define_insn "p9_xxbrq_v1ti"
3931 [(set (match_operand:V1TI 0 "vsx_register_operand" "=wa")
3932 (bswap:V1TI (match_operand:V1TI 1 "vsx_register_operand" "wa")))]
3935 [(set_attr "type" "vecperm")])
3937 (define_expand "p9_xxbrq_v16qi"
3938 [(use (match_operand:V16QI 0 "vsx_register_operand" "=wa"))
3939 (use (match_operand:V16QI 1 "vsx_register_operand" "=wa"))]
3942 rtx op0 = gen_lowpart (V1TImode, operands[0]);
3943 rtx op1 = gen_lowpart (V1TImode, operands[1]);
3944 emit_insn (gen_p9_xxbrq_v1ti (op0, op1));
3948 ;; Swap all bytes in each 64-bit element
3949 (define_insn "p9_xxbrd_<mode>"
3950 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
3951 (bswap:VSX_D (match_operand:VSX_D 1 "vsx_register_operand" "wa")))]
3954 [(set_attr "type" "vecperm")])
3956 ;; Swap all bytes in each 32-bit element
3957 (define_insn "p9_xxbrw_<mode>"
3958 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
3959 (bswap:VSX_W (match_operand:VSX_W 1 "vsx_register_operand" "wa")))]
3962 [(set_attr "type" "vecperm")])
3964 ;; Swap all bytes in each 16-bit element
3965 (define_insn "p9_xxbrh_v8hi"
3966 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
3967 (bswap:V8HI (match_operand:V8HI 1 "vsx_register_operand" "wa")))]
3970 [(set_attr "type" "vecperm")])
3973 ;; Operand numbers for the following peephole2
3975 [(SFBOOL_TMP_GPR 0) ;; GPR temporary
3976 (SFBOOL_TMP_VSX 1) ;; vector temporary
3977 (SFBOOL_MFVSR_D 2) ;; move to gpr dest
3978 (SFBOOL_MFVSR_A 3) ;; move to gpr src
3979 (SFBOOL_BOOL_D 4) ;; and/ior/xor dest
3980 (SFBOOL_BOOL_A1 5) ;; and/ior/xor arg1
3981 (SFBOOL_BOOL_A2 6) ;; and/ior/xor arg1
3982 (SFBOOL_SHL_D 7) ;; shift left dest
3983 (SFBOOL_SHL_A 8) ;; shift left arg
3984 (SFBOOL_MTVSR_D 9) ;; move to vecter dest
3985 (SFBOOL_BOOL_A_DI 10) ;; SFBOOL_BOOL_A1/A2 as DImode
3986 (SFBOOL_TMP_VSX_DI 11) ;; SFBOOL_TMP_VSX as DImode
3987 (SFBOOL_MTVSR_D_V4SF 12)]) ;; SFBOOL_MTVSRD_D as V4SFmode
3989 ;; Attempt to optimize some common GLIBC operations using logical operations to
3990 ;; pick apart SFmode operations. For example, there is code from e_powf.c
3991 ;; after macro expansion that looks like:
3996 ;; } ieee_float_shape_type;
4002 ;; ieee_float_shape_type gf_u;
4003 ;; gf_u.value = (t1);
4004 ;; (is) = gf_u.word;
4008 ;; ieee_float_shape_type sf_u;
4009 ;; sf_u.word = (is & 0xfffff000);
4010 ;; (t1) = sf_u.value;
4014 ;; This would result in two direct move operations (convert to memory format,
4015 ;; direct move to GPR, do the AND operation, direct move to VSX, convert to
4016 ;; scalar format). With this peephole, we eliminate the direct move to the
4017 ;; GPR, and instead move the integer mask value to the vector register after a
4018 ;; shift and do the VSX logical operation.
4020 ;; The insns for dealing with SFmode in GPR registers looks like:
4021 ;; (set (reg:V4SF reg2) (unspec:V4SF [(reg:SF reg1)] UNSPEC_VSX_CVDPSPN))
4023 ;; (set (reg:DI reg3) (unspec:DI [(reg:V4SF reg2)] UNSPEC_P8V_RELOAD_FROM_VSX))
4025 ;; (set (reg:DI reg3) (lshiftrt:DI (reg:DI reg3) (const_int 32)))
4027 ;; (set (reg:DI reg5) (and:DI (reg:DI reg3) (reg:DI reg4)))
4029 ;; (set (reg:DI reg6) (ashift:DI (reg:DI reg5) (const_int 32)))
4031 ;; (set (reg:SF reg7) (unspec:SF [(reg:DI reg6)] UNSPEC_P8V_MTVSRD))
4033 ;; (set (reg:SF reg7) (unspec:SF [(reg:SF reg7)] UNSPEC_VSX_CVSPDPN))
4036 [(match_scratch:DI SFBOOL_TMP_GPR "r")
4037 (match_scratch:V4SF SFBOOL_TMP_VSX "wa")
4040 (set (match_operand:DI SFBOOL_MFVSR_D "int_reg_operand")
4041 (unspec:DI [(match_operand:V4SF SFBOOL_MFVSR_A "vsx_register_operand")]
4042 UNSPEC_P8V_RELOAD_FROM_VSX))
4045 (set (match_dup SFBOOL_MFVSR_D)
4046 (lshiftrt:DI (match_dup SFBOOL_MFVSR_D)
4049 ;; AND/IOR/XOR operation on int
4050 (set (match_operand:SI SFBOOL_BOOL_D "int_reg_operand")
4051 (and_ior_xor:SI (match_operand:SI SFBOOL_BOOL_A1 "int_reg_operand")
4052 (match_operand:SI SFBOOL_BOOL_A2 "reg_or_cint_operand")))
4055 (set (match_operand:DI SFBOOL_SHL_D "int_reg_operand")
4056 (ashift:DI (match_operand:DI SFBOOL_SHL_A "int_reg_operand")
4060 (set (match_operand:SF SFBOOL_MTVSR_D "vsx_register_operand")
4061 (unspec:SF [(match_dup SFBOOL_SHL_D)] UNSPEC_P8V_MTVSRD))]
4063 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE
4064 /* The REG_P (xxx) tests prevents SUBREG's, which allows us to use REGNO
4065 to compare registers, when the mode is different. */
4066 && REG_P (operands[SFBOOL_MFVSR_D]) && REG_P (operands[SFBOOL_BOOL_D])
4067 && REG_P (operands[SFBOOL_BOOL_A1]) && REG_P (operands[SFBOOL_SHL_D])
4068 && REG_P (operands[SFBOOL_SHL_A]) && REG_P (operands[SFBOOL_MTVSR_D])
4069 && (REG_P (operands[SFBOOL_BOOL_A2])
4070 || CONST_INT_P (operands[SFBOOL_BOOL_A2]))
4071 && (REGNO (operands[SFBOOL_BOOL_D]) == REGNO (operands[SFBOOL_MFVSR_D])
4072 || peep2_reg_dead_p (3, operands[SFBOOL_MFVSR_D]))
4073 && (REGNO (operands[SFBOOL_MFVSR_D]) == REGNO (operands[SFBOOL_BOOL_A1])
4074 || (REG_P (operands[SFBOOL_BOOL_A2])
4075 && REGNO (operands[SFBOOL_MFVSR_D])
4076 == REGNO (operands[SFBOOL_BOOL_A2])))
4077 && REGNO (operands[SFBOOL_BOOL_D]) == REGNO (operands[SFBOOL_SHL_A])
4078 && (REGNO (operands[SFBOOL_SHL_D]) == REGNO (operands[SFBOOL_BOOL_D])
4079 || peep2_reg_dead_p (4, operands[SFBOOL_BOOL_D]))
4080 && peep2_reg_dead_p (5, operands[SFBOOL_SHL_D])"
4081 [(set (match_dup SFBOOL_TMP_GPR)
4082 (ashift:DI (match_dup SFBOOL_BOOL_A_DI)
4085 (set (match_dup SFBOOL_TMP_VSX_DI)
4086 (match_dup SFBOOL_TMP_GPR))
4088 (set (match_dup SFBOOL_MTVSR_D_V4SF)
4089 (and_ior_xor:V4SF (match_dup SFBOOL_MFVSR_A)
4090 (match_dup SFBOOL_TMP_VSX)))]
4092 rtx bool_a1 = operands[SFBOOL_BOOL_A1];
4093 rtx bool_a2 = operands[SFBOOL_BOOL_A2];
4094 int regno_mfvsr_d = REGNO (operands[SFBOOL_MFVSR_D]);
4095 int regno_tmp_vsx = REGNO (operands[SFBOOL_TMP_VSX]);
4096 int regno_mtvsr_d = REGNO (operands[SFBOOL_MTVSR_D]);
4098 if (CONST_INT_P (bool_a2))
4100 rtx tmp_gpr = operands[SFBOOL_TMP_GPR];
4101 emit_move_insn (tmp_gpr, bool_a2);
4102 operands[SFBOOL_BOOL_A_DI] = tmp_gpr;
4106 int regno_bool_a1 = REGNO (bool_a1);
4107 int regno_bool_a2 = REGNO (bool_a2);
4108 int regno_bool_a = (regno_mfvsr_d == regno_bool_a1
4109 ? regno_bool_a2 : regno_bool_a1);
4110 operands[SFBOOL_BOOL_A_DI] = gen_rtx_REG (DImode, regno_bool_a);
4113 operands[SFBOOL_TMP_VSX_DI] = gen_rtx_REG (DImode, regno_tmp_vsx);
4114 operands[SFBOOL_MTVSR_D_V4SF] = gen_rtx_REG (V4SFmode, regno_mtvsr_d);