aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2009-07-30 20:48:17 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2009-07-30 20:48:17 +0000
commit29e6733c20c98fe73c79ca9cac2dd758f3b3d67e (patch)
tree57363e9c9bcc2f879f86f63a88b7f0172e3f610d /gcc
parent1b3b24c2a6de2f8b4a0ce687e8f62d3eb1ee2b53 (diff)
downloadgcc-29e6733c20c98fe73c79ca9cac2dd758f3b3d67e.zip
gcc-29e6733c20c98fe73c79ca9cac2dd758f3b3d67e.tar.gz
gcc-29e6733c20c98fe73c79ca9cac2dd758f3b3d67e.tar.bz2
Add patch 5/6 for full power7/VSX support
Co-Authored-By: Pat Haugen <pthaugen@us.ibm.com> Co-Authored-By: Revital Eres <eres@il.ibm.com> From-SVN: r150271
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog200
-rw-r--r--gcc/config/rs6000/altivec.h59
-rw-r--r--gcc/config/rs6000/altivec.md67
-rw-r--r--gcc/config/rs6000/power7.md318
-rw-r--r--gcc/config/rs6000/ppc-asm.h139
-rw-r--r--gcc/config/rs6000/predicates.md10
-rw-r--r--gcc/config/rs6000/rs6000-c.c242
-rw-r--r--gcc/config/rs6000/rs6000.c676
-rw-r--r--gcc/config/rs6000/rs6000.h11
-rw-r--r--gcc/config/rs6000/rs6000.md233
-rw-r--r--gcc/config/rs6000/rs6000.opt4
-rw-r--r--gcc/config/rs6000/t-rs60002
-rw-r--r--gcc/config/rs6000/vector.md388
-rw-r--r--gcc/config/rs6000/vsx.md1339
-rw-r--r--gcc/doc/extend.texi105
-rw-r--r--gcc/doc/invoke.texi24
-rw-r--r--gcc/doc/md.texi17
-rw-r--r--gcc/testsuite/ChangeLog50
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapdi-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/vmx/vmx.exp2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-32.c59
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-6.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap-run.c102
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap16.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap32.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap64-1.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap64-2.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap64-3.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-2.c36
-rw-r--r--gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-3.c36
-rw-r--r--gcc/testsuite/gcc.target/powerpc/optimize-bswapsi-2.c55
-rw-r--r--gcc/testsuite/gcc.target/powerpc/popcount-2.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/popcount-3.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr39457.c56
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c38
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c38
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c212
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-4.c142
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-5.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-6.c146
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c150
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c152
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c152
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c48
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c48
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vector-5.c392
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vector-6.c81
-rw-r--r--gcc/testsuite/lib/target-supports.exp60
48 files changed, 5733 insertions, 239 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4784578..4358c84 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,203 @@
+2009-07-30 Michael Meissner <meissner@linux.vnet.ibm.com>
+ Pat Haugen <pthaugen@us.ibm.com>
+ Revital Eres <ERES@il.ibm.com>
+
+ * config/rs6000/vector.md (VEC_F): Add VSX support.
+ (VEC_A): Ditto.
+ (VEC_N): Ditto.
+ (mov<mode>): Ditto.
+ (vector_load_<mode>): Ditto.
+ (vector_store_<mode>): Ditto.
+ (vector GPR move split): Ditto.
+ (vec_reload_and_plus_<mptrsize>): Ditto.
+ (vec_reload_and_reg_<mptrsize>): Ditto.
+ (add<mode>3): Ditto.
+ (sub<mode>3): Ditto.
+ (mul<mode>3): Ditto.
+ (neg<mode>2): Ditto.
+ (abs<mode>2): Ditto.
+ (smin<mode>3): Ditto.
+ (smax<mode>3): Ditto.
+ (vector_eq<mode>): Ditto.
+ (vector_gt<mode>): Ditto.
+ (vector_ge<mode>): Ditto.
+ (vector_gtu<mode>): Ditto.
+ (vector_select_<mode>_uns): Ditto.
+ (vector_eq_<mode>_p): Ditto.
+ (vector_gt_<mode>_p): Ditto.
+ (vector_ge_<mode>_p): Ditto.
+ (vector_gtu_<mode>_p): Ditto.
+ (cr6_test_for_zero): Ditto.
+ (cr6_test_for_zero_reverse): Ditto.
+ (cr6_test_for_lt): Ditto.
+ (cr6_test_for_lt_reverse): Ditto.
+ (xor<mode>3): Ditto.
+ (ior<mode>3): Ditto.
+ (and<mode>3): Ditto.
+ (one_cmpl<mode>2): Ditto.
+ (nor<mode>2): Ditto.
+ (andc<mode>2): Ditto.
+ (float<VEC_int<mode>2): Ditto.
+ (unsigned_float<VEC_int><mode>2): Ditto.
+ (fix_trunc<mode><VEC_int>2): Ditto.
+ (fixuns_trunc<mode><VEC_int>2): Ditto.
+ (vec_init<mode>):
+ (vec_set<mode>): Ditto.
+ (vec_extract<mode>): Ditto.
+ (vec_interleave_highv4sf): Ditto.
+ (vec_interleave_lowv4sf): Ditto.
+ (vec_realign_load_<mode>): Ditto.
+ (vec_shl_<mode>): Ditto.
+ (vec_shr_<mode>): Ditto.
+ (div<mode>3): New patterns for VSX.
+ (vec_interleave_highv2df): Ditto.
+ (vec_interleave_lowv2df): Ditto.
+ (vec_pack_trunc_v2df): Ditto.
+ (vec_pack_sfix_trunc_v2df): Ditto.
+ (vec_pack_ufix_trunc_v2df): Ditto.
+ (vec_unpacks_hi_v4sf): Ditto.
+ (vec_unpacks_lo_v4sf): Ditto.
+ (vec_unpacks_float_hi_v4si): Ditto.
+ (vec_unpacku_float_lo_v4si): Ditto.
+ (vec_unpacku_float_hi_v4si): Ditto.
+ (vec_unpacks_float_lo_v4si): Ditto.
+ (movmisalign<mode>): Ditto.
+ (vector_ceil<mode>2): New patterns for vectorizing math library.
+ (vector_floor<mode>2): Ditto.
+ (vector_btrunc<mode>2): Ditto.
+ (vector_copysign<mode>3): Ditto.
+
+ * config/rs6000/predicates.md (easy_vector_constant_msb): New
+ predicate for setting the high bit in each word, used for
+ copysign.
+
+ * config/rs6000/ppc-asm.h (f19): Whitespace.
+ (f32-f63): Define if VSX.
+ (v0-v31): Define if Altivec.
+ (vs0-vs63): Define if VSX.
+
+ * config/rs6000/t-rs6000 (MD_INCLUDES): Add power7.md and vsx.md.
+
+ * config/rs6000/power7.md: New file, provide tuning parameters for
+ -mcpu=power7.
+
+ * config/rs6000/rs6000-c.c (rs6000_macro_to_expand): Add VSX
+ support.
+ (rs6000_cpu_cpp_builtins): Ditto.
+ (altivec_overloaded_builtins): Ditto.
+ (altivec_resolve_overloaded_builtin): Ditto.
+
+ * config/rs6000/rs6000.opt (-mno-vectorize-builtins): Add new
+ debug switch to disable vectorizing simple math builtin
+ functions.
+
+ * config/rs6000/rs6000.c (rs6000_builtin_vectorized_function):
+ Vectorize simple math builtin functions.
+ (TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION): Define target
+ hook to vectorize math builtins.
+ (rs6000_override_options): Enable -mvsx on -mcpu=power7.
+ (rs6000_builtin_conversion): Add VSX/power7 support.
+ (rs6000_builtin_vec_perm): Ditto.
+ (vsplits_constant): Add support for loading up a vector constant
+ with just the high bit set in each part.
+ (rs6000_expand_vector_init): Add VSX/power7 support.
+ (rs6000_expand_vector_set): Ditto.
+ (rs6000_expand_vector_extract): Ditto.
+ (rs6000_emit_move): Ditto.
+ (bdesc_3arg): Ditto.
+ (bdesc_2arg): Ditto.
+ (bdesc_1arg): Ditto.
+ (rs6000_expand_ternop_builtin): Ditto.
+ (altivec_expand_builtin): Ditto.
+ (rs6000_expand_unop_builtin): Ditto.
+ (rs6000_init_builtins): Ditto.
+ (altivec_init_builtins): Ditto.
+ (builtin_function_type): Ditto.
+ (rs6000_common_init_builtins): Ditto.
+ (rs6000_handle_altivec_attribute); Ditto.
+ (rs6000_mangle_type): Ditto.
+ (rs6000_vector_mode_supported_p): Ditto.
+ (rs6000_mode_dependent_address): Altivec addresses with AND -16
+ are mode dependent.
+
+ * config/rs6000/vsx.md: New file for VSX support.
+
+ * config/rs6000/rs6000.h (EASY_VECTOR_MSB): New macro for
+ identifing values with just the most significant bit set.
+ (enum rs6000_builtins): Add builtins for VSX. Add simple math
+ vectorized builtins.
+
+ * config/rs6000/altivec.md (UNSPEC_VRFIP): Delete.
+ (UNSPEC_VRFIM): Delete.
+ (splitter for loading up vector with most significant bit): New
+ splitter for vectorizing copysign.
+ (altivec_vrfiz): Rename from altivec_fturncv4sf2. Add support for
+ vectorizing simple math functions.
+ (altivec_vrfip): Add support for vectorizing simple math
+ functions.
+ (altivec_vrfim): Ditto.
+ (altivec_copysign_v4sf3): New insn for Altivec copysign support.
+
+ * config/rs6000/rs6000.md (UNSPEC_BPERM): New constant.
+ (power7.md, vsx.md): Include for power7 support.
+ (copysigndf3): Use VSX instructions if -mvsx.
+ (negdf2_fpr): Ditto.
+ (absdf2_fpr): Ditto.
+ (nabsdf2_fpr): Ditto.
+ (adddf3_fpr): Ditto.
+ (subdf3_fpr): Ditto.
+ (muldf3_fpr): Ditto.
+ (divdf3_fpr): Ditto.
+ (fix_truncdfdi2_fpr): Ditto.
+ (cmpdf_internal1): Ditto.
+ (fred, fred_fpr): Convert into expander/insn to add VSX support.
+ (btruncdf2, btruncdf2_fpr): Ditto.
+ (ceildf2, ceildf2_fpr): Ditto.
+ (floordf2, floordf2_fpr): Ditto.
+ (floatdidf2, floatdidf2_fpr): Ditto.
+ (fmadddf4_fpr): Name insn. Use VSX instructions if -mvsx.
+ (fmsubdf4_fpr): Ditto.
+ (fnmadddf4_fpr_1): Ditto.
+ (fnmadddf4_fpr_2): Ditto.
+ (fnmsubdf4_fpr_1): Ditto.
+ (fnmsubdf4_fpr_2): Ditto.
+ (fixuns_truncdfdi2): Add expander for VSX support.
+ (fix_truncdfdi2): Ditto.
+ (fix_truncdfsi2): Ditto.
+ (ftruncdf2): Ditto.
+ (btruncsf2): Whitespace.
+ (movdf_hardfloat32): Add support for VSX registers.
+ (movdf_softfloat32): Ditto.
+ (movdf_hardfloat64): Ditto.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_softfloat64): Ditto.
+ (movti splitters): Add check for vector registers supporting
+ TImode in the future.
+ (bpermd): Add power7 bpermd instruction.
+
+ * config/rs6000/altivec.h (vec_div): Define if VSX.
+ (vec_mul): Ditto.
+ (vec_msub): Ditto.
+ (vec_nmadd): Ditto.
+ (vec_nearbyint): Ditto.
+ (vec_rint): Ditto.
+ (vec_sqrt): Ditto.
+ (all predicates): Use the generic builtin function, and not the
+ V4SF specific function so that the predicates will work with
+ VSX's V2DF.
+ (vec_all_*): Ditto.
+ (vec_any_*): Ditto.
+
+ * doc/extend.texi (PowerPC Altivec/VSX Built-in Functions):
+ Document new VSX functions and types.
+
+ * doc/invoke.texi (PowerPc options): Document -mpopcntd, -mvsx
+ switches.
+
+ * doc/md.texi (PowerPC constraints): Document "wd", "wf", "ws",
+ "wa", and "j" constraints. Modify "v" to talk about Altivec
+ instead of just vector.
+
2009-07-30 Andrew MacLeod <amacleod@redhat.com>
PR debug/26475
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index 7b39799..bc4f30f 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -306,6 +306,17 @@
#define vec_splats __builtin_vec_splats
#define vec_promote __builtin_vec_promote
+#ifdef __VSX__
+/* VSX additions */
+#define vec_div __builtin_vec_div
+#define vec_mul __builtin_vec_mul
+#define vec_msub __builtin_vec_msub
+#define vec_nmadd __builtin_vec_nmadd
+#define vec_nearbyint __builtin_vec_nearbyint
+#define vec_rint __builtin_vec_rint
+#define vec_sqrt __builtin_vec_sqrt
+#endif
+
/* Predicates.
For C++, we use templates in order to allow non-parenthesized arguments.
For C, instead, we use macros since non-parenthesized arguments were
@@ -356,14 +367,14 @@ __altivec_scalar_pred(vec_any_out,
__builtin_altivec_vcmpbfp_p (__CR6_EQ_REV, a1, a2))
__altivec_unary_pred(vec_all_nan,
- __builtin_altivec_vcmpeqfp_p (__CR6_EQ, a1, a1))
+ __builtin_altivec_vcmpeq_p (__CR6_EQ, a1, a1))
__altivec_unary_pred(vec_any_nan,
- __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, a1, a1))
+ __builtin_altivec_vcmpeq_p (__CR6_LT_REV, a1, a1))
__altivec_unary_pred(vec_all_numeric,
- __builtin_altivec_vcmpeqfp_p (__CR6_LT, a1, a1))
+ __builtin_altivec_vcmpeq_p (__CR6_LT, a1, a1))
__altivec_unary_pred(vec_any_numeric,
- __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, a1, a1))
+ __builtin_altivec_vcmpeq_p (__CR6_EQ_REV, a1, a1))
__altivec_scalar_pred(vec_all_eq,
__builtin_vec_vcmpeq_p (__CR6_LT, a1, a2))
@@ -384,13 +395,13 @@ __altivec_scalar_pred(vec_any_lt,
__builtin_vec_vcmpgt_p (__CR6_EQ_REV, a2, a1))
__altivec_scalar_pred(vec_all_ngt,
- __builtin_altivec_vcmpgtfp_p (__CR6_EQ, a1, a2))
+ __builtin_altivec_vcmpgt_p (__CR6_EQ, a1, a2))
__altivec_scalar_pred(vec_all_nlt,
- __builtin_altivec_vcmpgtfp_p (__CR6_EQ, a2, a1))
+ __builtin_altivec_vcmpgt_p (__CR6_EQ, a2, a1))
__altivec_scalar_pred(vec_any_ngt,
- __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, a1, a2))
+ __builtin_altivec_vcmpgt_p (__CR6_LT_REV, a1, a2))
__altivec_scalar_pred(vec_any_nlt,
- __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, a2, a1))
+ __builtin_altivec_vcmpgt_p (__CR6_LT_REV, a2, a1))
/* __builtin_vec_vcmpge_p is vcmpgefp for floating-point vector types,
while for integer types it is converted to __builtin_vec_vcmpgt_p,
@@ -405,13 +416,13 @@ __altivec_scalar_pred(vec_any_ge,
__builtin_vec_vcmpge_p (__CR6_EQ_REV, a1, a2))
__altivec_scalar_pred(vec_all_nge,
- __builtin_altivec_vcmpgefp_p (__CR6_EQ, a1, a2))
+ __builtin_altivec_vcmpge_p (__CR6_EQ, a1, a2))
__altivec_scalar_pred(vec_all_nle,
- __builtin_altivec_vcmpgefp_p (__CR6_EQ, a2, a1))
+ __builtin_altivec_vcmpge_p (__CR6_EQ, a2, a1))
__altivec_scalar_pred(vec_any_nge,
- __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, a1, a2))
+ __builtin_altivec_vcmpge_p (__CR6_LT_REV, a1, a2))
__altivec_scalar_pred(vec_any_nle,
- __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, a2, a1))
+ __builtin_altivec_vcmpge_p (__CR6_LT_REV, a2, a1))
#undef __altivec_scalar_pred
#undef __altivec_unary_pred
@@ -423,11 +434,11 @@ __altivec_scalar_pred(vec_any_nle,
#define vec_all_in(a1, a2) __builtin_altivec_vcmpbfp_p (__CR6_EQ, (a1), (a2))
#define vec_any_out(a1, a2) __builtin_altivec_vcmpbfp_p (__CR6_EQ_REV, (a1), (a2))
-#define vec_all_nan(a1) __builtin_altivec_vcmpeqfp_p (__CR6_EQ, (a1), (a1))
-#define vec_any_nan(a1) __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, (a1), (a1))
+#define vec_all_nan(a1) __builtin_vec_vcmpeq_p (__CR6_EQ, (a1), (a1))
+#define vec_any_nan(a1) __builtin_vec_vcmpeq_p (__CR6_LT_REV, (a1), (a1))
-#define vec_all_numeric(a1) __builtin_altivec_vcmpeqfp_p (__CR6_LT, (a1), (a1))
-#define vec_any_numeric(a1) __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, (a1), (a1))
+#define vec_all_numeric(a1) __builtin_vec_vcmpeq_p (__CR6_LT, (a1), (a1))
+#define vec_any_numeric(a1) __builtin_vec_vcmpeq_p (__CR6_EQ_REV, (a1), (a1))
#define vec_all_eq(a1, a2) __builtin_vec_vcmpeq_p (__CR6_LT, (a1), (a2))
#define vec_all_ne(a1, a2) __builtin_vec_vcmpeq_p (__CR6_EQ, (a1), (a2))
@@ -439,10 +450,10 @@ __altivec_scalar_pred(vec_any_nle,
#define vec_any_gt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_EQ_REV, (a1), (a2))
#define vec_any_lt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_EQ_REV, (a2), (a1))
-#define vec_all_ngt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_EQ, (a1), (a2))
-#define vec_all_nlt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_EQ, (a2), (a1))
-#define vec_any_ngt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, (a1), (a2))
-#define vec_any_nlt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, (a2), (a1))
+#define vec_all_ngt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_EQ, (a1), (a2))
+#define vec_all_nlt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_EQ, (a2), (a1))
+#define vec_any_ngt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_LT_REV, (a1), (a2))
+#define vec_any_nlt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_LT_REV, (a2), (a1))
/* __builtin_vec_vcmpge_p is vcmpgefp for floating-point vector types,
while for integer types it is converted to __builtin_vec_vcmpgt_p,
@@ -452,10 +463,10 @@ __altivec_scalar_pred(vec_any_nle,
#define vec_any_le(a1, a2) __builtin_vec_vcmpge_p (__CR6_EQ_REV, (a2), (a1))
#define vec_any_ge(a1, a2) __builtin_vec_vcmpge_p (__CR6_EQ_REV, (a1), (a2))
-#define vec_all_nge(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_EQ, (a1), (a2))
-#define vec_all_nle(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_EQ, (a2), (a1))
-#define vec_any_nge(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, (a1), (a2))
-#define vec_any_nle(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, (a2), (a1))
+#define vec_all_nge(a1, a2) __builtin_vec_vcmpge_p (__CR6_EQ, (a1), (a2))
+#define vec_all_nle(a1, a2) __builtin_vec_vcmpge_p (__CR6_EQ, (a2), (a1))
+#define vec_any_nge(a1, a2) __builtin_vec_vcmpge_p (__CR6_LT_REV, (a1), (a2))
+#define vec_any_nle(a1, a2) __builtin_vec_vcmpge_p (__CR6_LT_REV, (a2), (a1))
#endif
/* These do not accept vectors, so they do not have a __builtin_vec_*
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 58af47c..53b1054 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -20,8 +20,8 @@
;; <http://www.gnu.org/licenses/>.
(define_constants
- [(UNSPEC_VCMPBFP 50)
;; 51-62 deleted
+ [(UNSPEC_VCMPBFP 64)
(UNSPEC_VMSUMU 65)
(UNSPEC_VMSUMM 66)
(UNSPEC_VMSUMSHM 68)
@@ -66,9 +66,9 @@
(UNSPEC_VSUMSWS 135)
(UNSPEC_VPERM 144)
(UNSPEC_VPERM_UNS 145)
- (UNSPEC_VRFIP 148)
+ ;; 148 deleted
(UNSPEC_VRFIN 149)
- (UNSPEC_VRFIM 150)
+ ;; 150 deleted
(UNSPEC_VCFUX 151)
(UNSPEC_VCFSX 152)
(UNSPEC_VCTUXS 153)
@@ -220,6 +220,35 @@
}
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
+;; Load up a vector with the most significant bit set by loading up -1 and
+;; doing a shift left
+(define_split
+ [(set (match_operand:VM 0 "altivec_register_operand" "")
+ (match_operand:VM 1 "easy_vector_constant_msb" ""))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && reload_completed"
+ [(const_int 0)]
+{
+ rtx dest = operands[0];
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtvec v;
+ int i, num_elements;
+
+ if (mode == V4SFmode)
+ {
+ mode = V4SImode;
+ dest = gen_lowpart (V4SImode, dest);
+ }
+
+ num_elements = GET_MODE_NUNITS (mode);
+ v = rtvec_alloc (num_elements);
+ for (i = 0; i < num_elements; i++)
+ RTVEC_ELT (v, i) = constm1_rtx;
+
+ emit_insn (gen_vec_initv4si (dest, gen_rtx_PARALLEL (mode, v)));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, gen_rtx_ASHIFT (mode, dest, dest)));
+ DONE;
+})
+
(define_split
[(set (match_operand:VM 0 "altivec_register_operand" "")
(match_operand:VM 1 "easy_vector_constant_add_self" ""))]
@@ -1310,7 +1339,7 @@
"vspltis<VI_char> %0,%1"
[(set_attr "type" "vecperm")])
-(define_insn "*altivec_ftruncv4sf2"
+(define_insn "*altivec_vrfiz"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
@@ -1337,10 +1366,10 @@
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vrfip"
+(define_insn "altivec_vrfip" ; ceil
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
- UNSPEC_VRFIP))]
+ UNSPEC_FRIP))]
"TARGET_ALTIVEC"
"vrfip %0,%1"
[(set_attr "type" "vecfloat")])
@@ -1353,10 +1382,10 @@
"vrfin %0,%1"
[(set_attr "type" "vecfloat")])
-(define_insn "altivec_vrfim"
+(define_insn "*altivec_vrfim" ; floor
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
- UNSPEC_VRFIM))]
+ UNSPEC_FRIM))]
"TARGET_ALTIVEC"
"vrfim %0,%1"
[(set_attr "type" "vecfloat")])
@@ -1431,6 +1460,28 @@
"vrefp %0,%1"
[(set_attr "type" "vecfloat")])
+(define_expand "altivec_copysign_v4sf3"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))
+ (use (match_operand:V4SF 2 "register_operand" ""))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "
+{
+ rtx mask = gen_reg_rtx (V4SImode);
+ rtvec v = rtvec_alloc (4);
+ unsigned HOST_WIDE_INT mask_val = ((unsigned HOST_WIDE_INT)1) << 31;
+
+ RTVEC_ELT (v, 0) = GEN_INT (mask_val);
+ RTVEC_ELT (v, 1) = GEN_INT (mask_val);
+ RTVEC_ELT (v, 2) = GEN_INT (mask_val);
+ RTVEC_ELT (v, 3) = GEN_INT (mask_val);
+
+ emit_insn (gen_vec_initv4si (mask, gen_rtx_PARALLEL (V4SImode, v)));
+ emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2],
+ gen_lowpart (V4SFmode, mask)));
+ DONE;
+}")
+
(define_insn "altivec_vsldoi_<mode>"
[(set (match_operand:VM 0 "register_operand" "=v")
(unspec:VM [(match_operand:VM 1 "register_operand" "v")
diff --git a/gcc/config/rs6000/power7.md b/gcc/config/rs6000/power7.md
new file mode 100644
index 0000000..3b6a95e
--- /dev/null
+++ b/gcc/config/rs6000/power7.md
@@ -0,0 +1,318 @@
+;; Scheduling description for IBM POWER7 processor.
+;; Copyright (C) 2009 Free Software Foundation, Inc.
+;;
+;; Contributed by Pat Haugen (pthaugen@us.ibm.com).
+
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_automaton "power7iu,power7lsu,power7vsu,power7misc")
+
+(define_cpu_unit "iu1_power7,iu2_power7" "power7iu")
+(define_cpu_unit "lsu1_power7,lsu2_power7" "power7lsu")
+(define_cpu_unit "vsu1_power7,vsu2_power7" "power7vsu")
+(define_cpu_unit "bpu_power7,cru_power7" "power7misc")
+(define_cpu_unit "du1_power7,du2_power7,du3_power7,du4_power7,du5_power7"
+ "power7misc")
+
+
+(define_reservation "DU_power7"
+ "du1_power7|du2_power7|du3_power7|du4_power7")
+
+(define_reservation "DU2F_power7"
+ "du1_power7+du2_power7")
+
+(define_reservation "DU4_power7"
+ "du1_power7+du2_power7+du3_power7+du4_power7")
+
+(define_reservation "FXU_power7"
+ "iu1_power7|iu2_power7")
+
+(define_reservation "VSU_power7"
+ "vsu1_power7|vsu2_power7")
+
+(define_reservation "LSU_power7"
+ "lsu1_power7|lsu2_power7")
+
+
+; Dispatch slots are allocated in order conforming to program order.
+(absence_set "du1_power7" "du2_power7,du3_power7,du4_power7,du5_power7")
+(absence_set "du2_power7" "du3_power7,du4_power7,du5_power7")
+(absence_set "du3_power7" "du4_power7,du5_power7")
+(absence_set "du4_power7" "du5_power7")
+
+
+; LS Unit
+(define_insn_reservation "power7-load" 2
+ (and (eq_attr "type" "load")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7")
+
+(define_insn_reservation "power7-load-ext" 3
+ (and (eq_attr "type" "load_ext")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,LSU_power7,FXU_power7")
+
+(define_insn_reservation "power7-load-update" 2
+ (and (eq_attr "type" "load_u")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,LSU_power7+FXU_power7")
+
+(define_insn_reservation "power7-load-update-indexed" 3
+ (and (eq_attr "type" "load_ux")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,FXU_power7,LSU_power7+FXU_power7")
+
+(define_insn_reservation "power7-load-ext-update" 4
+ (and (eq_attr "type" "load_ext_u")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,LSU_power7+FXU_power7,FXU_power7")
+
+(define_insn_reservation "power7-load-ext-update-indexed" 4
+ (and (eq_attr "type" "load_ext_ux")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,FXU_power7,LSU_power7+FXU_power7,FXU_power7")
+
+(define_insn_reservation "power7-fpload" 3
+ (and (eq_attr "type" "fpload")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7")
+
+(define_insn_reservation "power7-fpload-update" 3
+ (and (eq_attr "type" "fpload_u,fpload_ux")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,LSU_power7+FXU_power7")
+
+(define_insn_reservation "power7-store" 6 ; store-forwarding latency
+ (and (eq_attr "type" "store")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7+FXU_power7")
+
+(define_insn_reservation "power7-store-update" 6
+ (and (eq_attr "type" "store_u")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,LSU_power7+FXU_power7,FXU_power7")
+
+(define_insn_reservation "power7-store-update-indexed" 6
+ (and (eq_attr "type" "store_ux")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,LSU_power7+FXU_power7,FXU_power7")
+
+(define_insn_reservation "power7-fpstore" 6
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7+VSU_power7")
+
+(define_insn_reservation "power7-fpstore-update" 6
+ (and (eq_attr "type" "fpstore_u,fpstore_ux")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7+VSU_power7+FXU_power7")
+
+(define_insn_reservation "power7-larx" 3
+ (and (eq_attr "type" "load_l")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,LSU_power7")
+
+(define_insn_reservation "power7-stcx" 10
+ (and (eq_attr "type" "store_c")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,LSU_power7")
+
+(define_insn_reservation "power7-vecload" 3
+ (and (eq_attr "type" "vecload")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7")
+
+(define_insn_reservation "power7-vecstore" 6
+ (and (eq_attr "type" "vecstore")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,LSU_power7+VSU_power7")
+
+(define_insn_reservation "power7-sync" 11
+ (and (eq_attr "type" "sync")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,LSU_power7")
+
+
+; FX Unit
+(define_insn_reservation "power7-integer" 1
+ (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
+ var_shift_rotate,exts")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,FXU_power7")
+
+(define_insn_reservation "power7-cntlz" 2
+ (and (eq_attr "type" "cntlz")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,FXU_power7")
+
+(define_insn_reservation "power7-two" 2
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "power7"))
+ "DU_power7+DU_power7,FXU_power7,FXU_power7")
+
+(define_insn_reservation "power7-three" 3
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "power7"))
+ "DU_power7+DU_power7+DU_power7,FXU_power7,FXU_power7,FXU_power7")
+
+(define_insn_reservation "power7-cmp" 1
+ (and (eq_attr "type" "cmp,fast_compare")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,FXU_power7")
+
+(define_insn_reservation "power7-compare" 2
+ (and (eq_attr "type" "compare,delayed_compare,var_delayed_compare")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,FXU_power7,FXU_power7")
+
+(define_bypass 3 "power7-cmp,power7-compare" "power7-crlogical,power7-delayedcr")
+
+(define_insn_reservation "power7-mul" 4
+ (and (eq_attr "type" "imul,imul2,imul3,lmul")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,FXU_power7")
+
+(define_insn_reservation "power7-mul-compare" 5
+ (and (eq_attr "type" "imul_compare,lmul_compare")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,FXU_power7,nothing*3,FXU_power7")
+
+(define_insn_reservation "power7-idiv" 36
+ (and (eq_attr "type" "idiv")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,iu1_power7*36|iu2_power7*36")
+
+(define_insn_reservation "power7-ldiv" 68
+ (and (eq_attr "type" "ldiv")
+ (eq_attr "cpu" "power7"))
+ "DU2F_power7,iu1_power7*68|iu2_power7*68")
+
+(define_insn_reservation "power7-isync" 1 ;
+ (and (eq_attr "type" "isync")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,FXU_power7")
+
+
+; CR Unit
+(define_insn_reservation "power7-mtjmpr" 4
+ (and (eq_attr "type" "mtjmpr")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,FXU_power7")
+
+(define_insn_reservation "power7-mfjmpr" 5
+ (and (eq_attr "type" "mfjmpr")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,cru_power7+FXU_power7")
+
+(define_insn_reservation "power7-crlogical" 3
+ (and (eq_attr "type" "cr_logical")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,cru_power7")
+
+(define_insn_reservation "power7-delayedcr" 3
+ (and (eq_attr "type" "delayed_cr")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,cru_power7")
+
+(define_insn_reservation "power7-mfcr" 6
+ (and (eq_attr "type" "mfcr")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,cru_power7")
+
+(define_insn_reservation "power7-mfcrf" 3
+ (and (eq_attr "type" "mfcrf")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,cru_power7")
+
+(define_insn_reservation "power7-mtcr" 3
+ (and (eq_attr "type" "mtcr")
+ (eq_attr "cpu" "power7"))
+ "DU4_power7,cru_power7+FXU_power7")
+
+
+; BR Unit
+; Branches take dispatch Slot 4. The presence_sets prevent other insn from
+; grabbing previous dispatch slots once this is assigned.
+(define_insn_reservation "power7-branch" 3
+ (and (eq_attr "type" "jmpreg,branch")
+ (eq_attr "cpu" "power7"))
+ "(du5_power7\
+ |du4_power7+du5_power7\
+ |du3_power7+du4_power7+du5_power7\
+ |du2_power7+du3_power7+du4_power7+du5_power7\
+ |du1_power7+du2_power7+du3_power7+du4_power7+du5_power7),bpu_power7")
+
+
+; VS Unit (includes FP/VSX/VMX/DFP)
+(define_insn_reservation "power7-fp" 6
+ (and (eq_attr "type" "fp,dmul")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_bypass 8 "power7-fp" "power7-branch")
+
+(define_insn_reservation "power7-fpcompare" 4
+ (and (eq_attr "type" "fpcompare")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_insn_reservation "power7-sdiv" 26
+ (and (eq_attr "type" "sdiv")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_insn_reservation "power7-ddiv" 32
+ (and (eq_attr "type" "ddiv")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_insn_reservation "power7-sqrt" 31
+ (and (eq_attr "type" "ssqrt")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_insn_reservation "power7-dsqrt" 43
+ (and (eq_attr "type" "dsqrt")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_insn_reservation "power7-vecsimple" 2
+ (and (eq_attr "type" "vecsimple")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,VSU_power7")
+
+(define_insn_reservation "power7-veccmp" 7
+ (and (eq_attr "type" "veccmp")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,VSU_power7")
+
+(define_insn_reservation "power7-vecfloat" 7
+ (and (eq_attr "type" "vecfloat")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,VSU_power7")
+
+(define_bypass 6 "power7-vecfloat" "power7-vecfloat")
+
+(define_insn_reservation "power7-veccomplex" 7
+ (and (eq_attr "type" "veccomplex")
+ (eq_attr "cpu" "power7"))
+ "du1_power7,VSU_power7")
+
+(define_insn_reservation "power7-vecperm" 3
+ (and (eq_attr "type" "vecperm")
+ (eq_attr "cpu" "power7"))
+ "du2_power7,VSU_power7")
diff --git a/gcc/config/rs6000/ppc-asm.h b/gcc/config/rs6000/ppc-asm.h
index 147f109..c963eb9 100644
--- a/gcc/config/rs6000/ppc-asm.h
+++ b/gcc/config/rs6000/ppc-asm.h
@@ -87,7 +87,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define f16 16
#define f17 17
#define f18 18
-#define f19 19
+#define f19 19
#define f20 20
#define f21 21
#define f22 22
@@ -101,6 +101,143 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define f30 30
#define f31 31
+#ifdef __VSX__
+#define f32 32
+#define f33 33
+#define f34 34
+#define f35 35
+#define f36 36
+#define f37 37
+#define f38 38
+#define f39 39
+#define f40 40
+#define f41 41
+#define f42 42
+#define f43 43
+#define f44 44
+#define f45 45
+#define f46 46
+#define f47 47
+#define f48 48
+#define f49 49
+#define f50 30
+#define f51 51
+#define f52 52
+#define f53 53
+#define f54 54
+#define f55 55
+#define f56 56
+#define f57 57
+#define f58 58
+#define f59 59
+#define f60 60
+#define f61 61
+#define f62 62
+#define f63 63
+#endif
+
+#ifdef __ALTIVEC__
+#define v0 0
+#define v1 1
+#define v2 2
+#define v3 3
+#define v4 4
+#define v5 5
+#define v6 6
+#define v7 7
+#define v8 8
+#define v9 9
+#define v10 10
+#define v11 11
+#define v12 12
+#define v13 13
+#define v14 14
+#define v15 15
+#define v16 16
+#define v17 17
+#define v18 18
+#define v19 19
+#define v20 20
+#define v21 21
+#define v22 22
+#define v23 23
+#define v24 24
+#define v25 25
+#define v26 26
+#define v27 27
+#define v28 28
+#define v29 29
+#define v30 30
+#define v31 31
+#endif
+
+#ifdef __VSX__
+#define vs0 0
+#define vs1 1
+#define vs2 2
+#define vs3 3
+#define vs4 4
+#define vs5 5
+#define vs6 6
+#define vs7 7
+#define vs8 8
+#define vs9 9
+#define vs10 10
+#define vs11 11
+#define vs12 12
+#define vs13 13
+#define vs14 14
+#define vs15 15
+#define vs16 16
+#define vs17 17
+#define vs18 18
+#define vs19 19
+#define vs20 20
+#define vs21 21
+#define vs22 22
+#define vs23 23
+#define vs24 24
+#define vs25 25
+#define vs26 26
+#define vs27 27
+#define vs28 28
+#define vs29 29
+#define vs30 30
+#define vs31 31
+#define vs32 32
+#define vs33 33
+#define vs34 34
+#define vs35 35
+#define vs36 36
+#define vs37 37
+#define vs38 38
+#define vs39 39
+#define vs40 40
+#define vs41 41
+#define vs42 42
+#define vs43 43
+#define vs44 44
+#define vs45 45
+#define vs46 46
+#define vs47 47
+#define vs48 48
+#define vs49 49
+#define vs50 30
+#define vs51 51
+#define vs52 52
+#define vs53 53
+#define vs54 54
+#define vs55 55
+#define vs56 56
+#define vs57 57
+#define vs58 58
+#define vs59 59
+#define vs60 60
+#define vs61 61
+#define vs62 62
+#define vs63 63
+#endif
+
/*
* Macros to glue together two tokens.
*/
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 3e5c1a1..cf25cb7 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -377,6 +377,16 @@
return EASY_VECTOR_15_ADD_SELF (val);
})
+;; Same as easy_vector_constant but only for EASY_VECTOR_MSB.
+(define_predicate "easy_vector_constant_msb"
+ (and (match_code "const_vector")
+ (and (match_test "TARGET_ALTIVEC")
+ (match_test "easy_altivec_constant (op, mode)")))
+{
+ HOST_WIDE_INT val = const_vector_elt_as_int (op, GET_MODE_NUNITS (mode) - 1);
+ return EASY_VECTOR_MSB (val, GET_MODE_INNER (mode));
+})
+
;; Return 1 if operand is constant zero (scalars and vectors).
(define_predicate "zero_constant"
(and (match_code "const_int,const_double,const_vector")
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 3b3ba96..9435452 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -214,7 +214,8 @@ rs6000_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
|| rid_code == RID_SHORT || rid_code == RID_SIGNED
|| rid_code == RID_INT || rid_code == RID_CHAR
- || rid_code == RID_FLOAT)
+ || rid_code == RID_FLOAT
+ || (rid_code == RID_DOUBLE && TARGET_VSX))
{
expand_this = C_CPP_HASHNODE (__vector_keyword);
/* If the next keyword is bool or pixel, it
@@ -329,7 +330,42 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
if (TARGET_NO_LWSYNC)
builtin_define ("__NO_LWSYNC__");
if (TARGET_VSX)
- builtin_define ("__VSX__");
+ {
+ builtin_define ("__VSX__");
+
+ /* For the VSX builtin functions identical to Altivec functions, just map
+ the altivec builtin into the vsx version (the altivec functions
+ generate VSX code if -mvsx). */
+ builtin_define ("__builtin_vsx_xxland=__builtin_vec_and");
+ builtin_define ("__builtin_vsx_xxlandc=__builtin_vec_andc");
+ builtin_define ("__builtin_vsx_xxlnor=__builtin_vec_nor");
+ builtin_define ("__builtin_vsx_xxlor=__builtin_vec_or");
+ builtin_define ("__builtin_vsx_xxlxor=__builtin_vec_xor");
+ builtin_define ("__builtin_vsx_xxsel=__builtin_vec_sel");
+ builtin_define ("__builtin_vsx_vperm=__builtin_vec_perm");
+
+ /* Also map the a and m versions of the multiply/add instructions to the
+ builtin for people blindly going off the instruction manual. */
+ builtin_define ("__builtin_vsx_xvmaddadp=__builtin_vsx_xvmadddp");
+ builtin_define ("__builtin_vsx_xvmaddmdp=__builtin_vsx_xvmadddp");
+ builtin_define ("__builtin_vsx_xvmaddasp=__builtin_vsx_xvmaddsp");
+ builtin_define ("__builtin_vsx_xvmaddmsp=__builtin_vsx_xvmaddsp");
+ builtin_define ("__builtin_vsx_xvmsubadp=__builtin_vsx_xvmsubdp");
+ builtin_define ("__builtin_vsx_xvmsubmdp=__builtin_vsx_xvmsubdp");
+ builtin_define ("__builtin_vsx_xvmsubasp=__builtin_vsx_xvmsubsp");
+ builtin_define ("__builtin_vsx_xvmsubmsp=__builtin_vsx_xvmsubsp");
+ builtin_define ("__builtin_vsx_xvnmaddadp=__builtin_vsx_xvnmadddp");
+ builtin_define ("__builtin_vsx_xvnmaddmdp=__builtin_vsx_xvnmadddp");
+ builtin_define ("__builtin_vsx_xvnmaddasp=__builtin_vsx_xvnmaddsp");
+ builtin_define ("__builtin_vsx_xvnmaddmsp=__builtin_vsx_xvnmaddsp");
+ builtin_define ("__builtin_vsx_xvnmsubadp=__builtin_vsx_xvnmsubdp");
+ builtin_define ("__builtin_vsx_xvnmsubmdp=__builtin_vsx_xvnmsubdp");
+ builtin_define ("__builtin_vsx_xvnmsubasp=__builtin_vsx_xvnmsubsp");
+ builtin_define ("__builtin_vsx_xvnmsubmsp=__builtin_vsx_xvnmsubsp");
+ }
+
+ /* Tell users they can use __builtin_bswap{16,64}. */
+ builtin_define ("__HAVE_BSWAP__");
/* May be overridden by target configuration. */
RS6000_CPU_CPP_ENDIAN_BUILTINS();
@@ -393,7 +429,7 @@ struct altivec_builtin_types
};
const struct altivec_builtin_types altivec_overloaded_builtins[] = {
- /* Unary AltiVec builtins. */
+ /* Unary AltiVec/VSX builtins. */
{ ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V16QI,
RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V8HI,
@@ -402,6 +438,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V4SF,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABS, VSX_BUILTIN_XVABSDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_ABSS, ALTIVEC_BUILTIN_ABSS_V16QI,
RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_ABSS, ALTIVEC_BUILTIN_ABSS_V8HI,
@@ -410,8 +448,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_CEIL, ALTIVEC_BUILTIN_VRFIP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_CEIL, VSX_BUILTIN_XVRDPIP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_EXPTE, ALTIVEC_BUILTIN_VEXPTEFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_FLOOR, VSX_BUILTIN_XVRDPIM,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_FLOOR, ALTIVEC_BUILTIN_VRFIM,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_LOGE, ALTIVEC_BUILTIN_VLOGEFP,
@@ -444,6 +486,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_TRUNC, ALTIVEC_BUILTIN_VRFIZ,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_TRUNC, VSX_BUILTIN_XVRDPIZ,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHSB,
RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHSB,
@@ -489,7 +533,7 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_VUPKLSB, ALTIVEC_BUILTIN_VUPKLSB,
RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
- /* Binary AltiVec builtins. */
+ /* Binary AltiVec/VSX builtins. */
{ ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
@@ -528,6 +572,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, VSX_BUILTIN_XVADDDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_VADDFP, ALTIVEC_BUILTIN_VADDFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
@@ -673,9 +719,9 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
- RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
- RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
@@ -727,9 +773,9 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
- RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
- RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
@@ -812,6 +858,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, VSX_BUILTIN_XVCMPEQDP,
+ RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_VCMPEQFP, ALTIVEC_BUILTIN_VCMPEQFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
@@ -832,6 +880,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_CMPGE, ALTIVEC_BUILTIN_VCMPGEFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGE, VSX_BUILTIN_XVCMPGEDP,
+ RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTUB,
RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTSB,
@@ -846,6 +896,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, VSX_BUILTIN_XVCMPGTDP,
+ RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_VCMPGTFP, ALTIVEC_BUILTIN_VCMPGTFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VCMPGTSW, ALTIVEC_BUILTIN_VCMPGTSW,
@@ -874,6 +926,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPLE, ALTIVEC_BUILTIN_VCMPGEFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLE, VSX_BUILTIN_XVCMPGEDP,
+ RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTUB,
RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTSB,
@@ -888,6 +942,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTFP,
RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, VSX_BUILTIN_XVCMPGTDP,
+ RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_COPYSIGN, VSX_BUILTIN_CPSGNDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_COPYSIGN, ALTIVEC_BUILTIN_COPYSIGN_V4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_CTF, ALTIVEC_BUILTIN_VCFUX,
RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 },
{ ALTIVEC_BUILTIN_VEC_CTF, ALTIVEC_BUILTIN_VCFSX,
@@ -900,6 +960,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
{ ALTIVEC_BUILTIN_VEC_CTU, ALTIVEC_BUILTIN_VCTUXS,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
+ { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVSP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
@@ -1234,6 +1298,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, VSX_BUILTIN_XVMAXDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_VMAXFP, ALTIVEC_BUILTIN_VMAXFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW,
@@ -1410,6 +1476,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, VSX_BUILTIN_XVMINDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_VMINFP, ALTIVEC_BUILTIN_VMINFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW,
@@ -1460,6 +1528,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_VMINUB, ALTIVEC_BUILTIN_VMINUB,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { VSX_BUILTIN_VEC_MUL, VSX_BUILTIN_XVMULSP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { VSX_BUILTIN_VEC_MUL, VSX_BUILTIN_XVMULDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULEUB,
RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULESB,
@@ -1492,6 +1564,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V8HI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_VMULOUB, ALTIVEC_BUILTIN_VMULOUB,
RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NEARBYINT, VSX_BUILTIN_XVRDPI,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_NEARBYINT, VSX_BUILTIN_XVRSPI,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
@@ -1523,9 +1599,9 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
- RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
- RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
@@ -1622,6 +1698,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_VPKSHUS, ALTIVEC_BUILTIN_VPKSHUS,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RINT, VSX_BUILTIN_XVRDPIC,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_RINT, VSX_BUILTIN_XVRSPIC,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLB,
RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLB,
@@ -1658,6 +1738,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLW,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SQRT, VSX_BUILTIN_XVSQRTDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_SQRT, VSX_BUILTIN_XVSQRTSP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_VSLW, ALTIVEC_BUILTIN_VSLW,
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_VSLW, ALTIVEC_BUILTIN_VSLW,
@@ -1984,6 +2068,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, VSX_BUILTIN_XVSUBDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_VSUBFP, ALTIVEC_BUILTIN_VSUBFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
@@ -2145,9 +2231,9 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
- RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
- RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
@@ -2191,7 +2277,7 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
- /* Ternary AltiVec builtins. */
+ /* Ternary AltiVec/VSX builtins. */
{ ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
{ ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
@@ -2354,6 +2440,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_void, ~RS6000_BTI_float, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
{ ALTIVEC_BUILTIN_VEC_MADD, ALTIVEC_BUILTIN_VMADDFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_MADD, VSX_BUILTIN_XVMADDDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
{ ALTIVEC_BUILTIN_VEC_MADDS, ALTIVEC_BUILTIN_VMHADDSHS,
RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
{ ALTIVEC_BUILTIN_VEC_MLADD, ALTIVEC_BUILTIN_VMLADDUHM,
@@ -2366,6 +2454,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
{ ALTIVEC_BUILTIN_VEC_MRADDS, ALTIVEC_BUILTIN_VMHRADDSHS,
RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { VSX_BUILTIN_VEC_MSUB, VSX_BUILTIN_XVMSUBSP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { VSX_BUILTIN_VEC_MSUB, VSX_BUILTIN_XVMSUBDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
{ ALTIVEC_BUILTIN_VEC_MSUM, ALTIVEC_BUILTIN_VMSUMUBM,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI },
{ ALTIVEC_BUILTIN_VEC_MSUM, ALTIVEC_BUILTIN_VMSUMMBM,
@@ -2390,8 +2482,14 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V4SI },
{ ALTIVEC_BUILTIN_VEC_VMSUMUHS, ALTIVEC_BUILTIN_VMSUMUHS,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
+ { VSX_BUILTIN_VEC_NMADD, VSX_BUILTIN_XVNMADDSP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { VSX_BUILTIN_VEC_NMADD, VSX_BUILTIN_XVNMADDDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
{ ALTIVEC_BUILTIN_VEC_NMSUB, ALTIVEC_BUILTIN_VNMSUBFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_NMSUB, VSX_BUILTIN_XVNMSUBDP,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
{ ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DF,
RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V16QI },
{ ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DI,
@@ -2812,6 +2910,54 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
{ ALTIVEC_BUILTIN_VEC_STVRXL, ALTIVEC_BUILTIN_STVRXL,
RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DF,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DF,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI,
+ RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_NOT_OPAQUE },
/* Predicates. */
{ ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
@@ -2852,6 +2998,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_V4SI },
{ ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTFP_P,
RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VCMPGT_P, VSX_BUILTIN_XVCMPGTDP_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
{ ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
@@ -2900,6 +3048,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI },
{ ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQFP_P,
RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, VSX_BUILTIN_XVCMPEQDP_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
/* cmpge is the same as cmpgt for all cases except floating point.
@@ -2943,6 +3093,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_V4SI },
{ ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGEFP_P,
RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VCMPGE_P, VSX_BUILTIN_XVCMPGEDP_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
{ (enum rs6000_builtins) 0, (enum rs6000_builtins) 0, 0, 0, 0, 0 }
};
@@ -3064,8 +3216,10 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
const struct altivec_builtin_types *desc;
unsigned int n;
- if (fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST
- || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ if ((fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ && (fcode < VSX_BUILTIN_OVERLOADED_FIRST
+ || fcode > VSX_BUILTIN_OVERLOADED_LAST))
return NULL_TREE;
/* For now treat vec_splats and vec_promote as the same. */
@@ -3105,11 +3259,12 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
&& !INTEGRAL_TYPE_P (type))
goto bad;
unsigned_p = TYPE_UNSIGNED (type);
- if (type == long_long_unsigned_type_node
- || type == long_long_integer_type_node)
- goto bad;
switch (TYPE_MODE (type))
{
+ case DImode:
+ type = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
+ size = 2;
+ break;
case SImode:
type = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
size = 4;
@@ -3123,6 +3278,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
size = 16;
break;
case SFmode: type = V4SF_type_node; size = 4; break;
+ case DFmode: type = V2DF_type_node; size = 2; break;
default:
goto bad;
}
@@ -3139,7 +3295,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
return build_constructor (type, vec);
}
- /* For now use pointer tricks to do the extaction. */
+ /* For now use pointer tricks to do the extaction, unless we are on VSX
+ extracting a double from a constant offset. */
if (fcode == ALTIVEC_BUILTIN_VEC_EXTRACT)
{
tree arg1;
@@ -3148,6 +3305,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
tree arg1_inner_type;
tree decl, stmt;
tree innerptrtype;
+ enum machine_mode mode;
/* No second argument. */
if (nargs != 2)
@@ -3164,6 +3322,25 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
goto bad;
if (!INTEGRAL_TYPE_P (TREE_TYPE (arg2)))
goto bad;
+
+ /* If we can use the VSX xxpermdi instruction, use that for extract. */
+ mode = TYPE_MODE (arg1_type);
+ if ((mode == V2DFmode || mode == V2DImode) && VECTOR_MEM_VSX_P (mode)
+ && TREE_CODE (arg2) == INTEGER_CST
+ && TREE_INT_CST_HIGH (arg2) == 0
+ && (TREE_INT_CST_LOW (arg2) == 0 || TREE_INT_CST_LOW (arg2) == 1))
+ {
+ tree call = NULL_TREE;
+
+ if (mode == V2DFmode)
+ call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V2DF];
+ else if (mode == V2DImode)
+ call = rs6000_builtin_decls[VSX_BUILTIN_VEC_EXT_V2DI];
+
+ if (call)
+ return build_call_expr (call, 2, arg1, arg2);
+ }
+
/* Build *(((arg1_inner_type*)&(vector type){arg1})+arg2). */
arg1_inner_type = TREE_TYPE (arg1_type);
arg2 = build_binary_op (loc, BIT_AND_EXPR, arg2,
@@ -3193,7 +3370,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
return stmt;
}
- /* For now use pointer tricks to do the insertation. */
+ /* For now use pointer tricks to do the insertation, unless we are on VSX
+ inserting a double to a constant offset.. */
if (fcode == ALTIVEC_BUILTIN_VEC_INSERT)
{
tree arg0;
@@ -3203,7 +3381,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
tree arg1_inner_type;
tree decl, stmt;
tree innerptrtype;
-
+ enum machine_mode mode;
+
/* No second or third arguments. */
if (nargs != 3)
{
@@ -3220,6 +3399,27 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
goto bad;
if (!INTEGRAL_TYPE_P (TREE_TYPE (arg2)))
goto bad;
+
+ /* If we can use the VSX xxpermdi instruction, use that for insert. */
+ mode = TYPE_MODE (arg1_type);
+ if ((mode == V2DFmode || mode == V2DImode) && VECTOR_UNIT_VSX_P (mode)
+ && TREE_CODE (arg2) == INTEGER_CST
+ && TREE_INT_CST_HIGH (arg2) == 0
+ && (TREE_INT_CST_LOW (arg2) == 0 || TREE_INT_CST_LOW (arg2) == 1))
+ {
+ tree call = NULL_TREE;
+
+ if (mode == V2DFmode)
+ call = rs6000_builtin_decls[VSX_BUILTIN_VEC_SET_V2DF];
+ else if (mode == V2DImode)
+ call = rs6000_builtin_decls[VSX_BUILTIN_VEC_SET_V2DI];
+
+ /* Note, __builtin_vec_insert_<xxx> has vector and scalar types
+ reversed. */
+ if (call)
+ return build_call_expr (call, 3, arg1, arg0, arg2);
+ }
+
/* Build *(((arg1_inner_type*)&(vector type){arg1})+arg2) = arg0. */
arg1_inner_type = TREE_TYPE (arg1_type);
arg2 = build_binary_op (loc, BIT_AND_EXPR, arg2,
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index b077c83..25cacc4 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -837,6 +837,7 @@ static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
enum machine_mode, bool, bool, bool);
static bool rs6000_reg_live_or_pic_offset_p (int);
+static tree rs6000_builtin_vectorized_function (unsigned int, tree, tree);
static int rs6000_savres_strategy (rs6000_stack_t *, bool, int, int);
static void rs6000_restore_saved_cr (rtx, int);
static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT);
@@ -1395,6 +1396,10 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_HANDLE_OPTION
#define TARGET_HANDLE_OPTION rs6000_handle_option
+#undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
+#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
+ rs6000_builtin_vectorized_function
+
#undef TARGET_DEFAULT_TARGET_FLAGS
#define TARGET_DEFAULT_TARGET_FLAGS \
(TARGET_DEFAULT)
@@ -1871,20 +1876,14 @@ rs6000_init_hard_regno_mode_ok (void)
}
}
- /* V2DImode, prefer vsx over altivec, since the main use will be for
- vectorized floating point conversions. */
+ /* V2DImode, only allow under VSX, which can do V2DI insert/splat/extract.
+ Altivec doesn't have 64-bit support. */
if (TARGET_VSX)
{
rs6000_vector_mem[V2DImode] = VECTOR_VSX;
rs6000_vector_unit[V2DImode] = VECTOR_NONE;
rs6000_vector_align[V2DImode] = align64;
}
- else if (TARGET_ALTIVEC)
- {
- rs6000_vector_mem[V2DImode] = VECTOR_ALTIVEC;
- rs6000_vector_unit[V2DImode] = VECTOR_NONE;
- rs6000_vector_align[V2DImode] = align64;
- }
/* DFmode, see if we want to use the VSX unit. */
if (TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
@@ -2169,7 +2168,7 @@ rs6000_override_options (const char *default_cpu)
{"power7", PROCESSOR_POWER7,
POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
| MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
- /* | MASK_VSX */}, /* Don't add MASK_ISEL by default */
+ | MASK_VSX}, /* Don't add MASK_ISEL by default */
{"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
{"powerpc64", PROCESSOR_POWERPC64,
POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
@@ -2765,6 +2764,14 @@ rs6000_builtin_conversion (unsigned int tcode, tree type)
case FIX_TRUNC_EXPR:
switch (TYPE_MODE (type))
{
+ case V2DImode:
+ if (!VECTOR_UNIT_VSX_P (V2DFmode))
+ return NULL_TREE;
+
+ return TYPE_UNSIGNED (type)
+ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS_UNS]
+ : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS];
+
case V4SImode:
if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
return NULL_TREE;
@@ -2780,6 +2787,14 @@ rs6000_builtin_conversion (unsigned int tcode, tree type)
case FLOAT_EXPR:
switch (TYPE_MODE (type))
{
+ case V2DImode:
+ if (!VECTOR_UNIT_VSX_P (V2DFmode))
+ return NULL_TREE;
+
+ return TYPE_UNSIGNED (type)
+ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP]
+ : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP];
+
case V4SImode:
if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
return NULL_TREE;
@@ -2908,6 +2923,22 @@ rs6000_builtin_vec_perm (tree type, tree *mask_element_type)
d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
break;
+ case V2DFmode:
+ if (!TARGET_ALLOW_DF_PERMUTE)
+ return NULL_TREE;
+
+ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DF];
+ break;
+
+ case V2DImode:
+ if (!TARGET_ALLOW_DF_PERMUTE)
+ return NULL_TREE;
+
+ d = (uns_p
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI_UNS]
+ : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI]);
+ break;
+
default:
return NULL_TREE;
}
@@ -2981,6 +3012,136 @@ rs6000_parse_fpu_option (const char *option)
return FPU_NONE;
}
+/* Returns a function decl for a vectorized version of the builtin function
+ with builtin function code FN and the result vector type TYPE, or NULL_TREE
+ if it is not available. */
+
+static tree
+rs6000_builtin_vectorized_function (unsigned int fn, tree type_out,
+ tree type_in)
+{
+ enum machine_mode in_mode, out_mode;
+ int in_n, out_n;
+
+ if (TREE_CODE (type_out) != VECTOR_TYPE
+ || TREE_CODE (type_in) != VECTOR_TYPE
+ || !TARGET_VECTORIZE_BUILTINS)
+ return NULL_TREE;
+
+ out_mode = TYPE_MODE (TREE_TYPE (type_out));
+ out_n = TYPE_VECTOR_SUBPARTS (type_out);
+ in_mode = TYPE_MODE (TREE_TYPE (type_in));
+ in_n = TYPE_VECTOR_SUBPARTS (type_in);
+
+ switch (fn)
+ {
+ case BUILT_IN_COPYSIGN:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_CPSGNDP];
+ break;
+ case BUILT_IN_COPYSIGNF:
+ if (out_mode != SFmode || out_n != 4
+ || in_mode != SFmode || in_n != 4)
+ break;
+ if (VECTOR_UNIT_VSX_P (V4SFmode))
+ return rs6000_builtin_decls[VSX_BUILTIN_CPSGNSP];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode))
+ return rs6000_builtin_decls[ALTIVEC_BUILTIN_COPYSIGN_V4SF];
+ break;
+ case BUILT_IN_SQRT:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVSQRTDP];
+ break;
+ case BUILT_IN_SQRTF:
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVSQRTSP];
+ break;
+ case BUILT_IN_CEIL:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRDPIP];
+ break;
+ case BUILT_IN_CEILF:
+ if (out_mode != SFmode || out_n != 4
+ || in_mode != SFmode || in_n != 4)
+ break;
+ if (VECTOR_UNIT_VSX_P (V4SFmode))
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRSPIP];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode))
+ return rs6000_builtin_decls[ALTIVEC_BUILTIN_VRFIP];
+ break;
+ case BUILT_IN_FLOOR:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRDPIM];
+ break;
+ case BUILT_IN_FLOORF:
+ if (out_mode != SFmode || out_n != 4
+ || in_mode != SFmode || in_n != 4)
+ break;
+ if (VECTOR_UNIT_VSX_P (V4SFmode))
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRSPIM];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode))
+ return rs6000_builtin_decls[ALTIVEC_BUILTIN_VRFIM];
+ break;
+ case BUILT_IN_TRUNC:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRDPIZ];
+ break;
+ case BUILT_IN_TRUNCF:
+ if (out_mode != SFmode || out_n != 4
+ || in_mode != SFmode || in_n != 4)
+ break;
+ if (VECTOR_UNIT_VSX_P (V4SFmode))
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRSPIZ];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode))
+ return rs6000_builtin_decls[ALTIVEC_BUILTIN_VRFIZ];
+ break;
+ case BUILT_IN_NEARBYINT:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && flag_unsafe_math_optimizations
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRDPI];
+ break;
+ case BUILT_IN_NEARBYINTF:
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && flag_unsafe_math_optimizations
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRSPI];
+ break;
+ case BUILT_IN_RINT:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && !flag_trapping_math
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRDPIC];
+ break;
+ case BUILT_IN_RINTF:
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && !flag_trapping_math
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls[VSX_BUILTIN_XVRSPIC];
+ break;
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
+
/* Implement TARGET_HANDLE_OPTION. */
static bool
@@ -3621,6 +3782,11 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
&& (splat_val >= 0 || (step == 1 && copies == 1)))
;
+ /* Also check if are loading up the most significant bit which can be done by
+ loading up -1 and shifting the value left by -1. */
+ else if (EASY_VECTOR_MSB (splat_val, inner))
+ ;
+
else
return false;
@@ -3971,8 +4137,6 @@ rs6000_expand_vector_init (rtx target, rtx vals)
emit_insn (gen_rtx_SET (VOIDmode, target, const_vec));
return;
}
- else if (all_same && int_vector_p)
- ; /* Splat vector element. */
else
{
/* Load from constant pool. */
@@ -3981,8 +4145,66 @@ rs6000_expand_vector_init (rtx target, rtx vals)
}
}
- /* Store value to stack temp. Load vector element. Splat. */
- if (all_same)
+ /* Double word values on VSX can use xxpermdi or lxvdsx. */
+ if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
+ {
+ if (all_same)
+ {
+ rtx element = XVECEXP (vals, 0, 0);
+ if (mode == V2DFmode)
+ emit_insn (gen_vsx_splat_v2df (target, element));
+ else
+ emit_insn (gen_vsx_splat_v2di (target, element));
+ }
+ else
+ {
+ rtx op0 = copy_to_reg (XVECEXP (vals, 0, 0));
+ rtx op1 = copy_to_reg (XVECEXP (vals, 0, 1));
+ if (mode == V2DFmode)
+ emit_insn (gen_vsx_concat_v2df (target, op0, op1));
+ else
+ emit_insn (gen_vsx_concat_v2di (target, op0, op1));
+ }
+ return;
+ }
+
+ /* With single precision floating point on VSX, know that internally single
+ precision is actually represented as a double, and either make 2 V2DF
+ vectors, and convert these vectors to single precision, or do one
+ conversion, and splat the result to the other elements. */
+ if (mode == V4SFmode && VECTOR_MEM_VSX_P (mode))
+ {
+ if (all_same)
+ {
+ rtx freg = gen_reg_rtx (V4SFmode);
+ rtx sreg = copy_to_reg (XVECEXP (vals, 0, 0));
+
+ emit_insn (gen_vsx_xscvdpsp_scalar (freg, sreg));
+ emit_insn (gen_vsx_xxspltw_v4sf (target, freg, const0_rtx));
+ }
+ else
+ {
+ rtx dbl_even = gen_reg_rtx (V2DFmode);
+ rtx dbl_odd = gen_reg_rtx (V2DFmode);
+ rtx flt_even = gen_reg_rtx (V4SFmode);
+ rtx flt_odd = gen_reg_rtx (V4SFmode);
+
+ emit_insn (gen_vsx_concat_v2sf (dbl_even,
+ copy_to_reg (XVECEXP (vals, 0, 0)),
+ copy_to_reg (XVECEXP (vals, 0, 1))));
+ emit_insn (gen_vsx_concat_v2sf (dbl_odd,
+ copy_to_reg (XVECEXP (vals, 0, 2)),
+ copy_to_reg (XVECEXP (vals, 0, 3))));
+ emit_insn (gen_vsx_xvcvdpsp (flt_even, dbl_even));
+ emit_insn (gen_vsx_xvcvdpsp (flt_odd, dbl_odd));
+ emit_insn (gen_vec_extract_evenv4sf (target, flt_even, flt_odd));
+ }
+ return;
+ }
+
+ /* Store value to stack temp. Load vector element. Splat. However, splat
+ of 64-bit items is not supported on Altivec. */
+ if (all_same && GET_MODE_SIZE (mode) <= 4)
{
mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
emit_move_insn (adjust_address_nv (mem, inner_mode, 0),
@@ -4040,6 +4262,14 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
int width = GET_MODE_SIZE (inner_mode);
int i;
+ if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
+ {
+ rtx (*set_func) (rtx, rtx, rtx, rtx)
+ = ((mode == V2DFmode) ? gen_vsx_set_v2df : gen_vsx_set_v2di);
+ emit_insn (set_func (target, target, val, GEN_INT (elt)));
+ return;
+ }
+
/* Load single variable value. */
mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
emit_move_insn (adjust_address_nv (mem, inner_mode, 0), val);
@@ -4077,6 +4307,14 @@ rs6000_expand_vector_extract (rtx target, rtx vec, int elt)
enum machine_mode inner_mode = GET_MODE_INNER (mode);
rtx mem, x;
+ if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
+ {
+ rtx (*extract_func) (rtx, rtx, rtx)
+ = ((mode == V2DFmode) ? gen_vsx_extract_v2df : gen_vsx_extract_v2di);
+ emit_insn (extract_func (target, vec, GEN_INT (elt)));
+ return;
+ }
+
/* Allocate mode-sized buffer. */
mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
@@ -5447,6 +5685,10 @@ rs6000_mode_dependent_address (rtx addr)
case PRE_MODIFY:
return TARGET_UPDATE;
+ /* AND is only allowed in Altivec loads. */
+ case AND:
+ return true;
+
default:
break;
}
@@ -6048,6 +6290,8 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
case V2SFmode:
case V2SImode:
case V1DImode:
+ case V2DFmode:
+ case V2DImode:
if (CONSTANT_P (operands[1])
&& !easy_vector_constant (operands[1], mode))
operands[1] = force_const_mem (mode, operands[1]);
@@ -8192,6 +8436,59 @@ static const struct builtin_description bdesc_3arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL },
+ { MASK_VSX, CODE_FOR_vsx_fmaddv2df4, "__builtin_vsx_xvmadddp", VSX_BUILTIN_XVMADDDP },
+ { MASK_VSX, CODE_FOR_vsx_fmsubv2df4, "__builtin_vsx_xvmsubdp", VSX_BUILTIN_XVMSUBDP },
+ { MASK_VSX, CODE_FOR_vsx_fnmaddv2df4, "__builtin_vsx_xvnmadddp", VSX_BUILTIN_XVNMADDDP },
+ { MASK_VSX, CODE_FOR_vsx_fnmsubv2df4, "__builtin_vsx_xvnmsubdp", VSX_BUILTIN_XVNMSUBDP },
+
+ { MASK_VSX, CODE_FOR_vsx_fmaddv4sf4, "__builtin_vsx_xvmaddsp", VSX_BUILTIN_XVMADDSP },
+ { MASK_VSX, CODE_FOR_vsx_fmsubv4sf4, "__builtin_vsx_xvmsubsp", VSX_BUILTIN_XVMSUBSP },
+ { MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP },
+ { MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP },
+
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msub", VSX_BUILTIN_VEC_MSUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmadd", VSX_BUILTIN_VEC_NMADD },
+
+ { MASK_VSX, CODE_FOR_vector_select_v2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI },
+ { MASK_VSX, CODE_FOR_vector_select_v2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF },
+ { MASK_VSX, CODE_FOR_vector_select_v4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF },
+ { MASK_VSX, CODE_FOR_vector_select_v4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI },
+ { MASK_VSX, CODE_FOR_vector_select_v8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI },
+ { MASK_VSX, CODE_FOR_vector_select_v16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI },
+ { MASK_VSX, CODE_FOR_vector_select_v2di_uns, "__builtin_vsx_xxsel_2di_uns", VSX_BUILTIN_XXSEL_2DI_UNS },
+ { MASK_VSX, CODE_FOR_vector_select_v4si_uns, "__builtin_vsx_xxsel_4si_uns", VSX_BUILTIN_XXSEL_4SI_UNS },
+ { MASK_VSX, CODE_FOR_vector_select_v8hi_uns, "__builtin_vsx_xxsel_8hi_uns", VSX_BUILTIN_XXSEL_8HI_UNS },
+ { MASK_VSX, CODE_FOR_vector_select_v16qi_uns, "__builtin_vsx_xxsel_16qi_uns", VSX_BUILTIN_XXSEL_16QI_UNS },
+
+ { MASK_VSX, CODE_FOR_altivec_vperm_v2di, "__builtin_vsx_vperm_2di", VSX_BUILTIN_VPERM_2DI },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v2df, "__builtin_vsx_vperm_2df", VSX_BUILTIN_VPERM_2DF },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v4sf, "__builtin_vsx_vperm_4sf", VSX_BUILTIN_VPERM_4SF },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v4si, "__builtin_vsx_vperm_4si", VSX_BUILTIN_VPERM_4SI },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v8hi, "__builtin_vsx_vperm_8hi", VSX_BUILTIN_VPERM_8HI },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v16qi, "__builtin_vsx_vperm_16qi", VSX_BUILTIN_VPERM_16QI },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v2di_uns, "__builtin_vsx_vperm_2di_uns", VSX_BUILTIN_VPERM_2DI_UNS },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v4si_uns, "__builtin_vsx_vperm_4si_uns", VSX_BUILTIN_VPERM_4SI_UNS },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v8hi_uns, "__builtin_vsx_vperm_8hi_uns", VSX_BUILTIN_VPERM_8HI_UNS },
+ { MASK_VSX, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_vsx_vperm_16qi_uns", VSX_BUILTIN_VPERM_16QI_UNS },
+
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2df, "__builtin_vsx_xxpermdi_2df", VSX_BUILTIN_XXPERMDI_2DF },
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2di, "__builtin_vsx_xxpermdi_2di", VSX_BUILTIN_XXPERMDI_2DI },
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v4sf, "__builtin_vsx_xxpermdi_4sf", VSX_BUILTIN_XXPERMDI_4SF },
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v4si, "__builtin_vsx_xxpermdi_4si", VSX_BUILTIN_XXPERMDI_4SI },
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v8hi, "__builtin_vsx_xxpermdi_8hi", VSX_BUILTIN_XXPERMDI_8HI },
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v16qi, "__builtin_vsx_xxpermdi_16qi", VSX_BUILTIN_XXPERMDI_16QI },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxpermdi", VSX_BUILTIN_VEC_XXPERMDI },
+ { MASK_VSX, CODE_FOR_vsx_set_v2df, "__builtin_vsx_set_2df", VSX_BUILTIN_SET_2DF },
+ { MASK_VSX, CODE_FOR_vsx_set_v2di, "__builtin_vsx_set_2di", VSX_BUILTIN_SET_2DI },
+
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2di, "__builtin_vsx_xxsldwi_2di", VSX_BUILTIN_XXSLDWI_2DI },
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2df, "__builtin_vsx_xxsldwi_2df", VSX_BUILTIN_XXSLDWI_2DF },
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4sf, "__builtin_vsx_xxsldwi_4sf", VSX_BUILTIN_XXSLDWI_4SF },
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4si, "__builtin_vsx_xxsldwi_4si", VSX_BUILTIN_XXSLDWI_4SI },
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v8hi, "__builtin_vsx_xxsldwi_8hi", VSX_BUILTIN_XXSLDWI_8HI },
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v16qi, "__builtin_vsx_xxsldwi_16qi", VSX_BUILTIN_XXSLDWI_16QI },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxsldwi", VSX_BUILTIN_VEC_XXSLDWI },
+
{ 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB },
{ 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD },
{ 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 },
@@ -8337,9 +8634,50 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
{ MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
-
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
+ { MASK_ALTIVEC, CODE_FOR_vector_copysignv4sf3, "__builtin_altivec_copysignfp", ALTIVEC_BUILTIN_COPYSIGN_V4SF },
+
+ { MASK_VSX, CODE_FOR_addv2df3, "__builtin_vsx_xvadddp", VSX_BUILTIN_XVADDDP },
+ { MASK_VSX, CODE_FOR_subv2df3, "__builtin_vsx_xvsubdp", VSX_BUILTIN_XVSUBDP },
+ { MASK_VSX, CODE_FOR_mulv2df3, "__builtin_vsx_xvmuldp", VSX_BUILTIN_XVMULDP },
+ { MASK_VSX, CODE_FOR_divv2df3, "__builtin_vsx_xvdivdp", VSX_BUILTIN_XVDIVDP },
+ { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP },
+ { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP },
+ { MASK_VSX, CODE_FOR_vsx_tdivv2df3_fe, "__builtin_vsx_xvtdivdp_fe", VSX_BUILTIN_XVTDIVDP_FE },
+ { MASK_VSX, CODE_FOR_vsx_tdivv2df3_fg, "__builtin_vsx_xvtdivdp_fg", VSX_BUILTIN_XVTDIVDP_FG },
+ { MASK_VSX, CODE_FOR_vector_eqv2df, "__builtin_vsx_xvcmpeqdp", VSX_BUILTIN_XVCMPEQDP },
+ { MASK_VSX, CODE_FOR_vector_gtv2df, "__builtin_vsx_xvcmpgtdp", VSX_BUILTIN_XVCMPGTDP },
+ { MASK_VSX, CODE_FOR_vector_gev2df, "__builtin_vsx_xvcmpgedp", VSX_BUILTIN_XVCMPGEDP },
+
+ { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP },
+ { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP },
+ { MASK_VSX, CODE_FOR_mulv4sf3, "__builtin_vsx_xvmulsp", VSX_BUILTIN_XVMULSP },
+ { MASK_VSX, CODE_FOR_divv4sf3, "__builtin_vsx_xvdivsp", VSX_BUILTIN_XVDIVSP },
+ { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP },
+ { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP },
+ { MASK_VSX, CODE_FOR_vsx_tdivv4sf3_fe, "__builtin_vsx_xvtdivsp_fe", VSX_BUILTIN_XVTDIVSP_FE },
+ { MASK_VSX, CODE_FOR_vsx_tdivv4sf3_fg, "__builtin_vsx_xvtdivsp_fg", VSX_BUILTIN_XVTDIVSP_FG },
+ { MASK_VSX, CODE_FOR_vector_eqv4sf, "__builtin_vsx_xvcmpeqsp", VSX_BUILTIN_XVCMPEQSP },
+ { MASK_VSX, CODE_FOR_vector_gtv4sf, "__builtin_vsx_xvcmpgtsp", VSX_BUILTIN_XVCMPGTSP },
+ { MASK_VSX, CODE_FOR_vector_gev4sf, "__builtin_vsx_xvcmpgesp", VSX_BUILTIN_XVCMPGESP },
+
+ { MASK_VSX, CODE_FOR_smindf3, "__builtin_vsx_xsmindp", VSX_BUILTIN_XSMINDP },
+ { MASK_VSX, CODE_FOR_smaxdf3, "__builtin_vsx_xsmaxdp", VSX_BUILTIN_XSMAXDP },
+ { MASK_VSX, CODE_FOR_vsx_tdivdf3_fe, "__builtin_vsx_xstdivdp_fe", VSX_BUILTIN_XSTDIVDP_FE },
+ { MASK_VSX, CODE_FOR_vsx_tdivdf3_fg, "__builtin_vsx_xstdivdp_fg", VSX_BUILTIN_XSTDIVDP_FG },
+ { MASK_VSX, CODE_FOR_vector_copysignv2df3, "__builtin_vsx_cpsgndp", VSX_BUILTIN_CPSGNDP },
+ { MASK_VSX, CODE_FOR_vector_copysignv4sf3, "__builtin_vsx_cpsgnsp", VSX_BUILTIN_CPSGNSP },
+
+ { MASK_VSX, CODE_FOR_vsx_concat_v2df, "__builtin_vsx_concat_2df", VSX_BUILTIN_CONCAT_2DF },
+ { MASK_VSX, CODE_FOR_vsx_concat_v2di, "__builtin_vsx_concat_2di", VSX_BUILTIN_CONCAT_2DI },
+ { MASK_VSX, CODE_FOR_vsx_splat_v2df, "__builtin_vsx_splat_2df", VSX_BUILTIN_SPLAT_2DF },
+ { MASK_VSX, CODE_FOR_vsx_splat_v2di, "__builtin_vsx_splat_2di", VSX_BUILTIN_SPLAT_2DI },
+ { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4sf, "__builtin_vsx_xxmrghw", VSX_BUILTIN_XXMRGHW_4SF },
+ { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4si, "__builtin_vsx_xxmrghw_4si", VSX_BUILTIN_XXMRGHW_4SI },
+ { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4sf, "__builtin_vsx_xxmrglw", VSX_BUILTIN_XXMRGLW_4SF },
+ { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4si, "__builtin_vsx_xxmrglw_4si", VSX_BUILTIN_XXMRGLW_4SI },
+
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhm", ALTIVEC_BUILTIN_VEC_VADDUHM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubm", ALTIVEC_BUILTIN_VEC_VADDUBM },
@@ -8377,6 +8715,7 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_copysign", ALTIVEC_BUILTIN_VEC_COPYSIGN },
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW },
@@ -8466,6 +8805,9 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_mul", VSX_BUILTIN_VEC_MUL },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_div", VSX_BUILTIN_VEC_DIV },
+
{ 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
{ 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
{ 0, CODE_FOR_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 },
@@ -8661,6 +9003,19 @@ static const struct builtin_description_predicates bdesc_altivec_preds[] =
{ MASK_ALTIVEC, CODE_FOR_vector_gtu_v16qi_p, "__builtin_altivec_vcmpgtub_p",
ALTIVEC_BUILTIN_VCMPGTUB_P },
+ { MASK_VSX, CODE_FOR_vector_eq_v4sf_p, "__builtin_vsx_xvcmpeqsp_p",
+ VSX_BUILTIN_XVCMPEQSP_P },
+ { MASK_VSX, CODE_FOR_vector_ge_v4sf_p, "__builtin_vsx_xvcmpgesp_p",
+ VSX_BUILTIN_XVCMPGESP_P },
+ { MASK_VSX, CODE_FOR_vector_gt_v4sf_p, "__builtin_vsx_xvcmpgtsp_p",
+ VSX_BUILTIN_XVCMPGTSP_P },
+ { MASK_VSX, CODE_FOR_vector_eq_v2df_p, "__builtin_vsx_xvcmpeqdp_p",
+ VSX_BUILTIN_XVCMPEQDP_P },
+ { MASK_VSX, CODE_FOR_vector_ge_v2df_p, "__builtin_vsx_xvcmpgedp_p",
+ VSX_BUILTIN_XVCMPGEDP_P },
+ { MASK_VSX, CODE_FOR_vector_gt_v2df_p, "__builtin_vsx_xvcmpgtdp_p",
+ VSX_BUILTIN_XVCMPGTDP_P },
+
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpeq_p",
ALTIVEC_BUILTIN_VCMPEQ_P },
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpgt_p",
@@ -8724,7 +9079,11 @@ static const struct builtin_description bdesc_abs[] =
{ MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
{ MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
{ MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }
+ { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI },
+ { MASK_VSX, CODE_FOR_absv2df2, "__builtin_vsx_xvabsdp", VSX_BUILTIN_XVABSDP },
+ { MASK_VSX, CODE_FOR_vsx_nabsv2df2, "__builtin_vsx_xvnabsdp", VSX_BUILTIN_XVNABSDP },
+ { MASK_VSX, CODE_FOR_absv4sf2, "__builtin_vsx_xvabssp", VSX_BUILTIN_XVABSSP },
+ { MASK_VSX, CODE_FOR_vsx_nabsv4sf2, "__builtin_vsx_xvnabssp", VSX_BUILTIN_XVNABSSP },
};
/* Simple unary operations: VECb = foo (unsigned literal) or VECb =
@@ -8735,10 +9094,10 @@ static struct builtin_description bdesc_1arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vexptefp, "__builtin_altivec_vexptefp", ALTIVEC_BUILTIN_VEXPTEFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vlogefp, "__builtin_altivec_vlogefp", ALTIVEC_BUILTIN_VLOGEFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vrefp, "__builtin_altivec_vrefp", ALTIVEC_BUILTIN_VREFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vrfim, "__builtin_altivec_vrfim", ALTIVEC_BUILTIN_VRFIM },
+ { MASK_ALTIVEC, CODE_FOR_vector_floorv4sf2, "__builtin_altivec_vrfim", ALTIVEC_BUILTIN_VRFIM },
{ MASK_ALTIVEC, CODE_FOR_altivec_vrfin, "__builtin_altivec_vrfin", ALTIVEC_BUILTIN_VRFIN },
- { MASK_ALTIVEC, CODE_FOR_altivec_vrfip, "__builtin_altivec_vrfip", ALTIVEC_BUILTIN_VRFIP },
- { MASK_ALTIVEC, CODE_FOR_ftruncv4sf2, "__builtin_altivec_vrfiz", ALTIVEC_BUILTIN_VRFIZ },
+ { MASK_ALTIVEC, CODE_FOR_vector_ceilv4sf2, "__builtin_altivec_vrfip", ALTIVEC_BUILTIN_VRFIP },
+ { MASK_ALTIVEC, CODE_FOR_vector_btruncv4sf2, "__builtin_altivec_vrfiz", ALTIVEC_BUILTIN_VRFIZ },
{ MASK_ALTIVEC, CODE_FOR_altivec_vrsqrtefp, "__builtin_altivec_vrsqrtefp", ALTIVEC_BUILTIN_VRSQRTEFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vspltisb, "__builtin_altivec_vspltisb", ALTIVEC_BUILTIN_VSPLTISB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vspltish, "__builtin_altivec_vspltish", ALTIVEC_BUILTIN_VSPLTISH },
@@ -8750,6 +9109,65 @@ static struct builtin_description bdesc_1arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
+ { MASK_VSX, CODE_FOR_negv2df2, "__builtin_vsx_xvnegdp", VSX_BUILTIN_XVNEGDP },
+ { MASK_VSX, CODE_FOR_sqrtv2df2, "__builtin_vsx_xvsqrtdp", VSX_BUILTIN_XVSQRTDP },
+ { MASK_VSX, CODE_FOR_vsx_rsqrtev2df2, "__builtin_vsx_xvrsqrtedp", VSX_BUILTIN_XVRSQRTEDP },
+ { MASK_VSX, CODE_FOR_vsx_tsqrtv2df2_fe, "__builtin_vsx_xvtsqrtdp_fe", VSX_BUILTIN_XVTSQRTDP_FE },
+ { MASK_VSX, CODE_FOR_vsx_tsqrtv2df2_fg, "__builtin_vsx_xvtsqrtdp_fg", VSX_BUILTIN_XVTSQRTDP_FG },
+ { MASK_VSX, CODE_FOR_vsx_frev2df2, "__builtin_vsx_xvredp", VSX_BUILTIN_XVREDP },
+
+ { MASK_VSX, CODE_FOR_negv4sf2, "__builtin_vsx_xvnegsp", VSX_BUILTIN_XVNEGSP },
+ { MASK_VSX, CODE_FOR_sqrtv4sf2, "__builtin_vsx_xvsqrtsp", VSX_BUILTIN_XVSQRTSP },
+ { MASK_VSX, CODE_FOR_vsx_rsqrtev4sf2, "__builtin_vsx_xvrsqrtesp", VSX_BUILTIN_XVRSQRTESP },
+ { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2_fe, "__builtin_vsx_xvtsqrtsp_fe", VSX_BUILTIN_XVTSQRTSP_FE },
+ { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2_fg, "__builtin_vsx_xvtsqrtsp_fg", VSX_BUILTIN_XVTSQRTSP_FG },
+ { MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP },
+
+ { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvdpsp", VSX_BUILTIN_XSCVDPSP },
+ { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvspdp", VSX_BUILTIN_XSCVSPDP },
+ { MASK_VSX, CODE_FOR_vsx_xvcvdpsp, "__builtin_vsx_xvcvdpsp", VSX_BUILTIN_XVCVDPSP },
+ { MASK_VSX, CODE_FOR_vsx_xvcvspdp, "__builtin_vsx_xvcvspdp", VSX_BUILTIN_XVCVSPDP },
+ { MASK_VSX, CODE_FOR_vsx_tsqrtdf2_fe, "__builtin_vsx_xstsqrtdp_fe", VSX_BUILTIN_XSTSQRTDP_FE },
+ { MASK_VSX, CODE_FOR_vsx_tsqrtdf2_fg, "__builtin_vsx_xstsqrtdp_fg", VSX_BUILTIN_XSTSQRTDP_FG },
+
+ { MASK_VSX, CODE_FOR_vsx_fix_truncv2dfv2di2, "__builtin_vsx_xvcvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
+ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
+ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds_uns", VSX_BUILTIN_XVCVDPUXDS_UNS },
+ { MASK_VSX, CODE_FOR_vsx_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
+ { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
+ { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp_uns", VSX_BUILTIN_XVCVUXDDP_UNS },
+
+ { MASK_VSX, CODE_FOR_vsx_fix_truncv4sfv4si2, "__builtin_vsx_xvcvspsxws", VSX_BUILTIN_XVCVSPSXWS },
+ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv4sfv4si2, "__builtin_vsx_xvcvspuxws", VSX_BUILTIN_XVCVSPUXWS },
+ { MASK_VSX, CODE_FOR_vsx_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXWSP },
+ { MASK_VSX, CODE_FOR_vsx_floatunsv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
+
+ { MASK_VSX, CODE_FOR_vsx_xvcvdpsxws, "__builtin_vsx_xvcvdpsxws", VSX_BUILTIN_XVCVDPSXWS },
+ { MASK_VSX, CODE_FOR_vsx_xvcvdpuxws, "__builtin_vsx_xvcvdpuxws", VSX_BUILTIN_XVCVDPUXWS },
+ { MASK_VSX, CODE_FOR_vsx_xvcvsxwdp, "__builtin_vsx_xvcvsxwdp", VSX_BUILTIN_XVCVSXWDP },
+ { MASK_VSX, CODE_FOR_vsx_xvcvuxwdp, "__builtin_vsx_xvcvuxwdp", VSX_BUILTIN_XVCVUXWDP },
+ { MASK_VSX, CODE_FOR_vsx_xvrdpi, "__builtin_vsx_xvrdpi", VSX_BUILTIN_XVRDPI },
+ { MASK_VSX, CODE_FOR_vsx_xvrdpic, "__builtin_vsx_xvrdpic", VSX_BUILTIN_XVRDPIC },
+ { MASK_VSX, CODE_FOR_vsx_floorv2df2, "__builtin_vsx_xvrdpim", VSX_BUILTIN_XVRDPIM },
+ { MASK_VSX, CODE_FOR_vsx_ceilv2df2, "__builtin_vsx_xvrdpip", VSX_BUILTIN_XVRDPIP },
+ { MASK_VSX, CODE_FOR_vsx_btruncv2df2, "__builtin_vsx_xvrdpiz", VSX_BUILTIN_XVRDPIZ },
+
+ { MASK_VSX, CODE_FOR_vsx_xvcvspsxds, "__builtin_vsx_xvcvspsxds", VSX_BUILTIN_XVCVSPSXDS },
+ { MASK_VSX, CODE_FOR_vsx_xvcvspuxds, "__builtin_vsx_xvcvspuxds", VSX_BUILTIN_XVCVSPUXDS },
+ { MASK_VSX, CODE_FOR_vsx_xvcvsxdsp, "__builtin_vsx_xvcvsxdsp", VSX_BUILTIN_XVCVSXDSP },
+ { MASK_VSX, CODE_FOR_vsx_xvcvuxdsp, "__builtin_vsx_xvcvuxdsp", VSX_BUILTIN_XVCVUXDSP },
+ { MASK_VSX, CODE_FOR_vsx_xvrspi, "__builtin_vsx_xvrspi", VSX_BUILTIN_XVRSPI },
+ { MASK_VSX, CODE_FOR_vsx_xvrspic, "__builtin_vsx_xvrspic", VSX_BUILTIN_XVRSPIC },
+ { MASK_VSX, CODE_FOR_vsx_floorv4sf2, "__builtin_vsx_xvrspim", VSX_BUILTIN_XVRSPIM },
+ { MASK_VSX, CODE_FOR_vsx_ceilv4sf2, "__builtin_vsx_xvrspip", VSX_BUILTIN_XVRSPIP },
+ { MASK_VSX, CODE_FOR_vsx_btruncv4sf2, "__builtin_vsx_xvrspiz", VSX_BUILTIN_XVRSPIZ },
+
+ { MASK_VSX, CODE_FOR_vsx_xsrdpi, "__builtin_vsx_xsrdpi", VSX_BUILTIN_XSRDPI },
+ { MASK_VSX, CODE_FOR_vsx_xsrdpic, "__builtin_vsx_xsrdpic", VSX_BUILTIN_XSRDPIC },
+ { MASK_VSX, CODE_FOR_vsx_floordf2, "__builtin_vsx_xsrdpim", VSX_BUILTIN_XSRDPIM },
+ { MASK_VSX, CODE_FOR_vsx_ceildf2, "__builtin_vsx_xsrdpip", VSX_BUILTIN_XSRDPIP },
+ { MASK_VSX, CODE_FOR_vsx_btruncdf2, "__builtin_vsx_xsrdpiz", VSX_BUILTIN_XSRDPIZ },
+
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
@@ -8770,6 +9188,10 @@ static struct builtin_description bdesc_1arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_nearbyint", ALTIVEC_BUILTIN_VEC_NEARBYINT },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_rint", ALTIVEC_BUILTIN_VEC_RINT },
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_sqrt", ALTIVEC_BUILTIN_VEC_SQRT },
+
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vec_float_sisf", VECTOR_BUILTIN_FLOAT_V4SI_V4SF },
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vec_uns_float_sisf", VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF },
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
@@ -9293,6 +9715,36 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
}
break;
+ case CODE_FOR_vsx_xxpermdi_v2df:
+ case CODE_FOR_vsx_xxpermdi_v2di:
+ case CODE_FOR_vsx_xxsldwi_v16qi:
+ case CODE_FOR_vsx_xxsldwi_v8hi:
+ case CODE_FOR_vsx_xxsldwi_v4si:
+ case CODE_FOR_vsx_xxsldwi_v4sf:
+ case CODE_FOR_vsx_xxsldwi_v2di:
+ case CODE_FOR_vsx_xxsldwi_v2df:
+ /* Only allow 2-bit unsigned literals. */
+ STRIP_NOPS (arg2);
+ if (TREE_CODE (arg2) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg2) & ~0x3)
+ {
+ error ("argument 3 must be a 2-bit unsigned literal");
+ return const0_rtx;
+ }
+ break;
+
+ case CODE_FOR_vsx_set_v2df:
+ case CODE_FOR_vsx_set_v2di:
+ /* Only allow 1-bit unsigned literals. */
+ STRIP_NOPS (arg2);
+ if (TREE_CODE (arg2) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg2) & ~0x1)
+ {
+ error ("argument 3 must be a 1-bit unsigned literal");
+ return const0_rtx;
+ }
+ break;
+
default:
break;
}
@@ -9602,8 +10054,10 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
enum machine_mode tmode, mode0;
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- if (fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ if ((fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ || (fcode >= VSX_BUILTIN_OVERLOADED_FIRST
+ && fcode <= VSX_BUILTIN_OVERLOADED_LAST))
{
*expandedp = true;
error ("unresolved overload for Altivec builtin %qF", fndecl);
@@ -9711,18 +10165,24 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
case ALTIVEC_BUILTIN_VEC_INIT_V8HI:
case ALTIVEC_BUILTIN_VEC_INIT_V16QI:
case ALTIVEC_BUILTIN_VEC_INIT_V4SF:
+ case VSX_BUILTIN_VEC_INIT_V2DF:
+ case VSX_BUILTIN_VEC_INIT_V2DI:
return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
case ALTIVEC_BUILTIN_VEC_SET_V4SI:
case ALTIVEC_BUILTIN_VEC_SET_V8HI:
case ALTIVEC_BUILTIN_VEC_SET_V16QI:
case ALTIVEC_BUILTIN_VEC_SET_V4SF:
+ case VSX_BUILTIN_VEC_SET_V2DF:
+ case VSX_BUILTIN_VEC_SET_V2DI:
return altivec_expand_vec_set_builtin (exp);
case ALTIVEC_BUILTIN_VEC_EXT_V4SI:
case ALTIVEC_BUILTIN_VEC_EXT_V8HI:
case ALTIVEC_BUILTIN_VEC_EXT_V16QI:
case ALTIVEC_BUILTIN_VEC_EXT_V4SF:
+ case VSX_BUILTIN_VEC_EXT_V2DF:
+ case VSX_BUILTIN_VEC_EXT_V2DI:
return altivec_expand_vec_ext_builtin (exp, target);
default:
@@ -10245,6 +10705,11 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
if (fcode == RS6000_BUILTIN_BSWAP_HI)
return rs6000_expand_unop_builtin (CODE_FOR_bswaphi2, exp, target);
+ if (fcode == POWER7_BUILTIN_BPERMD)
+ return rs6000_expand_binop_builtin (((TARGET_64BIT)
+ ? CODE_FOR_bpermd_di
+ : CODE_FOR_bpermd_si), exp, target);
+
if (fcode == ALTIVEC_BUILTIN_MASK_FOR_LOAD
|| fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
{
@@ -10500,6 +10965,33 @@ rs6000_init_builtins (void)
TYPE_NAME (pixel_V8HI_type_node) = tdecl;
(*lang_hooks.decls.pushdecl) (tdecl);
+ if (TARGET_VSX)
+ {
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector double"),
+ unsigned_V2DI_type_node);
+ TYPE_NAME (V2DF_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
+
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector long"),
+ V2DI_type_node);
+ TYPE_NAME (V2DI_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
+
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector unsigned long"),
+ unsigned_V2DI_type_node);
+ TYPE_NAME (unsigned_V2DI_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
+
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector __bool long"),
+ bool_V2DI_type_node);
+ TYPE_NAME (bool_V2DI_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
+ }
+
if (TARGET_PAIRED_FLOAT)
paired_init_builtins ();
if (TARGET_SPE)
@@ -10531,6 +11023,15 @@ rs6000_init_builtins (void)
RS6000_BUILTIN_RECIP);
}
+ if (TARGET_POPCNTD)
+ {
+ enum machine_mode mode = (TARGET_64BIT) ? DImode : SImode;
+ tree ftype = builtin_function_type (mode, mode, mode, VOIDmode,
+ POWER7_BUILTIN_BPERMD,
+ "__builtin_bpermd");
+ def_builtin (MASK_POPCNTD, "__builtin_bpermd", ftype,
+ POWER7_BUILTIN_BPERMD);
+ }
if (TARGET_POWERPC)
{
/* Don't use builtin_function_type here, as it maps HI/QI to SI. */
@@ -10969,6 +11470,10 @@ altivec_init_builtins (void)
= build_function_type_list (integer_type_node,
integer_type_node, V4SF_type_node,
V4SF_type_node, NULL_TREE);
+ tree int_ftype_int_v2df_v2df
+ = build_function_type_list (integer_type_node,
+ integer_type_node, V2DF_type_node,
+ V2DF_type_node, NULL_TREE);
tree v4si_ftype_v4si
= build_function_type_list (V4SI_type_node, V4SI_type_node, NULL_TREE);
tree v8hi_ftype_v8hi
@@ -10977,6 +11482,8 @@ altivec_init_builtins (void)
= build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE);
tree v4sf_ftype_v4sf
= build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
+ tree v2df_ftype_v2df
+ = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE);
tree void_ftype_pcvoid_int_int
= build_function_type_list (void_type_node,
pcvoid_type_node, integer_type_node,
@@ -11079,8 +11586,10 @@ altivec_init_builtins (void)
{
enum machine_mode mode1;
tree type;
- bool is_overloaded = dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
+ bool is_overloaded = ((dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ || (dp->code >= VSX_BUILTIN_OVERLOADED_FIRST
+ && dp->code <= VSX_BUILTIN_OVERLOADED_LAST));
if (is_overloaded)
mode1 = VOIDmode;
@@ -11104,6 +11613,9 @@ altivec_init_builtins (void)
case V4SFmode:
type = int_ftype_int_v4sf_v4sf;
break;
+ case V2DFmode:
+ type = int_ftype_int_v2df_v2df;
+ break;
default:
gcc_unreachable ();
}
@@ -11134,6 +11646,9 @@ altivec_init_builtins (void)
case V4SFmode:
type = v4sf_ftype_v4sf;
break;
+ case V2DFmode:
+ type = v2df_ftype_v2df;
+ break;
default:
gcc_unreachable ();
}
@@ -11193,6 +11708,19 @@ altivec_init_builtins (void)
def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4sf", ftype,
ALTIVEC_BUILTIN_VEC_INIT_V4SF);
+ if (TARGET_VSX)
+ {
+ ftype = build_function_type_list (V2DF_type_node, double_type_node,
+ double_type_node, NULL_TREE);
+ def_builtin (MASK_VSX, "__builtin_vec_init_v2df", ftype,
+ VSX_BUILTIN_VEC_INIT_V2DF);
+
+ ftype = build_function_type_list (V2DI_type_node, intDI_type_node,
+ intDI_type_node, NULL_TREE);
+ def_builtin (MASK_VSX, "__builtin_vec_init_v2di", ftype,
+ VSX_BUILTIN_VEC_INIT_V2DI);
+ }
+
/* Access to the vec_set patterns. */
ftype = build_function_type_list (V4SI_type_node, V4SI_type_node,
intSI_type_node,
@@ -11218,6 +11746,21 @@ altivec_init_builtins (void)
def_builtin (MASK_ALTIVEC|MASK_VSX, "__builtin_vec_set_v4sf", ftype,
ALTIVEC_BUILTIN_VEC_SET_V4SF);
+ if (TARGET_VSX)
+ {
+ ftype = build_function_type_list (V2DF_type_node, V2DF_type_node,
+ double_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_VSX, "__builtin_vec_set_v2df", ftype,
+ VSX_BUILTIN_VEC_SET_V2DF);
+
+ ftype = build_function_type_list (V2DI_type_node, V2DI_type_node,
+ intDI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_VSX, "__builtin_vec_set_v2di", ftype,
+ VSX_BUILTIN_VEC_SET_V2DI);
+ }
+
/* Access to the vec_extract patterns. */
ftype = build_function_type_list (intSI_type_node, V4SI_type_node,
integer_type_node, NULL_TREE);
@@ -11238,6 +11781,19 @@ altivec_init_builtins (void)
integer_type_node, NULL_TREE);
def_builtin (MASK_ALTIVEC|MASK_VSX, "__builtin_vec_ext_v4sf", ftype,
ALTIVEC_BUILTIN_VEC_EXT_V4SF);
+
+ if (TARGET_VSX)
+ {
+ ftype = build_function_type_list (double_type_node, V2DF_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_VSX, "__builtin_vec_ext_v2df", ftype,
+ VSX_BUILTIN_VEC_EXT_V2DF);
+
+ ftype = build_function_type_list (intDI_type_node, V2DI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_VSX, "__builtin_vec_ext_v2di", ftype,
+ VSX_BUILTIN_VEC_EXT_V2DI);
+ }
}
/* Hash function for builtin functions with up to 3 arguments and a return
@@ -11333,6 +11889,14 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
case ALTIVEC_BUILTIN_VSEL_8HI_UNS:
case ALTIVEC_BUILTIN_VSEL_4SI_UNS:
case ALTIVEC_BUILTIN_VSEL_2DI_UNS:
+ case VSX_BUILTIN_VPERM_16QI_UNS:
+ case VSX_BUILTIN_VPERM_8HI_UNS:
+ case VSX_BUILTIN_VPERM_4SI_UNS:
+ case VSX_BUILTIN_VPERM_2DI_UNS:
+ case VSX_BUILTIN_XXSEL_16QI_UNS:
+ case VSX_BUILTIN_XXSEL_8HI_UNS:
+ case VSX_BUILTIN_XXSEL_4SI_UNS:
+ case VSX_BUILTIN_XXSEL_2DI_UNS:
h.uns_p[0] = 1;
h.uns_p[1] = 1;
h.uns_p[2] = 1;
@@ -11346,6 +11910,12 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
case ALTIVEC_BUILTIN_VPERM_4SF:
case ALTIVEC_BUILTIN_VPERM_2DI:
case ALTIVEC_BUILTIN_VPERM_2DF:
+ case VSX_BUILTIN_VPERM_16QI:
+ case VSX_BUILTIN_VPERM_8HI:
+ case VSX_BUILTIN_VPERM_4SI:
+ case VSX_BUILTIN_VPERM_4SF:
+ case VSX_BUILTIN_VPERM_2DI:
+ case VSX_BUILTIN_VPERM_2DF:
h.uns_p[3] = 1;
break;
@@ -11442,8 +12012,10 @@ rs6000_common_init_builtins (void)
|| (mask == 0 && !TARGET_PAIRED_FLOAT))
continue;
- if (d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
+ && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
{
if (! (type = opaque_ftype_opaque_opaque_opaque))
type = opaque_ftype_opaque_opaque_opaque
@@ -11481,8 +12053,10 @@ rs6000_common_init_builtins (void)
|| (mask == 0 && !TARGET_PAIRED_FLOAT))
continue;
- if (d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
+ && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
{
if (! (type = opaque_ftype_opaque_opaque))
type = opaque_ftype_opaque_opaque
@@ -11537,14 +12111,15 @@ rs6000_common_init_builtins (void)
enum machine_mode mode0, mode1;
tree type;
int mask = d->mask;
- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
if ((mask != 0 && (mask & target_flags) == 0)
|| (mask == 0 && !TARGET_PAIRED_FLOAT))
continue;
- if (is_overloaded)
+ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
+ && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
{
if (! (type = opaque_ftype_opaque))
type = opaque_ftype_opaque
@@ -22228,18 +22803,24 @@ rs6000_handle_altivec_attribute (tree *node,
mode = TYPE_MODE (type);
/* Check for invalid AltiVec type qualifiers. */
- if (type == long_unsigned_type_node || type == long_integer_type_node)
- {
- if (TARGET_64BIT)
- error ("use of %<long%> in AltiVec types is invalid for 64-bit code");
- else if (rs6000_warn_altivec_long)
- warning (0, "use of %<long%> in AltiVec types is deprecated; use %<int%>");
- }
- else if (type == long_long_unsigned_type_node
- || type == long_long_integer_type_node)
- error ("use of %<long long%> in AltiVec types is invalid");
- else if (type == double_type_node)
- error ("use of %<double%> in AltiVec types is invalid");
+ if (!TARGET_VSX)
+ {
+ if (type == long_unsigned_type_node || type == long_integer_type_node)
+ {
+ if (TARGET_64BIT)
+ error ("use of %<long%> in AltiVec types is invalid for "
+ "64-bit code without -mvsx");
+ else if (rs6000_warn_altivec_long)
+ warning (0, "use of %<long%> in AltiVec types is deprecated; "
+ "use %<int%>");
+ }
+ else if (type == long_long_unsigned_type_node
+ || type == long_long_integer_type_node)
+ error ("use of %<long long%> in AltiVec types is invalid without "
+ "-mvsx");
+ else if (type == double_type_node)
+ error ("use of %<double%> in AltiVec types is invalid without -mvsx");
+ }
else if (type == long_double_type_node)
error ("use of %<long double%> in AltiVec types is invalid");
else if (type == boolean_type_node)
@@ -22255,6 +22836,9 @@ rs6000_handle_altivec_attribute (tree *node,
unsigned_p = TYPE_UNSIGNED (type);
switch (mode)
{
+ case DImode:
+ result = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
+ break;
case SImode:
result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
break;
@@ -22265,10 +22849,12 @@ rs6000_handle_altivec_attribute (tree *node,
result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
break;
case SFmode: result = V4SF_type_node; break;
+ case DFmode: result = V2DF_type_node; break;
/* If the user says 'vector int bool', we may be handed the 'bool'
attribute _before_ the 'vector' attribute, and so select the
proper type in the 'b' case below. */
case V4SImode: case V8HImode: case V16QImode: case V4SFmode:
+ case V2DImode: case V2DFmode:
result = type;
default: break;
}
@@ -22276,6 +22862,7 @@ rs6000_handle_altivec_attribute (tree *node,
case 'b':
switch (mode)
{
+ case DImode: case V2DImode: result = bool_V2DI_type_node; break;
case SImode: case V4SImode: result = bool_V4SI_type_node; break;
case HImode: case V8HImode: result = bool_V8HI_type_node; break;
case QImode: case V16QImode: result = bool_V16QI_type_node;
@@ -22320,6 +22907,7 @@ rs6000_mangle_type (const_tree type)
if (type == bool_short_type_node) return "U6__bools";
if (type == pixel_type_node) return "u7__pixel";
if (type == bool_int_type_node) return "U6__booli";
+ if (type == bool_long_type_node) return "U6__booll";
/* Mangle IBM extended float long double as `g' (__float128) on
powerpc*-linux where long-double-64 previously was the default. */
@@ -24557,7 +25145,7 @@ rs6000_vector_mode_supported_p (enum machine_mode mode)
if (TARGET_SPE && SPE_VECTOR_MODE (mode))
return true;
- else if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
+ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
return true;
else
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 3153243..0c5e593 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1883,6 +1883,10 @@ typedef struct rs6000_args
&& EASY_VECTOR_15((n) >> 1) \
&& ((n) & 1) == 0)
+#define EASY_VECTOR_MSB(n,mode) \
+ (((unsigned HOST_WIDE_INT)n) == \
+ ((((unsigned HOST_WIDE_INT)GET_MODE_MASK (mode)) + 1) >> 1))
+
/* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and jump to WIN. This
@@ -2678,6 +2682,7 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_VEC_EXT_V8HI,
ALTIVEC_BUILTIN_VEC_EXT_V16QI,
ALTIVEC_BUILTIN_VEC_EXT_V4SF,
+ ALTIVEC_BUILTIN_COPYSIGN_V4SF,
/* Altivec overloaded builtins. */
ALTIVEC_BUILTIN_VCMPEQ_P,
@@ -2703,6 +2708,7 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_VEC_CMPGT,
ALTIVEC_BUILTIN_VEC_CMPLE,
ALTIVEC_BUILTIN_VEC_CMPLT,
+ ALTIVEC_BUILTIN_VEC_COPYSIGN,
ALTIVEC_BUILTIN_VEC_CTF,
ALTIVEC_BUILTIN_VEC_CTS,
ALTIVEC_BUILTIN_VEC_CTU,
@@ -2745,6 +2751,7 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_VEC_MTVSCR,
ALTIVEC_BUILTIN_VEC_MULE,
ALTIVEC_BUILTIN_VEC_MULO,
+ ALTIVEC_BUILTIN_VEC_NEARBYINT,
ALTIVEC_BUILTIN_VEC_NMSUB,
ALTIVEC_BUILTIN_VEC_NOR,
ALTIVEC_BUILTIN_VEC_OR,
@@ -2755,6 +2762,7 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_VEC_PERM,
ALTIVEC_BUILTIN_VEC_RE,
ALTIVEC_BUILTIN_VEC_RL,
+ ALTIVEC_BUILTIN_VEC_RINT,
ALTIVEC_BUILTIN_VEC_ROUND,
ALTIVEC_BUILTIN_VEC_RSQRTE,
ALTIVEC_BUILTIN_VEC_SEL,
@@ -2772,6 +2780,7 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_VEC_SPLTB,
ALTIVEC_BUILTIN_VEC_SPLTH,
ALTIVEC_BUILTIN_VEC_SPLTW,
+ ALTIVEC_BUILTIN_VEC_SQRT,
ALTIVEC_BUILTIN_VEC_SR,
ALTIVEC_BUILTIN_VEC_SRA,
ALTIVEC_BUILTIN_VEC_SRL,
@@ -3228,6 +3237,8 @@ enum rs6000_builtins
VSX_BUILTIN_XSRSQRTEDP,
VSX_BUILTIN_XSSQRTDP,
VSX_BUILTIN_XSSUBDP,
+ VSX_BUILTIN_CPSGNDP,
+ VSX_BUILTIN_CPSGNSP,
VSX_BUILTIN_XSTDIVDP_FE,
VSX_BUILTIN_XSTDIVDP_FG,
VSX_BUILTIN_XSTSQRTDP_FE,
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index ae1ea99..9524fe8 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -101,6 +101,7 @@
(UNSPEC_RSQRT 48)
(UNSPEC_TOCREL 49)
(UNSPEC_MACHOPIC_OFFSET 50)
+ (UNSPEC_BPERM 51)
])
;;
@@ -167,6 +168,7 @@
(include "power4.md")
(include "power5.md")
(include "power6.md")
+(include "power7.md")
(include "cell.md")
(include "xfpu.md")
@@ -5900,9 +5902,18 @@
(match_dup 5))
(match_dup 3)
(match_dup 4)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !HONOR_NANS (DFmode) && !HONOR_SIGNED_ZEROS (DFmode)"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && ((TARGET_PPC_GFXOPT
+ && !HONOR_NANS (DFmode)
+ && !HONOR_SIGNED_ZEROS (DFmode))
+ || VECTOR_UNIT_VSX_P (DFmode))"
{
+ if (VECTOR_UNIT_VSX_P (DFmode))
+ {
+ emit_insn (gen_vsx_copysigndf3 (operands[0], operands[1],
+ operands[2], CONST0_RTX (DFmode)));
+ DONE;
+ }
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (DFmode);
operands[5] = CONST0_RTX (DFmode);
@@ -6037,7 +6048,8 @@
(define_insn "*negdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fneg %0,%1"
[(set_attr "type" "fp")])
@@ -6050,14 +6062,16 @@
(define_insn "*absdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fabs %0,%1"
[(set_attr "type" "fp")])
(define_insn "*nabsdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fnabs %0,%1"
[(set_attr "type" "fp")])
@@ -6072,7 +6086,8 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fa|fadd} %0,%1,%2"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_addsub_d")])
@@ -6088,7 +6103,8 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (match_operand:DF 1 "gpc_reg_operand" "d")
(match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fs|fsub} %0,%1,%2"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_addsub_d")])
@@ -6104,7 +6120,8 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_mul_d")])
@@ -6122,7 +6139,8 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(div:DF (match_operand:DF 1 "gpc_reg_operand" "d")
(match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fd|fdiv} %0,%1,%2"
[(set_attr "type" "ddiv")])
@@ -6138,73 +6156,81 @@
DONE;
})
-(define_insn "fred"
+(define_expand "fred"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRES))]
- "TARGET_POPCNTB && flag_finite_math_only"
+ "(TARGET_POPCNTB || VECTOR_UNIT_VSX_P (DFmode)) && flag_finite_math_only"
+ "")
+
+(define_insn "*fred_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
+ "TARGET_POPCNTB && flag_finite_math_only && !VECTOR_UNIT_VSX_P (DFmode)"
"fre %0,%1"
[(set_attr "type" "fp")])
-(define_insn ""
+(define_insn "*fmadddf4_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_NONE_P (DFmode)"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fmsubdf4_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_NONE_P (DFmode)"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmadddf4_fpr_1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && HONOR_SIGNED_ZEROS (DFmode)"
+ && HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmadddf4_fpr_2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d"))
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && ! HONOR_SIGNED_ZEROS (DFmode)"
+ && ! HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmsubdf4_fpr_1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && HONOR_SIGNED_ZEROS (DFmode)"
+ && HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmsubdf4_fpr_2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (match_operand:DF 3 "gpc_reg_operand" "d")
(mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && ! HONOR_SIGNED_ZEROS (DFmode)"
+ && ! HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
@@ -6213,7 +6239,8 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
"(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT"
+ && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
@@ -6308,6 +6335,12 @@
"TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
"")
+(define_expand "fixuns_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_VSX"
+ "")
+
; For each of these conversions, there is a define_expand, a define_insn
; with a '#' template, and a define_split (with C code). The idea is
; to allow constant folding with the template of the define_insn,
@@ -6549,24 +6582,38 @@
"{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")])
-(define_insn "btruncdf2"
+(define_expand "btruncdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
+(define_insn "*btruncdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"friz %0,%1"
[(set_attr "type" "fp")])
(define_insn "btruncsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
"friz %0,%1"
[(set_attr "type" "fp")])
-(define_insn "ceildf2"
+(define_expand "ceildf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
+(define_insn "*ceildf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"frip %0,%1"
[(set_attr "type" "fp")])
@@ -6577,10 +6624,17 @@
"frip %0,%1"
[(set_attr "type" "fp")])
-(define_insn "floordf2"
+(define_expand "floordf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
+(define_insn "*floordf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"frim %0,%1"
[(set_attr "type" "fp")])
@@ -6591,6 +6645,7 @@
"frim %0,%1"
[(set_attr "type" "fp")])
+;; No VSX equivalent to frin
(define_insn "rounddf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))]
@@ -6605,6 +6660,12 @@
"frin %0,%1"
[(set_attr "type" "fp")])
+(define_expand "ftruncdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (fix:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "VECTOR_UNIT_VSX_P (DFmode)"
+ "")
+
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
[(set (match_operand:SI 0 "memory_operand" "=Z")
@@ -6620,17 +6681,40 @@
"TARGET_HARD_FLOAT && !TARGET_FPRS"
"")
-(define_insn "floatdidf2"
+(define_expand "floatdidf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "")
+
+(define_insn "*floatdidf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fcfid %0,%1"
[(set_attr "type" "fp")])
-(define_insn "fix_truncdfdi2"
+(define_expand "floatunsdidf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "TARGET_VSX"
+ "")
+
+(define_expand "fix_truncdfdi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (fix:DI (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "")
+
+(define_insn "*fix_truncdfdi2_fpr"
[(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
(fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
+ && TARGET_DOUBLE_FLOAT && TARGET_FPRS && !VECTOR_UNIT_VSX_P (DFmode)"
"fctidz %0,%1"
[(set_attr "type" "fp")])
@@ -8956,8 +9040,8 @@
;; The "??" is a kludge until we can figure out a more reasonable way
;; of handling these non-offsettable values.
(define_insn "*movdf_hardfloat32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r")
- (match_operand:DF 1 "input_operand" "r,m,r,d,m,d,G,H,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,!r,!r,!r")
+ (match_operand:DF 1 "input_operand" "r,m,r,ws,wa,Z,Z,ws,wa,d,m,d,j,G,H,F"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
@@ -9036,19 +9120,30 @@
return \"\";
}
case 3:
- return \"fmr %0,%1\";
case 4:
- return \"lfd%U1%X1 %0,%1\";
+ return \"xxlor %x0,%x1,%x1\";
case 5:
- return \"stfd%U0%X0 %1,%0\";
case 6:
+ return \"lxsd%U1x %x0,%y1\";
case 7:
case 8:
+ return \"stxsd%U0x %x1,%y0\";
+ case 9:
+ return \"fmr %0,%1\";
+ case 10:
+ return \"lfd%U1%X1 %0,%1\";
+ case 11:
+ return \"stfd%U0%X0 %1,%0\";
+ case 12:
+ return \"xxlxor %x0,%x0,%x0\";
+ case 13:
+ case 14:
+ case 15:
return \"#\";
}
}"
- [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
- (set_attr "length" "8,16,16,4,4,4,8,12,16")])
+ [(set_attr "type" "two,load,store,fp,fp,fpload,fpload,fpstore,fpstore,fp,fpload,fpstore,vecsimple,*,*,*")
+ (set_attr "length" "8,16,16,4,4,4,4,4,4,4,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat32"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
@@ -9096,19 +9191,26 @@
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*movdf_hardfloat64_mfpgpr"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d")
- (match_operand:DF 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,*c*l,!r,*h,!r,!r,!r,r,d")
+ (match_operand:DF 1 "input_operand" "r,Y,r,ws,?wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F,d,r"))]
"TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT
+ && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"@
std%U0%X0 %1,%0
ld%U1%X1 %0,%1
mr %0,%1
+ xxlor %x0,%x1,%x1
+ xxlor %x0,%x1,%x1
+ lxsd%U1x %x0,%y1
+ lxsd%U1x %x0,%y1
+ stxsd%U0x %x1,%y0
+ stxsd%U0x %x1,%y0
fmr %0,%1
lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0
+ xxlxor %x0,%x0,%x0
mt%0 %1
mf%1 %0
{cror 0,0,0|nop}
@@ -9117,33 +9219,40 @@
#
mftgpr %0,%1
mffgpr %0,%1"
- [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
+ [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fp,fpload,fpstore,vecsimple,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*movdf_hardfloat64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r")
- (match_operand:DF 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,*c*l,!r,*h,!r,!r,!r")
+ (match_operand:DF 1 "input_operand" "r,Y,r,ws,wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F"))]
"TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT
+ && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"@
std%U0%X0 %1,%0
ld%U1%X1 %0,%1
mr %0,%1
+ xxlor %x0,%x1,%x1
+ xxlor %x0,%x1,%x1
+ lxsd%U1x %x0,%y1
+ lxsd%U1x %x0,%y1
+ stxsd%U0x %x1,%y0
+ stxsd%U0x %x1,%y0
fmr %0,%1
lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0
+ xxlxor %x0,%x0,%x0
mt%0 %1
mf%1 %0
{cror 0,0,0|nop}
#
#
#"
- [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
+ [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fp,fpload,fpstore,vecsimple,mtjmpr,mfjmpr,*,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat64"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
@@ -9720,15 +9829,16 @@
(define_insn "*movti_ppc64"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r")
(match_operand:TI 1 "input_operand" "r,r,m"))]
- "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
- || gpc_reg_operand (operands[1], TImode))"
+ "(TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
+ || gpc_reg_operand (operands[1], TImode)))
+ && VECTOR_MEM_NONE_P (TImode)"
"#"
[(set_attr "type" "*,store,load")])
(define_split
[(set (match_operand:TI 0 "gpc_reg_operand" "")
(match_operand:TI 1 "const_double_operand" ""))]
- "TARGET_POWERPC64"
+ "TARGET_POWERPC64 && VECTOR_MEM_NONE_P (TImode)"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"
@@ -9754,7 +9864,7 @@
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "input_operand" ""))]
- "reload_completed
+ "reload_completed && VECTOR_MEM_NONE_P (TImode)
&& gpr_or_gpr_p (operands[0], operands[1])"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
@@ -12647,7 +12757,8 @@
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d")
(match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fcmpu %0,%1,%2"
[(set_attr "type" "fpcompare")])
@@ -15320,9 +15431,19 @@
}"
[(set_attr "type" "load")])
+(define_insn "bpermd_<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (unspec:P [(match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "gpc_reg_operand" "r")] UNSPEC_BPERM))]
+ "TARGET_POPCNTD"
+ "bpermd %0,%1,%2"
+ [(set_attr "type" "integer")])
+
+
(include "sync.md")
(include "vector.md")
+(include "vsx.md")
(include "altivec.md")
(include "spe.md")
(include "dfp.md")
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index ac61ffc..90af9dc 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -151,6 +151,10 @@ malign-branch-targets
Target Undocumented Report Var(TARGET_ALIGN_BRANCH_TARGETS) Init(-1)
; Explicitly set/unset whether rs6000_align_branch_targets is set
+mvectorize-builtins
+Target Undocumented Report Var(TARGET_VECTORIZE_BUILTINS) Init(-1)
+; Explicitly control whether we vectorize the builtins or not.
+
mupdate
Target Report Var(TARGET_UPDATE) Init(1)
Generate load/store with update instructions
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 0b8e311..66a367a 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -53,6 +53,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \
$(srcdir)/config/rs6000/power4.md \
$(srcdir)/config/rs6000/power5.md \
$(srcdir)/config/rs6000/power6.md \
+ $(srcdir)/config/rs6000/power7.md \
$(srcdir)/config/rs6000/cell.md \
$(srcdir)/config/rs6000/xfpu.md \
$(srcdir)/config/rs6000/predicates.md \
@@ -60,6 +61,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \
$(srcdir)/config/rs6000/darwin.md \
$(srcdir)/config/rs6000/sync.md \
$(srcdir)/config/rs6000/vector.md \
+ $(srcdir)/config/rs6000/vsx.md \
$(srcdir)/config/rs6000/altivec.md \
$(srcdir)/config/rs6000/spe.md \
$(srcdir)/config/rs6000/dfp.md \
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 1546db7..6366e4f 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -1,6 +1,7 @@
-;; Expander definitions for vector support. No instructions are in this file,
-;; this file provides the generic vector expander, and the actual vector
-;; instructions will be in altivec.md.
+;; Expander definitions for vector support between altivec & vsx. No
+;; instructions are in this file, this file provides the generic vector
+;; expander, and the actual vector instructions will be in altivec.md and
+;; vsx.md
;; Copyright (C) 2009
;; Free Software Foundation, Inc.
@@ -27,10 +28,10 @@
(define_mode_iterator VEC_I [V16QI V8HI V4SI])
;; Vector float modes
-(define_mode_iterator VEC_F [V4SF])
+(define_mode_iterator VEC_F [V4SF V2DF])
;; Vector arithmetic modes
-(define_mode_iterator VEC_A [V16QI V8HI V4SI V4SF])
+(define_mode_iterator VEC_A [V16QI V8HI V4SI V4SF V2DF])
;; Vector modes that need alginment via permutes
(define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
@@ -41,6 +42,9 @@
;; Vector modes for moves. Don't do TImode here.
(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
+;; Vector modes for types that don't need a realignment under VSX
+(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF])
+
;; Vector comparison modes
(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
@@ -75,7 +79,7 @@
(define_expand "mov<mode>"
[(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
(match_operand:VEC_M 1 "any_operand" ""))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
if (can_create_pseudo_p ())
{
@@ -89,24 +93,25 @@
}
})
-;; Generic vector floating point load/store instructions.
+;; Generic vector floating point load/store instructions. These will match
+;; insns defined in vsx.md or altivec.md depending on the switches.
(define_expand "vector_load_<mode>"
[(set (match_operand:VEC_M 0 "vfloat_operand" "")
(match_operand:VEC_M 1 "memory_operand" ""))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_store_<mode>"
[(set (match_operand:VEC_M 0 "memory_operand" "")
(match_operand:VEC_M 1 "vfloat_operand" ""))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
;; Splits if a GPR register was chosen for the move
(define_split
[(set (match_operand:VEC_L 0 "nonimmediate_operand" "")
(match_operand:VEC_L 1 "input_operand" ""))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
&& reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
[(pc)]
@@ -149,7 +154,7 @@
(and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "reg_or_cint_operand" "rI"))
(const_int -16)))]
- "TARGET_ALTIVEC && (reload_in_progress || reload_completed)"
+ "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
"#"
"&& reload_completed"
[(set (match_dup 0)
@@ -167,7 +172,7 @@
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(and:P (match_operand:P 1 "gpc_reg_operand" "r")
(const_int -16)))]
- "TARGET_ALTIVEC && (reload_in_progress || reload_completed)"
+ "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0)
@@ -180,68 +185,131 @@
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
(match_operand:VEC_F 2 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "sub<mode>3"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
(match_operand:VEC_F 2 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "mul<mode>3"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
(match_operand:VEC_F 2 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD"
+ "(VECTOR_UNIT_VSX_P (<MODE>mode)
+ || (VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD))"
"
{
- emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
}")
+(define_expand "div<mode>3"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "")
+
(define_expand "neg<mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
- emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
+ DONE;
+ }
}")
(define_expand "abs<mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
- emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
+ DONE;
+ }
}")
(define_expand "smin<mode>3"
[(set (match_operand:VEC_F 0 "register_operand" "")
(smin:VEC_F (match_operand:VEC_F 1 "register_operand" "")
(match_operand:VEC_F 2 "register_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "smax<mode>3"
[(set (match_operand:VEC_F 0 "register_operand" "")
(smax:VEC_F (match_operand:VEC_F 1 "register_operand" "")
(match_operand:VEC_F 2 "register_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
+(define_expand "sqrt<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "")
+
(define_expand "ftrunc<mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_ceil<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
+ UNSPEC_FRIP))]
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_floor<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
+ UNSPEC_FRIM))]
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
+(define_expand "vector_btrunc<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_copysign<mode>3"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (if_then_else:VEC_F
+ (ge:VEC_F (match_operand:VEC_F 2 "vfloat_operand" "")
+ (match_dup 3))
+ (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" ""))
+ (neg:VEC_F (abs:VEC_F (match_dup 1)))))]
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
+ "
+{
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+
+ operands[3] = CONST0_RTX (<MODE>mode);
+}")
+
;; Vector comparisons
(define_expand "vcond<mode>"
@@ -252,7 +320,7 @@
(match_operand:VEC_F 5 "vfloat_operand" "")])
(match_operand:VEC_F 1 "vfloat_operand" "")
(match_operand:VEC_F 2 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
@@ -302,21 +370,21 @@
[(set (match_operand:VEC_C 0 "vlogical_operand" "")
(eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
(match_operand:VEC_C 2 "vlogical_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_gt<mode>"
[(set (match_operand:VEC_C 0 "vlogical_operand" "")
(gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
(match_operand:VEC_C 2 "vlogical_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_ge<mode>"
[(set (match_operand:VEC_C 0 "vlogical_operand" "")
(ge:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
(match_operand:VEC_C 2 "vlogical_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_gtu<mode>"
@@ -342,7 +410,7 @@
(const_int 0))
(match_operand:VEC_L 2 "vlogical_operand" "")
(match_operand:VEC_L 1 "vlogical_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_select_<mode>_uns"
@@ -352,7 +420,7 @@
(const_int 0))
(match_operand:VEC_L 2 "vlogical_operand" "")
(match_operand:VEC_L 1 "vlogical_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
;; Expansions that compare vectors producing a vector result and a predicate,
@@ -366,7 +434,7 @@
(set (match_operand:VEC_A 0 "vlogical_operand" "")
(eq:VEC_A (match_dup 1)
(match_dup 2)))])]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_gt_<mode>_p"
@@ -378,7 +446,7 @@
(set (match_operand:VEC_A 0 "vlogical_operand" "")
(gt:VEC_A (match_dup 1)
(match_dup 2)))])]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_ge_<mode>_p"
@@ -390,7 +458,7 @@
(set (match_operand:VEC_F 0 "vfloat_operand" "")
(ge:VEC_F (match_dup 1)
(match_dup 2)))])]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "vector_gtu_<mode>_p"
@@ -402,16 +470,16 @@
(set (match_operand:VEC_I 0 "vlogical_operand" "")
(gtu:VEC_I (match_dup 1)
(match_dup 2)))])]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
-;; AltiVec predicates.
+;; AltiVec/VSX predicates.
(define_expand "cr6_test_for_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(eq:SI (reg:CC 74)
(const_int 0)))]
- "TARGET_ALTIVEC"
+ "TARGET_ALTIVEC || TARGET_VSX"
"")
(define_expand "cr6_test_for_zero_reverse"
@@ -419,14 +487,14 @@
(eq:SI (reg:CC 74)
(const_int 0)))
(set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
- "TARGET_ALTIVEC"
+ "TARGET_ALTIVEC || TARGET_VSX"
"")
(define_expand "cr6_test_for_lt"
[(set (match_operand:SI 0 "register_operand" "=r")
(lt:SI (reg:CC 74)
(const_int 0)))]
- "TARGET_ALTIVEC"
+ "TARGET_ALTIVEC || TARGET_VSX"
"")
(define_expand "cr6_test_for_lt_reverse"
@@ -434,7 +502,7 @@
(lt:SI (reg:CC 74)
(const_int 0)))
(set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
- "TARGET_ALTIVEC"
+ "TARGET_ALTIVEC || TARGET_VSX"
"")
@@ -443,82 +511,94 @@
[(set (match_operand:VEC_L 0 "vlogical_operand" "")
(xor:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
(match_operand:VEC_L 2 "vlogical_operand" "")))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "ior<mode>3"
[(set (match_operand:VEC_L 0 "vlogical_operand" "")
(ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
(match_operand:VEC_L 2 "vlogical_operand" "")))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "and<mode>3"
[(set (match_operand:VEC_L 0 "vlogical_operand" "")
(and:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
(match_operand:VEC_L 2 "vlogical_operand" "")))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "one_cmpl<mode>2"
[(set (match_operand:VEC_L 0 "vlogical_operand" "")
(not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "nor<mode>3"
[(set (match_operand:VEC_L 0 "vlogical_operand" "")
(not:VEC_L (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
(match_operand:VEC_L 2 "vlogical_operand" ""))))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
(define_expand "andc<mode>3"
[(set (match_operand:VEC_L 0 "vlogical_operand" "")
(and:VEC_L (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))
(match_operand:VEC_L 1 "vlogical_operand" "")))]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
"")
;; Same size conversions
(define_expand "float<VEC_int><mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
- emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
+ DONE;
+ }
}")
(define_expand "unsigned_float<VEC_int><mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
(unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
- emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
+ DONE;
+ }
}")
(define_expand "fix_trunc<mode><VEC_int>2"
[(set (match_operand:<VEC_INT> 0 "vint_operand" "")
(fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
- emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
+ DONE;
+ }
}")
(define_expand "fixuns_trunc<mode><VEC_int>2"
[(set (match_operand:<VEC_INT> 0 "vint_operand" "")
(unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
"
{
- emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
- DONE;
+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
+ {
+ emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
+ DONE;
+ }
}")
@@ -526,7 +606,7 @@
(define_expand "vec_init<mode>"
[(match_operand:VEC_E 0 "vlogical_operand" "")
(match_operand:VEC_E 1 "" "")]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
rs6000_expand_vector_init (operands[0], operands[1]);
DONE;
@@ -536,7 +616,7 @@
[(match_operand:VEC_E 0 "vlogical_operand" "")
(match_operand:<VEC_base> 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
DONE;
@@ -546,7 +626,7 @@
[(match_operand:<VEC_base> 0 "register_operand" "")
(match_operand:VEC_E 1 "vlogical_operand" "")
(match_operand 2 "const_int_operand" "")]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
rs6000_expand_vector_extract (operands[0], operands[1],
INTVAL (operands[2]));
@@ -568,7 +648,7 @@
(const_int 3)
(const_int 1)]))
(const_int 5)))]
- "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
"")
(define_expand "vec_interleave_lowv4sf"
@@ -585,23 +665,171 @@
(const_int 1)
(const_int 3)]))
(const_int 5)))]
- "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
+ "")
+
+(define_expand "vec_interleave_highv2df"
+ [(set (match_operand:V2DF 0 "vfloat_operand" "")
+ (vec_concat:V2DF
+ (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "")
+ (parallel [(const_int 0)]))
+ (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "")
+ (parallel [(const_int 0)]))))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "")
+
+(define_expand "vec_interleave_lowv2df"
+ [(set (match_operand:V2DF 0 "vfloat_operand" "")
+ (vec_concat:V2DF
+ (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "")
+ (parallel [(const_int 1)]))
+ (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "")
+ (parallel [(const_int 1)]))))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
"")
+;; Convert double word types to single word types
+(define_expand "vec_pack_trunc_v2df"
+ [(match_operand:V4SF 0 "vfloat_operand" "")
+ (match_operand:V2DF 1 "vfloat_operand" "")
+ (match_operand:V2DF 2 "vfloat_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
+{
+ rtx r1 = gen_reg_rtx (V4SFmode);
+ rtx r2 = gen_reg_rtx (V4SFmode);
+
+ emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
+ emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
+ emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2));
+ DONE;
+})
+
+(define_expand "vec_pack_sfix_trunc_v2df"
+ [(match_operand:V4SI 0 "vint_operand" "")
+ (match_operand:V2DF 1 "vfloat_operand" "")
+ (match_operand:V2DF 2 "vfloat_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
+{
+ rtx r1 = gen_reg_rtx (V4SImode);
+ rtx r2 = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
+ emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
+ emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
+ DONE;
+})
+
+(define_expand "vec_pack_ufix_trunc_v2df"
+ [(match_operand:V4SI 0 "vint_operand" "")
+ (match_operand:V2DF 1 "vfloat_operand" "")
+ (match_operand:V2DF 2 "vfloat_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
+{
+ rtx r1 = gen_reg_rtx (V4SImode);
+ rtx r2 = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
+ emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
+ emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
+ DONE;
+})
+
+;; Convert single word types to double word
+(define_expand "vec_unpacks_hi_v4sf"
+ [(match_operand:V2DF 0 "vfloat_operand" "")
+ (match_operand:V4SF 1 "vfloat_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
+{
+ rtx reg = gen_reg_rtx (V4SFmode);
+
+ emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1]));
+ emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
+ DONE;
+})
+
+(define_expand "vec_unpacks_lo_v4sf"
+ [(match_operand:V2DF 0 "vfloat_operand" "")
+ (match_operand:V4SF 1 "vfloat_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
+{
+ rtx reg = gen_reg_rtx (V4SFmode);
+
+ emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1]));
+ emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
+ DONE;
+})
+
+(define_expand "vec_unpacks_float_hi_v4si"
+ [(match_operand:V2DF 0 "vfloat_operand" "")
+ (match_operand:V4SI 1 "vint_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
+{
+ rtx reg = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
+ emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
+ DONE;
+})
+
+(define_expand "vec_unpacks_float_lo_v4si"
+ [(match_operand:V2DF 0 "vfloat_operand" "")
+ (match_operand:V4SI 1 "vint_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
+{
+ rtx reg = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
+ emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
+ DONE;
+})
+
+(define_expand "vec_unpacku_float_hi_v4si"
+ [(match_operand:V2DF 0 "vfloat_operand" "")
+ (match_operand:V4SI 1 "vint_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
+{
+ rtx reg = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
+ emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
+ DONE;
+})
+
+(define_expand "vec_unpacku_float_lo_v4si"
+ [(match_operand:V2DF 0 "vfloat_operand" "")
+ (match_operand:V4SI 1 "vint_operand" "")]
+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
+{
+ rtx reg = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
+ emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
+ DONE;
+})
+
+
;; Align vector loads with a permute.
(define_expand "vec_realign_load_<mode>"
[(match_operand:VEC_K 0 "vlogical_operand" "")
(match_operand:VEC_K 1 "vlogical_operand" "")
(match_operand:VEC_K 2 "vlogical_operand" "")
(match_operand:V16QI 3 "vlogical_operand" "")]
- "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], operands[2],
operands[3]));
DONE;
})
+;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
+;; since the load already handles it.
+(define_expand "movmisalign<mode>"
+ [(set (match_operand:VEC_N 0 "vfloat_operand" "")
+ (match_operand:VEC_N 1 "vfloat_operand" ""))]
+ "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
+ "")
+
;; Vector shift left in bits. Currently supported ony for shift
;; amounts that can be expressed as byte shifts (divisible by 8).
@@ -627,9 +855,18 @@
if (bitshift_val & 0x7)
FAIL;
byteshift_val = bitshift_val >> 3;
- shift = gen_rtx_CONST_INT (QImode, byteshift_val);
- insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
- shift);
+ if (TARGET_VSX && (byteshift_val & 0x3) == 0)
+ {
+ shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
+ insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
+ shift);
+ }
+ else
+ {
+ shift = gen_rtx_CONST_INT (QImode, byteshift_val);
+ insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
+ shift);
+ }
emit_insn (insn);
DONE;
@@ -659,9 +896,18 @@
if (bitshift_val & 0x7)
FAIL;
byteshift_val = 16 - (bitshift_val >> 3);
- shift = gen_rtx_CONST_INT (QImode, byteshift_val);
- insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
- shift);
+ if (TARGET_VSX && (byteshift_val & 0x3) == 0)
+ {
+ shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
+ insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
+ shift);
+ }
+ else
+ {
+ shift = gen_rtx_CONST_INT (QImode, byteshift_val);
+ insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
+ shift);
+ }
emit_insn (insn);
DONE;
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
new file mode 100644
index 0000000..c6aafa6f
--- /dev/null
+++ b/gcc/config/rs6000/vsx.md
@@ -0,0 +1,1339 @@
+;; VSX patterns.
+;; Copyright (C) 2009
+;; Free Software Foundation, Inc.
+;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; Iterator for both scalar and vector floating point types supported by VSX
+(define_mode_iterator VSX_B [DF V4SF V2DF])
+
+;; Iterator for the 2 64-bit vector types
+(define_mode_iterator VSX_D [V2DF V2DI])
+
+;; Iterator for the 2 32-bit vector types
+(define_mode_iterator VSX_W [V4SF V4SI])
+
+;; Iterator for vector floating point types supported by VSX
+(define_mode_iterator VSX_F [V4SF V2DF])
+
+;; Iterator for logical types supported by VSX
+(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
+
+;; Iterator for memory move. Handle TImode specially to allow
+;; it to use gprs as well as vsx registers.
+(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
+
+;; Iterator for types for load/store with update
+(define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF])
+
+;; Map into the appropriate load/store name based on the type
+(define_mode_attr VSm [(V16QI "vw4")
+ (V8HI "vw4")
+ (V4SI "vw4")
+ (V4SF "vw4")
+ (V2DF "vd2")
+ (V2DI "vd2")
+ (DF "d")
+ (TI "vw4")])
+
+;; Map into the appropriate suffix based on the type
+(define_mode_attr VSs [(V16QI "sp")
+ (V8HI "sp")
+ (V4SI "sp")
+ (V4SF "sp")
+ (V2DF "dp")
+ (V2DI "dp")
+ (DF "dp")
+ (SF "sp")
+ (TI "sp")])
+
+;; Map the register class used
+(define_mode_attr VSr [(V16QI "v")
+ (V8HI "v")
+ (V4SI "v")
+ (V4SF "wf")
+ (V2DI "wd")
+ (V2DF "wd")
+ (DF "ws")
+ (SF "d")
+ (TI "wd")])
+
+;; Map the register class used for float<->int conversions
+(define_mode_attr VSr2 [(V2DF "wd")
+ (V4SF "wf")
+ (DF "!f#r")])
+
+(define_mode_attr VSr3 [(V2DF "wa")
+ (V4SF "wa")
+ (DF "!f#r")])
+
+;; Map the register class for sp<->dp float conversions, destination
+(define_mode_attr VSr4 [(SF "ws")
+ (DF "f")
+ (V2DF "wd")
+ (V4SF "v")])
+
+;; Map the register class for sp<->dp float conversions, destination
+(define_mode_attr VSr5 [(SF "ws")
+ (DF "f")
+ (V2DF "v")
+ (V4SF "wd")])
+
+;; Same size integer type for floating point data
+(define_mode_attr VSi [(V4SF "v4si")
+ (V2DF "v2di")
+ (DF "di")])
+
+(define_mode_attr VSI [(V4SF "V4SI")
+ (V2DF "V2DI")
+ (DF "DI")])
+
+;; Word size for same size conversion
+(define_mode_attr VSc [(V4SF "w")
+ (V2DF "d")
+ (DF "d")])
+
+;; Bitsize for DF load with update
+(define_mode_attr VSbit [(SI "32")
+ (DI "64")])
+
+;; Map into either s or v, depending on whether this is a scalar or vector
+;; operation
+(define_mode_attr VSv [(V16QI "v")
+ (V8HI "v")
+ (V4SI "v")
+ (V4SF "v")
+ (V2DI "v")
+ (V2DF "v")
+ (TI "v")
+ (DF "s")])
+
+;; Appropriate type for add ops (and other simple FP ops)
+(define_mode_attr VStype_simple [(V2DF "vecfloat")
+ (V4SF "vecfloat")
+ (DF "fp")])
+
+(define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
+ (V4SF "fp_addsub_s")
+ (DF "fp_addsub_d")])
+
+;; Appropriate type for multiply ops
+(define_mode_attr VStype_mul [(V2DF "vecfloat")
+ (V4SF "vecfloat")
+ (DF "dmul")])
+
+(define_mode_attr VSfptype_mul [(V2DF "fp_mul_d")
+ (V4SF "fp_mul_s")
+ (DF "fp_mul_d")])
+
+;; Appropriate type for divide ops. For now, just lump the vector divide with
+;; the scalar divides
+(define_mode_attr VStype_div [(V2DF "ddiv")
+ (V4SF "sdiv")
+ (DF "ddiv")])
+
+(define_mode_attr VSfptype_div [(V2DF "fp_div_d")
+ (V4SF "fp_div_s")
+ (DF "fp_div_d")])
+
+;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
+;; the scalar sqrt
+(define_mode_attr VStype_sqrt [(V2DF "dsqrt")
+ (V4SF "sdiv")
+ (DF "ddiv")])
+
+(define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
+ (V4SF "fp_sqrt_s")
+ (DF "fp_sqrt_d")])
+
+;; Iterator and modes for sp<->dp conversions
+;; Because scalar SF values are represented internally as double, use the
+;; V4SF type to represent this than SF.
+(define_mode_iterator VSX_SPDP [DF V4SF V2DF])
+
+(define_mode_attr VS_spdp_res [(DF "V4SF")
+ (V4SF "V2DF")
+ (V2DF "V4SF")])
+
+(define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
+ (V4SF "xvcvspdp")
+ (V2DF "xvcvdpsp")])
+
+(define_mode_attr VS_spdp_type [(DF "fp")
+ (V4SF "vecfloat")
+ (V2DF "vecfloat")])
+
+;; Map the scalar mode for a vector type
+(define_mode_attr VS_scalar [(V2DF "DF")
+ (V2DI "DI")
+ (V4SF "SF")
+ (V4SI "SI")
+ (V8HI "HI")
+ (V16QI "QI")])
+
+;; Appropriate type for load + update
+(define_mode_attr VStype_load_update [(V16QI "vecload")
+ (V8HI "vecload")
+ (V4SI "vecload")
+ (V4SF "vecload")
+ (V2DI "vecload")
+ (V2DF "vecload")
+ (TI "vecload")
+ (DF "fpload")])
+
+;; Appropriate type for store + update
+(define_mode_attr VStype_store_update [(V16QI "vecstore")
+ (V8HI "vecstore")
+ (V4SI "vecstore")
+ (V4SF "vecstore")
+ (V2DI "vecstore")
+ (V2DF "vecstore")
+ (TI "vecstore")
+ (DF "fpstore")])
+
+;; Constants for creating unspecs
+(define_constants
+ [(UNSPEC_VSX_CONCAT 500)
+ (UNSPEC_VSX_CVDPSXWS 501)
+ (UNSPEC_VSX_CVDPUXWS 502)
+ (UNSPEC_VSX_CVSPDP 503)
+ (UNSPEC_VSX_CVSXWDP 504)
+ (UNSPEC_VSX_CVUXWDP 505)
+ (UNSPEC_VSX_CVSXDSP 506)
+ (UNSPEC_VSX_CVUXDSP 507)
+ (UNSPEC_VSX_CVSPSXDS 508)
+ (UNSPEC_VSX_CVSPUXDS 509)
+ (UNSPEC_VSX_MADD 510)
+ (UNSPEC_VSX_MSUB 511)
+ (UNSPEC_VSX_NMADD 512)
+ (UNSPEC_VSX_NMSUB 513)
+ (UNSPEC_VSX_RSQRTE 514)
+ (UNSPEC_VSX_TDIV 515)
+ (UNSPEC_VSX_TSQRT 516)
+ (UNSPEC_VSX_XXPERMDI 517)
+ (UNSPEC_VSX_SET 518)
+ (UNSPEC_VSX_ROUND_I 519)
+ (UNSPEC_VSX_ROUND_IC 520)
+ (UNSPEC_VSX_SLDWI 521)])
+
+;; VSX moves
+(define_insn "*vsx_mov<mode>"
+ [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
+ (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)
+ && (register_operand (operands[0], <MODE>mode)
+ || register_operand (operands[1], <MODE>mode))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 3:
+ return "stx<VSm>%U0x %x1,%y0";
+
+ case 1:
+ case 4:
+ return "lx<VSm>%U0x %x0,%y1";
+
+ case 2:
+ case 5:
+ return "xxlor %x0,%x1,%x1";
+
+ case 6:
+ case 7:
+ case 8:
+ return "#";
+
+ case 9:
+ case 10:
+ return "xxlxor %x0,%x0,%x0";
+
+ case 11:
+ return output_vec_const_move (operands);
+
+ case 12:
+ return "stvx %1,%y0";
+
+ case 13:
+ return "lvx %0,%y1";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
+
+;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
+;; unions. However for plain data movement, slightly favor the vector loads
+(define_insn "*vsx_movti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
+ (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
+ "VECTOR_MEM_VSX_P (TImode)
+ && (register_operand (operands[0], TImode)
+ || register_operand (operands[1], TImode))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "stxvd2%U0x %x1,%y0";
+
+ case 1:
+ return "lxvd2%U0x %x0,%y1";
+
+ case 2:
+ return "xxlor %x0,%x1,%x1";
+
+ case 3:
+ case 4:
+ case 5:
+ return "#";
+
+ case 6:
+ return "xxlxor %x0,%x0,%x0";
+
+ case 7:
+ return output_vec_const_move (operands);
+
+ case 8:
+ return "stvx %1,%y0";
+
+ case 9:
+ return "lvx %0,%y1";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
+
+;; Load/store with update
+;; Define insns that do load or store with update. Because VSX only has
+;; reg+reg addressing, pre-decrement or pre-increment is unlikely to be
+;; generated.
+;;
+;; In all these cases, we use operands 0 and 1 for the register being
+;; incremented because those are the operands that local-alloc will
+;; tie and these are the pair most likely to be tieable (and the ones
+;; that will benefit the most).
+
+(define_insn "*vsx_load<VSX_U:mode>_update_<P:mptrsize>"
+ [(set (match_operand:VSX_U 3 "vsx_register_operand" "=<VSr>,?wa")
+ (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
+ (match_operand:P 2 "gpc_reg_operand" "r,r"))))
+ (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
+ (plus:P (match_dup 1)
+ (match_dup 2)))]
+ "<P:tptrsize> && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "lx<VSm>ux %x3,%0,%2"
+ [(set_attr "type" "<VSX_U:VStype_load_update>")])
+
+(define_insn "*vsx_store<mode>_update_<P:mptrsize>"
+ [(set (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
+ (match_operand:P 2 "gpc_reg_operand" "r,r")))
+ (match_operand:VSX_U 3 "gpc_reg_operand" "<VSr>,?wa"))
+ (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
+ (plus:P (match_dup 1)
+ (match_dup 2)))]
+ "<P:tptrsize> && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "stx<VSm>ux %x3,%0,%2"
+ [(set_attr "type" "<VSX_U:VStype_store_update>")])
+
+;; We may need to have a varient on the pattern for use in the prologue
+;; that doesn't depend on TARGET_UPDATE.
+
+
+;; VSX scalar and vector floating point arithmetic instructions
+(define_insn "*vsx_add<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>add<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_sub<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>sub<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_mul<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>mul<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "*vsx_div<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>div<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_div>")
+ (set_attr "fp_type" "<VSfptype_div>")])
+
+;; *tdiv* instruction returning the FG flag
+(define_expand "vsx_tdiv<mode>3_fg"
+ [(set (match_dup 3)
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
+ (match_operand:VSX_B 2 "vsx_register_operand" "")]
+ UNSPEC_VSX_TDIV))
+ (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (gt:SI (match_dup 3)
+ (const_int 0)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ operands[3] = gen_reg_rtx (CCFPmode);
+})
+
+;; *tdiv* instruction returning the FE flag
+(define_expand "vsx_tdiv<mode>3_fe"
+ [(set (match_dup 3)
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")
+ (match_operand:VSX_B 2 "vsx_register_operand" "")]
+ UNSPEC_VSX_TDIV))
+ (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (eq:SI (match_dup 3)
+ (const_int 0)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ operands[3] = gen_reg_rtx (CCFPmode);
+})
+
+(define_insn "*vsx_tdiv<mode>3_internal"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_VSX_TDIV))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>tdiv<VSs> %0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_fre<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_FRES))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>re<VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_neg<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>neg<VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_abs<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>abs<VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_nabs<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_B
+ (abs:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>nabs<VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_smax<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>max<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_smin<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>min<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_sqrt<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>sqrt<VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_sqrt>")
+ (set_attr "fp_type" "<VSfptype_sqrt>")])
+
+(define_insn "vsx_rsqrte<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_VSX_RSQRTE))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>rsqrte<VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+;; *tsqrt* returning the fg flag
+(define_expand "vsx_tsqrt<mode>2_fg"
+ [(set (match_dup 3)
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
+ UNSPEC_VSX_TSQRT))
+ (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (gt:SI (match_dup 3)
+ (const_int 0)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ operands[3] = gen_reg_rtx (CCFPmode);
+})
+
+;; *tsqrt* returning the fe flag
+(define_expand "vsx_tsqrt<mode>2_fe"
+ [(set (match_dup 3)
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "")]
+ UNSPEC_VSX_TSQRT))
+ (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (eq:SI (match_dup 3)
+ (const_int 0)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ operands[3] = gen_reg_rtx (CCFPmode);
+})
+
+(define_insn "*vsx_tsqrt<mode>2_internal"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_VSX_TSQRT))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>tsqrt<VSs> %0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+;; Fused vector multiply/add instructions
+
+;; Note we have a pattern for the multiply/add operations that uses unspec and
+;; does not check -mfused-madd to allow users to use these ops when they know
+;; they want the fused multiply/add.
+
+(define_expand "vsx_fmadd<mode>4"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
+ (plus:VSX_B
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "")
+ (match_operand:VSX_B 2 "vsx_register_operand" ""))
+ (match_operand:VSX_B 3 "vsx_register_operand" "")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ if (!TARGET_FUSED_MADD)
+ {
+ emit_insn (gen_vsx_fmadd<mode>4_2 (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+})
+
+(define_insn "*vsx_fmadd<mode>4_1"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (plus:VSX_B
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
+ "@
+ x<VSv>madda<VSs> %x0,%x1,%x2
+ x<VSv>maddm<VSs> %x0,%x1,%x3
+ x<VSv>madda<VSs> %x0,%x1,%x2
+ x<VSv>maddm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "vsx_fmadd<mode>4_2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+ UNSPEC_VSX_MADD))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "@
+ x<VSv>madda<VSs> %x0,%x1,%x2
+ x<VSv>maddm<VSs> %x0,%x1,%x3
+ x<VSv>madda<VSs> %x0,%x1,%x2
+ x<VSv>maddm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_expand "vsx_fmsub<mode>4"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
+ (minus:VSX_B
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "")
+ (match_operand:VSX_B 2 "vsx_register_operand" ""))
+ (match_operand:VSX_B 3 "vsx_register_operand" "")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ if (!TARGET_FUSED_MADD)
+ {
+ emit_insn (gen_vsx_fmsub<mode>4_2 (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+})
+
+(define_insn "*vsx_fmsub<mode>4_1"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (minus:VSX_B
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
+ "@
+ x<VSv>msuba<VSs> %x0,%x1,%x2
+ x<VSv>msubm<VSs> %x0,%x1,%x3
+ x<VSv>msuba<VSs> %x0,%x1,%x2
+ x<VSv>msubm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "vsx_fmsub<mode>4_2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+ UNSPEC_VSX_MSUB))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "@
+ x<VSv>msuba<VSs> %x0,%x1,%x2
+ x<VSv>msubm<VSs> %x0,%x1,%x3
+ x<VSv>msuba<VSs> %x0,%x1,%x2
+ x<VSv>msubm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_expand "vsx_fnmadd<mode>4"
+ [(match_operand:VSX_B 0 "vsx_register_operand" "")
+ (match_operand:VSX_B 1 "vsx_register_operand" "")
+ (match_operand:VSX_B 2 "vsx_register_operand" "")
+ (match_operand:VSX_B 3 "vsx_register_operand" "")]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
+ {
+ emit_insn (gen_vsx_fnmadd<mode>4_1 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+ else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
+ {
+ emit_insn (gen_vsx_fnmadd<mode>4_2 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+ else
+ {
+ emit_insn (gen_vsx_fnmadd<mode>4_3 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+})
+
+(define_insn "vsx_fnmadd<mode>4_1"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (neg:VSX_B
+ (plus:VSX_B
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (DFmode)"
+ "@
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "vsx_fnmadd<mode>4_2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (minus:VSX_B
+ (mult:VSX_B
+ (neg:VSX_B
+ (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,<VSr>,wa,wa"))
+ (match_operand:VSX_B 2 "gpc_reg_operand" "<VSr>,0,wa,0"))
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
+ && !HONOR_SIGNED_ZEROS (DFmode)"
+ "@
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "vsx_fnmadd<mode>4_3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+ UNSPEC_VSX_NMADD))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "@
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3
+ x<VSv>nmadda<VSs> %x0,%x1,%x2
+ x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_expand "vsx_fnmsub<mode>4"
+ [(match_operand:VSX_B 0 "vsx_register_operand" "")
+ (match_operand:VSX_B 1 "vsx_register_operand" "")
+ (match_operand:VSX_B 2 "vsx_register_operand" "")
+ (match_operand:VSX_B 3 "vsx_register_operand" "")]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+{
+ if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
+ {
+ emit_insn (gen_vsx_fnmsub<mode>4_1 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+ else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
+ {
+ emit_insn (gen_vsx_fnmsub<mode>4_2 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+ else
+ {
+ emit_insn (gen_vsx_fnmsub<mode>4_3 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+})
+
+(define_insn "vsx_fnmsub<mode>4_1"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (neg:VSX_B
+ (minus:VSX_B
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (DFmode)"
+ "@
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "vsx_fnmsub<mode>4_2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (minus:VSX_B
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")
+ (mult:VSX_B
+ (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
+ && !HONOR_SIGNED_ZEROS (DFmode)"
+ "@
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+(define_insn "vsx_fnmsub<mode>4_3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+ UNSPEC_VSX_NMSUB))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "@
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3
+ x<VSv>nmsuba<VSs> %x0,%x1,%x2
+ x<VSv>nmsubm<VSs> %x0,%x1,%x3"
+ [(set_attr "type" "<VStype_mul>")
+ (set_attr "fp_type" "<VSfptype_mul>")])
+
+;; Vector conditional expressions (no scalar version for these instructions)
+(define_insn "vsx_eq<mode>"
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "xvcmpeq<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_gt<mode>"
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "xvcmpgt<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_ge<mode>"
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "xvcmpge<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+;; Floating point scalar compare
+(define_insn "*vsx_cmpdf_internal1"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
+ (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
+ (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_VSX_P (DFmode)"
+ "xscmpudp %0,%x1,%x2"
+ [(set_attr "type" "fpcompare")])
+
+;; Compare vectors producing a vector result and a predicate, setting CR6 to
+;; indicate a combined status
+(define_insn "*vsx_eq_<mode>_p"
+ [(set (reg:CC 74)
+ (unspec:CC
+ [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (eq:VSX_F (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "xvcmpeq<VSs>. %x0,%x1,%x2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "*vsx_gt_<mode>_p"
+ [(set (reg:CC 74)
+ (unspec:CC
+ [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (gt:VSX_F (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "xvcmpgt<VSs>. %x0,%x1,%x2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "*vsx_ge_<mode>_p"
+ [(set (reg:CC 74)
+ (unspec:CC
+ [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?wa"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (ge:VSX_F (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "xvcmpge<VSs>. %x0,%x1,%x2"
+ [(set_attr "type" "veccmp")])
+
+;; Vector select
+(define_insn "*vsx_xxsel<mode>"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (if_then_else:VSX_L
+ (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
+ (const_int 0))
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxsel %x0,%x3,%x2,%x1"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*vsx_xxsel<mode>_uns"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (if_then_else:VSX_L
+ (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
+ (const_int 0))
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxsel %x0,%x3,%x2,%x1"
+ [(set_attr "type" "vecperm")])
+
+;; Copy sign
+(define_insn "vsx_copysign<mode>3"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (if_then_else:VSX_B
+ (ge:VSX_B (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_B 3 "zero_constant" "j,j"))
+ (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))
+ (neg:VSX_B (abs:VSX_B (match_dup 1)))))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+;; For the conversions, limit the register class for the integer value to be
+;; the fprs because we don't want to add the altivec registers to movdi/movsi.
+;; For the unsigned tests, there isn't a generic double -> unsigned conversion
+;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
+(define_insn "vsx_float<VSi><mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>cvsx<VSc><VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_floatuns<VSi><mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>cvux<VSc><VSs> %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_fix_trunc<mode><VSi>2"
+ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
+ (fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_fixuns_trunc<mode><VSi>2"
+ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
+ (unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+;; Math rounding functions
+(define_insn "vsx_x<VSv>r<VSs>i"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_VSX_ROUND_I))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>r<VSs>i %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_x<VSv>r<VSs>ic"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_VSX_ROUND_IC))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>r<VSs>ic %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_btrunc<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>r<VSs>iz %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "*vsx_b2trunc<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_FRIZ))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>r<VSs>iz %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_floor<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_FRIM))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>r<VSs>im %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+(define_insn "vsx_ceil<mode>2"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ UNSPEC_FRIP))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "x<VSv>r<VSs>ip %x0,%x1"
+ [(set_attr "type" "<VStype_simple>")
+ (set_attr "fp_type" "<VSfptype_simple>")])
+
+
+;; VSX convert to/from double vector
+
+;; Convert between single and double precision
+;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
+;; scalar single precision instructions internally use the double format.
+;; Prefer the altivec registers, since we likely will need to do a vperm
+(define_insn "vsx_<VS_spdp_insn>"
+ [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
+ (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
+ UNSPEC_VSX_CVSPDP))]
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "<VS_spdp_insn> %x0,%x1"
+ [(set_attr "type" "<VS_spdp_type>")])
+
+;; xscvspdp, represent the scalar SF type as V4SF
+(define_insn "vsx_xscvspdp"
+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,?wa")
+ (unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
+ UNSPEC_VSX_CVSPDP))]
+ "VECTOR_UNIT_VSX_P (DFmode)"
+ "xscvspdp %x0,%x1"
+ [(set_attr "type" "fp")])
+
+;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
+;; format of scalars is actually DF.
+(define_insn "vsx_xscvdpsp_scalar"
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+ (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "f")]
+ UNSPEC_VSX_CVSPDP))]
+ "VECTOR_UNIT_VSX_P (DFmode)"
+ "xscvdpsp %x0,%x1"
+ [(set_attr "type" "fp")])
+
+;; Convert from 64-bit to 32-bit types
+;; Note, favor the Altivec registers since the usual use of these instructions
+;; is in vector converts and we need to use the Altivec vperm instruction.
+
+(define_insn "vsx_xvcvdpsxws"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
+ UNSPEC_VSX_CVDPSXWS))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvdpsxws %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "vsx_xvcvdpuxws"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
+ UNSPEC_VSX_CVDPUXWS))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvdpuxws %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "vsx_xvcvsxdsp"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
+ UNSPEC_VSX_CVSXDSP))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvsxdsp %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "vsx_xvcvuxdsp"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
+ UNSPEC_VSX_CVUXDSP))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvuxwdp %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+;; Convert from 32-bit to 64-bit types
+(define_insn "vsx_xvcvsxwdp"
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
+ UNSPEC_VSX_CVSXWDP))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvsxwdp %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "vsx_xvcvuxwdp"
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
+ UNSPEC_VSX_CVUXWDP))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvuxwdp %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "vsx_xvcvspsxds"
+ [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
+ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
+ UNSPEC_VSX_CVSPSXDS))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvspsxds %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "vsx_xvcvspuxds"
+ [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
+ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
+ UNSPEC_VSX_CVSPUXDS))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvspuxds %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+;; Logical and permute operations
+(define_insn "*vsx_and<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (and:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxland %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_ior<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlor %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_xor<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (xor:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlxor %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_one_cmpl<mode>2"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (not:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlnor %x0,%x1,%x1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_nor<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (not:VSX_L
+ (ior:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlnor %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_andc<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (and:VSX_L
+ (not:VSX_L
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlandc %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+
+;; Permute operations
+
+;; Build a V2DF/V2DI vector from two scalars
+(define_insn "vsx_concat_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:VSX_D
+ [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
+ (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
+ UNSPEC_VSX_CONCAT))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxpermdi %x0,%x1,%x2,0"
+ [(set_attr "type" "vecperm")])
+
+;; Special purpose concat using xxpermdi to glue two single precision values
+;; together, relying on the fact that internally scalar floats are represented
+;; as doubles. This is used to initialize a V4SF vector with 4 floats
+(define_insn "vsx_concat_v2sf"
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:V2DF
+ [(match_operand:SF 1 "vsx_register_operand" "f,f")
+ (match_operand:SF 2 "vsx_register_operand" "f,f")]
+ UNSPEC_VSX_CONCAT))]
+ "VECTOR_MEM_VSX_P (V2DFmode)"
+ "xxpermdi %x0,%x1,%x2,0"
+ [(set_attr "type" "vecperm")])
+
+;; Set the element of a V2DI/VD2F mode
+(define_insn "vsx_set_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
+ (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
+ (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
+ UNSPEC_VSX_SET))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+{
+ if (INTVAL (operands[3]) == 0)
+ return \"xxpermdi %x0,%x1,%x2,1\";
+ else if (INTVAL (operands[3]) == 1)
+ return \"xxpermdi %x0,%x2,%x1,0\";
+ else
+ gcc_unreachable ();
+}
+ [(set_attr "type" "vecperm")])
+
+;; Extract a DF/DI element from V2DF/V2DI
+(define_insn "vsx_extract_<mode>"
+ [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
+ (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+{
+ gcc_assert (UINTVAL (operands[2]) <= 1);
+ operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
+ return \"xxpermdi %x0,%x1,%x1,%3\";
+}
+ [(set_attr "type" "vecperm")])
+
+;; Optimize extracting element 0 from memory
+(define_insn "*vsx_extract_<mode>_zero"
+ [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
+ (vec_select:<VS_scalar>
+ (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
+ (parallel [(const_int 0)])))]
+ "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
+ "lxsd%U1x %x0,%y1"
+ [(set_attr "type" "fpload")
+ (set_attr "length" "4")])
+
+;; General double word oriented permute, allow the other vector types for
+;; optimizing the permute instruction.
+(define_insn "vsx_xxpermdi_<mode>"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
+ (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
+ (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
+ UNSPEC_VSX_XXPERMDI))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxpermdi %x0,%x1,%x2,%3"
+ [(set_attr "type" "vecperm")])
+
+;; Varient of xxpermdi that is emitted by the vec_interleave functions
+(define_insn "*vsx_xxpermdi2_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
+ (vec_concat:VSX_D
+ (vec_select:<VS_scalar>
+ (match_operand:VSX_D 1 "vsx_register_operand" "wd")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
+ (vec_select:<VS_scalar>
+ (match_operand:VSX_D 3 "vsx_register_operand" "wd")
+ (parallel
+ [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+{
+ gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
+ operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
+ | (INTVAL (operands[4]) & 1));
+ return \"xxpermdi %x0,%x1,%x3,%5\";
+}
+ [(set_attr "type" "vecperm")])
+
+;; V2DF/V2DI splat
+(define_insn "vsx_splat_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
+ (vec_duplicate:VSX_D
+ (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "@
+ xxpermdi %x0,%x1,%x1,0
+ xxpermdi %x0,%x1,%x1,0
+ lxvdsx %x0,%y1
+ xxpermdi %x0,%x1,%x1,0
+ xxpermdi %x0,%x1,%x1,0
+ lxvdsx %x0,%y1"
+ [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
+
+;; V4SF/V4SI splat
+(define_insn "vsx_xxspltw_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
+ (vec_duplicate:VSX_W
+ (vec_select:<VS_scalar>
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxspltw %x0,%x1,%2"
+ [(set_attr "type" "vecperm")])
+
+;; V4SF/V4SI interleave
+(define_insn "vsx_xxmrghw_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
+ (vec_merge:VSX_W
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (vec_select:VSX_W
+ (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (const_int 5)))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxmrghw %x0,%x1,%x2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "vsx_xxmrglw_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
+ (vec_merge:VSX_W
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (vec_select:VSX_W
+ (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (const_int 5)))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxmrglw %x0,%x1,%x2"
+ [(set_attr "type" "vecperm")])
+
+;; Shift left double by word immediate
+(define_insn "vsx_xxsldwi_<mode>"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "wa")
+ (match_operand:QI 3 "u5bit_cint_operand" "i")]
+ UNSPEC_VSX_SLDWI))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxsldwi %x0,%x1,%x2,%3"
+ [(set_attr "type" "vecperm")])
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 37c5089..b545c32 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7298,7 +7298,7 @@ instructions, but allow the compiler to schedule those calls.
* MIPS Loongson Built-in Functions::
* Other MIPS Built-in Functions::
* picoChip Built-in Functions::
-* PowerPC AltiVec Built-in Functions::
+* PowerPC AltiVec/VSX Built-in Functions::
* SPARC VIS Built-in Functions::
* SPU Built-in Functions::
@end menu
@@ -9776,7 +9776,7 @@ GCC defines the preprocessor macro @code{___GCC_HAVE_BUILTIN_MIPS_CACHE}
when this function is available.
@end table
-@node PowerPC AltiVec Built-in Functions
+@node PowerPC AltiVec/VSX Built-in Functions
@subsection PowerPC AltiVec Built-in Functions
GCC provides an interface for the PowerPC family of processors to access
@@ -9802,6 +9802,19 @@ vector bool int
vector float
@end smallexample
+If @option{-mvsx} is used the following additional vector types are
+implemented.
+
+@smallexample
+vector unsigned long
+vector signed long
+vector double
+@end smallexample
+
+The long types are only implemented for 64-bit code generation, and
+the long type is only used in the floating point/integer conversion
+instructions.
+
GCC's implementation of the high-level language interface available from
C and C++ code differs from Motorola's documentation in several ways.
@@ -10067,6 +10080,8 @@ vector signed char vec_vavgsb (vector signed char, vector signed char);
vector unsigned char vec_vavgub (vector unsigned char,
vector unsigned char);
+vector float vec_copysign (vector float);
+
vector float vec_ceil (vector float);
vector signed int vec_cmpb (vector float, vector float);
@@ -11669,6 +11684,92 @@ int vec_any_numeric (vector float);
int vec_any_out (vector float, vector float);
@end smallexample
+If the vector/scalar (VSX) instruction set is available, the following
+additional functions are available:
+
+@smallexample
+vector double vec_abs (vector double);
+vector double vec_add (vector double, vector double);
+vector double vec_and (vector double, vector double);
+vector double vec_and (vector double, vector bool long);
+vector double vec_and (vector bool long, vector double);
+vector double vec_andc (vector double, vector double);
+vector double vec_andc (vector double, vector bool long);
+vector double vec_andc (vector bool long, vector double);
+vector double vec_ceil (vector double);
+vector bool long vec_cmpeq (vector double, vector double);
+vector bool long vec_cmpge (vector double, vector double);
+vector bool long vec_cmpgt (vector double, vector double);
+vector bool long vec_cmple (vector double, vector double);
+vector bool long vec_cmplt (vector double, vector double);
+vector float vec_div (vector float, vector float);
+vector double vec_div (vector double, vector double);
+vector double vec_floor (vector double);
+vector double vec_madd (vector double, vector double, vector double);
+vector double vec_max (vector double, vector double);
+vector double vec_min (vector double, vector double);
+vector float vec_msub (vector float, vector float, vector float);
+vector double vec_msub (vector double, vector double, vector double);
+vector float vec_mul (vector float, vector float);
+vector double vec_mul (vector double, vector double);
+vector float vec_nearbyint (vector float);
+vector double vec_nearbyint (vector double);
+vector float vec_nmadd (vector float, vector float, vector float);
+vector double vec_nmadd (vector double, vector double, vector double);
+vector double vec_nmsub (vector double, vector double, vector double);
+vector double vec_nor (vector double, vector double);
+vector double vec_or (vector double, vector double);
+vector double vec_or (vector double, vector bool long);
+vector double vec_or (vector bool long, vector double);
+vector double vec_perm (vector double,
+ vector double,
+ vector unsigned char);
+vector float vec_rint (vector float);
+vector double vec_rint (vector double);
+vector double vec_sel (vector double, vector double, vector bool long);
+vector double vec_sel (vector double, vector double, vector unsigned long);
+vector double vec_sub (vector double, vector double);
+vector float vec_sqrt (vector float);
+vector double vec_sqrt (vector double);
+vector double vec_trunc (vector double);
+vector double vec_xor (vector double, vector double);
+vector double vec_xor (vector double, vector bool long);
+vector double vec_xor (vector bool long, vector double);
+int vec_all_eq (vector double, vector double);
+int vec_all_ge (vector double, vector double);
+int vec_all_gt (vector double, vector double);
+int vec_all_le (vector double, vector double);
+int vec_all_lt (vector double, vector double);
+int vec_all_nan (vector double);
+int vec_all_ne (vector double, vector double);
+int vec_all_nge (vector double, vector double);
+int vec_all_ngt (vector double, vector double);
+int vec_all_nle (vector double, vector double);
+int vec_all_nlt (vector double, vector double);
+int vec_all_numeric (vector double);
+int vec_any_eq (vector double, vector double);
+int vec_any_ge (vector double, vector double);
+int vec_any_gt (vector double, vector double);
+int vec_any_le (vector double, vector double);
+int vec_any_lt (vector double, vector double);
+int vec_any_nan (vector double);
+int vec_any_ne (vector double, vector double);
+int vec_any_nge (vector double, vector double);
+int vec_any_ngt (vector double, vector double);
+int vec_any_nle (vector double, vector double);
+int vec_any_nlt (vector double, vector double);
+int vec_any_numeric (vector double);
+@end smallexample
+
+GCC provides a few other builtins on Powerpc to access certain instructions:
+@smallexample
+float __builtin_recipdivf (float, float);
+float __builtin_rsqrtf (float);
+double __builtin_recipdiv (double, double);
+long __builtin_bpermd (long, long);
+int __builtin_bswap16 (int);
+@end smallexample
+
@node SPARC VIS Built-in Functions
@subsection SPARC VIS Built-in Functions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c256dde..fe24b98 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -738,7 +738,8 @@ See RS/6000 and PowerPC Options.
-maltivec -mno-altivec @gol
-mpowerpc-gpopt -mno-powerpc-gpopt @gol
-mpowerpc-gfxopt -mno-powerpc-gfxopt @gol
--mmfcrf -mno-mfcrf -mpopcntb -mno-popcntb -mfprnd -mno-fprnd @gol
+-mmfcrf -mno-mfcrf -mpopcntb -mno-popcntb -mpopcntd -mno-popcntd @gol
+-mfprnd -mno-fprnd @gol
-mcmpb -mno-cmpb -mmfpgpr -mno-mfpgpr -mhard-dfp -mno-hard-dfp @gol
-mnew-mnemonics -mold-mnemonics @gol
-mfull-toc -mminimal-toc -mno-fp-in-toc -mno-sum-in-toc @gol
@@ -752,7 +753,7 @@ See RS/6000 and PowerPC Options.
-mstrict-align -mno-strict-align -mrelocatable @gol
-mno-relocatable -mrelocatable-lib -mno-relocatable-lib @gol
-mtoc -mno-toc -mlittle -mlittle-endian -mbig -mbig-endian @gol
--mdynamic-no-pic -maltivec -mswdiv @gol
+-mdynamic-no-pic -maltivec -mswdiv @gol
-mprioritize-restricted-insns=@var{priority} @gol
-msched-costly-dep=@var{dependence_type} @gol
-minsert-sched-nops=@var{scheme} @gol
@@ -14116,6 +14117,8 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC:
@itemx -mno-mfcrf
@itemx -mpopcntb
@itemx -mno-popcntb
+@itemx -mpopcntd
+@itemx -mno-popcntd
@itemx -mfprnd
@itemx -mno-fprnd
@itemx -mcmpb
@@ -14140,6 +14143,8 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC:
@opindex mno-mfcrf
@opindex mpopcntb
@opindex mno-popcntb
+@opindex mpopcntd
+@opindex mno-popcntd
@opindex mfprnd
@opindex mno-fprnd
@opindex mcmpb
@@ -14189,6 +14194,9 @@ The @option{-mpopcntb} option allows GCC to generate the popcount and
double precision FP reciprocal estimate instruction implemented on the
POWER5 processor and other processors that support the PowerPC V2.02
architecture.
+The @option{-mpopcntd} option allows GCC to generate the popcount
+instruction implemented on the POWER7 processor and other processors
+that support the PowerPC V2.06 architecture.
The @option{-mfprnd} option allows GCC to generate the FP round to
integer instructions implemented on the POWER5+ processor and other
processors that support the PowerPC V2.03 architecture.
@@ -14267,9 +14275,9 @@ The @option{-mcpu} options automatically enable or disable the
following options:
@gccoptlist{-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple @gol
--mnew-mnemonics -mpopcntb -mpower -mpower2 -mpowerpc64 @gol
+-mnew-mnemonics -mpopcntb -mpopcntd -mpower -mpower2 -mpowerpc64 @gol
-mpowerpc-gpopt -mpowerpc-gfxopt -msingle-float -mdouble-float @gol
--msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr}
+-msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr -mvsx}
The particular options set for any particular CPU will vary between
compiler versions, depending on what setting seems to produce optimal
@@ -14370,6 +14378,14 @@ instructions.
This option has been deprecated. Use @option{-mspe} and
@option{-mno-spe} instead.
+@item -mvsx
+@itemx -mno-vsx
+@opindex mvsx
+@opindex mno-vsx
+Generate code that uses (does not use) vector/scalar (VSX)
+instructions, and also enable the use of built-in functions that allow
+more direct access to the VSX instruction set.
+
@item -mfloat-gprs=@var{yes/single/double/no}
@itemx -mfloat-gprs
@opindex mfloat-gprs
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index d9dca7a..0e516b0 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1916,7 +1916,19 @@ Floating point register (containing 64-bit value)
Floating point register (containing 32-bit value)
@item v
-Vector register
+Altivec vector register
+
+@item wd
+VSX vector register to hold vector double data
+
+@item wf
+VSX vector register to hold vector float data
+
+@item ws
+VSX vector register to hold scalar float data
+
+@item wa
+Any VSX register
@item h
@samp{MQ}, @samp{CTR}, or @samp{LINK} register
@@ -2029,6 +2041,9 @@ AND masks that can be performed by two rldic@{l, r@} instructions
@item W
Vector constant that does not require memory
+@item j
+Vector constant that is all zeros.
+
@end table
@item Intel 386---@file{config/i386/constraints.md}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 66b436d..4466ec7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,53 @@
+2009-07-30 Michael Meissner <meissner@linux.vnet.ibm.com>
+ Pat Haugen <pthaugen@us.ibm.com>
+ Revital Eres <ERES@il.ibm.com>
+
+ * testsuite/gcc.target/powerpc/altivec-32.c: New file to test
+ Altivec simple math function vectorization.
+
+ * testsuite/gcc.target/powerpc/bswap-run.c: New file to test swap
+ builtins.
+ * testsuite/gcc.target/powerpc/bswap16.c: Ditto.
+ * testsuite/gcc.target/powerpc/bswap32.c: Ditto.
+ * testsuite/gcc.target/powerpc/bswap64-1.c: Ditto.
+ * testsuite/gcc.target/powerpc/bswap64-2.c: Ditto.
+ * testsuite/gcc.target/powerpc/bswap64-3.c: Ditto.
+ * testsuite/gcc.target/powerpc/optimize-bswapdi-2.c: Ditto.
+ * testsuite/gcc.target/powerpc/optimize-bswapdi-3.c: Ditto.
+ * testsuite/gcc.target/powerpc/optimize-bswapsi-2.c: Ditto.
+
+ * testsuite/gcc.target/powerpc/popcount-2.c: New file to test
+ power7 popcntd instructions.
+ * testsuite/gcc.target/powerpc/popcount-3.c: Ditto.
+
+ * testsuite/gcc.target/powerpc/pr39457.c: New VSX test.
+ * testsuite/gcc.target/powerpc/vsx-builtin-1.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-builtin-2.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-builtin-3.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-builtin-4.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-builtin-5.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-builtin-6.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-vector-1.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-vector-2.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-vector-3.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-vector-4.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-vector-5.c: Ditto.
+ * testsuite/gcc.target/powerpc/vsx-vector-6.c: Ditto.
+
+ * testsuite/gcc.target/powerpc/altivec-6.c: Store the result of
+ vec_add, so the optimizer doesn't remove it.
+
+ * testsuite/gcc.dg/optimize-bswapdi-1.c: Add powerpc 64-bit to
+ systems that support bswap64.
+
+ * testsuite/gcc.dg/vmx/vmx.exp: Explicitly add -mno-vsx to
+ prevent VSX code generation.
+
+ * testsuite/lib/target-supports.exp (check_vsx_hw_available): New
+ function to test if VSX available.
+ (check_effective_target_powerpc_vsx_ok): Ditto.
+ (check_vmx_hw_available): Add explicit -mno-vsx.
+
2009-07-30 Janis Johnson <janis187@us.ibm.com>
PR c/39902
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c b/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c
index 449dc19..a6aea4a 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* } } */
+/* { dg-do compile { target alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */
/* { dg-require-effective-target stdint_types } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
diff --git a/gcc/testsuite/gcc.dg/vmx/vmx.exp b/gcc/testsuite/gcc.dg/vmx/vmx.exp
index 8a842e1..85c88d8 100644
--- a/gcc/testsuite/gcc.dg/vmx/vmx.exp
+++ b/gcc/testsuite/gcc.dg/vmx/vmx.exp
@@ -31,7 +31,7 @@ if {![istarget powerpc*-*-*]
# nothing but extensions.
global DEFAULT_VMXCFLAGS
if ![info exists DEFAULT_VMXCFLAGS] then {
- set DEFAULT_VMXCFLAGS "-maltivec -mabi=altivec -std=gnu99"
+ set DEFAULT_VMXCFLAGS "-maltivec -mabi=altivec -std=gnu99 -mno-vsx"
}
# If the target system supports AltiVec instructions, the default action
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-32.c b/gcc/testsuite/gcc.target/powerpc/altivec-32.c
new file mode 100644
index 0000000..83105f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-32.c
@@ -0,0 +1,59 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mcpu=power6 -m64 -maltivec" } */
+/* { dg-final { scan-assembler "vsel" } } */
+/* { dg-final { scan-assembler "vrfim" } } */
+/* { dg-final { scan-assembler "vrfip" } } */
+/* { dg-final { scan-assembler "vrfiz" } } */
+
+#ifndef SIZE
+#define SIZE 1024
+#endif
+
+float a[SIZE] __attribute__((__aligned__(32)));
+float b[SIZE] __attribute__((__aligned__(32)));
+float c[SIZE] __attribute__((__aligned__(32)));
+float d[SIZE] __attribute__((__aligned__(32)));
+float e[SIZE] __attribute__((__aligned__(32)));
+
+extern float floorf (float);
+extern float ceilf (float);
+extern float truncf (float);
+extern float copysignf (float, float);
+
+void
+vector_floor (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = floorf (b[i]);
+}
+
+void
+vector_ceil (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = ceilf (b[i]);
+}
+
+void
+vector_trunc (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = truncf (b[i]);
+}
+
+void
+vector_copysign (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = copysignf (b[i], c[i]);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-6.c b/gcc/testsuite/gcc.target/powerpc/altivec-6.c
index dc115f9..51d4116 100644
--- a/gcc/testsuite/gcc.target/powerpc/altivec-6.c
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-6.c
@@ -5,7 +5,7 @@
#include <altivec.h>
/* These denote "generic" GCC vectors. */
-static int __attribute__((vector_size(16))) x, y;
+static int __attribute__((vector_size(16))) x, y, z;
static vector signed int i,j;
static vector signed short s,t;
@@ -21,7 +21,7 @@ static int int1, int2;
void
b()
{
- vec_add (x, y);
+ z = vec_add (x, y);
/* Make sure the predicates accept correct argument types. */
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap-run.c b/gcc/testsuite/gcc.target/powerpc/bswap-run.c
new file mode 100644
index 0000000..484908a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bswap-run.c
@@ -0,0 +1,102 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-options "-O2 -std=gnu99" } */
+
+extern void abort (void);
+
+static unsigned char bytes[] = { 0, 1, 2, 0x80, 0xff };
+
+unsigned short b16a (unsigned short *p) { return __builtin_bswap16 (*p); }
+void b16b (unsigned short *p, unsigned short a) { *p = __builtin_bswap16 (a); }
+int b16c (unsigned short a) { return __builtin_bswap16 (a); }
+
+unsigned int b32a (unsigned int *p) { return __builtin_bswap32 (*p); }
+void b32b (unsigned int *p, unsigned int a) { *p = __builtin_bswap32 (a); }
+static unsigned int b32c (unsigned int a) { return __builtin_bswap32 (a); }
+
+unsigned long long b64a (unsigned long long *p) { return __builtin_bswap64 (*p); }
+void b64b (unsigned long long *p, unsigned long long a) { *p = __builtin_bswap64 (a); }
+unsigned long long b64c (unsigned long long a) { return __builtin_bswap64 (a); }
+
+int
+main (void)
+{
+ unsigned i1, i2, i3, i4, i5;
+ unsigned b1, b2, b3, b4, b5;
+ unsigned short b16_inp, b16_exp, b16_var;
+ unsigned int b32_inp, b32_exp, b32_var;
+ unsigned long long b64_inp, b64_exp, b64_var;
+
+ for (i1 = 0; i1 < sizeof (bytes); i1++)
+ {
+ b1 = bytes[i1];
+ for (i2 = 0; i2 < sizeof (bytes); i2++)
+ {
+ b2 = bytes[i2];
+ b16_inp = (b1 << 8) | b2;
+ b16_exp = (b2 << 8) | b1;
+
+ if (b16a (&b16_inp) != b16_exp)
+ abort ();
+
+ b16b (&b16_var, b16_inp);
+ if (b16_var != b16_exp)
+ abort ();
+
+ if (b16c (b16_inp) != b16_exp)
+ abort ();
+
+ for (i3 = 0; i3 < sizeof (bytes); i3++)
+ {
+ b3 = bytes[i3];
+ for (i4 = 0; i4 < sizeof (bytes); i4++)
+ {
+ b4 = bytes[i4];
+ b32_inp = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+ b32_exp = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
+
+ if (b32a (&b32_inp) != b32_exp)
+ abort ();
+
+ b32b (&b32_var, b32_inp);
+ if (b32_var != b32_exp)
+ abort ();
+
+ if (b32c (b32_inp) != b32_exp)
+ abort ();
+
+ for (i5 = 0; i5 < sizeof (bytes); i5++)
+ {
+ b5 = bytes[i5];
+ b64_inp = (((unsigned long long)b32_inp) << 32) | b5;
+ b64_exp = (((unsigned long long)b5) << 56) | b32_exp;
+
+ if (b64a (&b64_inp) != b64_exp)
+ abort ();
+
+ b64b (&b64_var, b64_inp);
+ if (b64_var != b64_exp)
+ abort ();
+
+ if (b64c (b64_inp) != b64_exp)
+ abort ();
+
+ b64_inp = (((unsigned long long)b5) << 56) | b32_inp;
+ b64_exp = (((unsigned long long)b32_exp) << 32) | b5;
+
+ if (b64a (&b64_inp) != b64_exp)
+ abort ();
+
+ b64b (&b64_var, b64_inp);
+ if (b64_var != b64_exp)
+ abort ();
+
+ if (b64c (b64_inp) != b64_exp)
+ abort ();
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap16.c b/gcc/testsuite/gcc.target/powerpc/bswap16.c
new file mode 100644
index 0000000..5eea4f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bswap16.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "lhbrx" } } */
+/* { dg-final { scan-assembler "sthbrx" } } */
+
+unsigned short us;
+unsigned int load_bswap16 (unsigned short *p) { return __builtin_bswap16 (*p); }
+void store_bswap16 (unsigned int a) { us = __builtin_bswap16 (a); }
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap32.c b/gcc/testsuite/gcc.target/powerpc/bswap32.c
new file mode 100644
index 0000000..1b1e189
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bswap32.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "lwbrx" } } */
+/* { dg-final { scan-assembler "stwbrx" } } */
+
+unsigned int ui;
+unsigned int load_bswap32 (unsigned int *p) { return __builtin_bswap32 (*p); }
+void store_bswap32 (unsigned int a) { ui = __builtin_bswap32 (a); }
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap64-1.c b/gcc/testsuite/gcc.target/powerpc/bswap64-1.c
new file mode 100644
index 0000000..480e1cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bswap64-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -mno-popcntd -mcpu=power5" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-final { scan-assembler "lwbrx" } } */
+/* { dg-final { scan-assembler "stwbrx" } } */
+
+unsigned long ul;
+unsigned long load_bswap64 (unsigned long *p) { return __builtin_bswap64 (*p); }
+void store_bswap64 (unsigned long a) { ul = __builtin_bswap64 (a); }
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap64-2.c b/gcc/testsuite/gcc.target/powerpc/bswap64-2.c
new file mode 100644
index 0000000..6c3d8ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bswap64-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -mpopcntd" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-final { scan-assembler "ldbrx" } } */
+/* { dg-final { scan-assembler "stdbrx" } } */
+
+unsigned long ul;
+unsigned long load_bswap64 (unsigned long *p) { return __builtin_bswap64 (*p); }
+void store_bswap64 (unsigned long a) { ul = __builtin_bswap64 (a); }
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap64-3.c b/gcc/testsuite/gcc.target/powerpc/bswap64-3.c
new file mode 100644
index 0000000..7f1138c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bswap64-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -mcpu=cell" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_ppu_ok } */
+/* { dg-final { scan-assembler "ldbrx" } } */
+/* { dg-final { scan-assembler "stdbrx" } } */
+
+unsigned long ul;
+unsigned long load_bswap64 (unsigned long *p) { return __builtin_bswap64 (*p); }
+void store_bswap64 (unsigned long a) { ul = __builtin_bswap64 (a); }
diff --git a/gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-2.c b/gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-2.c
new file mode 100644
index 0000000..7337e99
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-2.c
@@ -0,0 +1,36 @@
+/* { dg-require-effective-target stdint_types } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mcpu=power5" } */
+
+/* This is a clone of gcc-dg/optimize-bswapdi-1.c, redone to use load and stores
+ to test whether lwbrx/stwbrx is generated for normal power systems. */
+
+#include <stdint.h>
+#define __const_swab64(x) ((uint64_t)( \
+ (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
+
+
+/* This byte swap implementation is used by the Linux kernel and the
+ GNU C library. */
+
+uint64_t
+swap64_load (uint64_t *in)
+{
+ return __const_swab64 (*in);
+}
+
+void
+swap64_store (uint64_t *out, uint64_t in)
+{
+ *out = __const_swab64 (in);
+}
+
+/* { dg-final { scan-assembler-times "lwbrx" 2 } } */
+/* { dg-final { scan-assembler-times "stwbrx" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-3.c b/gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-3.c
new file mode 100644
index 0000000..9dcd824
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/optimize-bswapdi-3.c
@@ -0,0 +1,36 @@
+/* { dg-require-effective-target stdint_types } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mcpu=power7" } */
+
+/* This is a clone of gcc-dg/optimize-bswapdi-1.c, redone to use load and stores
+ to test whether ldbrx/stdbrx is generated for power7. */
+
+#include <stdint.h>
+#define __const_swab64(x) ((uint64_t)( \
+ (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
+
+
+/* This byte swap implementation is used by the Linux kernel and the
+ GNU C library. */
+
+uint64_t
+swap64_load (uint64_t *in)
+{
+ return __const_swab64 (*in);
+}
+
+void
+swap64_store (uint64_t *out, uint64_t in)
+{
+ *out = __const_swab64 (in);
+}
+
+/* { dg-final { scan-assembler "ldbrx" } } */
+/* { dg-final { scan-assembler "stdbrx" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/optimize-bswapsi-2.c b/gcc/testsuite/gcc.target/powerpc/optimize-bswapsi-2.c
new file mode 100644
index 0000000..34cc823
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/optimize-bswapsi-2.c
@@ -0,0 +1,55 @@
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-O2 -mcpu=power5" } */
+
+#include <stdint.h>
+
+/* This is a clone of gcc-dg/optimize-bswapsi-1.c, redone to use load and stores
+ to test whether lwbrx/stwbrx is generated for normal power systems. */
+
+#define __const_swab32(x) ((uint32_t)( \
+ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
+
+/* This byte swap implementation is used by the Linux kernel and the
+ GNU C library. */
+
+uint32_t
+swap32_a_load (uint32_t *in)
+{
+ return __const_swab32 (*in);
+}
+
+/* The OpenSSH byte swap implementation. */
+uint32_t
+swap32_b_load (uint32_t *in)
+{
+ uint32_t a;
+
+ a = (*in << 16) | (*in >> 16);
+ a = ((a & 0x00ff00ff) << 8) | ((a & 0xff00ff00) >> 8);
+
+ return a;
+}
+
+void
+swap32_a_store (uint32_t *out, uint32_t in)
+{
+ *out = __const_swab32 (in);
+}
+
+/* The OpenSSH byte swap implementation. */
+void
+swap32_b_store (uint32_t *out, uint32_t in)
+{
+ uint32_t a;
+
+ a = (in << 16) | (in >> 16);
+ a = ((a & 0x00ff00ff) << 8) | ((a & 0xff00ff00) >> 8);
+
+ *out = a;
+}
+
+/* { dg-final { scan-assembler-times "lwbrx" 2 } } */
+/* { dg-final { scan-assembler-times "stwbrx" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/popcount-2.c b/gcc/testsuite/gcc.target/powerpc/popcount-2.c
new file mode 100644
index 0000000..7546a3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/popcount-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { ilp32 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-options "-O2 -mcpu=power7 -m32" } */
+/* { dg-final { scan-assembler "popcntw" } } */
+
+int foo(int x)
+{
+ return __builtin_popcount(x);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/popcount-3.c b/gcc/testsuite/gcc.target/powerpc/popcount-3.c
new file mode 100644
index 0000000..c803532
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/popcount-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-options "-O2 -mcpu=power7 -m64" } */
+/* { dg-final { scan-assembler "popcntd" } } */
+
+long foo(int x)
+{
+ return __builtin_popcountl(x);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr39457.c b/gcc/testsuite/gcc.target/powerpc/pr39457.c
new file mode 100644
index 0000000..22057e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr39457.c
@@ -0,0 +1,56 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-options "-m64 -O2 -mminimal-toc" } */
+
+/* PR 39457 -- fix breakage because the compiler ran out of registers and
+ wanted to stash a floating point value to the LR/CTR register. */
+
+/* -O2 -m64 -mminimal-toc */
+typedef struct { void *s; } S;
+typedef void (*T1) (void);
+typedef void (*T2) (void *, void *, int, void *);
+char *fn1 (const char *, ...);
+void *fn2 (void);
+int fn3 (char *, int);
+int fn4 (const void *);
+int fn5 (const void *);
+long fn6 (void) __attribute__ ((__const__));
+int fn7 (void *, void *, void *);
+void *fn8 (void *, long);
+void *fn9 (void *, long, const char *, ...);
+void *fn10 (void *);
+long fn11 (void) __attribute__ ((__const__));
+long fn12 (void *, const char *, T1, T2, void *);
+void *fn13 (void *);
+long fn14 (void) __attribute__ ((__const__));
+extern void *v1;
+extern char *v2;
+extern int v3;
+
+void
+foo (void *x, char *z)
+{
+ void *i1, *i2;
+ int y;
+ if (v1)
+ return;
+ v1 = fn9 (fn10 (fn2 ()), fn6 (), "x", 0., "y", 0., 0);
+ y = 520 - (520 - fn4 (x)) / 2;
+ fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", fn8 (v1, fn14 ()), "x", 18.0,
+ "y", 16.0, "wid", 80.0, "hi", 500.0, 0);
+ fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 80.0, "y2",
+ 500.0, "f", fn3 ("fff", 0x0D0DFA00), 0);
+ fn13 (((S *) fn8 (v1, fn6 ()))->s);
+ fn12 (fn8 (v1, fn11 ()), "ev", (T1) fn7, 0, fn8 (v1, fn6 ()));
+ fn9 (fn8 (v1, fn6 ()), fn6 (), "wig",
+ fn8 (v1, fn14 ()), "x", 111.0, "y", 14.0, "wid", 774.0, "hi",
+ 500.0, 0);
+ v1 = fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 774.0, "y2",
+ 500.0, "f", fn3 ("gc", 0x0D0DFA00), 0);
+ fn1 (z, 0);
+ i1 = fn9 (fn8 (v1, fn6 ()), fn6 (), "pixbuf", x, "x",
+ 800 - fn5 (x) / 2, "y", y - fn4 (x), 0);
+ fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, "/ok/");
+ fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, 0);
+ i2 = fn9 (fn8 (v1, fn6 ()), fn6 (), "txt", "OK", "fnt", v2, "x",
+ 800, "y", y - fn4 (x) + 15, "ar", 0, "f", v3, 0);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c
new file mode 100644
index 0000000..42d5b60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c
@@ -0,0 +1,38 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xvadddp" } } */
+/* { dg-final { scan-assembler "xvsubdp" } } */
+/* { dg-final { scan-assembler "xvmuldp" } } */
+/* { dg-final { scan-assembler "xvmadd" } } */
+/* { dg-final { scan-assembler "xvmsub" } } */
+/* { dg-final { scan-assembler "xvnmadd" } } */
+/* { dg-final { scan-assembler "xvnmsub" } } */
+/* { dg-final { scan-assembler "xvdivdp" } } */
+/* { dg-final { scan-assembler "xvmaxdp" } } */
+/* { dg-final { scan-assembler "xvmindp" } } */
+/* { dg-final { scan-assembler "xvsqrtdp" } } */
+/* { dg-final { scan-assembler "xvrsqrtedp" } } */
+/* { dg-final { scan-assembler "xvabsdp" } } */
+/* { dg-final { scan-assembler "xvnabsdp" } } */
+/* { dg-final { scan-assembler "xvredp" } } */
+
+void use_builtins (__vector double *p, __vector double *q, __vector double *r, __vector double *s)
+{
+ p[0] = __builtin_vsx_xvadddp (q[0], r[0]);
+ p[1] = __builtin_vsx_xvsubdp (q[1], r[1]);
+ p[2] = __builtin_vsx_xvmuldp (q[2], r[2]);
+ p[3] = __builtin_vsx_xvdivdp (q[3], r[3]);
+ p[4] = __builtin_vsx_xvmaxdp (q[4], r[4]);
+ p[5] = __builtin_vsx_xvmindp (q[5], r[5]);
+ p[6] = __builtin_vsx_xvabsdp (q[6]);
+ p[7] = __builtin_vsx_xvnabsdp (q[7]);
+ p[8] = __builtin_vsx_xvsqrtdp (q[8]);
+ p[9] = __builtin_vsx_xvmadddp (q[9], r[9], s[9]);
+ p[10] = __builtin_vsx_xvmsubdp (q[10], r[10], s[10]);
+ p[11] = __builtin_vsx_xvnmadddp (q[11], r[11], s[11]);
+ p[12] = __builtin_vsx_xvnmsubdp (q[12], r[12], s[12]);
+ p[13] = __builtin_vsx_xvredp (q[13]);
+ p[14] = __builtin_vsx_xvrsqrtedp (q[14]);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c
new file mode 100644
index 0000000..6d883dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c
@@ -0,0 +1,38 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xvaddsp" } } */
+/* { dg-final { scan-assembler "xvsubsp" } } */
+/* { dg-final { scan-assembler "xvmulsp" } } */
+/* { dg-final { scan-assembler "xvmadd" } } */
+/* { dg-final { scan-assembler "xvmsub" } } */
+/* { dg-final { scan-assembler "xvnmadd" } } */
+/* { dg-final { scan-assembler "xvnmsub" } } */
+/* { dg-final { scan-assembler "xvdivsp" } } */
+/* { dg-final { scan-assembler "xvmaxsp" } } */
+/* { dg-final { scan-assembler "xvminsp" } } */
+/* { dg-final { scan-assembler "xvsqrtsp" } } */
+/* { dg-final { scan-assembler "xvabssp" } } */
+/* { dg-final { scan-assembler "xvnabssp" } } */
+/* { dg-final { scan-assembler "xvresp" } } */
+/* { dg-final { scan-assembler "xvrsqrtesp" } } */
+
+void use_builtins (__vector float *p, __vector float *q, __vector float *r, __vector float *s)
+{
+ p[0] = __builtin_vsx_xvaddsp (q[0], r[0]);
+ p[1] = __builtin_vsx_xvsubsp (q[1], r[1]);
+ p[2] = __builtin_vsx_xvmulsp (q[2], r[2]);
+ p[3] = __builtin_vsx_xvdivsp (q[3], r[3]);
+ p[4] = __builtin_vsx_xvmaxsp (q[4], r[4]);
+ p[5] = __builtin_vsx_xvminsp (q[5], r[5]);
+ p[6] = __builtin_vsx_xvabssp (q[6]);
+ p[7] = __builtin_vsx_xvnabssp (q[7]);
+ p[8] = __builtin_vsx_xvsqrtsp (q[8]);
+ p[9] = __builtin_vsx_xvmaddsp (q[9], r[9], s[9]);
+ p[10] = __builtin_vsx_xvmsubsp (q[10], r[10], s[10]);
+ p[11] = __builtin_vsx_xvnmaddsp (q[11], r[11], s[11]);
+ p[12] = __builtin_vsx_xvnmsubsp (q[12], r[12], s[12]);
+ p[13] = __builtin_vsx_xvresp (q[13]);
+ p[14] = __builtin_vsx_xvrsqrtesp (q[14]);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
new file mode 100644
index 0000000..8450920
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
@@ -0,0 +1,212 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xxsel" } } */
+/* { dg-final { scan-assembler "vperm" } } */
+/* { dg-final { scan-assembler "xvrdpi" } } */
+/* { dg-final { scan-assembler "xvrdpic" } } */
+/* { dg-final { scan-assembler "xvrdpim" } } */
+/* { dg-final { scan-assembler "xvrdpip" } } */
+/* { dg-final { scan-assembler "xvrdpiz" } } */
+/* { dg-final { scan-assembler "xvrspi" } } */
+/* { dg-final { scan-assembler "xvrspic" } } */
+/* { dg-final { scan-assembler "xvrspim" } } */
+/* { dg-final { scan-assembler "xvrspip" } } */
+/* { dg-final { scan-assembler "xvrspiz" } } */
+/* { dg-final { scan-assembler "xsrdpi" } } */
+/* { dg-final { scan-assembler "xsrdpic" } } */
+/* { dg-final { scan-assembler "xsrdpim" } } */
+/* { dg-final { scan-assembler "xsrdpip" } } */
+/* { dg-final { scan-assembler "xsrdpiz" } } */
+/* { dg-final { scan-assembler "xsmaxdp" } } */
+/* { dg-final { scan-assembler "xsmindp" } } */
+/* { dg-final { scan-assembler "xxland" } } */
+/* { dg-final { scan-assembler "xxlandc" } } */
+/* { dg-final { scan-assembler "xxlnor" } } */
+/* { dg-final { scan-assembler "xxlor" } } */
+/* { dg-final { scan-assembler "xxlxor" } } */
+/* { dg-final { scan-assembler "xvcmpeqdp" } } */
+/* { dg-final { scan-assembler "xvcmpgtdp" } } */
+/* { dg-final { scan-assembler "xvcmpgedp" } } */
+/* { dg-final { scan-assembler "xvcmpeqsp" } } */
+/* { dg-final { scan-assembler "xvcmpgtsp" } } */
+/* { dg-final { scan-assembler "xvcmpgesp" } } */
+/* { dg-final { scan-assembler "xxsldwi" } } */
+/* { dg-final { scan-assembler-not "call" } } */
+
+extern __vector int si[][4];
+extern __vector short ss[][4];
+extern __vector signed char sc[][4];
+extern __vector float f[][4];
+extern __vector unsigned int ui[][4];
+extern __vector unsigned short us[][4];
+extern __vector unsigned char uc[][4];
+extern __vector __bool int bi[][4];
+extern __vector __bool short bs[][4];
+extern __vector __bool char bc[][4];
+extern __vector __pixel p[][4];
+#ifdef __VSX__
+extern __vector double d[][4];
+extern __vector long sl[][4];
+extern __vector unsigned long ul[][4];
+extern __vector __bool long bl[][4];
+#endif
+
+int do_sel(void)
+{
+ int i = 0;
+
+ si[i][0] = __builtin_vsx_xxsel_4si (si[i][1], si[i][2], si[i][3]); i++;
+ ss[i][0] = __builtin_vsx_xxsel_8hi (ss[i][1], ss[i][2], ss[i][3]); i++;
+ sc[i][0] = __builtin_vsx_xxsel_16qi (sc[i][1], sc[i][2], sc[i][3]); i++;
+ f[i][0] = __builtin_vsx_xxsel_4sf (f[i][1], f[i][2], f[i][3]); i++;
+ d[i][0] = __builtin_vsx_xxsel_2df (d[i][1], d[i][2], d[i][3]); i++;
+
+ si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], bi[i][3]); i++;
+ ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], bs[i][3]); i++;
+ sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], bc[i][3]); i++;
+ f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], bi[i][3]); i++;
+ d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], bl[i][3]); i++;
+
+ si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], ui[i][3]); i++;
+ ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], us[i][3]); i++;
+ sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], uc[i][3]); i++;
+ f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], ui[i][3]); i++;
+ d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], ul[i][3]); i++;
+
+ return i;
+}
+
+int do_perm(void)
+{
+ int i = 0;
+
+ si[i][0] = __builtin_vsx_vperm_4si (si[i][1], si[i][2], uc[i][3]); i++;
+ ss[i][0] = __builtin_vsx_vperm_8hi (ss[i][1], ss[i][2], uc[i][3]); i++;
+ sc[i][0] = __builtin_vsx_vperm_16qi (sc[i][1], sc[i][2], uc[i][3]); i++;
+ f[i][0] = __builtin_vsx_vperm_4sf (f[i][1], f[i][2], uc[i][3]); i++;
+ d[i][0] = __builtin_vsx_vperm_2df (d[i][1], d[i][2], uc[i][3]); i++;
+
+ si[i][0] = __builtin_vsx_vperm (si[i][1], si[i][2], uc[i][3]); i++;
+ ss[i][0] = __builtin_vsx_vperm (ss[i][1], ss[i][2], uc[i][3]); i++;
+ sc[i][0] = __builtin_vsx_vperm (sc[i][1], sc[i][2], uc[i][3]); i++;
+ f[i][0] = __builtin_vsx_vperm (f[i][1], f[i][2], uc[i][3]); i++;
+ d[i][0] = __builtin_vsx_vperm (d[i][1], d[i][2], uc[i][3]); i++;
+
+ return i;
+}
+
+int do_xxperm (void)
+{
+ int i = 0;
+
+ d[i][0] = __builtin_vsx_xxpermdi_2df (d[i][1], d[i][2], 0); i++;
+ d[i][0] = __builtin_vsx_xxpermdi (d[i][1], d[i][2], 1); i++;
+ return i;
+}
+
+double x, y;
+void do_concat (void)
+{
+ d[0][0] = __builtin_vsx_concat_2df (x, y);
+}
+
+void do_set (void)
+{
+ d[0][0] = __builtin_vsx_set_2df (d[0][1], x, 0);
+ d[1][0] = __builtin_vsx_set_2df (d[1][1], y, 1);
+}
+
+extern double z[][4];
+
+int do_math (void)
+{
+ int i = 0;
+
+ d[i][0] = __builtin_vsx_xvrdpi (d[i][1]); i++;
+ d[i][0] = __builtin_vsx_xvrdpic (d[i][1]); i++;
+ d[i][0] = __builtin_vsx_xvrdpim (d[i][1]); i++;
+ d[i][0] = __builtin_vsx_xvrdpip (d[i][1]); i++;
+ d[i][0] = __builtin_vsx_xvrdpiz (d[i][1]); i++;
+
+ f[i][0] = __builtin_vsx_xvrspi (f[i][1]); i++;
+ f[i][0] = __builtin_vsx_xvrspic (f[i][1]); i++;
+ f[i][0] = __builtin_vsx_xvrspim (f[i][1]); i++;
+ f[i][0] = __builtin_vsx_xvrspip (f[i][1]); i++;
+ f[i][0] = __builtin_vsx_xvrspiz (f[i][1]); i++;
+
+ z[i][0] = __builtin_vsx_xsrdpi (z[i][1]); i++;
+ z[i][0] = __builtin_vsx_xsrdpic (z[i][1]); i++;
+ z[i][0] = __builtin_vsx_xsrdpim (z[i][1]); i++;
+ z[i][0] = __builtin_vsx_xsrdpip (z[i][1]); i++;
+ z[i][0] = __builtin_vsx_xsrdpiz (z[i][1]); i++;
+ z[i][0] = __builtin_vsx_xsmaxdp (z[i][1], z[i][0]); i++;
+ z[i][0] = __builtin_vsx_xsmindp (z[i][1], z[i][0]); i++;
+ return i;
+}
+
+int do_cmp (void)
+{
+ int i = 0;
+
+ d[i][0] = __builtin_vsx_xvcmpeqdp (d[i][1], d[i][2]); i++;
+ d[i][0] = __builtin_vsx_xvcmpgtdp (d[i][1], d[i][2]); i++;
+ d[i][0] = __builtin_vsx_xvcmpgedp (d[i][1], d[i][2]); i++;
+
+ f[i][0] = __builtin_vsx_xvcmpeqsp (f[i][1], f[i][2]); i++;
+ f[i][0] = __builtin_vsx_xvcmpgtsp (f[i][1], f[i][2]); i++;
+ f[i][0] = __builtin_vsx_xvcmpgesp (f[i][1], f[i][2]); i++;
+ return i;
+}
+
+int do_logical (void)
+{
+ int i = 0;
+
+ si[i][0] = __builtin_vsx_xxland (si[i][1], si[i][2]); i++;
+ si[i][0] = __builtin_vsx_xxlandc (si[i][1], si[i][2]); i++;
+ si[i][0] = __builtin_vsx_xxlnor (si[i][1], si[i][2]); i++;
+ si[i][0] = __builtin_vsx_xxlor (si[i][1], si[i][2]); i++;
+ si[i][0] = __builtin_vsx_xxlxor (si[i][1], si[i][2]); i++;
+
+ ss[i][0] = __builtin_vsx_xxland (ss[i][1], ss[i][2]); i++;
+ ss[i][0] = __builtin_vsx_xxlandc (ss[i][1], ss[i][2]); i++;
+ ss[i][0] = __builtin_vsx_xxlnor (ss[i][1], ss[i][2]); i++;
+ ss[i][0] = __builtin_vsx_xxlor (ss[i][1], ss[i][2]); i++;
+ ss[i][0] = __builtin_vsx_xxlxor (ss[i][1], ss[i][2]); i++;
+
+ sc[i][0] = __builtin_vsx_xxland (sc[i][1], sc[i][2]); i++;
+ sc[i][0] = __builtin_vsx_xxlandc (sc[i][1], sc[i][2]); i++;
+ sc[i][0] = __builtin_vsx_xxlnor (sc[i][1], sc[i][2]); i++;
+ sc[i][0] = __builtin_vsx_xxlor (sc[i][1], sc[i][2]); i++;
+ sc[i][0] = __builtin_vsx_xxlxor (sc[i][1], sc[i][2]); i++;
+
+ d[i][0] = __builtin_vsx_xxland (d[i][1], d[i][2]); i++;
+ d[i][0] = __builtin_vsx_xxlandc (d[i][1], d[i][2]); i++;
+ d[i][0] = __builtin_vsx_xxlnor (d[i][1], d[i][2]); i++;
+ d[i][0] = __builtin_vsx_xxlor (d[i][1], d[i][2]); i++;
+ d[i][0] = __builtin_vsx_xxlxor (d[i][1], d[i][2]); i++;
+
+ f[i][0] = __builtin_vsx_xxland (f[i][1], f[i][2]); i++;
+ f[i][0] = __builtin_vsx_xxlandc (f[i][1], f[i][2]); i++;
+ f[i][0] = __builtin_vsx_xxlnor (f[i][1], f[i][2]); i++;
+ f[i][0] = __builtin_vsx_xxlor (f[i][1], f[i][2]); i++;
+ f[i][0] = __builtin_vsx_xxlxor (f[i][1], f[i][2]); i++;
+ return i;
+}
+
+int do_xxsldwi (void)
+{
+ int i = 0;
+
+ si[i][0] = __builtin_vsx_xxsldwi (si[i][1], si[i][2], 0); i++;
+ ss[i][0] = __builtin_vsx_xxsldwi (ss[i][1], ss[i][2], 1); i++;
+ sc[i][0] = __builtin_vsx_xxsldwi (sc[i][1], sc[i][2], 2); i++;
+ ui[i][0] = __builtin_vsx_xxsldwi (ui[i][1], ui[i][2], 3); i++;
+ us[i][0] = __builtin_vsx_xxsldwi (us[i][1], us[i][2], 0); i++;
+ uc[i][0] = __builtin_vsx_xxsldwi (uc[i][1], uc[i][2], 1); i++;
+ f[i][0] = __builtin_vsx_xxsldwi (f[i][1], f[i][2], 2); i++;
+ d[i][0] = __builtin_vsx_xxsldwi (d[i][1], d[i][2], 3); i++;
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-4.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-4.c
new file mode 100644
index 0000000..bcf4863
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-4.c
@@ -0,0 +1,142 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xvcmpeqdp." } } */
+/* { dg-final { scan-assembler "xvcmpgtdp." } } */
+/* { dg-final { scan-assembler "xvcmpgedp." } } */
+/* { dg-final { scan-assembler "xvcmpeqsp." } } */
+/* { dg-final { scan-assembler "xvcmpgtsp." } } */
+/* { dg-final { scan-assembler "xvcmpgesp." } } */
+/* { dg-final { scan-assembler "vcmpbfp." } } */
+/* { dg-final { scan-assembler "vcmpequb." } } */
+/* { dg-final { scan-assembler "vcmpequh." } } */
+/* { dg-final { scan-assembler "vcmpequw." } } */
+/* { dg-final { scan-assembler "vcmpgtub." } } */
+/* { dg-final { scan-assembler "vcmpgtuh." } } */
+/* { dg-final { scan-assembler "vcmpgtuw." } } */
+/* { dg-final { scan-assembler "vcmpgtsb." } } */
+/* { dg-final { scan-assembler "vcmpgtsh." } } */
+/* { dg-final { scan-assembler "vcmpgtsw." } } */
+/* { dg-final { scan-assembler-not "vcmpeqfp" } } */
+/* { dg-final { scan-assembler-not "vcmpgtfp" } } */
+/* { dg-final { scan-assembler-not "vcmpgefp" } } */
+
+/* check that Altivec builtins generate VSX if -mvsx. */
+
+#include <altivec.h>
+
+int *v16qi_s (vector signed char *a, vector signed char *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 2;
+
+ return p;
+}
+
+int *v16qi_u (vector unsigned char *a, vector unsigned char *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 2;
+
+ return p;
+}
+
+int *v8hi_s (vector short *a, vector short *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 2;
+
+ return p;
+}
+
+int *v8hi_u (vector unsigned short *a, vector unsigned short *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 2;
+
+ return p;
+}
+
+int *v4si_s (vector int *a, vector int *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 2;
+
+ return p;
+}
+
+int *v4si_u (vector unsigned int *a, vector unsigned int *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 2;
+
+ return p;
+}
+
+int *v4sf (vector float *a, vector float *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 3;
+
+ if (vec_all_in (*a, *b)) /* veccmpbfp. */
+ *p++ = 4;
+
+ return p;
+}
+
+int *v2df (vector double *a, vector double *b, int *p)
+{
+ if (vec_all_eq (*a, *b))
+ *p++ = 1;
+
+ if (vec_all_gt (*a, *b))
+ *p++ = 2;
+
+ if (vec_all_ge (*a, *b))
+ *p++ = 3;
+
+ return p;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-5.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-5.c
new file mode 100644
index 0000000..5c24dc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-5.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "stxvd2x" } } */
+
+/* Make sure double extract doesn't use a store instruction. */
+
+double d0(__vector double v){ return __builtin_vec_extract (v, 0); }
+double d1(__vector double v){ return __builtin_vec_extract (v, 1); }
+
+double e0(vector double v){ return __builtin_vec_ext_v2df (v, 0); }
+double e1(vector double v){ return __builtin_vec_ext_v2df (v, 1); }
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-6.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-6.c
new file mode 100644
index 0000000..a722b83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-6.c
@@ -0,0 +1,146 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+
+/* Check whether tdiv and tsqrt instructions generate the correct code. */
+/* Each of the *tdiv* and *tsqrt* instructions should be generated exactly 3
+ times (the two calls in the _1 function should be combined). */
+/* { dg-final { scan-assembler-times "xstdivdp" 3 } } */
+/* { dg-final { scan-assembler-times "xvtdivdp" 3 } } */
+/* { dg-final { scan-assembler-times "xvtdivsp" 3 } } */
+/* { dg-final { scan-assembler-times "xstsqrtdp" 3 } } */
+/* { dg-final { scan-assembler-times "xvtsqrtdp" 3 } } */
+/* { dg-final { scan-assembler-times "xvtsqrtsp" 3 } } */
+
+void test_div_df_1 (double a, double b, int *p)
+{
+ p[0] = __builtin_vsx_xstdivdp_fe (a, b);
+ p[1] = __builtin_vsx_xstdivdp_fg (a, b);
+}
+
+int *test_div_df_2 (double a, double b, int *p)
+{
+ if (__builtin_vsx_xstdivdp_fe (a, b))
+ *p++ = 1;
+
+ return p;
+}
+
+int *test_div_df_3 (double a, double b, int *p)
+{
+ if (__builtin_vsx_xstdivdp_fg (a, b))
+ *p++ = 1;
+
+ return p;
+}
+
+void test_sqrt_df_1 (double a, int *p)
+{
+ p[0] = __builtin_vsx_xstsqrtdp_fe (a);
+ p[1] = __builtin_vsx_xstsqrtdp_fg (a);
+}
+
+int *test_sqrt_df_2 (double a, int *p)
+{
+ if (__builtin_vsx_xstsqrtdp_fe (a))
+ *p++ = 1;
+
+ return p;
+}
+
+int *test_sqrt_df_3 (double a, int *p)
+{
+ if (__builtin_vsx_xstsqrtdp_fg (a))
+ *p++ = 1;
+
+ return p;
+}
+
+void test_div_v2df_1 (__vector double *a, __vector double *b, int *p)
+{
+ p[0] = __builtin_vsx_xvtdivdp_fe (*a, *b);
+ p[1] = __builtin_vsx_xvtdivdp_fg (*a, *b);
+}
+
+int *test_div_v2df_2 (__vector double *a, __vector double *b, int *p)
+{
+ if (__builtin_vsx_xvtdivdp_fe (*a, *b))
+ *p++ = 1;
+
+ return p;
+}
+
+int *test_div_v2df_3 (__vector double *a, __vector double *b, int *p)
+{
+ if (__builtin_vsx_xvtdivdp_fg (*a, *b))
+ *p++ = 1;
+
+ return p;
+}
+
+void test_sqrt_v2df_1 (__vector double *a, int *p)
+{
+ p[0] = __builtin_vsx_xvtsqrtdp_fe (*a);
+ p[1] = __builtin_vsx_xvtsqrtdp_fg (*a);
+}
+
+int *test_sqrt_v2df_2 (__vector double *a, int *p)
+{
+ if (__builtin_vsx_xvtsqrtdp_fe (*a))
+ *p++ = 1;
+
+ return p;
+}
+
+int *test_sqrt_v2df_3 (__vector double *a, int *p)
+{
+ if (__builtin_vsx_xvtsqrtdp_fg (*a))
+ *p++ = 1;
+
+ return p;
+}
+
+void test_div_v4sf_1 (__vector float *a, __vector float *b, int *p)
+{
+ p[0] = __builtin_vsx_xvtdivsp_fe (*a, *b);
+ p[1] = __builtin_vsx_xvtdivsp_fg (*a, *b);
+}
+
+int *test_div_v4sf_2 (__vector float *a, __vector float *b, int *p)
+{
+ if (__builtin_vsx_xvtdivsp_fe (*a, *b))
+ *p++ = 1;
+
+ return p;
+}
+
+int *test_div_v4sf_3 (__vector float *a, __vector float *b, int *p)
+{
+ if (__builtin_vsx_xvtdivsp_fg (*a, *b))
+ *p++ = 1;
+
+ return p;
+}
+
+void test_sqrt_v4sf_1 (__vector float *a, int *p)
+{
+ p[0] = __builtin_vsx_xvtsqrtsp_fe (*a);
+ p[1] = __builtin_vsx_xvtsqrtsp_fg (*a);
+}
+
+int *test_sqrt_v4sf_2 (__vector float *a, int *p)
+{
+ if (__builtin_vsx_xvtsqrtsp_fe (*a))
+ *p++ = 1;
+
+ return p;
+}
+
+int *test_sqrt_v4sf_3 (__vector float *a, int *p)
+{
+ if (__builtin_vsx_xvtsqrtsp_fg (*a))
+ *p++ = 1;
+
+ return p;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c
new file mode 100644
index 0000000..55e999d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c
@@ -0,0 +1,150 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+
+/* Test simple extract/insert/slat operations. Make sure all types are
+ supported with various options. */
+
+#include <altivec.h>
+
+double extract_df_0_reg (vector double p) { return vec_extract (p, 0); }
+double extract_df_1_reg (vector double p) { return vec_extract (p, 1); }
+double extract_df_n_reg (vector double p, int n) { return vec_extract (p, n); }
+
+double extract_df_0_mem (vector double *p) { return vec_extract (*p, 0); }
+double extract_df_1_mem (vector double *p) { return vec_extract (*p, 1); }
+double extract_df_n_mem (vector double *p, int n) { return vec_extract (*p, n); }
+
+vector double insert_df_0 (vector double p, double x) { return vec_insert (x, p, 0); }
+vector double insert_df_1 (vector double p, double x) { return vec_insert (x, p, 1); }
+vector double insert_df_n (vector double p, double x, int n) { return vec_insert (x, p, n); }
+
+vector double splat_df_reg (double x) { return vec_splats (x); }
+vector double splat_df_mem (double *x) { return vec_splats (*x); }
+
+#ifdef _ARCH_PPC64
+#define ll long
+#else
+#define ll long long
+#endif
+
+ll extract_di_0_reg (vector ll p) { return vec_extract (p, 0); }
+ll extract_di_1_reg (vector ll p) { return vec_extract (p, 1); }
+ll extract_di_n_reg (vector ll p, int n) { return vec_extract (p, n); }
+
+ll extract_di_0_mem (vector ll *p) { return vec_extract (*p, 0); }
+ll extract_di_1_mem (vector ll *p) { return vec_extract (*p, 1); }
+ll extract_di_n_mem (vector ll *p, int n) { return vec_extract (*p, n); }
+
+vector ll insert_di_0 (vector ll p, ll x) { return vec_insert (x, p, 0); }
+vector ll insert_di_1 (vector ll p, ll x) { return vec_insert (x, p, 1); }
+vector ll insert_di_n (vector ll p, ll x, int n) { return vec_insert (x, p, n); }
+
+vector ll splat_di_reg (ll x) { return vec_splats (x); }
+vector ll splat_di_mem (ll *x) { return vec_splats (*x); }
+
+float extract_sf_0_reg (vector float p) { return vec_extract (p, 0); }
+float extract_sf_3_reg (vector float p) { return vec_extract (p, 3); }
+float extract_sf_n_reg (vector float p, int n) { return vec_extract (p, n); }
+
+float extract_sf_0_mem (vector float *p) { return vec_extract (*p, 0); }
+float extract_sf_3_mem (vector float *p) { return vec_extract (*p, 3); }
+float extract_sf_n_mem (vector float *p, int n) { return vec_extract (*p, n); }
+
+vector float insert_sf_0 (vector float p, float x) { return vec_insert (x, p, 0); }
+vector float insert_sf_3 (vector float p, float x) { return vec_insert (x, p, 3); }
+vector float insert_sf_n (vector float p, float x, int n) { return vec_insert (x, p, n); }
+
+vector float splat_sf_reg (float x) { return vec_splats (x); }
+vector float splat_sf_mem (float *x) { return vec_splats (*x); }
+
+int extract_si_0_reg (vector int p) { return vec_extract (p, 0); }
+int extract_si_3_reg (vector int p) { return vec_extract (p, 3); }
+int extract_si_n_reg (vector int p, int n) { return vec_extract (p, n); }
+
+int extract_si_0_mem (vector int *p) { return vec_extract (*p, 0); }
+int extract_si_3_mem (vector int *p) { return vec_extract (*p, 3); }
+int extract_si_n_mem (vector int *p, int n) { return vec_extract (*p, n); }
+
+vector int insert_si_0 (vector int p, int x) { return vec_insert (x, p, 0); }
+vector int insert_si_3 (vector int p, int x) { return vec_insert (x, p, 3); }
+vector int insert_si_n (vector int p, int x, int n) { return vec_insert (x, p, n); }
+
+vector int splat_si_reg (int x) { return vec_splats (x); }
+vector int splat_si_mem (int *x) { return vec_splats (*x); }
+
+unsigned int extract_usi_0_reg (vector unsigned int p) { return vec_extract (p, 0); }
+unsigned int extract_usi_3_reg (vector unsigned int p) { return vec_extract (p, 3); }
+unsigned int extract_usi_n_reg (vector unsigned int p, int n) { return vec_extract (p, n); }
+
+unsigned int extract_usi_0_mem (vector unsigned int *p) { return vec_extract (*p, 0); }
+unsigned int extract_usi_3_mem (vector unsigned int *p) { return vec_extract (*p, 3); }
+unsigned int extract_usi_n_mem (vector unsigned int *p, int n) { return vec_extract (*p, n); }
+
+vector unsigned int insert_usi_0 (vector unsigned int p, unsigned int x) { return vec_insert (x, p, 0); }
+vector unsigned int insert_usi_3 (vector unsigned int p, unsigned int x) { return vec_insert (x, p, 3); }
+vector unsigned int insert_usi_n (vector unsigned int p, unsigned int x, int n) { return vec_insert (x, p, n); }
+
+vector unsigned int splat_usi_reg (unsigned int x) { return vec_splats (x); }
+vector unsigned int splat_usi_mem (unsigned int *x) { return vec_splats (*x); }
+
+short extract_hi_0_reg (vector short p) { return vec_extract (p, 0); }
+short extract_hi_7_reg (vector short p) { return vec_extract (p, 7); }
+short extract_hi_n_reg (vector short p, int n) { return vec_extract (p, n); }
+
+short extract_hi_0_mem (vector short *p) { return vec_extract (*p, 0); }
+short extract_hi_7_mem (vector short *p) { return vec_extract (*p, 7); }
+short extract_hi_n_mem (vector short *p, int n) { return vec_extract (*p, n); }
+
+vector short insert_hi_0 (vector short p, short x) { return vec_insert (x, p, 0); }
+vector short insert_hi_7 (vector short p, short x) { return vec_insert (x, p, 7); }
+vector short insert_hi_n (vector short p, short x, int n) { return vec_insert (x, p, n); }
+
+vector short splat_hi_reg (short x) { return vec_splats (x); }
+vector short splat_hi_mem (short *x) { return vec_splats (*x); }
+
+unsigned short extract_uhi_0_reg (vector unsigned short p) { return vec_extract (p, 0); }
+unsigned short extract_uhi_7_reg (vector unsigned short p) { return vec_extract (p, 7); }
+unsigned short extract_uhi_n_reg (vector unsigned short p, int n) { return vec_extract (p, n); }
+
+unsigned short extract_uhi_0_mem (vector unsigned short *p) { return vec_extract (*p, 0); }
+unsigned short extract_uhi_7_mem (vector unsigned short *p) { return vec_extract (*p, 7); }
+unsigned short extract_uhi_n_mem (vector unsigned short *p, int n) { return vec_extract (*p, n); }
+
+vector unsigned short insert_uhi_0 (vector unsigned short p, unsigned short x) { return vec_insert (x, p, 0); }
+vector unsigned short insert_uhi_7 (vector unsigned short p, unsigned short x) { return vec_insert (x, p, 7); }
+vector unsigned short insert_uhi_n (vector unsigned short p, unsigned short x, int n) { return vec_insert (x, p, n); }
+
+vector unsigned short splat_uhi_reg (unsigned short x) { return vec_splats (x); }
+vector unsigned short splat_uhi_mem (unsigned short *x) { return vec_splats (*x); }
+
+signed char extract_qi_0_reg (vector signed char p) { return vec_extract (p, 0); }
+signed char extract_qi_1_reg5 (vector signed char p) { return vec_extract (p, 15); }
+signed char extract_qi_n_reg (vector signed char p, int n) { return vec_extract (p, n); }
+
+signed char extract_qi_0_mem (vector signed char *p) { return vec_extract (*p, 0); }
+signed char extract_qi_1_mem5 (vector signed char *p) { return vec_extract (*p, 15); }
+signed char extract_qi_n_mem (vector signed char *p, int n) { return vec_extract (*p, n); }
+
+vector signed char insert_qi_0 (vector signed char p, signed char x) { return vec_insert (x, p, 0); }
+vector signed char insert_qi_15 (vector signed char p, signed char x) { return vec_insert (x, p, 15); }
+vector signed char insert_qi_n (vector signed char p, signed char x, int n) { return vec_insert (x, p, n); }
+
+vector signed char splat_qi_reg (signed char x) { return vec_splats (x); }
+vector signed char splat_qi_mem (signed char *x) { return vec_splats (*x); }
+
+unsigned char extract_uqi_0_reg (vector unsigned char p) { return vec_extract (p, 0); }
+unsigned char extract_uqi_1_reg5 (vector unsigned char p) { return vec_extract (p, 15); }
+unsigned char extract_uqi_n_reg (vector unsigned char p, int n) { return vec_extract (p, n); }
+
+unsigned char extract_uqi_0_mem (vector unsigned char *p) { return vec_extract (*p, 0); }
+unsigned char extract_uqi_1_mem5 (vector unsigned char *p) { return vec_extract (*p, 15); }
+unsigned char extract_uqi_n_mem (vector unsigned char *p, int n) { return vec_extract (*p, n); }
+
+vector unsigned char insert_uqi_0 (vector unsigned char p, unsigned char x) { return vec_insert (x, p, 0); }
+vector unsigned char insert_uqi_15 (vector unsigned char p, unsigned char x) { return vec_insert (x, p, 15); }
+vector unsigned char insert_uqi_n (vector unsigned char p, unsigned char x, int n) { return vec_insert (x, p, n); }
+
+vector unsigned char splat_uqi_reg (unsigned char x) { return vec_splats (x); }
+vector unsigned char splat_uqi_mem (unsigned char *x) { return vec_splats (*x); }
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c
new file mode 100644
index 0000000..0bf3a7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c
@@ -0,0 +1,152 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mcpu=power7 -m64 -ffast-math" } */
+/* { dg-final { scan-assembler "xvadddp" } } */
+/* { dg-final { scan-assembler "xvsubdp" } } */
+/* { dg-final { scan-assembler "xvmuldp" } } */
+/* { dg-final { scan-assembler "xvdivdp" } } */
+/* { dg-final { scan-assembler "xvmadd" } } */
+/* { dg-final { scan-assembler "xvmsub" } } */
+/* { dg-final { scan-assembler "xvsqrtdp" } } */
+/* { dg-final { scan-assembler "xvcpsgndp" } } */
+/* { dg-final { scan-assembler "xvrdpim" } } */
+/* { dg-final { scan-assembler "xvrdpip" } } */
+/* { dg-final { scan-assembler "xvrdpiz" } } */
+/* { dg-final { scan-assembler "xvrdpic" } } */
+/* { dg-final { scan-assembler "xvrdpi " } } */
+
+#ifndef SIZE
+#define SIZE 1024
+#endif
+
+double a[SIZE] __attribute__((__aligned__(32)));
+double b[SIZE] __attribute__((__aligned__(32)));
+double c[SIZE] __attribute__((__aligned__(32)));
+double d[SIZE] __attribute__((__aligned__(32)));
+double e[SIZE] __attribute__((__aligned__(32)));
+
+void
+vector_add (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] + c[i];
+}
+
+void
+vector_subtract (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] - c[i];
+}
+
+void
+vector_multiply (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] * c[i];
+}
+
+void
+vector_multiply_add (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = (b[i] * c[i]) + d[i];
+}
+
+void
+vector_multiply_subtract (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = (b[i] * c[i]) - d[i];
+}
+
+void
+vector_divide (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] / c[i];
+}
+
+extern double sqrt (double);
+extern double floor (double);
+extern double ceil (double);
+extern double trunc (double);
+extern double nearbyint (double);
+extern double rint (double);
+extern double copysign (double, double);
+
+void
+vector_sqrt (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = sqrt (b[i]);
+}
+
+void
+vector_floor (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = floor (b[i]);
+}
+
+void
+vector_ceil (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = ceil (b[i]);
+}
+
+void
+vector_trunc (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = trunc (b[i]);
+}
+
+void
+vector_nearbyint (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = nearbyint (b[i]);
+}
+
+void
+vector_rint (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = rint (b[i]);
+}
+
+void
+vector_copysign (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = copysign (b[i], c[i]);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c
new file mode 100644
index 0000000..ba27b46
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c
@@ -0,0 +1,152 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mcpu=power7 -m64 -ffast-math" } */
+/* { dg-final { scan-assembler "xvaddsp" } } */
+/* { dg-final { scan-assembler "xvsubsp" } } */
+/* { dg-final { scan-assembler "xvmulsp" } } */
+/* { dg-final { scan-assembler "xvdivsp" } } */
+/* { dg-final { scan-assembler "xvmadd" } } */
+/* { dg-final { scan-assembler "xvmsub" } } */
+/* { dg-final { scan-assembler "xvsqrtsp" } } */
+/* { dg-final { scan-assembler "xvcpsgnsp" } } */
+/* { dg-final { scan-assembler "xvrspim" } } */
+/* { dg-final { scan-assembler "xvrspip" } } */
+/* { dg-final { scan-assembler "xvrspiz" } } */
+/* { dg-final { scan-assembler "xvrspic" } } */
+/* { dg-final { scan-assembler "xvrspi " } } */
+
+#ifndef SIZE
+#define SIZE 1024
+#endif
+
+float a[SIZE] __attribute__((__aligned__(32)));
+float b[SIZE] __attribute__((__aligned__(32)));
+float c[SIZE] __attribute__((__aligned__(32)));
+float d[SIZE] __attribute__((__aligned__(32)));
+float e[SIZE] __attribute__((__aligned__(32)));
+
+void
+vector_add (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] + c[i];
+}
+
+void
+vector_subtract (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] - c[i];
+}
+
+void
+vector_multiply (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] * c[i];
+}
+
+void
+vector_multiply_add (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = (b[i] * c[i]) + d[i];
+}
+
+void
+vector_multiply_subtract (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = (b[i] * c[i]) - d[i];
+}
+
+void
+vector_divide (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = b[i] / c[i];
+}
+
+extern float sqrtf (float);
+extern float floorf (float);
+extern float ceilf (float);
+extern float truncf (float);
+extern float nearbyintf (float);
+extern float rintf (float);
+extern float copysignf (float, float);
+
+void
+vector_sqrt (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = sqrtf (b[i]);
+}
+
+void
+vector_floor (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = floorf (b[i]);
+}
+
+void
+vector_ceil (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = ceilf (b[i]);
+}
+
+void
+vector_trunc (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = truncf (b[i]);
+}
+
+void
+vector_nearbyint (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = nearbyintf (b[i]);
+}
+
+void
+vector_rint (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = rintf (b[i]);
+}
+
+void
+vector_copysign (void)
+{
+ int i;
+
+ for (i = 0; i < SIZE; i++)
+ a[i] = copysignf (b[i], c[i]);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c
new file mode 100644
index 0000000..5f3bf5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c
@@ -0,0 +1,48 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mcpu=power7 -m64" } */
+/* { dg-final { scan-assembler "xvadddp" } } */
+/* { dg-final { scan-assembler "xvsubdp" } } */
+/* { dg-final { scan-assembler "xvmuldp" } } */
+/* { dg-final { scan-assembler "xvdivdp" } } */
+/* { dg-final { scan-assembler "xvmadd" } } */
+/* { dg-final { scan-assembler "xvmsub" } } */
+
+__vector double a, b, c, d;
+
+void
+vector_add (void)
+{
+ a = b + c;
+}
+
+void
+vector_subtract (void)
+{
+ a = b - c;
+}
+
+void
+vector_multiply (void)
+{
+ a = b * c;
+}
+
+void
+vector_multiply_add (void)
+{
+ a = (b * c) + d;
+}
+
+void
+vector_multiply_subtract (void)
+{
+ a = (b * c) - d;
+}
+
+void
+vector_divide (void)
+{
+ a = b / c;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c
new file mode 100644
index 0000000..a34ba8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c
@@ -0,0 +1,48 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mcpu=power7 -m64" } */
+/* { dg-final { scan-assembler "xvaddsp" } } */
+/* { dg-final { scan-assembler "xvsubsp" } } */
+/* { dg-final { scan-assembler "xvmulsp" } } */
+/* { dg-final { scan-assembler "xvdivsp" } } */
+/* { dg-final { scan-assembler "xvmadd" } } */
+/* { dg-final { scan-assembler "xvmsub" } } */
+
+__vector float a, b, c, d;
+
+void
+vector_add (void)
+{
+ a = b + c;
+}
+
+void
+vector_subtract (void)
+{
+ a = b - c;
+}
+
+void
+vector_multiply (void)
+{
+ a = b * c;
+}
+
+void
+vector_multiply_add (void)
+{
+ a = (b * c) + d;
+}
+
+void
+vector_multiply_subtract (void)
+{
+ a = (b * c) - d;
+}
+
+void
+vector_divide (void)
+{
+ a = b / c;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-5.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-5.c
new file mode 100644
index 0000000..65843e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-5.c
@@ -0,0 +1,392 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mvsx -O2" } */
+
+/* This will run, and someday we should add the support to test whether we are
+ running on VSX hardware. */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+
+static int errors = 0;
+#endif
+
+union args {
+ double scalar[2];
+ vector double vect;
+};
+
+union largs {
+ unsigned long scalar[2];
+ vector bool long vect;
+};
+
+static void
+do_test (union args *expected, union args *got, const char *name)
+{
+ if (expected->scalar[0] != got->scalar[0]
+ || expected->scalar[1] != got->scalar[1])
+ {
+#ifdef DEBUG
+ printf ("%s failed!\n", name);
+ errors++;
+#else
+ abort ();
+#endif
+ }
+}
+
+static void
+do_ltest (union largs *expected, union largs *got, const char *name)
+{
+ if (expected->scalar[0] != got->scalar[0]
+ || expected->scalar[1] != got->scalar[1])
+ {
+#ifdef DEBUG
+ printf ("%s failed!\n", name);
+ errors++;
+#else
+ abort ();
+#endif
+ }
+}
+
+
+/* Vec functions taking a single argument. */
+static vector double
+vabs (vector double arg)
+{
+ return vec_abs (arg);
+}
+
+static vector double
+vceil (vector double arg)
+{
+ return vec_ceil (arg);
+}
+
+static vector double
+vfloor (vector double arg)
+{
+ return vec_floor (arg);
+}
+
+static vector double
+vnearbyint (vector double arg)
+{
+ return vec_nearbyint (arg);
+}
+
+static vector double
+vrint (vector double arg)
+{
+ return vec_rint (arg);
+}
+
+static vector double
+vsqrt (vector double arg)
+{
+ return vec_sqrt (arg);
+}
+
+/* Single argument tests. */
+static struct
+{
+ union args result;
+ union args input;
+ vector double (*func) (vector double);
+ const char *name;
+} arg1_tests[] = {
+ /* result input function name */
+ { { 1.0, 2.0 }, { -1.0, 2.0 }, vabs, "vabs" },
+ { { 1.0, 2.0 }, { 1.0, -2.0 }, vabs, "vabs" },
+ { { 2.0, 2.0 }, { 1.1, 1.7 }, vceil, "vceil" },
+ { { -1.0, -1.0 }, { -1.1, -1.7 }, vceil, "vceil" },
+ { { -1.0, 2.0 }, { -1.5, 1.5 }, vceil, "vceil" },
+ { { 1.0, 1.0 }, { 1.1, 1.7 }, vfloor, "vfloor" },
+ { { -2.0, -2.0 }, { -1.1, -1.7 }, vfloor, "vfloor" },
+ { { -2.0, 1.0 }, { -1.5, 1.5 }, vfloor, "vfloor" },
+ { { 1.0, 2.0 }, { 1.1, 1.7 }, vnearbyint, "vnearbyint" },
+ { { -1.0, -2.0 }, { -1.1, -1.7 }, vnearbyint, "vnearbyint" },
+ { { -2.0, 2.0 }, { -1.5, 1.5 }, vnearbyint, "vnearbyint" },
+ { { 1.0, 2.0 }, { 1.1, 1.7 }, vrint, "vrint" },
+ { { -1.0, -2.0 }, { -1.1, -1.7 }, vrint, "vrint" },
+ { { -2.0, 2.0 }, { -1.5, 1.5 }, vrint, "vrint" },
+ { { 2.0, 4.0 }, { 4.0, 16.0 }, vsqrt, "vsqrt" },
+};
+
+static void
+test_arg1 (void)
+{
+ unsigned i;
+
+#ifdef DEBUG
+ printf ("Single argument tests:\n");
+#endif
+
+ for (i = 0; i < sizeof (arg1_tests) / sizeof (arg1_tests[0]); i++)
+ {
+ union args u;
+ u.vect = arg1_tests[i].func (arg1_tests[i].input.vect);
+
+#ifdef DEBUG
+ printf ("test %-16s: expected { %4g, %4g }, got { %4g, %4g }, input { %4g, %4g }\n",
+ arg1_tests[i].name,
+ arg1_tests[i].result.scalar[0],
+ arg1_tests[i].result.scalar[1],
+ u.scalar[0],
+ u.scalar[1],
+ arg1_tests[i].input.scalar[0],
+ arg1_tests[i].input.scalar[1]);
+#endif
+
+ do_test (&arg1_tests[i].result, &u, arg1_tests[i].name);
+ }
+
+ return;
+}
+
+
+/* Vect functions taking 2 arguments. */
+static vector double
+vadd (vector double arg1, vector double arg2)
+{
+ return vec_add (arg1, arg2);
+}
+
+static vector double
+vadd2 (vector double arg1, vector double arg2)
+{
+ return arg1 + arg2;
+}
+
+static vector double
+vsub (vector double arg1, vector double arg2)
+{
+ return vec_sub (arg1, arg2);
+}
+
+static vector double
+vsub2 (vector double arg1, vector double arg2)
+{
+ return arg1 - arg2;
+}
+
+static vector double
+vmul (vector double arg1, vector double arg2)
+{
+ return vec_mul (arg1, arg2);
+}
+
+static vector double
+vmul2 (vector double arg1, vector double arg2)
+{
+ return arg1 * arg2;
+}
+
+static vector double
+vdiv (vector double arg1, vector double arg2)
+{
+ return vec_div (arg1, arg2);
+}
+
+static vector double
+vdiv2 (vector double arg1, vector double arg2)
+{
+ return arg1 / arg2;
+}
+
+static vector double
+vmax (vector double arg1, vector double arg2)
+{
+ return vec_max (arg1, arg2);
+}
+
+static vector double
+vmin (vector double arg1, vector double arg2)
+{
+ return vec_min (arg1, arg2);
+}
+
+/* 2 argument tests. */
+static struct
+{
+ union args result;
+ union args input[2];
+ vector double (*func) (vector double, vector double);
+ const char *name;
+} arg2_tests[] = {
+ /* result */
+ { { 4.0, 6.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vadd, "vadd" },
+ { { 4.0, -6.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vadd, "vadd" },
+ { { 4.0, 6.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vadd2, "vadd2" },
+ { { 4.0, -6.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vadd2, "vadd2" },
+ { { -2.0, -2.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vsub, "vsub" },
+ { { -2.0, 2.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vsub, "vsub" },
+ { { -2.0, -2.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vsub2, "vsub2" },
+ { { -2.0, 2.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vsub2, "vsub2" },
+ { { 6.0, 4.0 }, { { 2.0, 8.0 }, { 3.0, 0.5 } }, vmul, "vmul" },
+ { { 6.0, 4.0 }, { { 2.0, 8.0 }, { 3.0, 0.5 } }, vmul2, "vmul2" },
+ { { 2.0, 0.5 }, { { 6.0, 4.0 }, { 3.0, 8.0 } }, vdiv, "vdiv" },
+ { { 2.0, 0.5 }, { { 6.0, 4.0 }, { 3.0, 8.0 } }, vdiv2, "vdiv2" },
+ { { 3.0, 4.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vmax, "vmax" },
+ { { 1.0, 4.0 }, { { 1.0, -2.0 }, { -3.0, 4.0 } }, vmax, "vmax" },
+ { { 1.0, 2.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vmin, "vmin" },
+ { { -3.0, -2.0 }, { { 1.0, -2.0 }, { -3.0, 4.0 } }, vmin, "vmin" },
+};
+
+static void
+test_arg2 (void)
+{
+ unsigned i;
+
+#ifdef DEBUG
+ printf ("\nTwo argument tests:\n");
+#endif
+
+ for (i = 0; i < sizeof (arg2_tests) / sizeof (arg2_tests[0]); i++)
+ {
+ union args u;
+ u.vect = arg2_tests[i].func (arg2_tests[i].input[0].vect,
+ arg2_tests[i].input[1].vect);
+
+#ifdef DEBUG
+ printf ("test %-16s: expected { %4g, %4g }, got { %4g, %4g }, input { %4g, %4g }, { %4g, %4g }\n",
+ arg2_tests[i].name,
+ arg2_tests[i].result.scalar[0],
+ arg2_tests[i].result.scalar[1],
+ u.scalar[0],
+ u.scalar[1],
+ arg2_tests[i].input[0].scalar[0],
+ arg2_tests[i].input[0].scalar[1],
+ arg2_tests[i].input[1].scalar[0],
+ arg2_tests[i].input[1].scalar[1]);
+#endif
+
+ do_test (&arg2_tests[i].result, &u, arg2_tests[i].name);
+ }
+
+ return;
+}
+
+
+/* Comparisons, returnning a boolean vector. */
+static vector bool long
+vcmpeq (vector double arg1, vector double arg2)
+{
+ return vec_cmpeq (arg1, arg2);
+}
+
+static vector bool long
+vcmplt (vector double arg1, vector double arg2)
+{
+ return vec_cmplt (arg1, arg2);
+}
+
+static vector bool long
+vcmple (vector double arg1, vector double arg2)
+{
+ return vec_cmple (arg1, arg2);
+}
+
+static vector bool long
+vcmpgt (vector double arg1, vector double arg2)
+{
+ return vec_cmpgt (arg1, arg2);
+}
+
+static vector bool long
+vcmpge (vector double arg1, vector double arg2)
+{
+ return vec_cmpge (arg1, arg2);
+}
+
+#define ONE 0xffffffffffffffffUL
+#define ZERO 0x0000000000000000UL
+
+/* comparison tests. */
+static struct
+{
+ union largs result;
+ union args input[2];
+ vector bool long (*func) (vector double, vector double);
+ const char *name;
+} argcmp_tests[] = {
+ { { ONE, ZERO }, { { 1.0, 2.0 }, { 1.0, -2.0 } }, vcmpeq, "vcmpeq" },
+ { { ZERO, ONE }, { { -1.0, 2.0 }, { 1.0, 2.0 } }, vcmpeq, "vcmpeq" },
+
+ { { ONE, ONE }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmple, "vcmple" },
+ { { ONE, ONE }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmple, "vcmple" },
+ { { ZERO, ZERO }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmple, "vcmple" },
+
+ { { ZERO, ZERO }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmplt, "vcmplt" },
+ { { ONE, ONE }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmplt, "vcmplt" },
+ { { ZERO, ZERO }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmplt, "vcmplt" },
+
+ { { ZERO, ZERO }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmpgt, "vcmpgt" },
+ { { ZERO, ZERO }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmpgt, "vcmpgt" },
+ { { ONE, ONE }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmpgt, "vcmpgt" },
+
+ { { ONE, ONE }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmpge, "vcmpge" },
+ { { ZERO, ZERO }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmpge, "vcmpge" },
+ { { ONE, ONE }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmpge, "vcmpge" },
+};
+
+static void
+test_argcmp (void)
+{
+ unsigned i;
+
+#ifdef DEBUG
+ printf ("\nComparison tests:\n");
+#endif
+
+ for (i = 0; i < sizeof (argcmp_tests) / sizeof (argcmp_tests[0]); i++)
+ {
+ union largs u;
+ u.vect = argcmp_tests[i].func (argcmp_tests[i].input[0].vect,
+ argcmp_tests[i].input[1].vect);
+
+#ifdef DEBUG
+ printf ("test %-16s: expected { 0x%016lx, 0x%016lx }, got { 0x%016lx, 0x%016lx }, input { %4g, %4g }, { %4g, %4g }\n",
+ argcmp_tests[i].name,
+ argcmp_tests[i].result.scalar[0],
+ argcmp_tests[i].result.scalar[1],
+ u.scalar[0],
+ u.scalar[1],
+ argcmp_tests[i].input[0].scalar[0],
+ argcmp_tests[i].input[0].scalar[1],
+ argcmp_tests[i].input[1].scalar[0],
+ argcmp_tests[i].input[1].scalar[1]);
+#endif
+
+ do_ltest (&argcmp_tests[i].result, &u, argcmp_tests[i].name);
+ }
+
+ return;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ test_arg1 ();
+ test_arg2 ();
+ test_argcmp ();
+
+#ifdef DEBUG
+ if (errors)
+ {
+ printf ("There were %d error(s)\n", errors);
+ return errors;
+ }
+ else
+ printf ("There were no errors\n");
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-6.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-6.c
new file mode 100644
index 0000000..f8e644b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-6.c
@@ -0,0 +1,81 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mvsx -O2" } */
+
+#include <altivec.h>
+
+void foo (vector double *out, vector double *in, vector long *p_l, vector bool long *p_b, vector unsigned char *p_uc, int *i)
+{
+ vector double in0 = in[0];
+ vector double in1 = in[1];
+ vector double in2 = in[2];
+ vector long inl = *p_l;
+ vector bool long inb = *p_b;
+ vector unsigned char uc = *p_uc;
+
+ *out++ = vec_abs (in0);
+ *out++ = vec_add (in0, in1);
+ *out++ = vec_and (in0, in1);
+ *out++ = vec_and (in0, inb);
+ *out++ = vec_and (inb, in0);
+ *out++ = vec_andc (in0, in1);
+ *out++ = vec_andc (in0, inb);
+ *out++ = vec_andc (inb, in0);
+ *out++ = vec_ceil (in0);
+ *p_b++ = vec_cmpeq (in0, in1);
+ *p_b++ = vec_cmpgt (in0, in1);
+ *p_b++ = vec_cmpge (in0, in1);
+ *p_b++ = vec_cmplt (in0, in1);
+ *p_b++ = vec_cmple (in0, in1);
+ *out++ = vec_div (in0, in1);
+ *out++ = vec_floor (in0);
+ *out++ = vec_madd (in0, in1, in2);
+ *out++ = vec_msub (in0, in1, in2);
+ *out++ = vec_max (in0, in1);
+ *out++ = vec_min (in0, in1);
+ *out++ = vec_msub (in0, in1, in2);
+ *out++ = vec_mul (in0, in1);
+ *out++ = vec_nearbyint (in0);
+ *out++ = vec_nmadd (in0, in1, in2);
+ *out++ = vec_nmsub (in0, in1, in2);
+ *out++ = vec_nor (in0, in1);
+ *out++ = vec_or (in0, in1);
+ *out++ = vec_or (in0, inb);
+ *out++ = vec_or (inb, in0);
+ *out++ = vec_perm (in0, in1, uc);
+ *out++ = vec_rint (in0);
+ *out++ = vec_sel (in0, in1, inl);
+ *out++ = vec_sel (in0, in1, inb);
+ *out++ = vec_sub (in0, in1);
+ *out++ = vec_sqrt (in0);
+ *out++ = vec_trunc (in0);
+ *out++ = vec_xor (in0, in1);
+ *out++ = vec_xor (in0, inb);
+ *out++ = vec_xor (inb, in0);
+
+ *i++ = vec_all_eq (in0, in1);
+ *i++ = vec_all_ge (in0, in1);
+ *i++ = vec_all_gt (in0, in1);
+ *i++ = vec_all_le (in0, in1);
+ *i++ = vec_all_lt (in0, in1);
+ *i++ = vec_all_nan (in0);
+ *i++ = vec_all_ne (in0, in1);
+ *i++ = vec_all_nge (in0, in1);
+ *i++ = vec_all_ngt (in0, in1);
+ *i++ = vec_all_nle (in0, in1);
+ *i++ = vec_all_nlt (in0, in1);
+ *i++ = vec_all_numeric (in0);
+ *i++ = vec_any_eq (in0, in1);
+ *i++ = vec_any_ge (in0, in1);
+ *i++ = vec_any_gt (in0, in1);
+ *i++ = vec_any_le (in0, in1);
+ *i++ = vec_any_lt (in0, in1);
+ *i++ = vec_any_nan (in0);
+ *i++ = vec_any_ne (in0, in1);
+ *i++ = vec_any_nge (in0, in1);
+ *i++ = vec_any_ngt (in0, in1);
+ *i++ = vec_any_nle (in0, in1);
+ *i++ = vec_any_nlt (in0, in1);
+ *i++ = vec_any_numeric (in0);
+}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index c847de0..050292b 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -902,6 +902,32 @@ proc check_sse2_hw_available { } {
}]
}
+# Return 1 if the target supports executing VSX instructions, 0
+# otherwise. Cache the result.
+
+proc check_vsx_hw_available { } {
+ return [check_cached_effective_target vsx_hw_available {
+ # Some simulators are known to not support VSX instructions.
+ # For now, disable on Darwin
+ if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ set options "-mvsx"
+ check_runtime_nocache vsx_hw_available {
+ int main()
+ {
+ #ifdef __MACH__
+ asm volatile ("xxlor vs0,vs0,vs0");
+ #else
+ asm volatile ("xxlor 0,0,0");
+ #endif
+ return 0;
+ }
+ } $options
+ }
+ }]
+}
+
# Return 1 if the target supports executing AltiVec instructions, 0
# otherwise. Cache the result.
@@ -912,12 +938,13 @@ proc check_vmx_hw_available { } {
expr 0
} else {
# Most targets don't require special flags for this test case, but
- # Darwin does.
+ # Darwin does. Just to be sure, make sure VSX is not enabled for
+ # the altivec tests.
if { [istarget *-*-darwin*]
|| [istarget *-*-aix*] } {
- set options "-maltivec"
+ set options "-maltivec -mno-vsx"
} else {
- set options ""
+ set options "-mno-vsx"
}
check_runtime_nocache vmx_hw_available {
int main()
@@ -1632,6 +1659,33 @@ proc check_effective_target_powerpc_altivec_ok { } {
}
}
+# Return 1 if this is a PowerPC target supporting -mvsx
+
+proc check_effective_target_powerpc_vsx_ok { } {
+ if { ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget rs6000-*-*] } {
+ # AltiVec is not supported on AIX before 5.3.
+ if { [istarget powerpc*-*-aix4*]
+ || [istarget powerpc*-*-aix5.1*]
+ || [istarget powerpc*-*-aix5.2*] } {
+ return 0
+ }
+ return [check_no_compiler_messages powerpc_vsx_ok object {
+ int main (void) {
+#ifdef __MACH__
+ asm volatile ("xxlor vs0,vs0,vs0");
+#else
+ asm volatile ("xxlor 0,0,0");
+#endif
+ return 0;
+ }
+ } "-mvsx"]
+ } else {
+ return 0
+ }
+}
+
# Return 1 if this is a PowerPC target supporting -mcpu=cell.
proc check_effective_target_powerpc_ppu_ok { } {