2 ;; Copyright (C) 2009-2017 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
2423 && TARGET_UPPER_REGS_SF"
2425 "&& reload_completed"
2428 rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2429 operands[3], operands[4]);
2433 ;; Expand the builtin form of xxpermdi to canonical rtl.
2434 (define_expand "vsx_xxpermdi_<mode>"
2435 [(match_operand:VSX_L 0 "vsx_register_operand")
2436 (match_operand:VSX_L 1 "vsx_register_operand")
2437 (match_operand:VSX_L 2 "vsx_register_operand")
2438 (match_operand:QI 3 "u5bit_cint_operand")]
2439 "VECTOR_MEM_VSX_P (<MODE>mode)"
2441 rtx target = operands[0];
2442 rtx op0 = operands[1];
2443 rtx op1 = operands[2];
2444 int mask = INTVAL (operands[3]);
2445 rtx perm0 = GEN_INT ((mask >> 1) & 1);
2446 rtx perm1 = GEN_INT ((mask & 1) + 2);
2447 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2449 if (<MODE>mode == V2DFmode)
2450 gen = gen_vsx_xxpermdi2_v2df_1;
2453 gen = gen_vsx_xxpermdi2_v2di_1;
2454 if (<MODE>mode != V2DImode)
2456 target = gen_lowpart (V2DImode, target);
2457 op0 = gen_lowpart (V2DImode, op0);
2458 op1 = gen_lowpart (V2DImode, op1);
2461 emit_insn (gen (target, op0, op1, perm0, perm1));
2465 ;; Special version of xxpermdi that retains big-endian semantics.
2466 (define_expand "vsx_xxpermdi_<mode>_be"
2467 [(match_operand:VSX_L 0 "vsx_register_operand")
2468 (match_operand:VSX_L 1 "vsx_register_operand")
2469 (match_operand:VSX_L 2 "vsx_register_operand")
2470 (match_operand:QI 3 "u5bit_cint_operand")]
2471 "VECTOR_MEM_VSX_P (<MODE>mode)"
2473 rtx target = operands[0];
2474 rtx op0 = operands[1];
2475 rtx op1 = operands[2];
2476 int mask = INTVAL (operands[3]);
2477 rtx perm0 = GEN_INT ((mask >> 1) & 1);
2478 rtx perm1 = GEN_INT ((mask & 1) + 2);
2479 rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
2481 if (<MODE>mode == V2DFmode)
2482 gen = gen_vsx_xxpermdi2_v2df_1;
2485 gen = gen_vsx_xxpermdi2_v2di_1;
2486 if (<MODE>mode != V2DImode)
2488 target = gen_lowpart (V2DImode, target);
2489 op0 = gen_lowpart (V2DImode, op0);
2490 op1 = gen_lowpart (V2DImode, op1);
2493 /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
2494 transformation we don't want; it is necessary for
2495 rs6000_expand_vec_perm_const_1 but not for this use. So we
2496 prepare for that by reversing the transformation here. */
2497 if (BYTES_BIG_ENDIAN)
2498 emit_insn (gen (target, op0, op1, perm0, perm1));
2501 rtx p0 = GEN_INT (3 - INTVAL (perm1));
2502 rtx p1 = GEN_INT (3 - INTVAL (perm0));
2503 emit_insn (gen (target, op1, op0, p0, p1));
2508 (define_insn "vsx_xxpermdi2_<mode>_1"
2509 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
2511 (vec_concat:<VS_double>
2512 (match_operand:VSX_D 1 "vsx_register_operand" "wd")
2513 (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
2514 (parallel [(match_operand 3 "const_0_to_1_operand" "")
2515 (match_operand 4 "const_2_to_3_operand" "")])))]
2516 "VECTOR_MEM_VSX_P (<MODE>mode)"
2520 /* For little endian, swap operands and invert/swap selectors
2521 to get the correct xxpermdi. The operand swap sets up the
2522 inputs as a little endian array. The selectors are swapped
2523 because they are defined to use big endian ordering. The
2524 selectors are inverted to get the correct doublewords for
2525 little endian ordering. */
2526 if (BYTES_BIG_ENDIAN)
2528 op3 = INTVAL (operands[3]);
2529 op4 = INTVAL (operands[4]);
2533 op3 = 3 - INTVAL (operands[4]);
2534 op4 = 3 - INTVAL (operands[3]);
2537 mask = (op3 << 1) | (op4 - 2);
2538 operands[3] = GEN_INT (mask);
2540 if (BYTES_BIG_ENDIAN)
2541 return "xxpermdi %x0,%x1,%x2,%3";
2543 return "xxpermdi %x0,%x2,%x1,%3";
2545 [(set_attr "type" "vecperm")])
2547 (define_expand "vec_perm_const<mode>"
2548 [(match_operand:VSX_D 0 "vsx_register_operand" "")
2549 (match_operand:VSX_D 1 "vsx_register_operand" "")
2550 (match_operand:VSX_D 2 "vsx_register_operand" "")
2551 (match_operand:V2DI 3 "" "")]
2552 "VECTOR_MEM_VSX_P (<MODE>mode)"
2554 if (rs6000_expand_vec_perm_const (operands))
2560 ;; Extraction of a single element in a small integer vector. Until ISA 3.0,
2561 ;; none of the small types were allowed in a vector register, so we had to
2562 ;; extract to a DImode and either do a direct move or store.
2563 (define_expand "vsx_extract_<mode>"
2564 [(parallel [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand")
2565 (vec_select:<VS_scalar>
2566 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand")
2567 (parallel [(match_operand:QI 2 "const_int_operand")])))
2568 (clobber (match_scratch:VSX_EXTRACT_I 3))])]
2569 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2571 /* If we have ISA 3.0, we can do a xxextractuw/vextractu{b,h}. */
2572 if (TARGET_VSX_SMALL_INTEGER && TARGET_P9_VECTOR)
2574 emit_insn (gen_vsx_extract_<mode>_p9 (operands[0], operands[1],
2580 (define_insn "vsx_extract_<mode>_p9"
2581 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,<VSX_EX>")
2582 (vec_select:<VS_scalar>
2583 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
2584 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
2585 (clobber (match_scratch:SI 3 "=r,X"))]
2586 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2587 && TARGET_VSX_SMALL_INTEGER"
2589 if (which_alternative == 0)
2594 HOST_WIDE_INT elt = INTVAL (operands[2]);
2595 HOST_WIDE_INT elt_adj = (!VECTOR_ELT_ORDER_BIG
2596 ? GET_MODE_NUNITS (<MODE>mode) - 1 - elt
2599 HOST_WIDE_INT unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
2600 HOST_WIDE_INT offset = unit_size * elt_adj;
2602 operands[2] = GEN_INT (offset);
2604 return "xxextractuw %x0,%x1,%2";
2606 return "vextractu<wd> %0,%1,%2";
2609 [(set_attr "type" "vecsimple")])
2612 [(set (match_operand:<VS_scalar> 0 "int_reg_operand")
2613 (vec_select:<VS_scalar>
2614 (match_operand:VSX_EXTRACT_I 1 "altivec_register_operand")
2615 (parallel [(match_operand:QI 2 "const_int_operand")])))
2616 (clobber (match_operand:SI 3 "int_reg_operand"))]
2617 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2618 && TARGET_VSX_SMALL_INTEGER && reload_completed"
2621 rtx op0_si = gen_rtx_REG (SImode, REGNO (operands[0]));
2622 rtx op1 = operands[1];
2623 rtx op2 = operands[2];
2624 rtx op3 = operands[3];
2625 HOST_WIDE_INT offset = INTVAL (op2) * GET_MODE_UNIT_SIZE (<MODE>mode);
2627 emit_move_insn (op3, GEN_INT (offset));
2628 if (VECTOR_ELT_ORDER_BIG)
2629 emit_insn (gen_vextu<wd>lx (op0_si, op3, op1));
2631 emit_insn (gen_vextu<wd>rx (op0_si, op3, op1));
2635 ;; Optimize zero extracts to eliminate the AND after the extract.
2636 (define_insn_and_split "*vsx_extract_<mode>_di_p9"
2637 [(set (match_operand:DI 0 "gpc_reg_operand" "=r,<VSX_EX>")
2639 (vec_select:<VS_scalar>
2640 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
2641 (parallel [(match_operand:QI 2 "const_int_operand" "n,n")]))))
2642 (clobber (match_scratch:SI 3 "=r,X"))]
2643 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2644 && TARGET_VSX_SMALL_INTEGER"
2646 "&& reload_completed"
2647 [(parallel [(set (match_dup 4)
2648 (vec_select:<VS_scalar>
2650 (parallel [(match_dup 2)])))
2651 (clobber (match_dup 3))])]
2653 operands[4] = gen_rtx_REG (<VS_scalar>mode, REGNO (operands[0]));
2656 ;; Optimize stores to use the ISA 3.0 scalar store instructions
2657 (define_insn_and_split "*vsx_extract_<mode>_store_p9"
2658 [(set (match_operand:<VS_scalar> 0 "memory_operand" "=Z,m")
2659 (vec_select:<VS_scalar>
2660 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>,v")
2661 (parallel [(match_operand:QI 2 "const_int_operand" "n,n")])))
2662 (clobber (match_scratch:<VS_scalar> 3 "=<VSX_EX>,&r"))
2663 (clobber (match_scratch:SI 4 "=X,&r"))]
2664 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
2665 && TARGET_VSX_SMALL_INTEGER"
2667 "&& reload_completed"
2668 [(parallel [(set (match_dup 3)
2669 (vec_select:<VS_scalar>
2671 (parallel [(match_dup 2)])))
2672 (clobber (match_dup 4))])
2676 (define_insn_and_split "*vsx_extract_si"
2677 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,wHwI,Z")
2679 (match_operand:V4SI 1 "gpc_reg_operand" "wJv,wJv,wJv")
2680 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n")])))
2681 (clobber (match_scratch:V4SI 3 "=wJv,wJv,wJv"))]
2682 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT
2683 && (!TARGET_P9_VECTOR || !TARGET_VSX_SMALL_INTEGER)"
2685 "&& reload_completed"
2688 rtx dest = operands[0];
2689 rtx src = operands[1];
2690 rtx element = operands[2];
2691 rtx vec_tmp = operands[3];
2694 if (!VECTOR_ELT_ORDER_BIG)
2695 element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2697 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2699 value = INTVAL (element);
2702 if (TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER)
2704 rtx si_tmp = gen_rtx_REG (SImode, REGNO (vec_tmp));
2705 emit_insn (gen_vsx_extract_v4si_p9 (si_tmp,src, element));
2708 emit_insn (gen_altivec_vspltw_direct (vec_tmp, src, element));
2713 if (MEM_P (operands[0]))
2715 if (can_create_pseudo_p ())
2716 dest = rs6000_address_for_fpconvert (dest);
2718 if (TARGET_VSX_SMALL_INTEGER)
2719 emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
2721 emit_insn (gen_stfiwx (dest, gen_rtx_REG (DImode, REGNO (vec_tmp))));
2724 else if (TARGET_VSX_SMALL_INTEGER)
2725 emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
2727 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
2728 gen_rtx_REG (DImode, REGNO (vec_tmp)));
2732 [(set_attr "type" "mftgpr,vecperm,fpstore")
2733 (set_attr "length" "8")])
2735 (define_insn_and_split "*vsx_extract_<mode>_p8"
2736 [(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r")
2737 (vec_select:<VS_scalar>
2738 (match_operand:VSX_EXTRACT_I2 1 "gpc_reg_operand" "v")
2739 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
2740 (clobber (match_scratch:VSX_EXTRACT_I2 3 "=v"))]
2741 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT
2742 && (!TARGET_P9_VECTOR || !TARGET_VSX_SMALL_INTEGER)"
2744 "&& reload_completed"
2747 rtx dest = operands[0];
2748 rtx src = operands[1];
2749 rtx element = operands[2];
2750 rtx vec_tmp = operands[3];
2753 if (!VECTOR_ELT_ORDER_BIG)
2754 element = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1 - INTVAL (element));
2756 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2758 value = INTVAL (element);
2759 if (<MODE>mode == V16QImode)
2762 emit_insn (gen_altivec_vspltb_direct (vec_tmp, src, element));
2766 else if (<MODE>mode == V8HImode)
2769 emit_insn (gen_altivec_vsplth_direct (vec_tmp, src, element));
2776 emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
2777 gen_rtx_REG (DImode, REGNO (vec_tmp)));
2780 [(set_attr "type" "mftgpr")])
2782 ;; Optimize extracting a single scalar element from memory.
2783 (define_insn_and_split "*vsx_extract_<mode>_load"
2784 [(set (match_operand:<VS_scalar> 0 "register_operand" "=r")
2785 (vec_select:<VS_scalar>
2786 (match_operand:VSX_EXTRACT_I 1 "memory_operand" "m")
2787 (parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
2788 (clobber (match_scratch:DI 3 "=&b"))]
2789 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2791 "&& reload_completed"
2792 [(set (match_dup 0) (match_dup 4))]
2794 operands[4] = rs6000_adjust_vec_address (operands[0], operands[1], operands[2],
2795 operands[3], <VS_scalar>mode);
2797 [(set_attr "type" "load")
2798 (set_attr "length" "8")])
2800 ;; Variable V16QI/V8HI/V4SI extract
2801 (define_insn_and_split "vsx_extract_<mode>_var"
2802 [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r")
2804 [(match_operand:VSX_EXTRACT_I 1 "input_operand" "wK,v,m")
2805 (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2806 UNSPEC_VSX_EXTRACT))
2807 (clobber (match_scratch:DI 3 "=r,r,&b"))
2808 (clobber (match_scratch:V2DI 4 "=X,&v,X"))]
2809 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2811 "&& reload_completed"
2814 rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
2815 operands[3], operands[4]);
2819 (define_insn_and_split "*vsx_extract_<VSX_EXTRACT_I:mode>_<SDI:mode>_var"
2820 [(set (match_operand:SDI 0 "gpc_reg_operand" "=r,r,r")
2822 (unspec:<VSX_EXTRACT_I:VS_scalar>
2823 [(match_operand:VSX_EXTRACT_I 1 "input_operand" "wK,v,m")
2824 (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
2825 UNSPEC_VSX_EXTRACT)))
2826 (clobber (match_scratch:DI 3 "=r,r,&b"))
2827 (clobber (match_scratch:V2DI 4 "=X,&v,X"))]
2828 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
2830 "&& reload_completed"
2833 machine_mode smode = <VSX_EXTRACT_I:MODE>mode;
2834 rs6000_split_vec_extract_var (gen_rtx_REG (smode, REGNO (operands[0])),
2835 operands[1], operands[2],
2836 operands[3], operands[4]);
2840 ;; VSX_EXTRACT optimizations
2841 ;; Optimize double d = (double) vec_extract (vi, <n>)
2842 ;; Get the element into the top position and use XVCVSWDP/XVCVUWDP
2843 (define_insn_and_split "*vsx_extract_si_<uns>float_df"
2844 [(set (match_operand:DF 0 "gpc_reg_operand" "=ws")
2847 (match_operand:V4SI 1 "gpc_reg_operand" "v")
2848 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
2849 (clobber (match_scratch:V4SI 3 "=v"))]
2850 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2855 rtx dest = operands[0];
2856 rtx src = operands[1];
2857 rtx element = operands[2];
2858 rtx v4si_tmp = operands[3];
2861 if (!VECTOR_ELT_ORDER_BIG)
2862 element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2864 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2866 value = INTVAL (element);
2869 if (GET_CODE (v4si_tmp) == SCRATCH)
2870 v4si_tmp = gen_reg_rtx (V4SImode);
2871 emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
2876 emit_insn (gen_vsx_xvcv<su>xwdp_df (dest, v4si_tmp));
2880 ;; Optimize <type> f = (<type>) vec_extract (vi, <n>)
2881 ;; where <type> is a floating point type that supported by the hardware that is
2882 ;; not double. First convert the value to double, and then to the desired
2884 (define_insn_and_split "*vsx_extract_si_<uns>float_<mode>"
2885 [(set (match_operand:VSX_EXTRACT_FL 0 "gpc_reg_operand" "=ww")
2886 (any_float:VSX_EXTRACT_FL
2888 (match_operand:V4SI 1 "gpc_reg_operand" "v")
2889 (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
2890 (clobber (match_scratch:V4SI 3 "=v"))
2891 (clobber (match_scratch:DF 4 "=ws"))]
2892 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
2897 rtx dest = operands[0];
2898 rtx src = operands[1];
2899 rtx element = operands[2];
2900 rtx v4si_tmp = operands[3];
2901 rtx df_tmp = operands[4];
2904 if (!VECTOR_ELT_ORDER_BIG)
2905 element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
2907 /* If the value is in the correct position, we can avoid doing the VSPLT<x>
2909 value = INTVAL (element);
2912 if (GET_CODE (v4si_tmp) == SCRATCH)
2913 v4si_tmp = gen_reg_rtx (V4SImode);
2914 emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
2919 if (GET_CODE (df_tmp) == SCRATCH)
2920 df_tmp = gen_reg_rtx (DFmode);
2922 emit_insn (gen_vsx_xvcv<su>xwdp_df (df_tmp, v4si_tmp));
2924 if (<MODE>mode == SFmode)
2925 emit_insn (gen_truncdfsf2 (dest, df_tmp));
2926 else if (<MODE>mode == TFmode && FLOAT128_IBM_P (TFmode))
2927 emit_insn (gen_extenddftf2_vsx (dest, df_tmp));
2928 else if (<MODE>mode == TFmode && FLOAT128_IEEE_P (TFmode)
2929 && TARGET_FLOAT128_HW)
2930 emit_insn (gen_extenddftf2_hw (dest, df_tmp));
2931 else if (<MODE>mode == IFmode && FLOAT128_IBM_P (IFmode))
2932 emit_insn (gen_extenddfif2 (dest, df_tmp));
2933 else if (<MODE>mode == KFmode && TARGET_FLOAT128_HW)
2934 emit_insn (gen_extenddfkf2_hw (dest, df_tmp));
2941 ;; Optimize <type> f = (<ftype>) vec_extract (<vtype>, <n>)
2942 ;; Where <ftype> is SFmode, DFmode (and KFmode/TFmode if those types are IEEE
2943 ;; 128-bit hardware types) and <vtype> is vector char, vector unsigned char,
2944 ;; vector short or vector unsigned short.
2945 (define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VS_scalar>_fl_<FL_CONV:mode>"
2946 [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=<FL_CONV:VSr3>")
2948 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2949 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
2950 (parallel [(match_operand:QI 2 "const_int_operand" "n")]))))
2951 (clobber (match_scratch:<VSX_EXTRACT_I:VS_scalar> 3 "=v"))]
2952 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
2953 && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER"
2955 "&& reload_completed"
2956 [(parallel [(set (match_dup 3)
2957 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2959 (parallel [(match_dup 2)])))
2960 (clobber (scratch:SI))])
2962 (sign_extend:DI (match_dup 3)))
2964 (float:<FL_CONV:MODE> (match_dup 4)))]
2966 operands[4] = gen_rtx_REG (DImode, REGNO (operands[3]));
2969 (define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VS_scalar>_ufl_<FL_CONV:mode>"
2970 [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=<FL_CONV:VSr3>")
2971 (unsigned_float:FL_CONV
2972 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2973 (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
2974 (parallel [(match_operand:QI 2 "const_int_operand" "n")]))))
2975 (clobber (match_scratch:<VSX_EXTRACT_I:VS_scalar> 3 "=v"))]
2976 "VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
2977 && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER"
2979 "&& reload_completed"
2980 [(parallel [(set (match_dup 3)
2981 (vec_select:<VSX_EXTRACT_I:VS_scalar>
2983 (parallel [(match_dup 2)])))
2984 (clobber (scratch:SI))])
2986 (float:<FL_CONV:MODE> (match_dup 4)))]
2988 operands[4] = gen_rtx_REG (DImode, REGNO (operands[3]));
2991 ;; V4SI/V8HI/V16QI set operation on ISA 3.0
2992 (define_insn "vsx_set_<mode>_p9"
2993 [(set (match_operand:VSX_EXTRACT_I 0 "gpc_reg_operand" "=<VSX_EX>")
2994 (unspec:VSX_EXTRACT_I
2995 [(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "0")
2996 (match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VSX_EX>")
2997 (match_operand:QI 3 "<VSX_EXTRACT_PREDICATE>" "n")]
2999 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
3000 && TARGET_UPPER_REGS_DI && TARGET_POWERPC64"
3002 int ele = INTVAL (operands[3]);
3003 int nunits = GET_MODE_NUNITS (<MODE>mode);
3005 if (!VECTOR_ELT_ORDER_BIG)
3006 ele = nunits - 1 - ele;
3008 operands[3] = GEN_INT (GET_MODE_SIZE (<VS_scalar>mode) * ele);
3009 if (<MODE>mode == V4SImode)
3010 return "xxinsertw %x0,%x2,%3";
3012 return "vinsert<wd> %0,%2,%3";
3014 [(set_attr "type" "vecperm")])
3016 ;; Expanders for builtins
3017 (define_expand "vsx_mergel_<mode>"
3018 [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
3019 (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
3020 (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
3021 "VECTOR_MEM_VSX_P (<MODE>mode)"
3026 /* Special handling for LE with -maltivec=be. */
3027 if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
3029 v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
3030 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
3034 v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
3035 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
3038 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
3039 emit_insn (gen_rtx_SET (operands[0], x));
3043 (define_expand "vsx_mergeh_<mode>"
3044 [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
3045 (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
3046 (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
3047 "VECTOR_MEM_VSX_P (<MODE>mode)"
3052 /* Special handling for LE with -maltivec=be. */
3053 if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
3055 v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
3056 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
3060 v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
3061 x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
3064 x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
3065 emit_insn (gen_rtx_SET (operands[0], x));
3070 (define_insn "vsx_splat_<mode>"
3071 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>,<VSa>,we")
3072 (vec_duplicate:VSX_D
3073 (match_operand:<VS_scalar> 1 "splat_input_operand" "<VS_64reg>,Z,b")))]
3074 "VECTOR_MEM_VSX_P (<MODE>mode)"
3076 xxpermdi %x0,%x1,%x1,0
3079 [(set_attr "type" "vecperm,vecload,vecperm")])
3081 ;; V4SI splat support
3082 (define_insn "vsx_splat_v4si"
3083 [(set (match_operand:V4SI 0 "vsx_register_operand" "=we,we")
3085 (match_operand:SI 1 "splat_input_operand" "r,Z")))]
3090 [(set_attr "type" "vecperm,vecload")])
3092 ;; SImode is not currently allowed in vector registers. This pattern
3093 ;; allows us to use direct move to get the value in a vector register
3094 ;; so that we can use XXSPLTW
3095 (define_insn "vsx_splat_v4si_di"
3096 [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,we")
3099 (match_operand:DI 1 "gpc_reg_operand" "wj,r"))))]
3100 "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
3104 [(set_attr "type" "vecperm")])
3106 ;; V4SF splat (ISA 3.0)
3107 (define_insn_and_split "vsx_splat_v4sf"
3108 [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,wa")
3110 (match_operand:SF 1 "splat_input_operand" "Z,wy,r")))]
3116 "&& reload_completed && vsx_register_operand (operands[1], SFmode)"
3118 (unspec:V4SF [(match_dup 1)] UNSPEC_VSX_CVDPSPN))
3120 (unspec:V4SF [(match_dup 0)
3121 (const_int 0)] UNSPEC_VSX_XXSPLTW))]
3123 [(set_attr "type" "vecload,vecperm,mftgpr")
3124 (set_attr "length" "4,8,4")])
3126 ;; V4SF/V4SI splat from a vector element
3127 (define_insn "vsx_xxspltw_<mode>"
3128 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
3129 (vec_duplicate:VSX_W
3130 (vec_select:<VS_scalar>
3131 (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
3133 [(match_operand:QI 2 "u5bit_cint_operand" "n")]))))]
3134 "VECTOR_MEM_VSX_P (<MODE>mode)"
3136 if (!BYTES_BIG_ENDIAN)
3137 operands[2] = GEN_INT (3 - INTVAL (operands[2]));
3139 return "xxspltw %x0,%x1,%2";
3141 [(set_attr "type" "vecperm")])
3143 (define_insn "vsx_xxspltw_<mode>_direct"
3144 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
3145 (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
3146 (match_operand:QI 2 "u5bit_cint_operand" "i")]
3147 UNSPEC_VSX_XXSPLTW))]
3148 "VECTOR_MEM_VSX_P (<MODE>mode)"
3149 "xxspltw %x0,%x1,%2"
3150 [(set_attr "type" "vecperm")])
3152 ;; V16QI/V8HI splat support on ISA 2.07
3153 (define_insn "vsx_vsplt<VSX_SPLAT_SUFFIX>_di"
3154 [(set (match_operand:VSX_SPLAT_I 0 "altivec_register_operand" "=v")
3155 (vec_duplicate:VSX_SPLAT_I
3156 (truncate:<VS_scalar>
3157 (match_operand:DI 1 "altivec_register_operand" "v"))))]
3158 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
3159 "vsplt<VSX_SPLAT_SUFFIX> %0,%1,<VSX_SPLAT_COUNT>"
3160 [(set_attr "type" "vecperm")])
3162 ;; V2DF/V2DI splat for use by vec_splat builtin
3163 (define_insn "vsx_xxspltd_<mode>"
3164 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
3165 (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa")
3166 (match_operand:QI 2 "u5bit_cint_operand" "i")]
3167 UNSPEC_VSX_XXSPLTD))]
3168 "VECTOR_MEM_VSX_P (<MODE>mode)"
3170 if ((VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 0)
3171 || (!VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 1))
3172 return "xxpermdi %x0,%x1,%x1,0";
3174 return "xxpermdi %x0,%x1,%x1,3";
3176 [(set_attr "type" "vecperm")])
3178 ;; V4SF/V4SI interleave
3179 (define_insn "vsx_xxmrghw_<mode>"
3180 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
3182 (vec_concat:<VS_double>
3183 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
3184 (match_operand:VSX_W 2 "vsx_register_operand" "wf,<VSa>"))
3185 (parallel [(const_int 0) (const_int 4)
3186 (const_int 1) (const_int 5)])))]
3187 "VECTOR_MEM_VSX_P (<MODE>mode)"
3189 if (BYTES_BIG_ENDIAN)
3190 return "xxmrghw %x0,%x1,%x2";
3192 return "xxmrglw %x0,%x2,%x1";
3194 [(set_attr "type" "vecperm")])
3196 (define_insn "vsx_xxmrglw_<mode>"
3197 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
3199 (vec_concat:<VS_double>
3200 (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
3201 (match_operand:VSX_W 2 "vsx_register_operand" "wf,?<VSa>"))
3202 (parallel [(const_int 2) (const_int 6)
3203 (const_int 3) (const_int 7)])))]
3204 "VECTOR_MEM_VSX_P (<MODE>mode)"
3206 if (BYTES_BIG_ENDIAN)
3207 return "xxmrglw %x0,%x1,%x2";
3209 return "xxmrghw %x0,%x2,%x1";
3211 [(set_attr "type" "vecperm")])
3213 ;; Shift left double by word immediate
3214 (define_insn "vsx_xxsldwi_<mode>"
3215 [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSa>")
3216 (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "<VSa>")
3217 (match_operand:VSX_L 2 "vsx_register_operand" "<VSa>")
3218 (match_operand:QI 3 "u5bit_cint_operand" "i")]
3220 "VECTOR_MEM_VSX_P (<MODE>mode)"
3221 "xxsldwi %x0,%x1,%x2,%3"
3222 [(set_attr "type" "vecperm")])
3225 ;; Vector reduction insns and splitters
3227 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
3228 [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
3232 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
3233 (parallel [(const_int 1)]))
3236 (parallel [(const_int 0)])))
3238 (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
3239 "VECTOR_UNIT_VSX_P (V2DFmode)"
3245 rtx tmp = (GET_CODE (operands[2]) == SCRATCH)
3246 ? gen_reg_rtx (V2DFmode)
3248 emit_insn (gen_vsx_xxsldwi_v2df (tmp, operands[1], operands[1], const2_rtx));
3249 emit_insn (gen_<VEC_reduc_rtx>v2df3 (operands[0], tmp, operands[1]));
3252 [(set_attr "length" "8")
3253 (set_attr "type" "veccomplex")])
3255 (define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
3256 [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
3258 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
3259 (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
3260 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
3261 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
3262 "VECTOR_UNIT_VSX_P (V4SFmode)"
3268 rtx op0 = operands[0];
3269 rtx op1 = operands[1];
3270 rtx tmp2, tmp3, tmp4;
3272 if (can_create_pseudo_p ())
3274 tmp2 = gen_reg_rtx (V4SFmode);
3275 tmp3 = gen_reg_rtx (V4SFmode);
3276 tmp4 = gen_reg_rtx (V4SFmode);
3285 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
3286 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
3287 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
3288 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (op0, tmp4, tmp3));
3291 [(set_attr "length" "16")
3292 (set_attr "type" "veccomplex")])
3294 ;; Combiner patterns with the vector reduction patterns that knows we can get
3295 ;; to the top element of the V2DF array without doing an extract.
3297 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
3298 [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws")
3303 (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
3304 (parallel [(const_int 1)]))
3307 (parallel [(const_int 0)])))
3309 (parallel [(const_int 1)])))
3310 (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
3311 "VECTOR_UNIT_VSX_P (V2DFmode)"
3317 rtx hi = gen_highpart (DFmode, operands[1]);
3318 rtx lo = (GET_CODE (operands[2]) == SCRATCH)
3319 ? gen_reg_rtx (DFmode)
3322 emit_insn (gen_vsx_extract_v2df (lo, operands[1], const1_rtx));
3323 emit_insn (gen_<VEC_reduc_rtx>df3 (operands[0], hi, lo));
3326 [(set_attr "length" "8")
3327 (set_attr "type" "veccomplex")])
3329 (define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
3330 [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
3333 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
3334 (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
3335 (parallel [(const_int 3)])))
3336 (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
3337 (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
3338 (clobber (match_scratch:V4SF 4 "=0,0"))]
3339 "VECTOR_UNIT_VSX_P (V4SFmode)"
3345 rtx op0 = operands[0];
3346 rtx op1 = operands[1];
3347 rtx tmp2, tmp3, tmp4, tmp5;
3349 if (can_create_pseudo_p ())
3351 tmp2 = gen_reg_rtx (V4SFmode);
3352 tmp3 = gen_reg_rtx (V4SFmode);
3353 tmp4 = gen_reg_rtx (V4SFmode);
3354 tmp5 = gen_reg_rtx (V4SFmode);
3364 emit_insn (gen_vsx_xxsldwi_v4sf (tmp2, op1, op1, const2_rtx));
3365 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp3, tmp2, op1));
3366 emit_insn (gen_vsx_xxsldwi_v4sf (tmp4, tmp3, tmp3, GEN_INT (3)));
3367 emit_insn (gen_<VEC_reduc_rtx>v4sf3 (tmp5, tmp4, tmp3));
3368 emit_insn (gen_vsx_xscvspdp_scalar2 (op0, tmp5));
3371 [(set_attr "length" "20")
3372 (set_attr "type" "veccomplex")])
3375 ;; Power8 Vector fusion. The fused ops must be physically adjacent.
3377 [(set (match_operand:P 0 "base_reg_operand" "")
3378 (match_operand:P 1 "short_cint_operand" ""))
3379 (set (match_operand:VSX_M 2 "vsx_register_operand" "")
3380 (mem:VSX_M (plus:P (match_dup 0)
3381 (match_operand:P 3 "int_reg_operand" ""))))]
3382 "TARGET_VSX && TARGET_P8_FUSION && !TARGET_P9_VECTOR"
3383 "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M:VSm>x %x2,%0,%3"
3384 [(set_attr "length" "8")
3385 (set_attr "type" "vecload")])
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_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 ;; ISA 3.0 vector extend sign support
3401 (define_insn "vsx_sign_extend_qi_<mode>"
3402 [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
3404 [(match_operand:V16QI 1 "vsx_register_operand" "v")]
3405 UNSPEC_VSX_SIGN_EXTEND))]
3408 [(set_attr "type" "vecexts")])
3410 (define_insn "vsx_sign_extend_hi_<mode>"
3411 [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v")
3413 [(match_operand:V8HI 1 "vsx_register_operand" "v")]
3414 UNSPEC_VSX_SIGN_EXTEND))]
3417 [(set_attr "type" "vecexts")])
3419 (define_insn "*vsx_sign_extend_si_v2di"
3420 [(set (match_operand:V2DI 0 "vsx_register_operand" "=v")
3421 (unspec:V2DI [(match_operand:V4SI 1 "vsx_register_operand" "v")]
3422 UNSPEC_VSX_SIGN_EXTEND))]
3425 [(set_attr "type" "vecexts")])
3428 ;; ISA 3.0 Binary Floating-Point Support
3430 ;; VSX Scalar Extract Exponent Double-Precision
3431 (define_insn "xsxexpdp"
3432 [(set (match_operand:DI 0 "register_operand" "=r")
3433 (unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
3434 UNSPEC_VSX_SXEXPDP))]
3435 "TARGET_P9_VECTOR && TARGET_64BIT"
3437 [(set_attr "type" "integer")])
3439 ;; VSX Scalar Extract Significand Double-Precision
3440 (define_insn "xsxsigdp"
3441 [(set (match_operand:DI 0 "register_operand" "=r")
3442 (unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
3443 UNSPEC_VSX_SXSIGDP))]
3444 "TARGET_P9_VECTOR && TARGET_64BIT"
3446 [(set_attr "type" "integer")])
3448 ;; VSX Scalar Insert Exponent Double-Precision
3449 (define_insn "xsiexpdp"
3450 [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
3451 (unspec:DF [(match_operand:DI 1 "register_operand" "r")
3452 (match_operand:DI 2 "register_operand" "r")]
3453 UNSPEC_VSX_SIEXPDP))]
3454 "TARGET_P9_VECTOR && TARGET_64BIT"
3455 "xsiexpdp %x0,%1,%2"
3456 [(set_attr "type" "fpsimple")])
3458 ;; VSX Scalar Insert Exponent Double-Precision Floating Point Argument
3459 (define_insn "xsiexpdpf"
3460 [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
3461 (unspec:DF [(match_operand:DF 1 "register_operand" "r")
3462 (match_operand:DI 2 "register_operand" "r")]
3463 UNSPEC_VSX_SIEXPDP))]
3464 "TARGET_P9_VECTOR && TARGET_64BIT"
3465 "xsiexpdp %x0,%1,%2"
3466 [(set_attr "type" "fpsimple")])
3468 ;; VSX Scalar Compare Exponents Double-Precision
3469 (define_expand "xscmpexpdp_<code>"
3473 [(match_operand:DF 1 "vsx_register_operand" "wa")
3474 (match_operand:DF 2 "vsx_register_operand" "wa")]
3475 UNSPEC_VSX_SCMPEXPDP)
3477 (set (match_operand:SI 0 "register_operand" "=r")
3478 (CMP_TEST:SI (match_dup 3)
3482 operands[3] = gen_reg_rtx (CCFPmode);
3485 (define_insn "*xscmpexpdp"
3486 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
3488 (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "wa")
3489 (match_operand:DF 2 "vsx_register_operand" "wa")]
3490 UNSPEC_VSX_SCMPEXPDP)
3491 (match_operand:SI 3 "zero_constant" "j")))]
3493 "xscmpexpdp %0,%x1,%x2"
3494 [(set_attr "type" "fpcompare")])
3496 ;; VSX Scalar Test Data Class Double- and Single-Precision
3497 ;; (The lt bit is set if operand 1 is negative. The eq bit is set
3498 ;; if any of the conditions tested by operand 2 are satisfied.
3499 ;; The gt and unordered bits are cleared to zero.)
3500 (define_expand "xststdc<Fvsx>"
3504 [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3505 (match_operand:SI 2 "u7bit_cint_operand" "n")]
3508 (set (match_operand:SI 0 "register_operand" "=r")
3509 (eq:SI (match_dup 3)
3513 operands[3] = gen_reg_rtx (CCFPmode);
3514 operands[4] = CONST0_RTX (SImode);
3517 ;; The VSX Scalar Test Data Class Double- and Single-Precision
3518 ;; instruction may also be used to test for negative value.
3519 (define_expand "xststdcneg<Fvsx>"
3523 [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3527 (set (match_operand:SI 0 "register_operand" "=r")
3528 (lt:SI (match_dup 2)
3532 operands[2] = gen_reg_rtx (CCFPmode);
3533 operands[3] = CONST0_RTX (SImode);
3536 (define_insn "*xststdc<Fvsx>"
3537 [(set (match_operand:CCFP 0 "" "=y")
3539 (unspec:SFDF [(match_operand:SFDF 1 "vsx_register_operand" "wa")
3540 (match_operand:SI 2 "u7bit_cint_operand" "n")]
3542 (match_operand:SI 3 "zero_constant" "j")))]
3544 "xststdc<Fvsx> %0,%x1,%2"
3545 [(set_attr "type" "fpcompare")])
3547 ;; VSX Vector Extract Exponent Double and Single Precision
3548 (define_insn "xvxexp<VSs>"
3549 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3551 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
3554 "xvxexp<VSs> %x0,%x1"
3555 [(set_attr "type" "vecsimple")])
3557 ;; VSX Vector Extract Significand Double and Single Precision
3558 (define_insn "xvxsig<VSs>"
3559 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3561 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
3564 "xvxsig<VSs> %x0,%x1"
3565 [(set_attr "type" "vecsimple")])
3567 ;; VSX Vector Insert Exponent Double and Single Precision
3568 (define_insn "xviexp<VSs>"
3569 [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
3571 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3572 (match_operand:VSX_F 2 "vsx_register_operand" "wa")]
3575 "xviexp<VSs> %x0,%x1,%x2"
3576 [(set_attr "type" "vecsimple")])
3578 ;; VSX Vector Test Data Class Double and Single Precision
3579 ;; The corresponding elements of the result vector are all ones
3580 ;; if any of the conditions tested by operand 3 are satisfied.
3581 (define_insn "xvtstdc<VSs>"
3582 [(set (match_operand:<VSI> 0 "vsx_register_operand" "=wa")
3584 [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
3585 (match_operand:SI 2 "u7bit_cint_operand" "n")]
3586 UNSPEC_VSX_VTSTDC))]
3588 "xvtstdc<VSs> %x0,%x1,%2"
3589 [(set_attr "type" "vecsimple")])
3591 ;; ISA 3.0 String Operations Support
3593 ;; Compare vectors producing a vector result and a predicate, setting CR6
3594 ;; to indicate a combined status. This pattern matches v16qi, v8hi, and
3595 ;; v4si modes. It does not match v2df, v4sf, or v2di modes. There's no
3596 ;; need to match v4sf, v2df, or v2di modes because those are expanded
3597 ;; to use Power8 instructions.
3598 (define_insn "*vsx_ne_<mode>_p"
3599 [(set (reg:CC CR6_REGNO)
3601 [(ne:CC (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
3602 (match_operand:VSX_EXTRACT_I 2 "gpc_reg_operand" "v"))]
3604 (set (match_operand:VSX_EXTRACT_I 0 "gpc_reg_operand" "=v")
3605 (ne:VSX_EXTRACT_I (match_dup 1)
3608 "vcmpne<VSX_EXTRACT_WIDTH>. %0,%1,%2"
3609 [(set_attr "type" "vecsimple")])
3611 (define_insn "*vector_nez_<mode>_p"
3612 [(set (reg:CC CR6_REGNO)
3613 (unspec:CC [(unspec:VI
3614 [(match_operand:VI 1 "gpc_reg_operand" "v")
3615 (match_operand:VI 2 "gpc_reg_operand" "v")]
3618 (set (match_operand:VI 0 "gpc_reg_operand" "=v")
3619 (unspec:VI [(match_dup 1)
3623 "vcmpnez<VSX_EXTRACT_WIDTH>. %0,%1,%2"
3624 [(set_attr "type" "vecsimple")])
3626 ;; Load VSX Vector with Length
3627 (define_expand "lxvl"
3629 (match_operand:DI 2 "register_operand"))
3630 (set (match_operand:V16QI 0 "vsx_register_operand")
3632 [(match_operand:DI 1 "gpc_reg_operand")
3635 "TARGET_P9_VECTOR && TARGET_64BIT"
3637 operands[3] = gen_reg_rtx (DImode);
3640 (define_insn "*lxvl"
3641 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3643 [(match_operand:DI 1 "gpc_reg_operand" "b")
3644 (match_operand:DI 2 "register_operand" "+r")]
3646 "TARGET_P9_VECTOR && TARGET_64BIT"
3647 "sldi %2,%2, 56\; lxvl %x0,%1,%2"
3648 [(set_attr "length" "8")
3649 (set_attr "type" "vecload")])
3651 ;; Store VSX Vector with Length
3652 (define_expand "stxvl"
3654 (match_operand:DI 2 "register_operand"))
3655 (set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand"))
3657 [(match_operand:V16QI 0 "vsx_register_operand")
3660 "TARGET_P9_VECTOR && TARGET_64BIT"
3662 operands[3] = gen_reg_rtx (DImode);
3665 (define_insn "*stxvl"
3666 [(set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand" "b"))
3668 [(match_operand:V16QI 0 "vsx_register_operand" "wa")
3669 (match_operand:DI 2 "register_operand" "+r")]
3671 "TARGET_P9_VECTOR && TARGET_64BIT"
3672 "sldi %2,%2\;stxvl %x0,%1,%2"
3673 [(set_attr "length" "8")
3674 (set_attr "type" "vecstore")])
3676 ;; Vector Compare Not Equal Byte
3677 (define_insn "vcmpneb"
3678 [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
3679 (unspec:V16QI [(match_operand:V16QI 1 "altivec_register_operand" "v")
3680 (match_operand:V16QI 2 "altivec_register_operand" "v")]
3684 [(set_attr "type" "vecsimple")])
3686 ;; Vector Compare Not Equal or Zero Byte
3687 (define_insn "vcmpnezb"
3688 [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
3690 [(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 Half Word
3698 (define_insn "vcmpneh"
3699 [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
3700 (unspec:V8HI [(match_operand:V8HI 1 "altivec_register_operand" "v")
3701 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3705 [(set_attr "type" "vecsimple")])
3707 ;; Vector Compare Not Equal or Zero Half Word
3708 (define_insn "vcmpnezh"
3709 [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
3710 (unspec:V8HI [(match_operand:V8HI 1 "altivec_register_operand" "v")
3711 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3715 [(set_attr "type" "vecsimple")])
3717 ;; Vector Compare Not Equal Word
3718 (define_insn "vcmpnew"
3719 [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
3721 [(match_operand:V4SI 1 "altivec_register_operand" "v")
3722 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3726 [(set_attr "type" "vecsimple")])
3728 ;; Vector Compare Not Equal or Zero Word
3729 (define_insn "vcmpnezw"
3730 [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
3731 (unspec:V4SI [(match_operand:V4SI 1 "altivec_register_operand" "v")
3732 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3736 [(set_attr "type" "vecsimple")])
3738 ;; Vector Count Leading Zero Least-Significant Bits Byte
3739 (define_insn "vclzlsbb"
3740 [(set (match_operand:SI 0 "register_operand" "=r")
3742 [(match_operand:V16QI 1 "altivec_register_operand" "v")]
3746 [(set_attr "type" "vecsimple")])
3748 ;; Vector Count Trailing Zero Least-Significant Bits Byte
3749 (define_insn "vctzlsbb"
3750 [(set (match_operand:SI 0 "register_operand" "=r")
3752 [(match_operand:V16QI 1 "altivec_register_operand" "v")]
3756 [(set_attr "type" "vecsimple")])
3758 ;; Vector Extract Unsigned Byte Left-Indexed
3759 (define_insn "vextublx"
3760 [(set (match_operand:SI 0 "register_operand" "=r")
3762 [(match_operand:SI 1 "register_operand" "r")
3763 (match_operand:V16QI 2 "altivec_register_operand" "v")]
3767 [(set_attr "type" "vecsimple")])
3769 ;; Vector Extract Unsigned Byte Right-Indexed
3770 (define_insn "vextubrx"
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 Half Word Left-Indexed
3781 (define_insn "vextuhlx"
3782 [(set (match_operand:SI 0 "register_operand" "=r")
3784 [(match_operand:SI 1 "register_operand" "r")
3785 (match_operand:V8HI 2 "altivec_register_operand" "v")]
3789 [(set_attr "type" "vecsimple")])
3791 ;; Vector Extract Unsigned Half Word Right-Indexed
3792 (define_insn "vextuhrx"
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 Word Left-Indexed
3803 (define_insn "vextuwlx"
3804 [(set (match_operand:SI 0 "register_operand" "=r")
3806 [(match_operand:SI 1 "register_operand" "r")
3807 (match_operand:V4SI 2 "altivec_register_operand" "v")]
3811 [(set_attr "type" "vecsimple")])
3813 ;; Vector Extract Unsigned Word Right-Indexed
3814 (define_insn "vextuwrx"
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 insert/extract word at arbitrary byte values. Note, the little
3825 ;; endian version needs to adjust the byte number, and the V4SI element in
3827 (define_expand "vextract4b"
3828 [(set (match_operand:DI 0 "gpc_reg_operand")
3829 (unspec:DI [(match_operand:V16QI 1 "vsx_register_operand")
3830 (match_operand:QI 2 "const_0_to_12_operand")]
3831 UNSPEC_XXEXTRACTUW))]
3834 if (!VECTOR_ELT_ORDER_BIG)
3835 operands[2] = GEN_INT (12 - INTVAL (operands[2]));
3838 (define_insn_and_split "*vextract4b_internal"
3839 [(set (match_operand:DI 0 "gpc_reg_operand" "=wj,r")
3840 (unspec:DI [(match_operand:V16QI 1 "vsx_register_operand" "wa,v")
3841 (match_operand:QI 2 "const_0_to_12_operand" "n,n")]
3842 UNSPEC_XXEXTRACTUW))]
3845 xxextractuw %x0,%x1,%2
3847 "&& reload_completed && int_reg_operand (operands[0], DImode)"
3850 rtx op0 = operands[0];
3851 rtx op1 = operands[1];
3852 rtx op2 = operands[2];
3853 rtx op0_si = gen_rtx_REG (SImode, REGNO (op0));
3854 rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (op1));
3856 emit_move_insn (op0, op2);
3857 if (VECTOR_ELT_ORDER_BIG)
3858 emit_insn (gen_vextuwlx (op0_si, op0_si, op1_v4si));
3860 emit_insn (gen_vextuwrx (op0_si, op0_si, op1_v4si));
3863 [(set_attr "type" "vecperm")])
3865 (define_expand "vinsert4b"
3866 [(set (match_operand:V16QI 0 "vsx_register_operand")
3867 (unspec:V16QI [(match_operand:V4SI 1 "vsx_register_operand")
3868 (match_operand:V16QI 2 "vsx_register_operand")
3869 (match_operand:QI 3 "const_0_to_12_operand")]
3873 if (!VECTOR_ELT_ORDER_BIG)
3875 rtx op1 = operands[1];
3876 rtx v4si_tmp = gen_reg_rtx (V4SImode);
3877 emit_insn (gen_vsx_xxpermdi_v4si_be (v4si_tmp, op1, op1, const1_rtx));
3878 operands[1] = v4si_tmp;
3879 operands[3] = GEN_INT (12 - INTVAL (operands[3]));
3883 (define_insn "*vinsert4b_internal"
3884 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3885 (unspec:V16QI [(match_operand:V4SI 1 "vsx_register_operand" "wa")
3886 (match_operand:V16QI 2 "vsx_register_operand" "0")
3887 (match_operand:QI 3 "const_0_to_12_operand" "n")]
3890 "xxinsertw %x0,%x1,%3"
3891 [(set_attr "type" "vecperm")])
3893 (define_expand "vinsert4b_di"
3894 [(set (match_operand:V16QI 0 "vsx_register_operand")
3895 (unspec:V16QI [(match_operand:DI 1 "vsx_register_operand")
3896 (match_operand:V16QI 2 "vsx_register_operand")
3897 (match_operand:QI 3 "const_0_to_12_operand")]
3901 if (!VECTOR_ELT_ORDER_BIG)
3902 operands[3] = GEN_INT (12 - INTVAL (operands[3]));
3905 (define_insn "*vinsert4b_di_internal"
3906 [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
3907 (unspec:V16QI [(match_operand:DI 1 "vsx_register_operand" "wj")
3908 (match_operand:V16QI 2 "vsx_register_operand" "0")
3909 (match_operand:QI 3 "const_0_to_12_operand" "n")]
3912 "xxinsertw %x0,%x1,%3"
3913 [(set_attr "type" "vecperm")])
3916 ;; Support for ISA 3.0 vector byte reverse
3918 ;; Swap all bytes with in a vector
3919 (define_insn "p9_xxbrq_v1ti"
3920 [(set (match_operand:V1TI 0 "vsx_register_operand" "=wa")
3921 (bswap:V1TI (match_operand:V1TI 1 "vsx_register_operand" "wa")))]
3924 [(set_attr "type" "vecperm")])
3926 (define_expand "p9_xxbrq_v16qi"
3927 [(use (match_operand:V16QI 0 "vsx_register_operand" "=wa"))
3928 (use (match_operand:V16QI 1 "vsx_register_operand" "=wa"))]
3931 rtx op0 = gen_lowpart (V1TImode, operands[0]);
3932 rtx op1 = gen_lowpart (V1TImode, operands[1]);
3933 emit_insn (gen_p9_xxbrq_v1ti (op0, op1));
3937 ;; Swap all bytes in each 64-bit element
3938 (define_insn "p9_xxbrd_<mode>"
3939 [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
3940 (bswap:VSX_D (match_operand:VSX_D 1 "vsx_register_operand" "wa")))]
3943 [(set_attr "type" "vecperm")])
3945 ;; Swap all bytes in each 32-bit element
3946 (define_insn "p9_xxbrw_<mode>"
3947 [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
3948 (bswap:VSX_W (match_operand:VSX_W 1 "vsx_register_operand" "wa")))]
3951 [(set_attr "type" "vecperm")])
3953 ;; Swap all bytes in each 16-bit element
3954 (define_insn "p9_xxbrh_v8hi"
3955 [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
3956 (bswap:V8HI (match_operand:V8HI 1 "vsx_register_operand" "wa")))]
3959 [(set_attr "type" "vecperm")])
3962 ;; Operand numbers for the following peephole2
3964 [(SFBOOL_TMP_GPR 0) ;; GPR temporary
3965 (SFBOOL_TMP_VSX 1) ;; vector temporary
3966 (SFBOOL_MFVSR_D 2) ;; move to gpr dest
3967 (SFBOOL_MFVSR_A 3) ;; move to gpr src
3968 (SFBOOL_BOOL_D 4) ;; and/ior/xor dest
3969 (SFBOOL_BOOL_A1 5) ;; and/ior/xor arg1
3970 (SFBOOL_BOOL_A2 6) ;; and/ior/xor arg1
3971 (SFBOOL_SHL_D 7) ;; shift left dest
3972 (SFBOOL_SHL_A 8) ;; shift left arg
3973 (SFBOOL_MTVSR_D 9) ;; move to vecter dest
3974 (SFBOOL_BOOL_A_DI 10) ;; SFBOOL_BOOL_A1/A2 as DImode
3975 (SFBOOL_TMP_VSX_DI 11) ;; SFBOOL_TMP_VSX as DImode
3976 (SFBOOL_MTVSR_D_V4SF 12)]) ;; SFBOOL_MTVSRD_D as V4SFmode
3978 ;; Attempt to optimize some common GLIBC operations using logical operations to
3979 ;; pick apart SFmode operations. For example, there is code from e_powf.c
3980 ;; after macro expansion that looks like:
3985 ;; } ieee_float_shape_type;
3991 ;; ieee_float_shape_type gf_u;
3992 ;; gf_u.value = (t1);
3993 ;; (is) = gf_u.word;
3997 ;; ieee_float_shape_type sf_u;
3998 ;; sf_u.word = (is & 0xfffff000);
3999 ;; (t1) = sf_u.value;
4003 ;; This would result in two direct move operations (convert to memory format,
4004 ;; direct move to GPR, do the AND operation, direct move to VSX, convert to
4005 ;; scalar format). With this peephole, we eliminate the direct move to the
4006 ;; GPR, and instead move the integer mask value to the vector register after a
4007 ;; shift and do the VSX logical operation.
4009 ;; The insns for dealing with SFmode in GPR registers looks like:
4010 ;; (set (reg:V4SF reg2) (unspec:V4SF [(reg:SF reg1)] UNSPEC_VSX_CVDPSPN))
4012 ;; (set (reg:DI reg3) (unspec:DI [(reg:V4SF reg2)] UNSPEC_P8V_RELOAD_FROM_VSX))
4014 ;; (set (reg:DI reg3) (lshiftrt:DI (reg:DI reg3) (const_int 32)))
4016 ;; (set (reg:DI reg5) (and:DI (reg:DI reg3) (reg:DI reg4)))
4018 ;; (set (reg:DI reg6) (ashift:DI (reg:DI reg5) (const_int 32)))
4020 ;; (set (reg:SF reg7) (unspec:SF [(reg:DI reg6)] UNSPEC_P8V_MTVSRD))
4022 ;; (set (reg:SF reg7) (unspec:SF [(reg:SF reg7)] UNSPEC_VSX_CVSPDPN))
4025 [(match_scratch:DI SFBOOL_TMP_GPR "r")
4026 (match_scratch:V4SF SFBOOL_TMP_VSX "wa")
4029 (set (match_operand:DI SFBOOL_MFVSR_D "int_reg_operand")
4030 (unspec:DI [(match_operand:V4SF SFBOOL_MFVSR_A "vsx_register_operand")]
4031 UNSPEC_P8V_RELOAD_FROM_VSX))
4034 (set (match_dup SFBOOL_MFVSR_D)
4035 (lshiftrt:DI (match_dup SFBOOL_MFVSR_D)
4038 ;; AND/IOR/XOR operation on int
4039 (set (match_operand:SI SFBOOL_BOOL_D "int_reg_operand")
4040 (and_ior_xor:SI (match_operand:SI SFBOOL_BOOL_A1 "int_reg_operand")
4041 (match_operand:SI SFBOOL_BOOL_A2 "reg_or_cint_operand")))
4044 (set (match_operand:DI SFBOOL_SHL_D "int_reg_operand")
4045 (ashift:DI (match_operand:DI SFBOOL_SHL_A "int_reg_operand")
4049 (set (match_operand:SF SFBOOL_MTVSR_D "vsx_register_operand")
4050 (unspec:SF [(match_dup SFBOOL_SHL_D)] UNSPEC_P8V_MTVSRD))]
4052 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE
4053 /* The REG_P (xxx) tests prevents SUBREG's, which allows us to use REGNO
4054 to compare registers, when the mode is different. */
4055 && REG_P (operands[SFBOOL_MFVSR_D]) && REG_P (operands[SFBOOL_BOOL_D])
4056 && REG_P (operands[SFBOOL_BOOL_A1]) && REG_P (operands[SFBOOL_SHL_D])
4057 && REG_P (operands[SFBOOL_SHL_A]) && REG_P (operands[SFBOOL_MTVSR_D])
4058 && (REG_P (operands[SFBOOL_BOOL_A2])
4059 || CONST_INT_P (operands[SFBOOL_BOOL_A2]))
4060 && (REGNO (operands[SFBOOL_BOOL_D]) == REGNO (operands[SFBOOL_MFVSR_D])
4061 || peep2_reg_dead_p (3, operands[SFBOOL_MFVSR_D]))
4062 && (REGNO (operands[SFBOOL_MFVSR_D]) == REGNO (operands[SFBOOL_BOOL_A1])
4063 || (REG_P (operands[SFBOOL_BOOL_A2])
4064 && REGNO (operands[SFBOOL_MFVSR_D])
4065 == REGNO (operands[SFBOOL_BOOL_A2])))
4066 && REGNO (operands[SFBOOL_BOOL_D]) == REGNO (operands[SFBOOL_SHL_A])
4067 && (REGNO (operands[SFBOOL_SHL_D]) == REGNO (operands[SFBOOL_BOOL_D])
4068 || peep2_reg_dead_p (4, operands[SFBOOL_BOOL_D]))
4069 && peep2_reg_dead_p (5, operands[SFBOOL_SHL_D])"
4070 [(set (match_dup SFBOOL_TMP_GPR)
4071 (ashift:DI (match_dup SFBOOL_BOOL_A_DI)
4074 (set (match_dup SFBOOL_TMP_VSX_DI)
4075 (match_dup SFBOOL_TMP_GPR))
4077 (set (match_dup SFBOOL_MTVSR_D_V4SF)
4078 (and_ior_xor:V4SF (match_dup SFBOOL_MFVSR_A)
4079 (match_dup SFBOOL_TMP_VSX)))]
4081 rtx bool_a1 = operands[SFBOOL_BOOL_A1];
4082 rtx bool_a2 = operands[SFBOOL_BOOL_A2];
4083 int regno_mfvsr_d = REGNO (operands[SFBOOL_MFVSR_D]);
4084 int regno_tmp_vsx = REGNO (operands[SFBOOL_TMP_VSX]);
4085 int regno_mtvsr_d = REGNO (operands[SFBOOL_MTVSR_D]);
4087 if (CONST_INT_P (bool_a2))
4089 rtx tmp_gpr = operands[SFBOOL_TMP_GPR];
4090 emit_move_insn (tmp_gpr, bool_a2);
4091 operands[SFBOOL_BOOL_A_DI] = tmp_gpr;
4095 int regno_bool_a1 = REGNO (bool_a1);
4096 int regno_bool_a2 = REGNO (bool_a2);
4097 int regno_bool_a = (regno_mfvsr_d == regno_bool_a1
4098 ? regno_bool_a2 : regno_bool_a1);
4099 operands[SFBOOL_BOOL_A_DI] = gen_rtx_REG (DImode, regno_bool_a);
4102 operands[SFBOOL_TMP_VSX_DI] = gen_rtx_REG (DImode, regno_tmp_vsx);
4103 operands[SFBOOL_MTVSR_D_V4SF] = gen_rtx_REG (V4SFmode, regno_mtvsr_d);