public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/gcc] rhel-f41-base: 4.4.0-0.23
@ 2026-06-29 12:24 Jakub Jelinek
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2026-06-29 12:24 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/gcc
Branch : rhel-f41-base
Commit : 8ac0ea7ebe76968715b52d52ad7faffbca031dfb
Author : Jakub Jelinek <jakub@fedoraproject.org>
Date : 2009-03-07T09:37:59+00:00
Stats : +9509/-9618 in 6 file(s)
URL : https://src.fedoraproject.org/rpms/gcc/c/8ac0ea7ebe76968715b52d52ad7faffbca031dfb?branch=rhel-f41-base
Log:
4.4.0-0.23
---
diff --git a/.cvsignore b/.cvsignore
index 7659195..e548bd1 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,3 +1,3 @@
fastjar-0.97.tar.gz
-gcc-4.4.0-20090304.tar.bz2
+gcc-4.4.0-20090307.tar.bz2
cloog-ppl-0.15.tar.gz
diff --git a/gcc.spec b/gcc.spec
index 59b75b8..fcd9e5e 100644
--- a/gcc.spec
+++ b/gcc.spec
@@ -434,7 +434,7 @@ which are required to compile with the GNAT.
%patch22 -p0 -b .raw-string~
%patch24 -p0 -b .atom~
%patch25 -p0 -b .pr39226~
-%patch26 -p0 -b .power7~
+#%patch26 -p0 -b .power7~
# This testcase doesn't compile.
rm libjava/testsuite/libjava.lang/PR35020*
@@ -1779,7 +1779,6 @@ fi
- fix DW_AT_decl_line on DW_TAG_imported* (#488771, PR debug/39387)
- fix SCCVN with SSA names occurring in abnormal PHIs (#488061,
PR tree-optimization/39362)
-- preliminary Power7 support
* Wed Mar 4 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-0.22
- update from trunk
diff --git a/gcc44-power7.patch b/gcc44-power7.patch
new file mode 100644
index 0000000..a9c1948
--- /dev/null
+++ b/gcc44-power7.patch
@@ -0,0 +1,9506 @@
+2009-03-06 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mvsx-scalar-memory): New switch, to switch to
+ use VSX reg+reg addressing for all scalar double precision
+ floating point.
+ * config/rs6000/rs6000.opt (-vsx-scalar-memory): Ditto.
+
+ * configure.ac (gcc_cv_as_powerpc_mfpgpr): Set binutils version to
+ 2.19.2.
+ (gcc_cv_as_powerpc_cmpb): Ditto.
+ (gcc_cv_as_powerpc_dfp): Ditto.
+ (gcc_cv_as_powerpc_vsx): Ditto.
+ (gcc_cv_as_powerpc_popcntd): Ditto.
+ * configure: Regenerate.
+
+ * config/rs6000/vector.md (VEC_int): New mode attribute for vector
+ conversions.
+ (VEC_INT): Ditto.
+ (ftrunc<mode>2): Make this a define_expand.
+ (float<VEC_int><mode>2): New vector conversion support to add VSX
+ 32 bit int/32 bit floating point convert and 64 bit int/64 bit
+ floating point vector instructions.
+ (unsigned_float<VEC_int><mode>2): Ditto.
+ (fix_trunc<mode><VEC_int>2): Ditto.
+ (fixuns_trunc<mode><VEC_int>2): Ditto.
+
+ * config/rs6000/predicates.md (easy_fp_constant): 0.0 is an easy
+ constant under VSX.
+ (indexed_or_indirect_operand): Add VSX load/store with update
+ support.
+
+ * config/rs6000/rs6000.c (rs6000_debug_addr): New global for
+ -mdebug=addr.
+ (rs6000_init_hard_regno_mode_ok): Add -mvsx-scalar-memory
+ support.
+ (rs6000_override_options): Add -mdebug=addr support.
+ (rs6000_builtin_conversion): Add VSX same size conversions.
+ (rs6000_legitimize_address): Add -mdebug=addr support. Add
+ support for VSX load/store with update instructions.
+ (rs6000_legitimize_reload_address): Ditto.
+ (rs6000_legitimate_address): Ditto.
+ (rs6000_mode_dependent_address): Ditto.
+ (print_operand): Ditto.
+ (bdesc_1arg): Add builtins for conversion that calls either the
+ VSX or Altivec insn pattern.
+ (rs6000_common_init_builtins): Ditto.
+
+ * config/rs6000/vsx.md (VSX_I): Delete, no longer used.
+ (VSi): New mode attribute for conversions.
+ (VSI): Ditto.
+ (VSc): Ditto.
+ (vsx_mov<mode>): Add load/store with update support.
+ (vsx_load<mode>_update*): New insns for load/store with update
+ support.
+ (vsx_store<mode>_update*): Ditto.
+ (vsx_fmadd<mode>4): Generate correct code for V4SF.
+ (vsx_fmsub<mode>4): Ditto.
+ (vsx_fnmadd<mode>4_*): Ditto.
+ (vsx_fnmsub<mode>4_*): Ditto.
+ (vsx_float<VSi><mode>2): New insn for vector conversion.
+ (vsx_floatuns<VSi><mode>2): Ditto.
+ (vsx_fix_trunc<mode><VSi>2): Ditto.
+ (vsx_fixuns_trunc<mode><VSi>2): Ditto.
+ (vsx_xxmrghw): New insn for V4SF interleave.
+ (vsx_xxmrglw): Ditto.
+
+ * config/rs6000/rs6000.h (rs6000_debug_addr): -mdebug=addr
+ support.
+ (TARGET_DEBUG_ADDR): Ditto.
+ (rs6000_builtins): Add VSX instructions for eventual VSX
+ builtins.
+
+ * config/rs6000/altivec.md (altivec_vmrghsf): Don't do the altivec
+ instruction if VSX.
+ (altivec_vmrglsf): Ditto.
+
+ * config/rs6000/rs6000.md (movdf_hardfloat32): Add support for
+ using xxlxor to zero a floating register if VSX.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_hardfloat64): Ditto.
+
+2009-03-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (vsx_xxmrglw): Delete for now, use Altivec.
+ (vsx_xxmrghw): Ditto.
+
+ * config/rs6000/altivec.md (altivec_vmrghsf): Use this insn even
+ on VSX systems.
+ (altivec_vmrglsf): Ditto.
+
+ * config/rs6000/rs6000.h (ASM_CPU_NATIVE_SPEC): Use %(asm_default)
+ if we are running as a cross compiler.
+
+ * config/rs6000/vector.md (vec_interleave_highv4sf): Use correct
+ constants for the extraction.
+ (vec_interleave_lowv4sf): Ditto.
+
+ * config/rs6000/rs6000.md (floordf2): Fix typo, make this a
+ define_expand, not define_insn.
+
+ * config/rs6000/aix53.h (ASM_CPU_SPEC): If -mcpu=native, call
+ %:local_cpu_detect(asm) to get the appropriate assembler flags for
+ the machine.
+ * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto.
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Ditto.
+ (ASM_CPU_NATIVE_SPEC): New spec to get asm options if
+ -mcpu=native.
+ (EXTRA_SPECS): Add ASM_CPU_NATIVE_SPEC.
+
+ * config/rs6000/driver-rs6000.c (asm_names): New static array to
+ give the appropriate asm switches if -mcpu=native.
+ (host_detect_local_cpu): Add support for "asm".
+
+ * config/rs6000/rs6000.c (processor_target_table): Don't turn on
+ -misel by default for power7.
+
+2009-03-02 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_swdivdf): Revert last
+ change, since we reverted the floating multiply/add changes.
+
+ * doc/md.texi (Machine Constraints): Update rs6000 constraints.
+
+ * config/rs6000/vector.md (neg<mode>2): Fix typo to enable
+ vectorized negation.
+ (ftrunc<mode>2): Move ftrunc expander here from altivec.md, and
+ add V2DF case.
+ (vec_interleave_highv4sf): Correct type to be V4SF, not V4SI.
+ (vec_extract_evenv2df): Add expander.
+ (vec_extract_oddv2df): Ditto.
+
+ * config/rs6000/vsx.md (vsx_ftrunc<mode>2): New VSX pattern for
+ truncate.
+ (vsx_ftruncdf2): Ditto.
+ (vsx_xxspltw): New instruction for word splat.
+ (vsx_xxmrglw): Whitespace changes. Fix typo from V4SI to v4SF.
+ (vsx_xxmrghw): Ditto.
+
+ * config/rs6000/altivec.md (altivec_vmrghsf): Whitespace changes.
+ (altivec_vmrglsf): Ditto.
+ (altivec_vspltsf): Disable if we have VSX.
+ (altivec_ftruncv4sf2): Move expander to vector.md, rename insn.
+
+ * config/rs6000/rs6000.md (ftruncdf2): Add expander for VSX.
+
+ * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok):
+ Reenable vectorizing V4SF under altivec.
+ (rs6000_hard_regno_mode_ok): Don't allow floating values in LR,
+ CTR, MQ. Also, VRSAVE/VSCR are both 32-bits.
+ (rs6000_init_hard_regno_mode_ok): Print some of the special
+ registers if -mdebug=reg.
+
+ * config/rs6000/rs6000.md (floating multiply/add insns): Go back
+ to the original semantics for multiply add/subtract, particularly
+ with -ffast-math.
+
+ * config/rs6000/vsx.md (floating multiply/add insns): Mirror the
+ rs6000 floating point multiply/add insns in VSX.
+
+2009-03-01 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (VEC_L): At TImode.
+ (VEC_M): Like VEC_L, except no TImode.
+ (VEC_base): Add TImode support.
+ (mov<mode>): Use VEC_M, not VEC_L. If there is no extra
+ optimization for the move, just generate the standard move.
+ (vector_store_<mode>): Ditto.
+ (vector_load_<mode>): Ditto.
+ (vec_init<mode>): Use vec_init_operand predicate.
+
+ * config/rs6000/predicates.md (vec_init_operand): New predicate.
+
+ * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow mode
+ in a VSX register if there is a move operation.
+ (rs6000_vector_reg_class): Add internal register number to the
+ debug output.
+ (rs6000_init_hard_regno_mode_ok): Reorganize so all of the code
+ for a given type is located together. If not -mvsx, make "ws"
+ constraint become NO_REGS, not FLOAT_REGS. Change -mdebug=reg
+ output.
+ (rs6000_expand_vector_init): Before calling gen_vsx_concat_v2df,
+ make sure the two float arguments are copied into registers.
+ (rs6000_legitimate_offset_address_p): If no vsx or altivec, don't
+ disallow offset addressing. Add V2DImode. If TImode is handled
+ by the vector unit, allow indexed addressing. Change default case
+ to be a fatal_insn instead of gcc_unreachable.
+ (rs6000_handle_altivec_attribute): Add support for vector double
+ if -mvsx.
+ (rs6000_register_move_cost): Add support for VSX_REGS. Know that
+ under VSX, you can move between float and altivec registers
+ cheaply.
+ (rs6000_emit_swdivdf): Change the pattern of the negate multiply
+ and subtract operation.
+
+ * config/rs6000/vsx.md (VSX_I): Add TImode.
+ (VSX_L): Add TImode.
+ (VSm): Ditto.
+ (VSs): Ditto.
+ (VSr): Ditto.
+ (UNSPEC_VSX_CONCAT_V2DF): New constant.
+ (vsx_fre<mode>2): Add reciprocal estimate.
+ (vsx_freDF2): Ditto.
+ (vsx_fnmadd<mode>4): Rework pattern so it matches the
+ canonicalization that the compiler does.
+ (vsx_fnmsub<mode>4): Ditto.
+ (vsx_fnmaddDF4): Ditto.
+ (vsx_fnmsubDF4): Ditto.
+ (vsx_vsel<mode>): Use vsx_register_operand, not register_operand.
+ (vsx_adddf3): Ditto.
+ (vsx_subdf3): Ditto.
+ (vsx_muldf3): Ditto.
+ (vsx_divdf3): Ditto.
+ (vsx_negdf3): Ditto.
+ (vsx_absdf2): Ditto.
+ (vsx_nabsdf2): Ditto.
+ (vsx_copysign<mode>3): Add copysign support.
+ (vsx_copysignDF3): Ditto.
+ (vsx_concat_v2df): Rewrite to use an UNSPEC.
+ (vsx_set_v2df): Use "ws" constraint for scalar float.
+ (vsx_splatv2df): Ditto.
+
+ * config/rs6000/rs6000.h (VECTOR_UNIT_NONE_P): New macro to say no
+ vector support.
+ (VECTOR_MEM_NONE_P): Ditto.
+ (VSX_MOVE_MODE): Add V2DImode, TImode.
+
+ * config/rs6000/altivec.md (VM): Add V2DI, TI.
+ (build_vector_mask_for_load): Fix thinko in VSX case.
+
+ * config/rs6000/rs6000.md (fmaddsf4_powerpc): Name previously
+ unnamed pattern. Fix insns so combine will generate the negative
+ multiply and subtract operations.
+ (fmaddsf4_power): Ditto.
+ (fmsubsf4_powerpc): Ditto.
+ (fmsubsf4_power): Ditto.
+ (fnmaddsf4_powerpc): Ditto.
+ (fnmaddsf4_power): Ditto.
+ (fnmsubsf4_powerpc): Ditto.
+ (fnmsubsf4_power): Ditto.
+ (fnsubsf4_powerpc2): Ditto.
+ (fnsubsf4_power2): Ditto.
+ (fmadddf4_powerpc): Ditto.
+ (fmadddf4_power): Ditto.
+ (fmsubdf4_powerpc): Ditto.
+ (fmsubdf4_power): Ditto.
+ (fnmadddf4_powerpc): Ditto.
+ (fnmadddf4_power): Ditto.
+ (fnmsubdf4_powerpc): Ditto.
+ (fnmsubdf4_power): Ditto.
+ (copysigndf3): If VSX, call the VSX copysign.
+ (fred): Split into an expander and insn. On insn, disable if
+ VSX.
+ (movdf_hardfloat32): Rework VSX support.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_hardfloat64): Ditto.
+ (movti_ppc64): If vector unit is handling TImode, disable this
+ pattern.
+
+2009-02-28 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/ppc-asm.h: If __VSX__ define the additional scalar
+ floating point registers that overlap with th Altivec registers.
+
+2009-02-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/spe.md (spe_fixuns_truncdfsi2): Rename from
+ fixuns_truncdfsi2, and move fixuns_truncdfsi2 into rs6000.md.
+
+ * config/rs6000/ppc-asm.h: If __ALTIVEC__ is defined, define the
+ Altivec registers. If __VSX__ is defined, define the VSX
+ registers.
+
+ * config/rs6000/rs6000.opt (-mvsx-scalar-double): Make this on by
+ default.
+ (-misel): Make this a target mask instead of a variable.
+
+ * config/rs6000/rs6000.c (rs6000_isel): Delete global variable.
+ (rs6000_explicit_options): Delete isel field.
+ (POWERPC_MASKS): Add MASK_ISEL.
+ (processor_target_table): Add MASK_ISEL to 8540, 8548, e500mc, and
+ power7 processors.
+ (rs6000_override_options): Move -misel to a target mask.
+ (rs6000_handle_option): Ditto.
+ (rs6000_emit_int_cmove): Add support for 64-bit isel.
+
+ * config/rs6000/vsx.md (vsx_floatdidf2): New scalar floating point
+ pattern to support VSX conversion and rounding instructions.
+ (vsx_floatunsdidf2): Ditto.
+ (vsx_fix_trundfdi2): Ditto.
+ (vsx_fixuns_trundfdi2): Ditto.
+ (vsx_btrundf2): Ditto.
+ (vsx_floordf2): Ditto.
+ (vsx_ceildf2): Ditto.
+
+ * config/rs6000/rs6000.h (rs6000_isel): Delete global.
+ (TARGET_ISEL): Delete, since -misel is now a target mask.
+ (TARGET_ISEL64): New target option for -misel on 64-bit systems.
+
+ * config/rs6000/altivec.md (altivec_gtu<mode>): Use gtu, not geu.
+
+ * config/rs6000/rs6000.md (sel): New mode attribute for 64-bit
+ ISEL support.
+ (mov<mode>cc): Add 64-bit ISEL support.
+ (isel_signed_<mode>): Ditto.
+ (isel_unsigned_<mode>): Ditto.
+ (fixuns_truncdfsi2): Move expander here from spe.md.
+ (fixuns_truncdfdi2): New expander for unsigned floating point
+ conversion on power7.
+ (btruncdf2): Split into expander and insn. On the insn, disallow
+ on VSX, so the VSX instruction will be generated.
+ (ceildf2): Ditto.
+ (floordf2): Ditto.
+ (floatdidf2): Ditto.
+ (fix_truncdfdi2): Ditto.
+ (smindi3): Define if we have -misel on 64-bit systems.
+ (smaxdi3): Ditto.
+ (umindi3): Ditto.
+ (umaxdi3): Ditto.
+
+ * config/rs6000/e500.h (CHECK_E500_OPTIONS): Disable -mvsx on
+ E500.
+
+2009-02-26 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/constraints.md ("wd" constraint): Change the
+ variable that holds the register class to use.
+ ("wf" constraint): Ditto.
+ ("ws" constraint): Ditto.
+ ("wa" constraint): Ditto.
+
+ * config/rs6000/rs6000.opt (-mvsx-vector-memory): Make this on by
+ default.
+ (-mvsx-vector-float): Ditto.
+
+ * config/rs6000/rs6000.c (rs6000_vector_reg_class): New global to
+ hold the register classes for the vector modes.
+ (rs6000_vsx_v4sf_regclass): Delete, move into
+ rs6000_vector_reg_class.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_reg_class): Rename from rs6000_vsx_any_regclass.
+ (rs6000_hard_regno_mode_ok): Rework VSX, Altivec registers.
+ (rs6000_init_hard_regno_mode_ok): Setup rs6000_vector_reg_class.
+ Drop rs6000_vsx_*_regclass. By default, use all 64 registers for
+ V4SF and V2DF. Use VSX_REG_CLASS_P macro instead of separate
+ tests. Update -mdebug=reg printout.
+ (rs6000_preferred_reload_class): If VSX, prefer FLOAT_REGS for
+ scalar floating point and ALTIVEC_REGS for the types that have
+ altivec instructions.
+ (rs6000_secondary_memory_needed): If VSX, we can copy between FPR
+ and Altivec registers without needed memory.
+ (rs6000_secondary_reload_class): Delete ATTRIBUTE_UNUSED from an
+ argument that is used. If VSX, we can copy between FPR and
+ Altivec registers directly.
+
+ * config/rs6000/rs6000.h (VSX_MOVE_MODE): Add in the Altivec
+ types.
+ (rs6000_vsx_v4sf_regclass): Delete.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_reg_class): Rename from rs6000_vsx_any_reg_class.
+ (rs6000_vector_reg_class): New global to map machine mode to the
+ preferred register class to use for that mode.
+ (VSX_REG_CLASS_P): New macro to return true for all of the
+ register classes VSX items can be in.
+
+2009-02-25 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mvsx-vector-memory): Rename from
+ -mvsx-vector-move.
+ (-mvsx-vector-logical): Delete.
+
+ * config/rs6000/aix53.h (ASM_CPU_SPEC): Add power7 support.
+ * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto.
+
+ * config/rs6000/vector.md (all insns); Change from using
+ rs6000_vector_info to VECTOR_MEM_* or VECTOR_UNIT_* macros.
+
+ * config/rs6000/constraints.md ("wi" constraint): Delete.
+ ("wl" constraint): Ditto.
+ ("ws" constraint): Change to use rs6000_vsx_df_regclass.
+
+ * config/rs6000/rs6000.opt (-mvsx-vector-memory): Rename from
+ -mvsx-vector-move.
+ (-mvsx-vector-float): Make default 0, not 1.
+ (-mvsx-vector-double): Make default -1, not 1.
+ (-mvsx-vector-logical): Delete.
+
+ * config/rs6000/rs6000.c (rs6000_vector_info): Delete.
+ (rs6000_vector_unit): New global array to say what vector unit is
+ used for arithmetic instructions.
+ (rs6000_vector_move): New global array to say what vector unit is
+ used for memory references.
+ (rs6000_vsx_int_regclass): Delete.
+ (rs6000_vsx_logical_regclass): Delete.
+ (rs6000_hard_regno_nregs_internal): Switch from using
+ rs6000_vector_info to rs6000_vector_unit, rs6000_vector_move.
+ (rs6000_hard_regno_mode_ok): Ditto. Reformat code somewhat.
+ (rs6000_debug_vector_unit): New array to print vector unit
+ information if -mdebug=reg.
+ (rs6000_init_hard_regno_mode_ok): Rework to better describe VSX
+ and Altivec register sets.
+ (builtin_mask_for_load): Return 0 if -mvsx.
+ (rs6000_legitimize_reload_address): Allow AND in VSX addresses.
+ (rs6000_legitimate_address): Ditto.
+ (bdesc_3arg): Delete vselv2di builtin.
+ (rs6000_emit_minmax): Use rs6000_vector_unit instead of
+ rs6000_vector_info.
+ (rs6000_vector_mode_supported_p): Ditto.
+
+ * config/rs6000/vsx.md (all insns): Change from using
+ rs6000_vector_info to VECTOR_MEM_* and VECTOR_UNIT_* macros.
+ (VSr): Change to use "v" register class, not "wi".
+ (vsx_mov<mode>): Combine floating and integer. Allow prefered
+ register class, and then use ?wa for all VSX registers.
+ (vsx_fmadddf4): Use ws constraint, not f.
+ (vsx_fmsubdf4): Ditto.
+ (vsx_fnmadddf4): Ditto.
+ (vsx_fnmsubdf4): Ditto.
+ (vsx_and<mode>3): Use preferred register class, and then ?wa to
+ catch all VSX registers.
+ (vsx_ior<mode>3): Ditto.
+ (vsx_xor<mode>3): Ditto.
+ (vsx_one_cmpl<mode>2): Ditto.
+ (vsx_nor<mode>3): Ditto.
+ (vsx_andc<mode>3): Ditto.
+
+ * config/rs6000/rs6000.h (rs6000_vector_struct): Delete.
+ (rs6000_vector_info): Ditto.
+ (rs6000_vector_unit): New global array to say whether a machine
+ mode arithmetic is handled by a particular vector unit.
+ (rs6000_vector_mem): New global array to say which vector unit to
+ use for moves.
+ (VECTOR_UNIT_*): New macros to say which vector unit to use.
+ (VECTOR_MEM_*): Ditto.
+ (rs6000_vsx_int_regclass): Delete.
+ (rs6000_vsx_logical_regclass): Delete.
+
+ * config/rs6000/altivec.md (all insns): Change from using
+ rs6000_vector_info to VECTOR_MEM_* and VECTOR_UNIT_* macros.
+ (build_vector_mask_for_load): Disable if VSX.
+
+ * config/rs6000/rs6000.md (all DF insns): Change how the VSX
+ exclusion is done.
+
+2009-02-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_debug_reg): New global.
+ (rs6000_debug_reg_print): New function to print register classes
+ for a given register range.
+ (rs6000_init_hard_regno_mode_ok): If -mdebug=reg, print out the
+ register class, call used, fixed information for most of the
+ registers. Print the vsx register class variables.
+ (rs6000_override_options): Add -mdebug=reg support.
+
+ * config/rs6000/rs6000.h (rs6000_debug_reg): New global.
+ (TARGET_DEBUG_REG): New target switch for -mdebug=reg.
+
+2009-02-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * reload.c (subst_reloads): Change gcc_assert into a fatal_insn.
+
+ * config/rs6000/vector.md (VEC_I): Reorder iterator.
+ (VEC_L): Ditto.
+ (VEC_C): New iterator field for vector comparisons.
+ (VEC_base): New mode attribute that mapes the vector type to the
+ base type.
+ (all insns): Switch to use rs6000_vector_info to determine whether
+ the insn is valid instead of using TARGET_VSX or TARGET_ALTIVEC.
+ (vcond<mode>): Move here from altivec, and add VSX support.
+ (vcondu<mode>): Ditto.
+ (vector_eq<mode>): New expander for vector comparisons.
+ (vector_gt<mode>): Ditto.
+ (vector_ge<mode>): Ditto.
+ (vector_gtu<mode>): Ditto.
+ (vector_geu<mode>): Ditto.
+ (vector_vsel<mode>): New expander for vector select.
+ (vec_init<mode>): Move expander from altivec.md and generalize for
+ VSX.
+ (vec_set<mode>): Ditto.
+ (vec_extract<mode>): Ditto.
+ (vec_interleave_highv4sf): Ditto.
+ (vec_interleave_lowv4sf): Ditto.
+ (vec_interleave_highv2df): New expander for VSX.
+ (vec_interleave_lowv2df): Ditto.
+
+ * config/rs6000/contraints.md (toplevel): Add comment on the
+ available constraint letters.
+ ("w" constraint): Delete, in favor of using "w" as a two letter
+ constraint.
+ ("wd" constraint): New VSX constraint.
+ ("wf" constraint): Ditto.
+ ("wi" constraint): Ditto.
+ ("wl" constraint): Ditto.
+ ("ws" constraint): Ditto.
+ ("wa" constraint): Ditto.
+
+ * config/rs6000/predicates.md (indexed_or_indirect_operand):
+ Disable altivec support allowing AND of memory address if -mvsx.
+
+ * config/rs6000/rs6000.opt (-mvsx-vector-move): New switches to
+ allow finer control over whether VSX, Altivec, or the traditional
+ instructions are used.
+ (-mvsx-scalar-move): Ditto.
+ (-mvsx-vector-float): Ditto.
+ (-mvsx-vector-double): Ditto.
+ (-mvsx-vector-logical): Ditto.
+ (-mvsx-scalar-double): Ditto.
+
+ * config/rs6000/rs6000.c (rs6000_vector_info): New global to hold
+ various information about which vector instruction set to use, and
+ the alignment of data.
+ (rs6000_vsx_v4sf_regclass): New global to hold VSX register
+ class.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_int_regclass): Ditto.
+ (rs6000_vsx_logical_regclass): Ditto.
+ (rs6000_vsx_any_regclass): Ditto.
+ (rs6000_hard_regno_nregs_internal): Rewrite to fine tune
+ VSX/Altivec register selection.
+ (rs6000_hard_regno_mode_ok): Ditto.
+ (rs6000_init_hard_regno_mode_ok): Set up the vector information
+ globals based on the -mvsx-* switches.
+ (rs6000_override_options): Add warnings for -mvsx and
+ -mlittle-endian or -mavoid-indexed-addresses.
+ (rs6000_builtin_vec_perm): Add V2DF/V2DI support.
+ (rs6000_expand_vector_init): Add V2DF support.
+ (rs6000_expand_vector_set): Ditto.
+ (rs6000_expand_vector_extract): Ditto.
+ (avoiding_indexed_address_p): Add VSX support.
+ (rs6000_legitimize_address): Ditto.
+ (rs6000_legitimize_reload_address): Ditto.
+ (rs6000_legitimite_address): Ditto.
+ (USE_ALTIVEC_FOR_ARG_P): Ditto.
+ (function_arg_boundary): Ditto.
+ (function_arg_advance): Ditto.
+ (function_arg): Ditto.
+ (get_vec_cmp_insn): Delete.
+ (rs6000_emit_vector_vsx): New function for VSX vector compare.
+ (rs6000_emit_vector_altivec): New function for Altivec vector
+ compare.
+ (get_vsel_insn): Delete.
+ (rs6000_emit_vector_select): Ditto.
+ (rs6000_override_options): If -mvsx, turn on -maltivec by
+ default.
+ (rs6000_builtin_vec_perm): Add support for V2DI, V2DF modes.
+ (bdesc_3arg): Add vector select and vector permute builtins for
+ V2DI and V2DF types. Switch to using the vector_* expander
+ instead of altivec_*.
+ (rs6000_init_builtins): Initialize new type nodes for VSX.
+ Initialize __vector double type. Initialize common builtins for
+ VSX.
+ (rs6000_emit_vector_compare): Add VSX support.
+ (rs6000_vector_mode_supported_p): If VSX, support V2DF.
+
+ * config/rs6000/vsx.md (VSX_I): New iterator for integer modes.
+ (VSX_L): Reorder iterator.
+ (lx_<mode>_vsx): Delete, no longer needed.
+ (stx_<mode>_vsx): Ditto.
+ (all insns): Change to use vsx_<name> instead of <name>_vsx for
+ consistancy with the other rs6000 md files. Change to use the new
+ "w" constraints for all insns. Change to use rs6000_vector_info
+ deciding whether to execute the instruction or not.
+ (vsx_mov<mode>): Rewrite constraints so GPR registers are not
+ chosen as reload targets. Split integer vector loads into a
+ separate insn, and favor the altivec register over the VSX fp
+ registers.
+ (vsx_fmadd<mode>4): Use <mode>, not <type>.
+ (vsx_fmsub<mode>4): Ditto.
+ (vsx_eq<mode>): New insns for V2DF/V4SF vector compare.
+ (vsx_gt<mode>): Ditto.
+ (vsx_ge<mode>): Ditto.
+ (vsx_vsel<mode>): New insns for VSX vector select.
+ (vsx_xxpermdi): New insn for DF permute.
+ (vsx_splatv2df): New insn for DF splat support.
+ (vsx_xxmrglw): New insns for DF interleave.
+ (vsx_xxmrghw): Ditto.
+
+ * config/rs6000/rs000.h (enum rs6000_vector): New enum to
+ describe which vector unit is being used.
+ (struct rs6000_vector_struct): New struct to describe the various
+ aspects about the current vector instruction set.
+ (rs6000_vector_info): New global to describe the current vector
+ instruction set.
+ (SLOW_UNALIGNED_ACCESS): If rs6000_vector_info has alignment
+ information for a type, use that.
+ (VSX_VECTOR_MOVE_MODE): New macro for all VSX vectors that are
+ supported by move instructions.
+ (VSX_MOVE_MODE): New macro for all VSX moves.
+ (enum rs6000_builtins): Add V2DI/V2DF vector select and permute
+ builtins.
+ (rs6000_builtin_type_index): Add new types for VSX vectors.
+ (rs6000_vsx_v4sf_regclass): New global to hold VSX register
+ class.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_int_regclass): Ditto.
+ (rs6000_vsx_logical_regclass): Ditto.
+ (rs6000_vsx_any_regclass): Ditto.
+
+ * config/rs6000/altivec.md (UNSPEC_VCMP*): Delete unspec
+ constants no longer needed.
+ (UNSPEC_VSEL*): Ditto.
+ (altivec_lvx_<mode>): Delete, no longer needed.
+ (altivec_stvx_<mode>): Ditto.
+ (all insns): Rewrite to be consistant of altivec_<insn>. Switch
+ to use rs6000_vector_info to determine whether to issue to the
+ altivec form of the instructions.
+ (mov<mode>_altivec): Rewrite constraints so GPR registers are not
+ chosen as reload targets.
+ (altivec_eq<mode>): Rewrite vector conditionals, permute, select
+ to use iterators, and work with VSX.
+ (altivec_gt<mode>): Ditto.
+ (altivec_ge<mode>): Ditto.
+ (altivec_gtu<mode>): Ditto.
+ (altivec_geu<mode>): Ditto.
+ (altivec_vsel<mode>): Ditto.
+ (altivec_vperm_<mode>): Ditto.
+ (altivec_vcmp*): Rewrite to not use unspecs any more, and use mode
+ iterators, add VSX support.
+ (vcondv4si): Move to vector.md.
+ (vconduv4si): Ditto.
+ (vcondv8hi): Ditto.
+ (vconduv8hi): Ditto.
+ (vcondv16qi): Ditto.
+ (vconduv16qi): Ditto.
+
+ * config/rs6000/rs6000.md (negdf2_fpr): Add support for
+ -mvsx-scalar-double.
+ (absdf2_fpr): Ditto.
+ (nabsdf2_fpr): Ditto.
+ (adddf3_fpr): Ditto.
+ (subdf3_fpr): Ditto.
+ (muldf3_fpr): Ditto.
+ (divdf3_fpr): Ditto.
+ (DF multiply/add patterns): Ditto.
+ (sqrtdf2): Ditto.
+ (movdf_hardfloat32): Add VSX support.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_hardfloat64): Ditto.
+
+ * doc/invoke.texi (-mvsx-*): Add new vsx switches.
+
+2009-02-13 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config.in: Update two comments.
+
+ * config/rs6000/vector.md (VEC_L): Add V2DI type.
+ (move<mode>): Use VEC_L to get all vector types, and delete the
+ separate integer mode move definitions.
+ (vector_load_<mode>): Ditto.
+ (vector_store_<mode>): Ditto.
+ (vector move splitters): Move GPR register splitters here from
+ altivec.md.
+
+ * config/rs6000/constraints.md ("j"): Add "j" constraint to match
+ the mode's 0 value.
+
+ * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Only
+ count the FPRs as being 128 bits if the mode is a VSX type.
+ (rs6000_hard_regno_mode_ok): Ditto.
+ (rs6000_emit_minmax): Use new VSX_MODE instead of separate tests.
+
+ * config/rs6000/vsx.md (VSX_L): Add V2DImode.
+ (VSm): Rename from VSX_mem, add modes for integer vectors. Change
+ all uses.
+ (VSs): Rename from VSX_op, add modes for integer vectors. Change
+ all uses.
+ (VSr): New mode address to give the register class.
+ (mov<mode>_vsx): Use VSr to get the register preferences. Add
+ explicit 0 option.
+ (scalar double precision patterns): Do not use v register
+ constraint right now.
+ (logical patterns): Use VSr mode attribute for register
+ preferences.
+
+ * config/rs6000/rs6000.h (VSX_SCALAR_MODE): New macro.
+ (VSX_MODE): Ditto.
+
+ * config/rs6000/altivec.md (VM): New mode iterator for memory
+ operations. Add V2DI mode.
+ (mov_altivec_<mode>): Disable if -mvsx for all modes, not just
+ V4SFmode.
+ (gpr move splitters): Move to vector.md.
+ (and<mode>3_altivec): Use VM mode iterator, not V.
+ (ior<mode>3_altivec): Ditto.
+ (xor<mode>3_altivec): Ditto.
+ (one_cmpl<mode>2_altivec): Ditto.
+ (nor<mode>3_altivec): Ditto.
+ (andc<mode>3_altivec): Ditto.
+
+ * config/rs6000/rs6000.md (movdf_hardfloat): Back out vsx changes.
+ (movdf_hardfloat64_vsx): Delete.
+
+2009-02-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md: New file to abstract out the expanders
+ for vector operations from alitvec.md.
+
+ * config/rs6000/predicates.md (vsx_register_operand): New
+ predicate to match VSX registers.
+ (vfloat_operand): New predicate to match registers used for vector
+ floating point operations.
+ (vint_operand): New predicate to match registers used for vector
+ integer operations.
+ (vlogical_operand): New predicate to match registers used for
+ vector logical operations.
+
+ * config/rs6000/rs6000-protos.h (rs6000_hard_regno_nregs): Change
+ from a function to an array.
+ (rs6000_class_max_nregs): Add declaration.
+
+ * config/rs6000/t-rs6000 (MD_INCLUDES): Define to include all of
+ the .md files included by rs6000.md.
+
+ * config/rs6000/rs6000.c (rs6000_class_max_nregs): New global
+ array to pre-calculate CLASS_MAX_NREGS.
+ (rs6000_hard_regno_nregs): Change from a function to an array to
+ pre-calculate HARD_REGNO_NREGS.
+ (rs6000_hard_regno_nregs_internal): Rename from
+ rs6000_hard_regno_nregs and add VSX support.
+ (rs6000_hard_regno_mode_ok): Add VSX support, and switch to use
+ lookup table rs6000_hard_regno_nregs.
+ (rs6000_init_hard_regno_mode_ok): Add initialization of
+ rs6000_hard_regno_nregs, and rs6000_class_max_nregs global
+ arrays.
+ (rs6000_override_options): Add some warnings for things that are
+ incompatible with -mvsx.
+ (rs6000_legitimate_offset_address_p): Add V2DFmode.
+ (rs6000_conditional_register_usage): Enable altivec registers if
+ -mvsx.
+ (bdesc_2arg): Change the name of the nor pattern.
+ (altivec_expand_ld_builtin): Change the names of the load
+ patterns to be the generic vector loads.
+ (altivec_expand_st_builtin): Change the names of the store
+ patterns to be the generic vector stores.
+ (print_operand): Add 'x' to print out a VSX register properly.
+ (rs6000_emit_minmax): Directly emit the min/max patterns for VSX
+ and Altivec.
+
+ * config/rs6000/vsx.md: New file to add all of the VSX specific
+ instructions. Add support for load, store, move, add, subtract,
+ multiply, multiply/add, divide, negate, absolute value, maximum,
+ minimum, sqrt, and, or, xor, and complent, xor, one's complement,
+ and nor instructions.
+
+ * config/rs6000/rs6000.h (UNITS_PER_VSX_WORD): Define.
+ (VSX_REGNO_P): New macro for VSX registers.
+ (VFLOAT_REGNO): New macro for vector floating point registers.
+ (VINT_REGNO): New macro for vector integer registers.
+ (VLOGICAL_REGNO): New macro for vector logical registers.
+ (VSX_VECTOR_MODE): New macro for vector modes supported by VSX.
+ (HARD_REGNO_NREGS): Switch to using pre-computed table.
+ (CLASS_MAX_NREGS): Ditto.
+
+ * config/rs6000/altivec.md (altivec_lvx_<mode>): Delete, repalced
+ by expanders in vector.md.
+ (altivec_stvx_<mode>): Ditto.
+ (mov<mode>): Ditto.
+ (mov_altivec_<mode>): Rename from mov<mode>_internal, and prefer
+ using VSX if available.
+ (addv4sf3_altivec): Rename from standard name, and prefer using
+ VSX if available.
+ (subv4sf3_altivec): Ditto.
+ (mulv4sf3_altivec): Ditto.
+ (smaxv4sf3_altivec): Ditto.
+ (sminv4sf3_altivec): Ditto.
+ (and<mode>3_altivec): Ditto.
+ (ior<mode>3_altivec): Ditto.
+ (xor<mode>3_altivec): Ditto.
+ (one_cmpl<mode>2): Ditto.
+ (nor<mode>3_altivec): Ditto.
+ (andc<mode>3_altivec): Ditto.
+ (absv4sf2_altivec): Ditto.
+ (vcondv4sf): Move to vector.md.
+
+ * config/rs6000/rs6000.md (negdf2_fpr): Add !TARGET_VSX to prefer
+ the version in vsx.md if -mvsx is available.
+ (absdf2_fpr): Ditto.
+ (nabsdf2_fpr): Ditto.
+ (adddf3_fpr): Ditto.
+ (subdf3_fpr): Ditto.
+ (muldf3_fpr): Ditto.
+ (multiply/add patterns): Ditto.
+ (movdf_hardfloat64): Disable if -mvsx.
+ (movdf_hardfloat64_vsx): Clone from movdf_hardfloat64 and add VSX
+ support.
+ (vector.md): Include new .md file.
+ (vsx.md): Ditto.
+
+2009-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mvsx, -mno-vsx): Document new switches.
+
+ * config/rs6000/linux64.opt (-mprofile-kernel): Move to being a
+ variable to reduce the number of target flag bits.
+ * config/rs6000/sysv4.opt (-mbit-align): Ditto.
+ (-mbit-word): Ditto.
+ (-mregnames): Ditto.
+ * config/rs6000/rs6000.opt (-mupdate, -mno-update): Ditto.
+ (-mvsx): New switch, enable VSX support.
+
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
+ __VSX__ if the vector/scalar instruction set is available.
+
+ * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Change
+ to allow -mprofile-kernel to be a variable.
+
+ * config/rs6000/rs6000.c (processor_target_table): Set -mvsx for
+ power7 cpus.
+ (POWERPC_MASKS): Add -mvsx.
+
+ * config/rs6000/rs6000.h (ADDITIONAL_REGISTER_NAMES): Add VSX
+ register names for the registers that overlap with the floating
+ point and altivec registers.
+
+ * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS):
+ TARGET_NO_BITFIELD_WORD is now a variable, not a target mask.
+
+2009-02-11 Pat Haugen <pthaugen@us.ibm.com>
+ Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mpopcntd, -mno-popcntd): Document new
+ switches.
+
+ * configure.ac (powerpc*-*-*): Test for the assembler having the
+ popcntd instruction.
+ * configure: Regenerate.
+ * config.in (HAVE_AS_POPCNTD): Add default value for configure
+ test.
+
+ * config/rs6000/power7.md: New file.
+
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
+ _ARCH_PWR7 if the popcntd instruction is available.
+
+ * config/rs6000/rs6000.opt (-mpopcntd): New switch to
+ enable/disable the use of the popcntd and popcntw instructions.
+ (-mfused-madd, -mno-fused-madd): Move to being a separate variable
+ because we are out of mask bits.
+
+ * config/rs6000/rs6000.c (power7_cost): Define.
+ (rs6000_override_options): Add Power7 support.
+ (rs6000_issue_rate): Ditto.
+ (insn_must_be_first_in_group): Ditto.
+ (insn_must_be_last_in_group): Ditto.
+ (rs6000_emit_popcount): Add support for using the popcntw and
+ popcntd instructions.
+
+ * config/rs6000/rs6000.h (ASM_CPU_POWER7_SPEC): Switch to using
+ popcntd as the test for a power7 assembler instead of vector
+ scalar instructions.
+ * (TARGET_POPCNTD): If assembler does not support the popcntd
+ instruction, disable using it.
+ (processor_type): Add Power7 entry.
+
+ * config/rs6000/rs6000.md (define_attr "cpu"): Add power7.
+ (power7.md): Include it.
+ (andi./andis./nor. patterns): Change insn type to fast_compare.
+ (popcntwsi2): Add popcntw support.
+ (popcntddi2): Add popcntd support.
+
+testsuite/
+2009-03-01 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsx-vector-1.c: Fix typos.
+ * gcc.target/powerpc/vsx-vector-2.c: Ditto.
+
+ * gcc.target/powerpc/vsx-vector-3.c: New file, test __vector
+ double.
+
+ * gcc.target/powerpc/vsx-vector-4.c: New file, test __vector float
+ uses VSX instructions if -mvsx.
+
+ * gcc.dg/vmx/vmx.exp (DEFAULT_VMXCLFAGS): Add -mno-vsx.
+
+ * lib/target-supports.exp (check_vsx_hw_available): New function
+ to test for VSX.
+ (check_vmx_hw_available): Add -mno-vsx to options.
+ (check_effective_target_powerpc_vsx_ok): New function to check if
+ the powerpc compiler can support VSX.
+
+2009-02-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsx-vector-1.c: New file to test VSX code
+ generation.
+ * gcc.target/powerpc/vsx-vector-2.c: Ditto.
+
+2009-02-01 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/popcount-2.c: New file for power7 support.
+ * gcc.target/powerpc/popcount-3.c: Ditto.
+
+--- gcc/doc/invoke.texi (.../trunk) (revision 144557)
++++ gcc/doc/invoke.texi (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -712,7 +712,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
+@@ -726,7 +727,9 @@ 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 -mvsx -mvsx-vector-memory @gol
++-mvsx-vector-float -mvsx-vector-double @gol
++-mvsx-scalar-double -mvsx-scalar-memory @gol
+ -mprioritize-restricted-insns=@var{priority} @gol
+ -msched-costly-dep=@var{dependence_type} @gol
+ -minsert-sched-nops=@var{scheme} @gol
+@@ -13512,6 +13515,8 @@ These @samp{-m} options are defined for
+ @itemx -mno-mfcrf
+ @itemx -mpopcntb
+ @itemx -mno-popcntb
++@itemx -mpopcntd
++@itemx -mno-popcntd
+ @itemx -mfprnd
+ @itemx -mno-fprnd
+ @itemx -mcmpb
+@@ -13536,6 +13541,8 @@ These @samp{-m} options are defined for
+ @opindex mno-mfcrf
+ @opindex mpopcntb
+ @opindex mno-popcntb
++@opindex mpopcntd
++@opindex mno-popcntd
+ @opindex mfprnd
+ @opindex mno-fprnd
+ @opindex mcmpb
+@@ -13585,6 +13592,9 @@ The @option{-mpopcntb} option allows GCC
+ 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.
+@@ -13663,9 +13673,9 @@ The @option{-mcpu} options automatically
+ 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
+@@ -13766,6 +13776,44 @@ 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 -mvsx-vector-memory
++@itemx -mno-vsx-vector-memory
++If @option{-mvsx}, use VSX memory reference instructions for vectors
++instead of the Altivec instructions This option is a temporary switch
++to tune the compiler, and may not be supported in future versions.
++
++@item -mvsx-vector-float
++@itemx -mno-vsx-vector-float
++If @option{-mvsx}, use VSX arithmetic instructions for float vectors.
++This option is a temporary switch to tune the compiler, and may not be
++supported in future versions.
++
++@item -mvsx-vector-double
++@itemx -mno-vsx-vector-double
++If @option{-mvsx}, use VSX arithmetic instructions for double
++vectors. This option is a temporary switch to tune the
++compiler, and may not be supported in future versions.
++
++@item -mvsx-scalar-double
++@itemx -mno-vsx-scalar-double
++If @option{-mvsx}, use VSX arithmetic instructions for scalar double.
++This option is a temporary switch to tune the compiler, and may not be
++supported in future versions.
++
++@item -mvsx-scalar-memory
++@itemx -mno-vsx-scalar-memory
++If @option{-mvsx}, use VSX memory reference instructions for scalar
++double. This option is a temporary switch to tune the compiler, and
++may not be supported in future versions.
++
+ @item -mfloat-gprs=@var{yes/single/double/no}
+ @itemx -mfloat-gprs
+ @opindex mfloat-gprs
+--- gcc/doc/md.texi (.../trunk) (revision 144557)
++++ gcc/doc/md.texi (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -1905,7 +1905,19 @@ Address base register
+ Floating point register
+
+ @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
+@@ -1991,6 +2003,9 @@ AND masks that can be performed by two r
+ @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}
+--- gcc/reload.c (.../trunk) (revision 144557)
++++ gcc/reload.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -6255,8 +6255,14 @@ subst_reloads (rtx insn)
+ *r->where = reloadreg;
+ }
+ /* If reload got no reg and isn't optional, something's wrong. */
+- else
+- gcc_assert (rld[r->what].optional);
++ else if (!rld[r->what].optional)
++ {
++ char buffer[100];
++ sprintf (buffer,
++ "unable to find register for reload, replacement #%d",
++ i);
++ fatal_insn (buffer, insn);
++ }
+ }
+ }
+ \f
+--- gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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);
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,74 @@
++/* { 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" } } */
++
++#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];
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,74 @@
++/* { 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" } } */
++
++#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];
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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;
++}
+--- gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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);
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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;
++}
+--- gcc/testsuite/gcc.dg/vmx/vmx.exp (.../trunk) (revision 144557)
++++ gcc/testsuite/gcc.dg/vmx/vmx.exp (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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
+--- gcc/testsuite/lib/target-supports.exp (.../trunk) (revision 144557)
++++ gcc/testsuite/lib/target-supports.exp (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -873,6 +873,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.
+
+@@ -883,12 +909,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()
+@@ -1519,6 +1546,33 @@ proc check_effective_target_powerpc_alti
+ }
+ }
+
++# 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 { } {
+--- gcc/config.in (.../trunk) (revision 144557)
++++ gcc/config.in (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -334,12 +334,18 @@
+ #endif
+
+
+-/* Define if your assembler supports popcntb field. */
++/* Define if your assembler supports popcntb instruction. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_AS_POPCNTB
+ #endif
+
+
++/* Define if your assembler supports popcntd instruction. */
++#ifndef USED_FOR_TARGET
++#undef HAVE_AS_POPCNTD
++#endif
++
++
+ /* Define if your assembler supports .register. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_AS_REGISTER_PSEUDO_OP
+--- gcc/configure.ac (.../trunk) (revision 144557)
++++ gcc/configure.ac (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -2,7 +2,7 @@
+ # Process this file with autoconf to generate a configuration script.
+
+ # Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+-# 2007, 2008 Free Software Foundation, Inc.
++# 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ #This file is part of GCC.
+
+@@ -3080,7 +3080,7 @@ foo: nop
+ esac
+
+ gcc_GAS_CHECK_FEATURE([move fp gpr support],
+- gcc_cv_as_powerpc_mfpgpr, [9,99,0],,
++ gcc_cv_as_powerpc_mfpgpr, [2,19,2],,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_MFPGPR, 1,
+ [Define if your assembler supports mffgpr and mftgpr.])])
+@@ -3114,7 +3114,7 @@ LCF0:
+ esac
+
+ gcc_GAS_CHECK_FEATURE([compare bytes support],
+- gcc_cv_as_powerpc_cmpb, [9,99,0], -a32,
++ gcc_cv_as_powerpc_cmpb, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_CMPB, 1,
+ [Define if your assembler supports cmpb.])])
+@@ -3129,7 +3129,7 @@ LCF0:
+ esac
+
+ gcc_GAS_CHECK_FEATURE([decimal float support],
+- gcc_cv_as_powerpc_dfp, [9,99,0], -a32,
++ gcc_cv_as_powerpc_dfp, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_DFP, 1,
+ [Define if your assembler supports DFP instructions.])])
+@@ -3144,11 +3144,26 @@ LCF0:
+ esac
+
+ gcc_GAS_CHECK_FEATURE([vector-scalar support],
+- gcc_cv_as_powerpc_vsx, [9,99,0], -a32,
++ gcc_cv_as_powerpc_vsx, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_VSX, 1,
+ [Define if your assembler supports VSX instructions.])])
+
++ case $target in
++ *-*-aix*) conftest_s=' .machine "pwr7"
++ .csect .text[[PR]]
++ popcntd 3,3';;
++ *) conftest_s=' .machine power7
++ .text
++ popcntd 3,3';;
++ esac
++
++ gcc_GAS_CHECK_FEATURE([popcntd support],
++ gcc_cv_as_powerpc_popcntd, [2,19,2], -a32,
++ [$conftest_s],,
++ [AC_DEFINE(HAVE_AS_POPCNTD, 1,
++ [Define if your assembler supports POPCNTD instructions.])])
++
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_powerpc_gnu_attribute, [2,18,0],,
+ [.gnu_attribute 4,1],,
+--- gcc/configure (.../trunk) (revision 144557)
++++ gcc/configure (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -23225,7 +23225,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set}
+ else
+ gcc_cv_as_powerpc_mfpgpr=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_mfpgpr=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23321,7 +23321,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}"
+ else
+ gcc_cv_as_powerpc_cmpb=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_cmpb=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23367,7 +23367,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" =
+ else
+ gcc_cv_as_powerpc_dfp=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_dfp=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23413,7 +23413,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" =
+ else
+ gcc_cv_as_powerpc_vsx=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_vsx=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23443,6 +23443,52 @@ _ACEOF
+
+ fi
+
++ case $target in
++ *-*-aix*) conftest_s=' .machine "pwr7"
++ .csect .text[PR]
++ popcntd 3,3';;
++ *) conftest_s=' .machine power7
++ .text
++ popcntd 3,3';;
++ esac
++
++ echo "$as_me:$LINENO: checking assembler for popcntd support" >&5
++echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6
++if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ gcc_cv_as_powerpc_popcntd=no
++ if test $in_tree_gas = yes; then
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
++ then gcc_cv_as_powerpc_popcntd=yes
++fi
++ elif test x$gcc_cv_as != x; then
++ echo "$conftest_s" > conftest.s
++ if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }
++ then
++ gcc_cv_as_powerpc_popcntd=yes
++ else
++ echo "configure: failed program was" >&5
++ cat conftest.s >&5
++ fi
++ rm -f conftest.o conftest.s
++ fi
++fi
++echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5
++echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6
++if test $gcc_cv_as_powerpc_popcntd = yes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_AS_POPCNTD 1
++_ACEOF
++
++fi
++
+ echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5
+ echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6
+ if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then
+--- gcc/config/rs6000/aix53.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/aix53.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -57,20 +57,24 @@ do { \
+ #undef ASM_SPEC
+ #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
+
+-/* Common ASM definitions used by ASM_SPEC amongst the various targets
+- for handling -mcpu=xxx switches. */
++/* Common ASM definitions used by ASM_SPEC amongst the various targets for
++ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
++ provide the default assembler options if the user uses -mcpu=native, so if
++ you make changes here, make them there also. */
+ #undef ASM_CPU_SPEC
+ #define ASM_CPU_SPEC \
+ "%{!mcpu*: %{!maix64: \
+ %{mpowerpc64: -mppc64} \
+ %{maltivec: -m970} \
+ %{!maltivec: %{!mpower64: %(asm_default)}}}} \
++%{mcpu=native: %(asm_cpu_native)} \
+ %{mcpu=power3: -m620} \
+ %{mcpu=power4: -mpwr4} \
+ %{mcpu=power5: -mpwr5} \
+ %{mcpu=power5+: -mpwr5x} \
+ %{mcpu=power6: -mpwr6} \
+ %{mcpu=power6x: -mpwr6} \
++%{mcpu=power7: -mpwr7} \
+ %{mcpu=powerpc: -mppc} \
+ %{mcpu=rs64a: -mppc} \
+ %{mcpu=603: -m603} \
+--- gcc/config/rs6000/vector.md (.../trunk) (revision 0)
++++ gcc/config/rs6000/vector.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,518 @@
++;; 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.
++;; 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/>.
++
++
++;; Vector int modes
++(define_mode_iterator VEC_I [V16QI V8HI V4SI])
++
++;; Vector float modes
++(define_mode_iterator VEC_F [V4SF V2DF])
++
++;; Vector logical modes
++(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
++
++;; Vector modes for moves. Don't do TImode here.
++(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
++
++;; Vector comparison modes
++(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
++
++;; Base type from vector mode
++(define_mode_attr VEC_base [(V16QI "QI")
++ (V8HI "HI")
++ (V4SI "SI")
++ (V2DI "DI")
++ (V4SF "SF")
++ (V2DF "DF")
++ (TI "TI")])
++
++;; Same size integer type for floating point data
++(define_mode_attr VEC_int [(V4SF "v4si")
++ (V2DF "v2di")])
++
++(define_mode_attr VEC_INT [(V4SF "V4SI")
++ (V2DF "V2DI")])
++
++;; Vector move instructions.
++(define_expand "mov<mode>"
++ [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
++ (match_operand:VEC_M 1 "any_operand" ""))]
++ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ /* modes without special handling just generate the normal SET operation. */
++ if (<MODE>mode != TImode && <MODE>mode != V2DImode && <MODE>mode != V2DFmode)
++ {
++ rs6000_emit_move (operands[0], operands[1], <MODE>mode);
++ DONE;
++ }
++ else if (!vlogical_operand (operands[0], <MODE>mode)
++ && !vlogical_operand (operands[1], <MODE>mode))
++ operands[1] = force_reg (<MODE>mode, operands[1]);
++})
++
++;; 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_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_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_OR_VSX_P (<MODE>mode)
++ && reload_completed
++ && gpr_or_gpr_p (operands[0], operands[1])"
++ [(pc)]
++{
++ rs6000_split_multireg_move (operands[0], operands[1]);
++ DONE;
++})
++
++\f
++;; Generic floating point vector arithmetic support
++(define_expand "add<mode>3"
++ [(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_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_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_VSX_P (<MODE>mode)
++ || (VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD))"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_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_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_OR_VSX_P (<MODE>mode)"
++ "")
++
++\f
++;; Vector comparisons
++(define_expand "vcond<mode>"
++ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
++ (if_then_else:VEC_F
++ (match_operator 3 "comparison_operator"
++ [(match_operand:VEC_F 4 "vfloat_operand" "")
++ (match_operand:VEC_F 5 "vfloat_operand" "")])
++ (match_operand:VEC_F 1 "vfloat_operand" "")
++ (match_operand:VEC_F 2 "vfloat_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++ "
++{
++ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
++ operands[3], operands[4], operands[5]))
++ DONE;
++ else
++ FAIL;
++}")
++
++(define_expand "vcond<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "")
++ (if_then_else:VEC_I
++ (match_operator 3 "comparison_operator"
++ [(match_operand:VEC_I 4 "vint_operand" "")
++ (match_operand:VEC_I 5 "vint_operand" "")])
++ (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "
++{
++ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
++ operands[3], operands[4], operands[5]))
++ DONE;
++ else
++ FAIL;
++}")
++
++(define_expand "vcondu<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "=v")
++ (if_then_else:VEC_I
++ (match_operator 3 "comparison_operator"
++ [(match_operand:VEC_I 4 "vint_operand" "")
++ (match_operand:VEC_I 5 "vint_operand" "")])
++ (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "
++{
++ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
++ operands[3], operands[4], operands[5]))
++ DONE;
++ else
++ FAIL;
++}")
++
++(define_expand "vector_eq<mode>"
++ [(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_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_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_OR_VSX_P (<MODE>mode)"
++ "")
++
++(define_expand "vector_gtu<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "")
++ (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "")
++
++(define_expand "vector_geu<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "")
++ (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "")
++
++;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
++;; which is in the reverse order that we want
++(define_expand "vector_vsel<mode>"
++ [(match_operand:VEC_F 0 "vlogical_operand" "")
++ (match_operand:VEC_F 1 "vlogical_operand" "")
++ (match_operand:VEC_F 2 "vlogical_operand" "")
++ (match_operand:VEC_F 3 "vlogical_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++ "
++{
++ if (VECTOR_UNIT_VSX_P (<MODE>mode))
++ emit_insn (gen_vsx_vsel<mode> (operands[0], operands[3],
++ operands[2], operands[1]));
++ else
++ emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
++ operands[2], operands[1]));
++ DONE;
++}")
++
++(define_expand "vector_vsel<mode>"
++ [(match_operand:VEC_I 0 "vlogical_operand" "")
++ (match_operand:VEC_I 1 "vlogical_operand" "")
++ (match_operand:VEC_I 2 "vlogical_operand" "")
++ (match_operand:VEC_I 3 "vlogical_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "
++{
++ emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
++ operands[2], operands[1]));
++ DONE;
++}")
++
++\f
++;; Vector logical instructions
++(define_expand "xor<mode>3"
++ [(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_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_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_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_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_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_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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
++ {
++ emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
++ DONE;
++ }
++}")
++
++\f
++;; Vector initialization, set, extract
++(define_expand "vec_init<mode>"
++ [(match_operand:VEC_C 0 "vlogical_operand" "")
++ (match_operand:VEC_C 1 "vec_init_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ rs6000_expand_vector_init (operands[0], operands[1]);
++ DONE;
++})
++
++(define_expand "vec_set<mode>"
++ [(match_operand:VEC_C 0 "vlogical_operand" "")
++ (match_operand:<VEC_base> 1 "register_operand" "")
++ (match_operand 2 "const_int_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
++ DONE;
++})
++
++(define_expand "vec_extract<mode>"
++ [(match_operand:<VEC_base> 0 "register_operand" "")
++ (match_operand:VEC_C 1 "vlogical_operand" "")
++ (match_operand 2 "const_int_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ rs6000_expand_vector_extract (operands[0], operands[1],
++ INTVAL (operands[2]));
++ DONE;
++})
++
++;; Interleave patterns
++(define_expand "vec_interleave_highv4sf"
++ [(set (match_operand:V4SF 0 "vfloat_operand" "")
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
++ "")
++
++(define_expand "vec_interleave_lowv4sf"
++ [(set (match_operand:V4SF 0 "vfloat_operand" "")
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
++ "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)"
++ "")
++
++;; For 2 element vectors, even/odd is the same as high/low
++(define_expand "vec_extract_evenv2df"
++ [(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_extract_oddv2df"
++ [(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)"
++ "")
+--- gcc/config/rs6000/spe.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/spe.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -99,7 +99,7 @@ (define_insn "*divsf3_gpr"
+
+ ;; Floating point conversion instructions.
+
+-(define_insn "fixuns_truncdfsi2"
++(define_insn "spe_fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+--- gcc/config/rs6000/constraints.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/constraints.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -17,6 +17,8 @@
+ ;; along with GCC; see the file COPYING3. If not see
+ ;; <http://www.gnu.org/licenses/>.
+
++;; Available constraint letters: "e", "k", "u", "A", "B", "C", "D"
++
+ ;; Register constraints
+
+ (define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS
+@@ -50,6 +52,23 @@ (define_register_constraint "y" "CR_REGS
+ (define_register_constraint "z" "XER_REGS"
+ "@internal")
+
++;; Use w as a prefix to add VSX modes
++;; vector double (V2DF)
++(define_register_constraint "wd" "rs6000_vector_reg_class[V2DFmode]"
++ "@internal")
++
++;; vector float (V4SF)
++(define_register_constraint "wf" "rs6000_vector_reg_class[V4SFmode]"
++ "@internal")
++
++;; scalar double (DF)
++(define_register_constraint "ws" "rs6000_vector_reg_class[DFmode]"
++ "@internal")
++
++;; any VSX register
++(define_register_constraint "wa" "rs6000_vsx_reg_class"
++ "@internal")
++
+ ;; Integer constraints
+
+ (define_constraint "I"
+@@ -159,3 +178,7 @@ (define_constraint "t"
+ (define_constraint "W"
+ "vector constant that does not require memory"
+ (match_operand 0 "easy_vector_constant"))
++
++(define_constraint "j"
++ "Zero vector constant"
++ (match_test "(op == const0_rtx || op == CONST0_RTX (GET_MODE (op)))"))
+--- gcc/config/rs6000/predicates.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/predicates.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -38,6 +38,37 @@ (define_predicate "altivec_register_oper
+ || ALTIVEC_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
++;; Return 1 if op is a VSX register.
++(define_predicate "vsx_register_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VSX_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
++;; Return 1 if op is a vector register that operates on floating point vectors
++;; (either altivec or VSX).
++(define_predicate "vfloat_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VFLOAT_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
++;; Return 1 if op is a vector register that operates on integer vectors
++;; (only altivec, VSX doesn't support integer vectors)
++(define_predicate "vint_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VINT_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
++;; Return 1 if op is a vector register to do logical operations on (and, or,
++;; xor, etc.)
++(define_predicate "vlogical_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VLOGICAL_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
+ ;; Return 1 if op is XER register.
+ (define_predicate "xer_operand"
+ (and (match_code "reg")
+@@ -234,6 +265,10 @@ (define_predicate "easy_fp_constant"
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
+
+ case DFmode:
++ /* The constant 0.f is easy under VSX. */
++ if (op == CONST0_RTX (DFmode) && VECTOR_UNIT_VSX_P (DFmode))
++ return 1;
++
+ /* Force constants to memory before reload to utilize
+ compress_float_constant.
+ Avoid this when flag_unsafe_math_optimizations is enabled
+@@ -396,13 +431,16 @@ (define_predicate "indexed_or_indirect_o
+ (match_code "mem")
+ {
+ op = XEXP (op, 0);
+- if (TARGET_ALTIVEC
+- && ALTIVEC_VECTOR_MODE (mode)
++ if (VECTOR_MEM_ALTIVEC_P (mode)
+ && GET_CODE (op) == AND
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && INTVAL (XEXP (op, 1)) == -16)
+ op = XEXP (op, 0);
+
++ else if (VECTOR_MEM_VSX_P (mode)
++ && GET_CODE (op) == PRE_MODIFY)
++ op = XEXP (op, 1);
++
+ return indexed_or_indirect_address (op, mode);
+ })
+
+@@ -1336,3 +1374,19 @@ (define_predicate "stmw_operation"
+
+ return 1;
+ })
++
++;; Return true if the operand is a legitimate parallel for vec_init
++(define_predicate "vec_init_operand"
++ (match_code "parallel")
++{
++ /* Disallow V2DF mode with MEM's unless both are the same under VSX. */
++ if (mode == V2DFmode && VECTOR_UNIT_VSX_P (mode))
++ {
++ rtx op0 = XVECEXP (op, 0, 0);
++ rtx op1 = XVECEXP (op, 0, 1);
++ if ((MEM_P (op0) || MEM_P (op1)) && !rtx_equal_p (op0, op1))
++ return 0;
++ }
++
++ return 1;
++})
+--- gcc/config/rs6000/ppc-asm.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/ppc-asm.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -63,7 +63,7 @@
+ #define f16 16
+ #define f17 17
+ #define f18 18
+-#define f19 19
++#define f19 19
+ #define f20 20
+ #define f21 21
+ #define f22 22
+@@ -77,6 +77,143 @@
+ #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.
+ */
+--- gcc/config/rs6000/linux64.opt (.../trunk) (revision 144557)
++++ gcc/config/rs6000/linux64.opt (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -20,5 +20,5 @@
+ ; <http://www.gnu.org/licenses/>.
+
+ mprofile-kernel
+-Target Report Mask(PROFILE_KERNEL)
++Target Report Var(TARGET_PROFILE_KERNEL)
+ Call mcount for profiling before a function prologue
+--- gcc/config/rs6000/sysv4.opt (.../trunk) (revision 144557)
++++ gcc/config/rs6000/sysv4.opt (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -32,7 +32,7 @@ Target RejectNegative Joined
+ Specify bit size of immediate TLS offsets
+
+ mbit-align
+-Target Report Mask(NO_BITFIELD_TYPE)
++Target Report Var(TARGET_NO_BITFIELD_TYPE)
+ Align to the base type of the bit-field
+
+ mstrict-align
+@@ -87,11 +87,11 @@ Target Report Mask(EABI)
+ Use EABI
+
+ mbit-word
+-Target Report Mask(NO_BITFIELD_WORD)
++Target Report Var(TARGET_NO_BITFIELD_WORD)
+ Allow bit-fields to cross word boundaries
+
+ mregnames
+-Target Mask(REGNAMES)
++Target Var(TARGET_REGNAMES)
+ Use alternate register names
+
+ ;; FIXME: Does nothing.
+--- gcc/config/rs6000/rs6000-protos.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000-protos.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -64,9 +64,14 @@ extern int insvdi_rshift_rlwimi_p (rtx,
+ extern int registers_ok_for_quad_peep (rtx, rtx);
+ extern int mems_ok_for_quad_peep (rtx, rtx);
+ extern bool gpr_or_gpr_p (rtx, rtx);
++extern enum reg_class rs6000_preferred_reload_class(rtx, enum reg_class);
+ extern enum reg_class rs6000_secondary_reload_class (enum reg_class,
+ enum machine_mode, rtx);
+-
++extern bool rs6000_secondary_memory_needed (enum reg_class, enum reg_class,
++ enum machine_mode);
++extern bool rs6000_cannot_change_mode_class (enum machine_mode,
++ enum machine_mode,
++ enum reg_class);
+ extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
+ rtx, rtx, rtx);
+ extern void paired_expand_vector_move (rtx operands[]);
+@@ -170,7 +175,6 @@ extern int rs6000_register_move_cost (en
+ enum reg_class, enum reg_class);
+ extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
+ extern bool rs6000_tls_referenced_p (rtx);
+-extern int rs6000_hard_regno_nregs (int, enum machine_mode);
+ extern void rs6000_conditional_register_usage (void);
+
+ /* Declare functions in rs6000-c.c */
+@@ -189,4 +193,6 @@ const char * rs6000_xcoff_strip_dollar (
+ void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands);
+
+ extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
++extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES];
++extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER];
+ #endif /* rs6000-protos.h */
+--- gcc/config/rs6000/t-rs6000 (.../trunk) (revision 144557)
++++ gcc/config/rs6000/t-rs6000 (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -16,3 +16,33 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs60
+
+ # The rs6000 backend doesn't cause warnings in these files.
+ insn-conditions.o-warn =
++
++MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \
++ $(srcdir)/config/rs6000/rios2.md \
++ $(srcdir)/config/rs6000/rs64.md \
++ $(srcdir)/config/rs6000/mpc.md \
++ $(srcdir)/config/rs6000/40x.md \
++ $(srcdir)/config/rs6000/440.md \
++ $(srcdir)/config/rs6000/603.md \
++ $(srcdir)/config/rs6000/6xx.md \
++ $(srcdir)/config/rs6000/7xx.md \
++ $(srcdir)/config/rs6000/7450.md \
++ $(srcdir)/config/rs6000/8540.md \
++ $(srcdir)/config/rs6000/e300c2c3.md \
++ $(srcdir)/config/rs6000/e500mc.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 \
++ $(srcdir)/config/rs6000/constraints.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 \
++ $(srcdir)/config/rs6000/paired.md
+--- gcc/config/rs6000/power7.md (.../trunk) (revision 0)
++++ gcc/config/rs6000/power7.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,320 @@
++;; 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")
++
++
+--- gcc/config/rs6000/rs6000-c.c (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000-c.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -265,6 +265,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+ builtin_define ("_ARCH_PWR6X");
+ if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
+ builtin_define ("_ARCH_COM");
++ if (TARGET_POPCNTD)
++ builtin_define ("_ARCH_PWR7");
+ if (TARGET_ALTIVEC)
+ {
+ builtin_define ("__ALTIVEC__");
+@@ -306,6 +308,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+ /* Used by libstdc++. */
+ if (TARGET_NO_LWSYNC)
+ builtin_define ("__NO_LWSYNC__");
++ if (TARGET_VSX)
++ builtin_define ("__VSX__");
+
+ /* May be overridden by target configuration. */
+ RS6000_CPU_CPP_ENDIAN_BUILTINS();
+--- gcc/config/rs6000/rs6000.opt (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.opt (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -111,24 +111,44 @@ mhard-float
+ Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
+ Use hardware floating point
+
+-mno-update
+-Target Report RejectNegative Mask(NO_UPDATE)
+-Do not generate load/store with update instructions
++mpopcntd
++Target Report Mask(POPCNTD)
++Use PowerPC V2.06 popcntd instruction
++
++mvsx
++Target Report Mask(VSX)
++Use vector/scalar (VSX) instructions
++
++mvsx-vector-memory
++Target Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
++If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
++
++mvsx-vector-float
++Target Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
++If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
++
++mvsx-vector-double
++Target Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
++If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
++
++mvsx-scalar-double
++Target Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
++If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
++
++mvsx-scalar-memory
++Target Report Var(TARGET_VSX_SCALAR_MEMORY)
++If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
+
+ mupdate
+-Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
++Target Report Var(TARGET_UPDATE) Init(1)
+ Generate load/store with update instructions
+
+ mavoid-indexed-addresses
+ Target Report Var(TARGET_AVOID_XFORM) Init(-1)
+ Avoid generation of indexed load/store instructions when possible
+
+-mno-fused-madd
+-Target Report RejectNegative Mask(NO_FUSED_MADD)
+-Do not generate fused multiply/add instructions
+-
+ mfused-madd
+-Target Report RejectNegative InverseMask(NO_FUSED_MADD, FUSED_MADD)
++Target Report Var(TARGET_FUSED_MADD) Init(1)
+ Generate fused multiply/add instructions
+
+ msched-prolog
+@@ -194,7 +214,7 @@ Target RejectNegative Joined
+ -mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead
+
+ misel
+-Target
++Target Report Mask(ISEL)
+ Generate isel instructions
+
+ misel=
+--- gcc/config/rs6000/linux64.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/linux64.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -114,7 +114,7 @@ extern int dot_symbols;
+ error (INVALID_32BIT, "32"); \
+ if (TARGET_PROFILE_KERNEL) \
+ { \
+- target_flags &= ~MASK_PROFILE_KERNEL; \
++ SET_PROFILE_KERNEL (0); \
+ error (INVALID_32BIT, "profile-kernel"); \
+ } \
+ } \
+--- gcc/config/rs6000/rs6000.c (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -178,9 +178,6 @@ int rs6000_spe;
+ /* Nonzero if we want SPE ABI extensions. */
+ int rs6000_spe_abi;
+
+-/* Nonzero to use isel instructions. */
+-int rs6000_isel;
+-
+ /* Nonzero if floating point operations are done in the GPRs. */
+ int rs6000_float_gprs = 0;
+
+@@ -227,10 +224,18 @@ int dot_symbols;
+ const char *rs6000_debug_name;
+ int rs6000_debug_stack; /* debug stack applications */
+ int rs6000_debug_arg; /* debug argument handling */
++int rs6000_debug_reg; /* debug register classes */
++int rs6000_debug_addr; /* debug memory addressing */
+
+ /* Value is TRUE if register/mode pair is acceptable. */
+ bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+
++/* Maximum number of registers needed for a given register class and mode. */
++unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES];
++
++/* How many registers are needed for a given register and mode. */
++unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
++
+ /* Built in types. */
+
+ tree rs6000_builtin_types[RS6000_BTI_MAX];
+@@ -270,7 +275,6 @@ struct {
+ bool altivec_abi; /* True if -mabi=altivec/no-altivec used. */
+ bool spe; /* True if -mspe= was used. */
+ bool float_gprs; /* True if -mfloat-gprs= was used. */
+- bool isel; /* True if -misel was used. */
+ bool long_double; /* True if -mlong-double- was used. */
+ bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */
+ bool vrsave; /* True if -mvrsave was used. */
+@@ -286,6 +290,18 @@ struct builtin_description
+ const char *const name;
+ const enum rs6000_builtins code;
+ };
++
++/* Describe the vector unit used for modes. */
++enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES];
++enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES];
++enum reg_class rs6000_vector_reg_class[NUM_MACHINE_MODES];
++
++/* Describe the alignment of a vector. */
++int rs6000_vector_align[NUM_MACHINE_MODES];
++
++/* Describe the register classes used by VSX instructions. */
++enum reg_class rs6000_vsx_reg_class = NO_REGS;
++
+ \f
+ /* Target cpu costs. */
+
+@@ -749,6 +765,25 @@ struct processor_costs power6_cost = {
+ 16, /* prefetch streams */
+ };
+
++/* Instruction costs on POWER7 processors. */
++static const
++struct processor_costs power7_cost = {
++ COSTS_N_INSNS (2), /* mulsi */
++ COSTS_N_INSNS (2), /* mulsi_const */
++ COSTS_N_INSNS (2), /* mulsi_const9 */
++ COSTS_N_INSNS (2), /* muldi */
++ COSTS_N_INSNS (18), /* divsi */
++ COSTS_N_INSNS (34), /* divdi */
++ COSTS_N_INSNS (3), /* fp */
++ COSTS_N_INSNS (3), /* dmul */
++ COSTS_N_INSNS (13), /* sdiv */
++ COSTS_N_INSNS (16), /* ddiv */
++ 128, /* cache line size */
++ 32, /* l1 cache */
++ 256, /* l2 cache */
++ 12, /* prefetch streams */
++};
++
+ \f
+ static bool rs6000_function_ok_for_sibcall (tree, tree);
+ static const char *rs6000_invalid_within_doloop (const_rtx);
+@@ -963,12 +998,10 @@ static tree rs6000_gimplify_va_arg (tree
+ static bool rs6000_must_pass_in_stack (enum machine_mode, const_tree);
+ static bool rs6000_scalar_mode_supported_p (enum machine_mode);
+ static bool rs6000_vector_mode_supported_p (enum machine_mode);
+-static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
+- enum machine_mode);
++static rtx rs6000_emit_vector_compare_vsx (enum rtx_code, rtx, rtx, rtx);
++static rtx rs6000_emit_vector_compare_altivec (enum rtx_code, rtx, rtx, rtx);
+ static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
+ enum machine_mode);
+-static int get_vsel_insn (enum machine_mode);
+-static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
+ static tree rs6000_stack_protect_fail (void);
+
+ const int INSN_NOT_AVAILABLE = -1;
+@@ -1045,6 +1078,9 @@ static const char alt_reg_names[][8] =
+ #endif
+ #ifndef TARGET_PROFILE_KERNEL
+ #define TARGET_PROFILE_KERNEL 0
++#define SET_PROFILE_KERNEL(N)
++#else
++#define SET_PROFILE_KERNEL(N) TARGET_PROFILE_KERNEL = (N)
+ #endif
+
+ /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
+@@ -1299,28 +1335,96 @@ static const char alt_reg_names[][8] =
+
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ \f
++/* Return number of consecutive hard regs needed starting at reg REGNO
++ to hold something of mode MODE.
++ This is ordinarily the length in words of a value of mode MODE
++ but can be less for certain modes in special long registers.
++
++ For the SPE, GPRs are 64 bits but only 32 bits are visible in
++ scalar instructions. The upper 32 bits are only available to the
++ SIMD instructions.
++
++ POWER and PowerPC GPRs hold 32 bits worth;
++ PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
++
++static int
++rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
++{
++ unsigned HOST_WIDE_INT reg_size;
++
++ if (FP_REGNO_P (regno))
++ reg_size = (VECTOR_UNIT_VSX_P (mode)
++ ? UNITS_PER_VSX_WORD
++ : UNITS_PER_FP_WORD);
++
++ else if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
++ reg_size = UNITS_PER_SPE_WORD;
++
++ else if (ALTIVEC_REGNO_P (regno))
++ reg_size = UNITS_PER_ALTIVEC_WORD;
++
++ /* The value returned for SCmode in the E500 double case is 2 for
++ ABI compatibility; storing an SCmode value in a single register
++ would require function_arg and rs6000_spe_function_arg to handle
++ SCmode so as to pass the value correctly in a pair of
++ registers. */
++ else if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
++ && !DECIMAL_FLOAT_MODE_P (mode))
++ reg_size = UNITS_PER_FP_WORD;
++
++ else
++ reg_size = UNITS_PER_WORD;
++
++ return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
++}
+
+ /* Value is 1 if hard register REGNO can hold a value of machine-mode
+ MODE. */
+ static int
+ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
+ {
++ int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1;
++
++ /* VSX registers that overlap the FPR registers are larger than for non-VSX
++ implementations. Don't allow an item to be split between a FP register
++ and an Altivec register. */
++ if (VECTOR_UNIT_VSX_P (mode) || VECTOR_MEM_VSX_P (mode))
++ {
++ enum reg_class rclass = rs6000_vector_reg_class[mode];
++ if (FP_REGNO_P (regno))
++ return ((rclass == FLOAT_REGS || rclass == VSX_REGS)
++ && FP_REGNO_P (last_regno));
++
++ if (ALTIVEC_REGNO_P (regno))
++ return ((rclass == ALTIVEC_REGS || rclass == VSX_REGS)
++ && ALTIVEC_REGNO_P (last_regno));
++ }
++
+ /* The GPRs can hold any mode, but values bigger than one register
+ cannot go past R31. */
+ if (INT_REGNO_P (regno))
+- return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
++ return INT_REGNO_P (last_regno);
+
+- /* The float registers can only hold floating modes and DImode.
+- This excludes the 32-bit decimal float mode for now. */
++ /* The float registers (except for VSX vector modes) can only hold floating
++ modes and DImode. This excludes the 32-bit decimal float mode for
++ now. */
+ if (FP_REGNO_P (regno))
+- return
+- ((SCALAR_FLOAT_MODE_P (mode)
+- && (mode != TDmode || (regno % 2) == 0)
+- && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
+- || (GET_MODE_CLASS (mode) == MODE_INT
++ {
++ if (SCALAR_FLOAT_MODE_P (mode)
++ && (mode != TDmode || (regno % 2) == 0)
++ && FP_REGNO_P (last_regno))
++ return 1;
++
++ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
+- || (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
+- && PAIRED_VECTOR_MODE (mode)));
++ return 1;
++
++ if (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
++ && PAIRED_VECTOR_MODE (mode))
++ return 1;
++
++ return 0;
++ }
+
+ /* The CR register can only hold CC modes. */
+ if (CR_REGNO_P (regno))
+@@ -1331,28 +1435,312 @@ rs6000_hard_regno_mode_ok (int regno, en
+
+ /* AltiVec only in AldyVec registers. */
+ if (ALTIVEC_REGNO_P (regno))
+- return ALTIVEC_VECTOR_MODE (mode);
++ return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode);
+
+ /* ...but GPRs can hold SIMD data on the SPE in one register. */
+ if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return 1;
+
+- /* We cannot put TImode anywhere except general register and it must be
+- able to fit within the register set. */
++ /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. You
++ really don't want to spill your floating point values to those
++ registers. Also do it for the old MQ register in the power. */
++ if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)
++ return (GET_MODE_CLASS (mode) == MODE_INT
++ && GET_MODE_SIZE (mode) <= UNITS_PER_WORD);
++
++ /* The VRSAVE/VSCR registers are 32-bits (they are fixed, but add this for
++ completeness). */
++ if (regno == VRSAVE_REGNO || regno == VSCR_REGNO)
++ return (mode == SImode);
++
++ /* We cannot put TImode anywhere except general register and it must be able
++ to fit within the register set. In the future, allow TImode in the
++ Altivec or VSX registers. */
+
+ return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
+ }
+
+-/* Initialize rs6000_hard_regno_mode_ok_p table. */
++/* Print interesting facts about registers. */
+ static void
+-rs6000_init_hard_regno_mode_ok (void)
++rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
+ {
+ int r, m;
+
++ for (r = first_regno; r <= last_regno; ++r)
++ {
++ const char *comma = "";
++ int len;
++
++ if (first_regno == last_regno)
++ fprintf (stderr, "%s:\t", reg_name);
++ else
++ fprintf (stderr, "%s%d:\t", reg_name, r - first_regno);
++
++ len = 8;
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ if (rs6000_hard_regno_mode_ok_p[m][r] && rs6000_hard_regno_nregs[m][r])
++ {
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ len = 8;
++ comma = "";
++ }
++
++ if (rs6000_hard_regno_nregs[m][r] > 1)
++ len += fprintf (stderr, "%s%s/%d", comma, GET_MODE_NAME (m),
++ rs6000_hard_regno_nregs[m][r]);
++ else
++ len += fprintf (stderr, "%s%s", comma, GET_MODE_NAME (m));
++
++ comma = ", ";
++ }
++
++ if (call_used_regs[r])
++ {
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ len = 8;
++ comma = "";
++ }
++
++ len += fprintf (stderr, "%s%s", comma, "call-used");
++ comma = ", ";
++ }
++
++ if (fixed_regs[r])
++ {
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ len = 8;
++ comma = "";
++ }
++
++ len += fprintf (stderr, "%s%s", comma, "fixed");
++ comma = ", ";
++ }
++
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ comma = "";
++ }
++
++ fprintf (stderr, "%sregno = %d\n", comma, r);
++ }
++}
++
++/* Map enum rs6000_vector to string. */
++static const char *
++rs6000_debug_vector_unit[] = {
++ "none",
++ "altivec",
++ "vsx",
++ "paired",
++ "spe",
++ "other"
++};
++
++/* Initialize the various global tables that are based on register size. */
++static void
++rs6000_init_hard_regno_mode_ok (void)
++{
++ int r, m, c;
++ enum reg_class vsx_rc = (TARGET_ALTIVEC ? VSX_REGS : FLOAT_REGS);
++ bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS);
++
++ /* Precalculate vector information, this must be set up before the
++ rs6000_hard_regno_nregs_internal below. */
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ {
++ rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
++ rs6000_vector_reg_class[m] = NO_REGS;
++ }
++
++ /* TODO, add TI/V2DI mode for moving data if Altivec or VSX. */
++
++ /* V2DF mode, VSX only. */
++ if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE)
++ {
++ rs6000_vector_unit[V2DFmode] = VECTOR_VSX;
++ rs6000_vector_mem[V2DFmode] = VECTOR_VSX;
++ rs6000_vector_align[V2DFmode] = 64;
++ }
++
++ /* V4SF mode, either VSX or Altivec. */
++ if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_FLOAT)
++ {
++ rs6000_vector_unit[V4SFmode] = VECTOR_VSX;
++ if (TARGET_VSX_VECTOR_MEMORY || !TARGET_ALTIVEC)
++ {
++ rs6000_vector_align[V4SFmode] = 32;
++ rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
++ } else {
++ rs6000_vector_align[V4SFmode] = 128;
++ rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
++ }
++ }
++ else if (float_p && TARGET_ALTIVEC)
++ {
++ rs6000_vector_unit[V4SFmode] = VECTOR_ALTIVEC;
++ rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
++ rs6000_vector_align[V4SFmode] = 128;
++ }
++
++ /* V16QImode, V8HImode, V4SImode are Altivec only, but possibly do VSX loads
++ and stores. */
++ if (TARGET_ALTIVEC)
++ {
++ rs6000_vector_unit[V4SImode] = VECTOR_ALTIVEC;
++ rs6000_vector_unit[V8HImode] = VECTOR_ALTIVEC;
++ rs6000_vector_unit[V16QImode] = VECTOR_ALTIVEC;
++
++ rs6000_vector_reg_class[V16QImode] = ALTIVEC_REGS;
++ rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
++ rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
++
++ if (TARGET_VSX && TARGET_VSX_VECTOR_MEMORY)
++ {
++ rs6000_vector_mem[V4SImode] = VECTOR_VSX;
++ rs6000_vector_mem[V8HImode] = VECTOR_VSX;
++ rs6000_vector_mem[V16QImode] = VECTOR_VSX;
++ rs6000_vector_align[V4SImode] = 32;
++ rs6000_vector_align[V8HImode] = 32;
++ rs6000_vector_align[V16QImode] = 32;
++ }
++ else
++ {
++ rs6000_vector_mem[V4SImode] = VECTOR_ALTIVEC;
++ rs6000_vector_mem[V8HImode] = VECTOR_ALTIVEC;
++ rs6000_vector_mem[V16QImode] = VECTOR_ALTIVEC;
++ rs6000_vector_align[V4SImode] = 128;
++ rs6000_vector_align[V8HImode] = 128;
++ rs6000_vector_align[V16QImode] = 128;
++ }
++ }
++
++ /* DFmode, see if we want to use the VSX unit. */
++ if (float_p && TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
++ {
++ rs6000_vector_unit[DFmode] = VECTOR_VSX;
++ rs6000_vector_align[DFmode] = 64;
++ rs6000_vector_mem[DFmode]
++ = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
++ }
++
++ /* TODO, add SPE and paired floating point vector support. */
++
++ /* Set the VSX register classes. */
++ rs6000_vector_reg_class[V4SFmode]
++ = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
++ ? vsx_rc
++ : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
++ ? ALTIVEC_REGS
++ : NO_REGS));
++
++ rs6000_vector_reg_class[V2DFmode]
++ = (VECTOR_UNIT_VSX_P (V2DFmode) ? vsx_rc : NO_REGS);
++
++ rs6000_vector_reg_class[DFmode]
++ = ((!float_p || !VECTOR_UNIT_VSX_P (DFmode))
++ ? NO_REGS
++ : ((TARGET_VSX_SCALAR_MEMORY)
++ ? vsx_rc
++ : FLOAT_REGS));
++
++ rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
++
++ /* Precalculate HARD_REGNO_NREGS. */
++ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ rs6000_hard_regno_nregs[m][r] = rs6000_hard_regno_nregs_internal (r, m);
++
++ /* Precalculate HARD_REGNO_MODE_OK. */
+ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
+ if (rs6000_hard_regno_mode_ok (r, m))
+ rs6000_hard_regno_mode_ok_p[m][r] = true;
++
++ /* Precalculate CLASSS_MAX_NREGS sizes. */
++ for (c = 0; c < LIM_REG_CLASSES; ++c)
++ {
++ int reg_size;
++
++ if (TARGET_VSX && VSX_REG_CLASS_P (c))
++ reg_size = UNITS_PER_VSX_WORD;
++
++ else if (c == ALTIVEC_REGS)
++ reg_size = UNITS_PER_ALTIVEC_WORD;
++
++ else if (c == FLOAT_REGS)
++ reg_size = UNITS_PER_FP_WORD;
++
++ else
++ reg_size = UNITS_PER_WORD;
++
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ rs6000_class_max_nregs[m][c]
++ = (GET_MODE_SIZE (m) + reg_size - 1) / reg_size;
++ }
++
++ if (TARGET_E500_DOUBLE)
++ rs6000_class_max_nregs[DFmode][GENERAL_REGS] = 1;
++
++ if (TARGET_DEBUG_REG)
++ {
++ const char *nl = (const char *)0;
++
++ fprintf (stderr, "Register information: (last virtual reg = %d)\n",
++ LAST_VIRTUAL_REGISTER);
++ rs6000_debug_reg_print (0, 31, "gr");
++ rs6000_debug_reg_print (32, 63, "fp");
++ rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
++ LAST_ALTIVEC_REGNO,
++ "vs");
++ rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
++ rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
++ rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
++ rs6000_debug_reg_print (MQ_REGNO, MQ_REGNO, "mq");
++ rs6000_debug_reg_print (XER_REGNO, XER_REGNO, "xer");
++ rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave");
++ rs6000_debug_reg_print (VSCR_REGNO, VSCR_REGNO, "vscr");
++ rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a");
++ rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f");
++
++ fprintf (stderr,
++ "\n"
++ "V16QI reg_class = %s\n"
++ "V8HI reg_class = %s\n"
++ "V4SI reg_class = %s\n"
++ "V2DI reg_class = %s\n"
++ "V4SF reg_class = %s\n"
++ "V2DF reg_class = %s\n"
++ "DF reg_class = %s\n"
++ "vsx reg_class = %s\n\n",
++ reg_class_names[rs6000_vector_reg_class[V16QImode]],
++ reg_class_names[rs6000_vector_reg_class[V8HImode]],
++ reg_class_names[rs6000_vector_reg_class[V4SImode]],
++ reg_class_names[rs6000_vector_reg_class[V2DImode]],
++ reg_class_names[rs6000_vector_reg_class[V4SFmode]],
++ reg_class_names[rs6000_vector_reg_class[V2DFmode]],
++ reg_class_names[rs6000_vector_reg_class[DFmode]],
++ reg_class_names[rs6000_vsx_reg_class]);
++
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
++ {
++ nl = "\n";
++ fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n",
++ GET_MODE_NAME (m),
++ rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
++ rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]);
++ }
++
++ if (nl)
++ fputs (nl, stderr);
++ }
+ }
+
+ #if TARGET_MACHO
+@@ -1482,12 +1870,15 @@ rs6000_override_options (const char *def
+ {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+- {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN},
++ {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
++ | MASK_ISEL},
+ /* 8548 has a dummy entry for now. */
+- {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN},
++ {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
++ | MASK_ISEL},
+ {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
+- {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
++ {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
++ | MASK_ISEL},
+ {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"970", PROCESSOR_POWER4,
+ POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+@@ -1520,9 +1911,10 @@ rs6000_override_options (const char *def
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
+ | MASK_MFPGPR},
+- {"power7", PROCESSOR_POWER5,
++ {"power7", PROCESSOR_POWER7,
+ POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
+- | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP},
++ | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
++ | 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},
+@@ -1549,7 +1941,8 @@ rs6000_override_options (const char *def
+ POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
+ | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
+- | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP)
++ | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
++ | MASK_POPCNTD | MASK_VSX | MASK_ISEL)
+ };
+
+ set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
+@@ -1594,10 +1987,6 @@ rs6000_override_options (const char *def
+ }
+ }
+
+- if ((TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
+- && !rs6000_explicit_options.isel)
+- rs6000_isel = 1;
+-
+ if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
+ || rs6000_cpu == PROCESSOR_PPCE500MC)
+ {
+@@ -1642,15 +2031,47 @@ rs6000_override_options (const char *def
+ }
+ }
+
++ /* Add some warnings for VSX. Enable -maltivec unless the user explicitly
++ used -mno-altivec */
++ if (TARGET_VSX)
++ {
++ const char *msg = NULL;
++ if (!TARGET_HARD_FLOAT || !TARGET_FPRS
++ || !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT)
++ msg = "-mvsx requires hardware floating point";
++ else if (TARGET_PAIRED_FLOAT)
++ msg = "-mvsx and -mpaired are incompatible";
++ /* The hardware will allow VSX and little endian, but until we make sure
++ things like vector select, etc. work don't allow VSX on little endian
++ systems at this point. */
++ else if (!BYTES_BIG_ENDIAN)
++ msg = "-mvsx used with little endian code";
++ else if (TARGET_AVOID_XFORM > 0)
++ msg = "-mvsx needs indexed addressing";
++
++ if (msg)
++ {
++ warning (0, msg);
++ target_flags &= MASK_VSX;
++ }
++ else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC) == 0)
++ target_flags |= MASK_ALTIVEC;
++ }
++
+ /* Set debug flags */
+ if (rs6000_debug_name)
+ {
+ if (! strcmp (rs6000_debug_name, "all"))
+- rs6000_debug_stack = rs6000_debug_arg = 1;
++ rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
++ = rs6000_debug_addr = 1;
+ else if (! strcmp (rs6000_debug_name, "stack"))
+ rs6000_debug_stack = 1;
+ else if (! strcmp (rs6000_debug_name, "arg"))
+ rs6000_debug_arg = 1;
++ else if (! strcmp (rs6000_debug_name, "reg"))
++ rs6000_debug_reg = 1;
++ else if (! strcmp (rs6000_debug_name, "addr"))
++ rs6000_debug_addr = 1;
+ else
+ error ("unknown -mdebug-%s switch", rs6000_debug_name);
+ }
+@@ -1741,8 +2162,8 @@ rs6000_override_options (const char *def
+ rs6000_spe = 0;
+ if (!rs6000_explicit_options.float_gprs)
+ rs6000_float_gprs = 0;
+- if (!rs6000_explicit_options.isel)
+- rs6000_isel = 0;
++ if (!(target_flags_explicit & MASK_ISEL))
++ target_flags &= ~MASK_ISEL;
+ }
+
+ /* Detect invalid option combinations with E500. */
+@@ -1751,12 +2172,14 @@ rs6000_override_options (const char *def
+ rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
+ && rs6000_cpu != PROCESSOR_POWER5
+ && rs6000_cpu != PROCESSOR_POWER6
++ && rs6000_cpu != PROCESSOR_POWER7
+ && rs6000_cpu != PROCESSOR_CELL);
+ rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
+ || rs6000_cpu == PROCESSOR_POWER5);
+ rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
+ || rs6000_cpu == PROCESSOR_POWER5
+- || rs6000_cpu == PROCESSOR_POWER6);
++ || rs6000_cpu == PROCESSOR_POWER6
++ || rs6000_cpu == PROCESSOR_POWER7);
+
+ rs6000_sched_restricted_insns_priority
+ = (rs6000_sched_groups ? 1 : 0);
+@@ -1951,6 +2374,10 @@ rs6000_override_options (const char *def
+ rs6000_cost = &power6_cost;
+ break;
+
++ case PROCESSOR_POWER7:
++ rs6000_cost = &power7_cost;
++ break;
++
+ default:
+ gcc_unreachable ();
+ }
+@@ -2001,7 +2428,7 @@ rs6000_override_options (const char *def
+ static tree
+ rs6000_builtin_mask_for_load (void)
+ {
+- if (TARGET_ALTIVEC)
++ if (TARGET_ALTIVEC && !TARGET_VSX)
+ return altivec_builtin_mask_for_load;
+ else
+ return 0;
+@@ -2015,18 +2442,19 @@ rs6000_builtin_mask_for_load (void)
+ static tree
+ rs6000_builtin_conversion (enum tree_code code, tree type)
+ {
+- if (!TARGET_ALTIVEC)
+- return NULL_TREE;
+-
+ switch (code)
+ {
+ case FIX_TRUNC_EXPR:
+ switch (TYPE_MODE (type))
+ {
+ case V4SImode:
++ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
++ return NULL_TREE;
++
+ return TYPE_UNSIGNED (type)
+- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTUXS]
+- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTSXS];
++ ? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI]
++ : rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI];
++
+ default:
+ return NULL_TREE;
+ }
+@@ -2035,9 +2463,12 @@ rs6000_builtin_conversion (enum tree_cod
+ switch (TYPE_MODE (type))
+ {
+ case V4SImode:
++ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
++ return NULL_TREE;
++
+ return TYPE_UNSIGNED (type)
+- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFUX]
+- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
++ ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
++ : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
+ default:
+ return NULL_TREE;
+ }
+@@ -2150,6 +2581,14 @@ rs6000_builtin_vec_perm (tree type, tree
+ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
+ break;
+
++ case V2DFmode:
++ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DF];
++ break;
++
++ case V2DImode:
++ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI];
++ break;
++
+ default:
+ return NULL_TREE;
+ }
+@@ -2229,6 +2668,7 @@ static bool
+ rs6000_handle_option (size_t code, const char *arg, int value)
+ {
+ enum fpu_type_t fpu_type = FPU_NONE;
++ int isel;
+
+ switch (code)
+ {
+@@ -2331,14 +2771,14 @@ rs6000_handle_option (size_t code, const
+ rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
+ break;
+
+- case OPT_misel:
+- rs6000_explicit_options.isel = true;
+- rs6000_isel = value;
+- break;
+-
+ case OPT_misel_:
+- rs6000_explicit_options.isel = true;
+- rs6000_parse_yes_no_option ("isel", arg, &(rs6000_isel));
++ target_flags_explicit |= MASK_ISEL;
++ isel = 0;
++ rs6000_parse_yes_no_option ("isel", arg, &isel);
++ if (isel)
++ target_flags |= MASK_ISEL;
++ else
++ target_flags &= ~MASK_ISEL;
+ break;
+
+ case OPT_mspe:
+@@ -2967,6 +3407,9 @@ output_vec_const_move (rtx *operands)
+ vec = operands[1];
+ mode = GET_MODE (dest);
+
++ if (TARGET_VSX && zero_constant (vec, mode))
++ return "xxlxor %x0,%x0,%x0";
++
+ if (TARGET_ALTIVEC)
+ {
+ rtx splat_vec;
+@@ -3190,20 +3633,21 @@ rs6000_expand_vector_init (rtx target, r
+ if (n_var == 0)
+ {
+ rtx const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+- if (mode != V4SFmode && all_const_zero)
++ bool int_vector_p = (GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
++ if ((int_vector_p || TARGET_VSX) && all_const_zero)
+ {
+ /* Zero register. */
+ emit_insn (gen_rtx_SET (VOIDmode, target,
+ gen_rtx_XOR (mode, target, target)));
+ return;
+ }
+- else if (mode != V4SFmode && easy_vector_constant (const_vec, mode))
++ else if (int_vector_p && easy_vector_constant (const_vec, mode))
+ {
+ /* Splat immediate. */
+ emit_insn (gen_rtx_SET (VOIDmode, target, const_vec));
+ return;
+ }
+- else if (all_same)
++ else if (all_same && int_vector_p)
+ ; /* Splat vector element. */
+ else
+ {
+@@ -3213,6 +3657,18 @@ rs6000_expand_vector_init (rtx target, r
+ }
+ }
+
++ if (mode == V2DFmode)
++ {
++ gcc_assert (TARGET_VSX);
++ if (all_same)
++ emit_insn (gen_vsx_splatv2df (target, XVECEXP (vals, 0, 0)));
++ else
++ emit_insn (gen_vsx_concat_v2df (target,
++ copy_to_reg (XVECEXP (vals, 0, 0)),
++ copy_to_reg (XVECEXP (vals, 0, 1))));
++ return;
++ }
++
+ /* Store value to stack temp. Load vector element. Splat. */
+ if (all_same)
+ {
+@@ -3272,6 +3728,13 @@ rs6000_expand_vector_set (rtx target, rt
+ int width = GET_MODE_SIZE (inner_mode);
+ int i;
+
++ if (mode == V2DFmode)
++ {
++ gcc_assert (TARGET_VSX);
++ emit_insn (gen_vsx_set_v2df (target, val, target, 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);
+@@ -3309,6 +3772,13 @@ rs6000_expand_vector_extract (rtx target
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ rtx mem, x;
+
++ if (mode == V2DFmode)
++ {
++ gcc_assert (TARGET_VSX);
++ emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt)));
++ return;
++ }
++
+ /* Allocate mode-sized buffer. */
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
+
+@@ -3627,9 +4097,13 @@ rs6000_legitimate_offset_address_p (enum
+ case V8HImode:
+ case V4SFmode:
+ case V4SImode:
+- /* AltiVec vector modes. Only reg+reg addressing is valid and
++ case V2DFmode:
++ case V2DImode:
++ /* AltiVec/VSX vector modes. Only reg+reg addressing is valid and
+ constant offset zero should not occur due to canonicalization. */
+- return false;
++ if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
++ return false;
++ break;
+
+ case V4HImode:
+ case V2SImode:
+@@ -3646,6 +4120,11 @@ rs6000_legitimate_offset_address_p (enum
+ if (TARGET_E500_DOUBLE)
+ return SPE_CONST_OFFSET_OK (offset);
+
++ /* If we are using VSX scalar loads, restrict ourselves to reg+reg
++ addressing. */
++ if (VECTOR_MEM_VSX_P (DFmode))
++ return false;
++
+ case DDmode:
+ case DImode:
+ /* On e500v2, we may have:
+@@ -3716,7 +4195,9 @@ avoiding_indexed_address_p (enum machine
+ {
+ /* Avoid indexed addressing for modes that have non-indexed
+ load/store instruction forms. */
+- return TARGET_AVOID_XFORM && !ALTIVEC_VECTOR_MODE (mode);
++ return (TARGET_AVOID_XFORM
++ && (!TARGET_ALTIVEC || !ALTIVEC_VECTOR_MODE (mode))
++ && (!TARGET_VSX || !VSX_VECTOR_MODE (mode)));
+ }
+
+ inline bool
+@@ -3808,25 +4289,30 @@ rtx
+ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+ {
++ rtx ret = NULL_RTX;
++ rtx orig_x = x;
++
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
+ if (model != 0)
+- return rs6000_legitimize_tls_address (x, model);
++ ret = rs6000_legitimize_tls_address (x, model);
+ }
+
+- if (GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000
+- && !((TARGET_POWERPC64
+- && (mode == DImode || mode == TImode)
+- && (INTVAL (XEXP (x, 1)) & 3) != 0)
+- || SPE_VECTOR_MODE (mode)
+- || ALTIVEC_VECTOR_MODE (mode)
+- || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+- || mode == DImode || mode == DDmode
+- || mode == TDmode))))
++ else if (GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000)
++ >= 0x10000)
++ && !((TARGET_POWERPC64
++ && (mode == DImode || mode == TImode)
++ && (INTVAL (XEXP (x, 1)) & 3) != 0)
++ || (TARGET_SPE && SPE_VECTOR_MODE (mode))
++ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
++ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
++ || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
++ || mode == DImode || mode == DDmode
++ || mode == TDmode))))
+ {
+ HOST_WIDE_INT high_int, low_int;
+ rtx sum;
+@@ -3834,7 +4320,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+ high_int = INTVAL (XEXP (x, 1)) - low_int;
+ sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
+ GEN_INT (high_int)), 0);
+- return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
++ ret = gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
+ }
+ else if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+@@ -3850,32 +4336,29 @@ rs6000_legitimize_address (rtx x, rtx ol
+ && mode != TFmode
+ && mode != TDmode)
+ {
+- return gen_rtx_PLUS (Pmode, XEXP (x, 0),
+- force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
++ ret = gen_rtx_PLUS (Pmode, XEXP (x, 0),
++ force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
+ }
+- else if (ALTIVEC_VECTOR_MODE (mode))
++ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+ {
+- rtx reg;
+-
+ /* Make sure both operands are registers. */
+ if (GET_CODE (x) == PLUS)
+- return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
+- force_reg (Pmode, XEXP (x, 1)));
+-
+- reg = force_reg (Pmode, x);
+- return reg;
++ ret = gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
++ force_reg (Pmode, XEXP (x, 1)));
++ else
++ ret = force_reg (Pmode, x);
+ }
+- else if (SPE_VECTOR_MODE (mode)
++ else if ((TARGET_SPE && SPE_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+ || mode == DDmode || mode == TDmode
+ || mode == DImode)))
+ {
+ if (mode == DImode)
+- return NULL_RTX;
+- /* We accept [reg + reg] and [reg + OFFSET]. */
++ ret = NULL_RTX;
+
+- if (GET_CODE (x) == PLUS)
+- {
++ /* We accept [reg + reg] and [reg + OFFSET]. */
++ else if (GET_CODE (x) == PLUS)
++ {
+ rtx op1 = XEXP (x, 0);
+ rtx op2 = XEXP (x, 1);
+ rtx y;
+@@ -3894,12 +4377,12 @@ rs6000_legitimize_address (rtx x, rtx ol
+ y = gen_rtx_PLUS (Pmode, op1, op2);
+
+ if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2))
+- return force_reg (Pmode, y);
++ ret = force_reg (Pmode, y);
+ else
+- return y;
++ ret = y;
+ }
+-
+- return force_reg (Pmode, x);
++ else
++ ret = force_reg (Pmode, x);
+ }
+ else if (TARGET_ELF
+ && TARGET_32BIT
+@@ -3915,7 +4398,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_elf_high (reg, x));
+- return gen_rtx_LO_SUM (Pmode, reg, x);
++ ret = gen_rtx_LO_SUM (Pmode, reg, x);
+ }
+ else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
+ && ! flag_pic
+@@ -3933,17 +4416,34 @@ rs6000_legitimize_address (rtx x, rtx ol
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_macho_high (reg, x));
+- return gen_rtx_LO_SUM (Pmode, reg, x);
++ ret = gen_rtx_LO_SUM (Pmode, reg, x);
+ }
+ else if (TARGET_TOC
+ && GET_CODE (x) == SYMBOL_REF
+ && constant_pool_expr_p (x)
+ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
+ {
+- return create_TOC_reference (x);
++ ret = create_TOC_reference (x);
+ }
+ else
+- return NULL_RTX;
++ ret = NULL_RTX;
++
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_legitimize_address: mode %s, original addr:\n",
++ GET_MODE_NAME (mode));
++ debug_rtx (orig_x);
++ if (ret)
++ {
++ fprintf (stderr, "New addr:\n");
++ debug_rtx (ret);
++ }
++ else
++ fprintf (stderr, "NULL returned\n");
++ }
++
++ return ret;
+ }
+
+ /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
+@@ -4232,6 +4732,9 @@ rs6000_legitimize_reload_address (rtx x,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED, int *win)
+ {
++ rtx orig_x = x;
++ rtx ret = NULL_RTX;
++
+ /* We must recognize output that we have already generated ourselves. */
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+@@ -4243,17 +4746,17 @@ rs6000_legitimize_reload_address (rtx x,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+ #if TARGET_MACHO
+- if (DEFAULT_ABI == ABI_DARWIN && flag_pic
+- && GET_CODE (x) == LO_SUM
+- && GET_CODE (XEXP (x, 0)) == PLUS
+- && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
+- && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+- && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
+- && machopic_operand_p (XEXP (x, 1)))
++ else if (DEFAULT_ABI == ABI_DARWIN && flag_pic
++ && GET_CODE (x) == LO_SUM
++ && GET_CODE (XEXP (x, 0)) == PLUS
++ && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
++ && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
++ && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
++ && machopic_operand_p (XEXP (x, 1)))
+ {
+ /* Result of previous invocation of this function on Darwin
+ floating point constant. */
+@@ -4261,40 +4764,42 @@ rs6000_legitimize_reload_address (rtx x,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+ #endif
+
+ /* Force ld/std non-word aligned offset into base register by wrapping
+ in offset 0. */
+- if (GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && REGNO (XEXP (x, 0)) < 32
+- && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && (INTVAL (XEXP (x, 1)) & 3) != 0
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
+- && TARGET_POWERPC64)
++ else if (GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && REGNO (XEXP (x, 0)) < 32
++ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && (INTVAL (XEXP (x, 1)) & 3) != 0
++ && !ALTIVEC_VECTOR_MODE (mode)
++ && !VSX_VECTOR_MODE (mode)
++ && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
++ && TARGET_POWERPC64)
+ {
+ x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+- if (GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
+- && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && !SPE_VECTOR_MODE (mode)
+- && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+- || mode == DDmode || mode == TDmode
+- || mode == DImode))
+- && !ALTIVEC_VECTOR_MODE (mode))
++ else if (GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
++ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && !SPE_VECTOR_MODE (mode)
++ && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
++ || mode == DDmode || mode == TDmode
++ || mode == DImode))
++ && !ALTIVEC_VECTOR_MODE (mode)
++ && !VSX_VECTOR_MODE (mode))
+ {
+ HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
+ HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
+@@ -4305,42 +4810,44 @@ rs6000_legitimize_reload_address (rtx x,
+ if (high + low != val)
+ {
+ *win = 0;
+- return x;
++ ret = x;
+ }
++ else
++ {
++ /* Reload the high part into a base reg; leave the low part
++ in the mem directly. */
+
+- /* Reload the high part into a base reg; leave the low part
+- in the mem directly. */
+-
+- x = gen_rtx_PLUS (GET_MODE (x),
+- gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+- GEN_INT (high)),
+- GEN_INT (low));
++ x = gen_rtx_PLUS (GET_MODE (x),
++ gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
++ GEN_INT (high)),
++ GEN_INT (low));
+
+- push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+- opnum, (enum reload_type)type);
+- *win = 1;
+- return x;
++ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
++ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
++ opnum, (enum reload_type)type);
++ *win = 1;
++ return x;
++ }
+ }
+
+- if (GET_CODE (x) == SYMBOL_REF
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && !SPE_VECTOR_MODE (mode)
++ else if (GET_CODE (x) == SYMBOL_REF
++ && VECTOR_MEM_NONE_P (mode)
++ && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
+ #if TARGET_MACHO
+- && DEFAULT_ABI == ABI_DARWIN
+- && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
++ && DEFAULT_ABI == ABI_DARWIN
++ && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+ #else
+- && DEFAULT_ABI == ABI_V4
+- && !flag_pic
++ && DEFAULT_ABI == ABI_V4
++ && !flag_pic
+ #endif
+- /* Don't do this for TFmode or TDmode, since the result isn't offsettable.
+- The same goes for DImode without 64-bit gprs and DFmode and DDmode
+- without fprs. */
+- && mode != TFmode
+- && mode != TDmode
+- && (mode != DImode || TARGET_POWERPC64)
+- && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
+- || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
++ /* Don't do this for TFmode or TDmode, since the result isn't
++ offsettable. The same goes for DImode without 64-bit gprs and
++ DFmode and DDmode without fprs. */
++ && mode != TFmode
++ && mode != TDmode
++ && (mode != DImode || TARGET_POWERPC64)
++ && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
++ || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
+ {
+ #if TARGET_MACHO
+ if (flag_pic)
+@@ -4359,37 +4866,61 @@ rs6000_legitimize_reload_address (rtx x,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+ /* Reload an offset address wrapped by an AND that represents the
+ masking of the lower bits. Strip the outer AND and let reload
+ convert the offset address into an indirect address. */
+- if (TARGET_ALTIVEC
+- && ALTIVEC_VECTOR_MODE (mode)
+- && GET_CODE (x) == AND
+- && GET_CODE (XEXP (x, 0)) == PLUS
+- && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && INTVAL (XEXP (x, 1)) == -16)
++ else if (VECTOR_MEM_ALTIVEC_P (mode)
++ && GET_CODE (x) == AND
++ && GET_CODE (XEXP (x, 0)) == PLUS
++ && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
++ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && INTVAL (XEXP (x, 1)) == -16)
+ {
+ x = XEXP (x, 0);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+- if (TARGET_TOC
+- && GET_CODE (x) == SYMBOL_REF
+- && constant_pool_expr_p (x)
+- && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
++ else if (TARGET_TOC
++ && GET_CODE (x) == SYMBOL_REF
++ && constant_pool_expr_p (x)
++ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
+ {
+ x = create_TOC_reference (x);
+ *win = 1;
+- return x;
++ ret = x;
++ }
++
++ else
++ {
++ *win = 0;
++ ret = x;
+ }
+- *win = 0;
+- return x;
++
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_legitimize_reload_address: mode = %s, opnum = %d, "
++ "type = %d, ind_levels = %d, win = %d, original addr:\n",
++ GET_MODE_NAME (mode), opnum, type, ind_levels, *win);
++ debug_rtx (orig_x);
++
++ if (orig_x == ret)
++ fprintf (stderr, "Same address returned\n");
++ else if (!ret)
++ fprintf (stderr, "NULL returned\n");
++ else
++ {
++ fprintf (stderr, "New address:\n");
++ debug_rtx (ret);
++ }
++ }
++
++ return ret;
+ }
+
+ /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+@@ -4412,77 +4943,101 @@ rs6000_legitimize_reload_address (rtx x,
+ int
+ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
+ {
++ int ret;
++ rtx orig_x = x;
++
+ /* If this is an unaligned stvx/ldvx type address, discard the outer AND. */
+ if (TARGET_ALTIVEC
+- && ALTIVEC_VECTOR_MODE (mode)
++ && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ && GET_CODE (x) == AND
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) == -16)
+ x = XEXP (x, 0);
+
+ if (RS6000_SYMBOL_REF_TLS_P (x))
+- return 0;
+- if (legitimate_indirect_address_p (x, reg_ok_strict))
+- return 1;
+- if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && !SPE_VECTOR_MODE (mode)
+- && mode != TFmode
+- && mode != TDmode
+- /* Restrict addressing for DI because of our SUBREG hackery. */
+- && !(TARGET_E500_DOUBLE
+- && (mode == DFmode || mode == DDmode || mode == DImode))
+- && TARGET_UPDATE
+- && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
+- return 1;
+- if (legitimate_small_data_p (mode, x))
+- return 1;
+- if (legitimate_constant_pool_address_p (x))
+- return 1;
++ ret = 0;
++ else if (legitimate_indirect_address_p (x, reg_ok_strict))
++ ret = 1;
++ else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
++ && !VECTOR_MEM_ALTIVEC_P (mode)
++ /* && !VECTOR_MEM_VSX_P (mode) */
++ && (TARGET_SPE && !SPE_VECTOR_MODE (mode))
++ && mode != TFmode
++ && mode != TDmode
++ /* Restrict addressing for DI because of our SUBREG hackery. */
++ && !(TARGET_E500_DOUBLE
++ && (mode == DFmode || mode == DDmode || mode == DImode))
++ && TARGET_UPDATE
++ && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
++ ret = 1;
++ else if (legitimate_small_data_p (mode, x))
++ ret = 1;
++ else if (legitimate_constant_pool_address_p (x))
++ ret = 1;
+ /* If not REG_OK_STRICT (before reload) let pass any stack offset. */
+- if (! reg_ok_strict
+- && GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && (XEXP (x, 0) == virtual_stack_vars_rtx
+- || XEXP (x, 0) == arg_pointer_rtx)
+- && GET_CODE (XEXP (x, 1)) == CONST_INT)
+- return 1;
+- if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
+- return 1;
+- if (mode != TImode
+- && mode != TFmode
+- && mode != TDmode
+- && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+- || TARGET_POWERPC64
+- || (mode != DFmode && mode != DDmode)
+- || (TARGET_E500_DOUBLE && mode != DDmode))
+- && (TARGET_POWERPC64 || mode != DImode)
+- && !avoiding_indexed_address_p (mode)
+- && legitimate_indexed_address_p (x, reg_ok_strict))
+- return 1;
+- if (GET_CODE (x) == PRE_MODIFY
+- && mode != TImode
+- && mode != TFmode
+- && mode != TDmode
+- && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
+- || TARGET_POWERPC64
+- || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
+- && (TARGET_POWERPC64 || mode != DImode)
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && !SPE_VECTOR_MODE (mode)
+- /* Restrict addressing for DI because of our SUBREG hackery. */
+- && !(TARGET_E500_DOUBLE
+- && (mode == DFmode || mode == DDmode || mode == DImode))
+- && TARGET_UPDATE
+- && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
+- && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
+- || (!avoiding_indexed_address_p (mode)
+- && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
+- && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
+- return 1;
+- if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
+- return 1;
+- return 0;
++ else if (! reg_ok_strict
++ && GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && (XEXP (x, 0) == virtual_stack_vars_rtx
++ || XEXP (x, 0) == arg_pointer_rtx)
++ && GET_CODE (XEXP (x, 1)) == CONST_INT)
++ ret = 1;
++ else if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
++ ret = 1;
++ else if (mode != TImode
++ && mode != TFmode
++ && mode != TDmode
++ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
++ || TARGET_POWERPC64
++ || (mode != DFmode && mode != DDmode)
++ || (TARGET_E500_DOUBLE && mode != DDmode))
++ && (TARGET_POWERPC64 || mode != DImode)
++ && !avoiding_indexed_address_p (mode)
++ && legitimate_indexed_address_p (x, reg_ok_strict))
++ ret = 1;
++ else if (GET_CODE (x) == PRE_MODIFY
++ && VECTOR_MEM_VSX_P (mode)
++ && TARGET_UPDATE
++ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)
++ && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
++ ret = 1;
++ else if (GET_CODE (x) == PRE_MODIFY
++ && mode != TImode
++ && mode != TFmode
++ && mode != TDmode
++ && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
++ || TARGET_POWERPC64
++ || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
++ && (TARGET_POWERPC64 || mode != DImode)
++ && !VECTOR_MEM_ALTIVEC_P (mode)
++ && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
++ /* Restrict addressing for DI because of our SUBREG hackery. */
++ && !(TARGET_E500_DOUBLE
++ && (mode == DFmode || mode == DDmode || mode == DImode))
++ && TARGET_UPDATE
++ && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
++ && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
++ || (!avoiding_indexed_address_p (mode)
++ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
++ && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
++ ret = 1;
++ else if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
++ ret = 1;
++ else
++ ret = 0;
++
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_legitimate_address: return = %d, mode = %s, "
++ "strict = %d\n",
++ ret,
++ GET_MODE_NAME (mode),
++ reg_ok_strict);
++ debug_rtx (orig_x);
++ }
++
++ return ret;
+ }
+
+ /* Go to LABEL if ADDR (a legitimate address expression)
+@@ -4499,28 +5054,40 @@ rs6000_legitimate_address (enum machine_
+ bool
+ rs6000_mode_dependent_address (rtx addr)
+ {
++ bool ret = false;
++
+ switch (GET_CODE (addr))
+ {
+ case PLUS:
+ if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
+- return val + 12 + 0x8000 >= 0x10000;
++ ret = (val + 12 + 0x8000 >= 0x10000);
+ }
+ break;
+
+ case LO_SUM:
+- return true;
++ ret = true;
++ break;
+
+ /* Auto-increment cases are now treated generically in recog.c. */
+ case PRE_MODIFY:
+- return TARGET_UPDATE;
++ ret = (TARGET_UPDATE != 0);
++ break;
+
+ default:
+ break;
+ }
+
+- return false;
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_mode_dependent_address: ret = %d\n",
++ (int)ret);
++ debug_rtx (addr);
++ }
++
++ return ret;
+ }
+
+ /* Implement FIND_BASE_TERM. */
+@@ -4571,43 +5138,6 @@ rs6000_offsettable_memref_p (rtx op)
+ return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1);
+ }
+
+-/* Return number of consecutive hard regs needed starting at reg REGNO
+- to hold something of mode MODE.
+- This is ordinarily the length in words of a value of mode MODE
+- but can be less for certain modes in special long registers.
+-
+- For the SPE, GPRs are 64 bits but only 32 bits are visible in
+- scalar instructions. The upper 32 bits are only available to the
+- SIMD instructions.
+-
+- POWER and PowerPC GPRs hold 32 bits worth;
+- PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
+-
+-int
+-rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
+-{
+- if (FP_REGNO_P (regno))
+- return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+-
+- if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+- return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
+-
+- if (ALTIVEC_REGNO_P (regno))
+- return
+- (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
+-
+- /* The value returned for SCmode in the E500 double case is 2 for
+- ABI compatibility; storing an SCmode value in a single register
+- would require function_arg and rs6000_spe_function_arg to handle
+- SCmode so as to pass the value correctly in a pair of
+- registers. */
+- if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
+- && !DECIMAL_FLOAT_MODE_P (mode))
+- return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+-
+- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+-}
+-
+ /* Change register usage conditional on target flags. */
+ void
+ rs6000_conditional_register_usage (void)
+@@ -4672,14 +5202,14 @@ rs6000_conditional_register_usage (void)
+ = call_really_used_regs[14] = 1;
+ }
+
+- if (!TARGET_ALTIVEC)
++ if (!TARGET_ALTIVEC && !TARGET_VSX)
+ {
+ for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
+ fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
+ call_really_used_regs[VRSAVE_REGNO] = 1;
+ }
+
+- if (TARGET_ALTIVEC)
++ if (TARGET_ALTIVEC || TARGET_VSX)
+ global_regs[VSCR_REGNO] = 1;
+
+ if (TARGET_ALTIVEC_ABI)
+@@ -5101,6 +5631,8 @@ rs6000_emit_move (rtx dest, rtx source,
+ 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]);
+@@ -5270,6 +5802,9 @@ rs6000_emit_move (rtx dest, rtx source,
+ break;
+
+ case TImode:
++ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (TImode))
++ break;
++
+ rs6000_eliminate_indexed_memrefs (operands);
+
+ if (TARGET_POWER)
+@@ -5285,7 +5820,7 @@ rs6000_emit_move (rtx dest, rtx source,
+ break;
+
+ default:
+- gcc_unreachable ();
++ fatal_insn ("bad move", gen_rtx_SET (VOIDmode, dest, source));
+ }
+
+ /* Above, we may have called force_const_mem which may have returned
+@@ -5305,10 +5840,10 @@ rs6000_emit_move (rtx dest, rtx source,
+ && TARGET_HARD_FLOAT && TARGET_FPRS)
+
+ /* Nonzero if we can use an AltiVec register to pass this arg. */
+-#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
+- (ALTIVEC_VECTOR_MODE (MODE) \
+- && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
+- && TARGET_ALTIVEC_ABI \
++#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
++ ((ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)) \
++ && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
++ && TARGET_ALTIVEC_ABI \
+ && (NAMED))
+
+ /* Return a nonzero value to say to return the function value in
+@@ -5549,7 +6084,7 @@ function_arg_boundary (enum machine_mode
+ && int_size_in_bytes (type) >= 8
+ && int_size_in_bytes (type) < 16))
+ return 64;
+- else if (ALTIVEC_VECTOR_MODE (mode)
++ else if ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) >= 16))
+ return 128;
+@@ -5694,7 +6229,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
+ cum->nargs_prototype--;
+
+ if (TARGET_ALTIVEC_ABI
+- && (ALTIVEC_VECTOR_MODE (mode)
++ && ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) == 16)))
+ {
+@@ -6288,7 +6823,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum
+ else
+ return gen_rtx_REG (mode, cum->vregno);
+ else if (TARGET_ALTIVEC_ABI
+- && (ALTIVEC_VECTOR_MODE (mode)
++ && ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) == 16)))
+ {
+@@ -7212,10 +7747,13 @@ static const struct builtin_description
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
++ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
++ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
+@@ -7289,18 +7827,18 @@ static struct builtin_description bdesc_
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv16qi, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv8hi, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv4si, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv4sf, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
++ { MASK_ALTIVEC, CODE_FOR_vector_gev4sf, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtuv16qi, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtuv8hi, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtuv4si, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv16qi, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv8hi, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv4si, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv4sf, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
+ { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
+@@ -7331,7 +7869,7 @@ static struct builtin_description bdesc_
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
++ { MASK_ALTIVEC, CODE_FOR_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
+ { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
+@@ -7796,6 +8334,11 @@ static struct builtin_description bdesc_
+ { 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_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 },
++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
++
+ /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
+ end with SPE_BUILTIN_EVSUBFUSIAAW. */
+ { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
+@@ -8352,16 +8895,16 @@ altivec_expand_ld_builtin (tree exp, rtx
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
+- icode = CODE_FOR_altivec_lvx_v16qi;
++ icode = CODE_FOR_vector_load_v16qi;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
+- icode = CODE_FOR_altivec_lvx_v8hi;
++ icode = CODE_FOR_vector_load_v8hi;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
+- icode = CODE_FOR_altivec_lvx_v4si;
++ icode = CODE_FOR_vector_load_v4si;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
+- icode = CODE_FOR_altivec_lvx_v4sf;
++ icode = CODE_FOR_vector_load_v4sf;
+ break;
+ default:
+ *expandedp = false;
+@@ -8405,16 +8948,16 @@ altivec_expand_st_builtin (tree exp, rtx
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
+- icode = CODE_FOR_altivec_stvx_v16qi;
++ icode = CODE_FOR_vector_store_v16qi;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
+- icode = CODE_FOR_altivec_stvx_v8hi;
++ icode = CODE_FOR_vector_store_v8hi;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
+- icode = CODE_FOR_altivec_stvx_v4si;
++ icode = CODE_FOR_vector_store_v4si;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
+- icode = CODE_FOR_altivec_stvx_v4sf;
++ icode = CODE_FOR_vector_store_v4sf;
+ break;
+ default:
+ *expandedp = false;
+@@ -9372,6 +9915,8 @@ rs6000_init_builtins (void)
+ {
+ V2SI_type_node = build_vector_type (intSI_type_node, 2);
+ V2SF_type_node = build_vector_type (float_type_node, 2);
++ V2DI_type_node = build_vector_type (intDI_type_node, 2);
++ V2DF_type_node = build_vector_type (double_type_node, 2);
+ V4HI_type_node = build_vector_type (intHI_type_node, 4);
+ V4SI_type_node = build_vector_type (intSI_type_node, 4);
+ V4SF_type_node = build_vector_type (float_type_node, 4);
+@@ -9404,7 +9949,10 @@ rs6000_init_builtins (void)
+ uintHI_type_internal_node = unsigned_intHI_type_node;
+ intSI_type_internal_node = intSI_type_node;
+ uintSI_type_internal_node = unsigned_intSI_type_node;
++ intDI_type_internal_node = intDI_type_node;
++ uintDI_type_internal_node = unsigned_intDI_type_node;
+ float_type_internal_node = float_type_node;
++ double_type_internal_node = float_type_node;
+ void_type_internal_node = void_type_node;
+
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+@@ -9462,13 +10010,18 @@ rs6000_init_builtins (void)
+ get_identifier ("__vector __pixel"),
+ pixel_V8HI_type_node));
+
++ if (TARGET_VSX)
++ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
++ get_identifier ("__vector double"),
++ V2DF_type_node));
++
+ if (TARGET_PAIRED_FLOAT)
+ paired_init_builtins ();
+ if (TARGET_SPE)
+ spe_init_builtins ();
+ if (TARGET_ALTIVEC)
+ altivec_init_builtins ();
+- if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT)
++ if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT || TARGET_VSX)
+ rs6000_common_init_builtins ();
+ if (TARGET_PPC_GFXOPT)
+ {
+@@ -10407,6 +10960,26 @@ rs6000_common_init_builtins (void)
+ tree int_ftype_v8hi_v8hi
+ = build_function_type_list (integer_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
++ tree v2df_ftype_v2df_v2df_v2df
++ = build_function_type_list (V2DF_type_node,
++ V2DF_type_node, V2DF_type_node,
++ V2DF_type_node, NULL_TREE);
++ tree v2di_ftype_v2di_v2di_v2di
++ = build_function_type_list (V2DI_type_node,
++ V2DI_type_node, V2DI_type_node,
++ V2DI_type_node, NULL_TREE);
++ tree v2df_ftype_v2df_v2df_v16qi
++ = build_function_type_list (V2DF_type_node,
++ V2DF_type_node, V2DF_type_node,
++ V16QI_type_node, NULL_TREE);
++ tree v2di_ftype_v2di_v2di_v16qi
++ = build_function_type_list (V2DI_type_node,
++ V2DI_type_node, V2DI_type_node,
++ V16QI_type_node, NULL_TREE);
++ tree v4sf_ftype_v4si
++ = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
++ tree v4si_ftype_v4sf
++ = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
+
+ /* Add the simple ternary operators. */
+ d = bdesc_3arg;
+@@ -10443,6 +11016,12 @@ rs6000_common_init_builtins (void)
+ case VOIDmode:
+ type = opaque_ftype_opaque_opaque_opaque;
+ break;
++ case V2DImode:
++ type = v2di_ftype_v2di_v2di_v2di;
++ break;
++ case V2DFmode:
++ type = v2df_ftype_v2df_v2df_v2df;
++ break;
+ case V4SImode:
+ type = v4si_ftype_v4si_v4si_v4si;
+ break;
+@@ -10466,6 +11045,12 @@ rs6000_common_init_builtins (void)
+ {
+ switch (mode0)
+ {
++ case V2DImode:
++ type = v2di_ftype_v2di_v2di_v16qi;
++ break;
++ case V2DFmode:
++ type = v2df_ftype_v2df_v2df_v16qi;
++ break;
+ case V4SImode:
+ type = v4si_ftype_v4si_v4si_v16qi;
+ break;
+@@ -10721,6 +11306,10 @@ rs6000_common_init_builtins (void)
+ type = v2si_ftype_v2sf;
+ else if (mode0 == V2SImode && mode1 == QImode)
+ type = v2si_ftype_char;
++ else if (mode0 == V4SImode && mode1 == V4SFmode)
++ type = v4si_ftype_v4sf;
++ else if (mode0 == V4SFmode && mode1 == V4SImode)
++ type = v4sf_ftype_v4si;
+ else
+ gcc_unreachable ();
+
+@@ -11601,13 +12190,101 @@ rs6000_instantiate_decls (void)
+ instantiate_decl_rtl (cfun->machine->sdmode_stack_slot);
+ }
+
++/* Given an rtx X being reloaded into a reg required to be
++ in class CLASS, return the class of reg to actually use.
++ In general this is just CLASS; but on some machines
++ in some cases it is preferable to use a more restrictive class.
++
++ On the RS/6000, we have to return NO_REGS when we want to reload a
++ floating-point CONST_DOUBLE to force it to be copied to memory.
++
++ We also don't want to reload integer values into floating-point
++ registers if we can at all help it. In fact, this can
++ cause reload to die, if it tries to generate a reload of CTR
++ into a FP register and discovers it doesn't have the memory location
++ required.
++
++ ??? Would it be a good idea to have reload do the converse, that is
++ try to reload floating modes into FP registers if possible?
++ */
++
++enum reg_class
++rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
++{
++ enum machine_mode mode = GET_MODE (x);
++
++ if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
++ && VSX_REG_CLASS_P (rclass))
++ return rclass;
++
++ if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS
++ && easy_vector_constant (x, mode))
++ return rclass;
++
++ if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
++ return NO_REGS;
++
++ if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
++ return GENERAL_REGS;
++
++ /* For VSX, prefer the traditional registers. */
++ if (rclass == VSX_REGS)
++ {
++ if (mode == DFmode)
++ return FLOAT_REGS;
++
++ if (ALTIVEC_VECTOR_MODE (mode))
++ return ALTIVEC_REGS;
++ }
++
++ return rclass;
++}
++
++/* If we are copying between FP or AltiVec registers and anything else, we need
++ a memory location. The exception is when we are targeting ppc64 and the
++ move to/from fpr to gpr instructions are available. Also, under VSX, you
++ can copy vector registers from the FP register set to the Altivec register
++ set and vice versa. */
++
++bool
++rs6000_secondary_memory_needed (enum reg_class class1,
++ enum reg_class class2,
++ enum machine_mode mode)
++{
++ if (class1 == class2)
++ return false;
++
++ if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1)
++ && VSX_REG_CLASS_P (class2))
++ return false;
++
++ if (class1 == FLOAT_REGS
++ && (!TARGET_MFPGPR || !TARGET_POWERPC64
++ || ((mode != DFmode)
++ && (mode != DDmode)
++ && (mode != DImode))))
++ return true;
++
++ if (class2 == FLOAT_REGS
++ && (!TARGET_MFPGPR || !TARGET_POWERPC64
++ || ((mode != DFmode)
++ && (mode != DDmode)
++ && (mode != DImode))))
++ return true;
++
++ if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
++ return true;
++
++ return false;
++}
++
+ /* Return the register class of a scratch register needed to copy IN into
+ or out of a register in RCLASS in MODE. If it can be done directly,
+ NO_REGS is returned. */
+
+ enum reg_class
+ rs6000_secondary_reload_class (enum reg_class rclass,
+- enum machine_mode mode ATTRIBUTE_UNUSED,
++ enum machine_mode mode,
+ rtx in)
+ {
+ int regno;
+@@ -11663,6 +12340,13 @@ rs6000_secondary_reload_class (enum reg_
+ && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
+ return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+
++ /* Memory, and FP/altivec registers can go into fp/altivec registers under
++ VSX. */
++ if (TARGET_VSX
++ && (regno == -1 || VSX_REGNO_P (regno))
++ && VSX_REG_CLASS_P (rclass))
++ return NO_REGS;
++
+ /* Memory, and AltiVec registers can go into AltiVec registers. */
+ if ((regno == -1 || ALTIVEC_REGNO_P (regno))
+ && rclass == ALTIVEC_REGS)
+@@ -11676,6 +12360,28 @@ rs6000_secondary_reload_class (enum reg_
+ /* Otherwise, we need GENERAL_REGS. */
+ return GENERAL_REGS;
+ }
++
++/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
++
++bool
++rs6000_cannot_change_mode_class (enum machine_mode from,
++ enum machine_mode to,
++ enum reg_class rclass)
++{
++ return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
++ ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
++ || TARGET_IEEEQUAD)
++ && reg_classes_intersect_p (FLOAT_REGS, rclass))
++ : (((TARGET_E500_DOUBLE
++ && ((((to) == DFmode) + ((from) == DFmode)) == 1
++ || (((to) == TFmode) + ((from) == TFmode)) == 1
++ || (((to) == DDmode) + ((from) == DDmode)) == 1
++ || (((to) == TDmode) + ((from) == TDmode)) == 1
++ || (((to) == DImode) + ((from) == DImode)) == 1))
++ || (TARGET_SPE
++ && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
++ && reg_classes_intersect_p (GENERAL_REGS, rclass)));
++}
+ \f
+ /* Given a comparison operation, return the bit number in CCR to test. We
+ know this is a valid comparison.
+@@ -12406,6 +13112,26 @@ print_operand (FILE *file, rtx x, int co
+ fprintf (file, "%d", i + 1);
+ return;
+
++ case 'x':
++ /* X is a FPR or Altivec register used in a VSX context. */
++ if (GET_CODE (x) != REG || !VSX_REGNO_P (REGNO (x)))
++ output_operand_lossage ("invalid %%x value");
++ else
++ {
++ int reg = REGNO (x);
++ int vsx_reg = (FP_REGNO_P (reg)
++ ? reg - 32
++ : reg - FIRST_ALTIVEC_REGNO + 32);
++
++#ifdef TARGET_REGNAMES
++ if (TARGET_REGNAMES)
++ fprintf (file, "%%vs%d", vsx_reg);
++ else
++#endif
++ fprintf (file, "%d", vsx_reg);
++ }
++ return;
++
+ case 'X':
+ if (GET_CODE (x) == MEM
+ && (legitimate_indexed_address_p (XEXP (x, 0), 0)
+@@ -12518,13 +13244,16 @@ print_operand (FILE *file, rtx x, int co
+
+ /* Fall through. Must be [reg+reg]. */
+ }
+- if (TARGET_ALTIVEC
++ if (VECTOR_MEM_ALTIVEC_P (GET_MODE (x))
+ && GET_CODE (tmp) == AND
+ && GET_CODE (XEXP (tmp, 1)) == CONST_INT
+ && INTVAL (XEXP (tmp, 1)) == -16)
+ tmp = XEXP (tmp, 0);
++ else if (VECTOR_MEM_VSX_P (GET_MODE (x))
++ && GET_CODE (tmp) == PRE_MODIFY)
++ tmp = XEXP (tmp, 1);
+ if (GET_CODE (tmp) == REG)
+- fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
++ fprintf (file, "%s,%s", reg_names[0], reg_names[REGNO (tmp)]);
+ else
+ {
+ if (!GET_CODE (tmp) == PLUS
+@@ -13296,55 +14025,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr
+ return string;
+ }
+
+-/* Return insn index for the vector compare instruction for given CODE,
+- and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is
+- not available. */
++/* Return insn for VSX comparisons. */
+
+-static int
+-get_vec_cmp_insn (enum rtx_code code,
+- enum machine_mode dest_mode,
+- enum machine_mode op_mode)
++static rtx
++rs6000_emit_vector_compare_vsx (enum rtx_code code,
++ rtx mask,
++ rtx op0,
++ rtx op1)
+ {
+- if (!TARGET_ALTIVEC)
+- return INSN_NOT_AVAILABLE;
+-
+ switch (code)
+ {
++ default:
++ break;
++
+ case EQ:
+- if (dest_mode == V16QImode && op_mode == V16QImode)
+- return UNSPEC_VCMPEQUB;
+- if (dest_mode == V8HImode && op_mode == V8HImode)
+- return UNSPEC_VCMPEQUH;
+- if (dest_mode == V4SImode && op_mode == V4SImode)
+- return UNSPEC_VCMPEQUW;
+- if (dest_mode == V4SImode && op_mode == V4SFmode)
+- return UNSPEC_VCMPEQFP;
++ case GT:
++ case GE:
++ emit_insn (gen_rtx_SET (VOIDmode,
++ mask,
++ gen_rtx_fmt_ee (code, GET_MODE (mask),
++ op0,
++ op1)));
++ return mask;
++ }
++
++ return NULL_RTX;
++}
++
++/* Return insn for Altivec comparisons. */
++
++static rtx
++rs6000_emit_vector_compare_altivec (enum rtx_code code,
++ rtx mask,
++ rtx op0,
++ rtx op1)
++{
++ switch (code)
++ {
++ default:
+ break;
++
+ case GE:
+- if (dest_mode == V4SImode && op_mode == V4SFmode)
+- return UNSPEC_VCMPGEFP;
++ if (GET_MODE (mask) != V4SFmode)
++ return NULL_RTX;
++ /* fall through */
++ case EQ:
+ case GT:
+- if (dest_mode == V16QImode && op_mode == V16QImode)
+- return UNSPEC_VCMPGTSB;
+- if (dest_mode == V8HImode && op_mode == V8HImode)
+- return UNSPEC_VCMPGTSH;
+- if (dest_mode == V4SImode && op_mode == V4SImode)
+- return UNSPEC_VCMPGTSW;
+- if (dest_mode == V4SImode && op_mode == V4SFmode)
+- return UNSPEC_VCMPGTFP;
+- break;
+ case GTU:
+- if (dest_mode == V16QImode && op_mode == V16QImode)
+- return UNSPEC_VCMPGTUB;
+- if (dest_mode == V8HImode && op_mode == V8HImode)
+- return UNSPEC_VCMPGTUH;
+- if (dest_mode == V4SImode && op_mode == V4SImode)
+- return UNSPEC_VCMPGTUW;
+- break;
+- default:
+- break;
++ emit_insn (gen_rtx_SET (VOIDmode,
++ mask,
++ gen_rtx_fmt_ee (code, GET_MODE (mask),
++ op0,
++ op1)));
++ return mask;
+ }
+- return INSN_NOT_AVAILABLE;
++
++ return NULL_RTX;
+ }
+
+ /* Emit vector compare for operands OP0 and OP1 using code RCODE.
+@@ -13355,129 +14091,111 @@ rs6000_emit_vector_compare (enum rtx_cod
+ rtx op0, rtx op1,
+ enum machine_mode dmode)
+ {
+- int vec_cmp_insn;
+ rtx mask;
+- enum machine_mode dest_mode;
+- enum machine_mode op_mode = GET_MODE (op1);
++ bool swap_operands = false;
++ bool try_again = false;
+
+- gcc_assert (TARGET_ALTIVEC);
++ gcc_assert (TARGET_ALTIVEC || TARGET_VSX);
+ gcc_assert (GET_MODE (op0) == GET_MODE (op1));
+
+- /* Floating point vector compare instructions uses destination V4SImode.
+- Move destination to appropriate mode later. */
+- if (dmode == V4SFmode)
+- dest_mode = V4SImode;
+- else
+- dest_mode = dmode;
++ mask = gen_reg_rtx (dmode);
+
+- mask = gen_reg_rtx (dest_mode);
+- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
++ /* Try for VSX before Altivec. */
++ if (TARGET_VSX && VSX_VECTOR_MODE (dmode))
++ {
++ rtx vsx = rs6000_emit_vector_compare_vsx (rcode, mask, op0, op1);
++ if (vsx)
++ return vsx;
++ }
++ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dmode))
++ {
++ rtx av = rs6000_emit_vector_compare_altivec (rcode, mask, op0, op1);
++ if (av)
++ return av;
++ }
+
+- if (vec_cmp_insn == INSN_NOT_AVAILABLE)
++ switch (rcode)
+ {
+- bool swap_operands = false;
+- bool try_again = false;
+- switch (rcode)
+- {
+- case LT:
+- rcode = GT;
+- swap_operands = true;
+- try_again = true;
+- break;
+- case LTU:
+- rcode = GTU;
+- swap_operands = true;
+- try_again = true;
+- break;
+- case NE:
+- case UNLE:
+- case UNLT:
+- case UNGE:
+- case UNGT:
+- /* Invert condition and try again.
+- e.g., A != B becomes ~(A==B). */
+- {
+- enum rtx_code rev_code;
+- enum insn_code nor_code;
+- rtx eq_rtx;
+-
+- rev_code = reverse_condition_maybe_unordered (rcode);
+- eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1,
+- dest_mode);
+-
+- nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code;
+- gcc_assert (nor_code != CODE_FOR_nothing);
+- emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
++ case LT:
++ rcode = GT;
++ swap_operands = true;
++ try_again = true;
++ break;
++ case LTU:
++ rcode = GTU;
++ swap_operands = true;
++ try_again = true;
++ break;
++ case NE:
++ case UNLE:
++ case UNLT:
++ case UNGE:
++ case UNGT:
++ /* Invert condition and try again.
++ e.g., A != B becomes ~(A==B). */
++ {
++ enum rtx_code rev_code;
++ enum insn_code nor_code;
++ rtx eq_rtx;
++
++ rev_code = reverse_condition_maybe_unordered (rcode);
++ eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, dmode);
++
++ nor_code = optab_handler (one_cmpl_optab, (int)dmode)->insn_code;
++ gcc_assert (nor_code != CODE_FOR_nothing);
++ emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
++ return mask;
++ }
++ break;
++ case GE:
++ case GEU:
++ case LE:
++ case LEU:
++ /* Try GT/GTU/LT/LTU OR EQ */
++ {
++ rtx c_rtx, eq_rtx;
++ enum insn_code ior_code;
++ enum rtx_code new_code;
+
+- if (dmode != dest_mode)
+- {
+- rtx temp = gen_reg_rtx (dest_mode);
+- convert_move (temp, mask, 0);
+- return temp;
+- }
+- return mask;
+- }
+- break;
+- case GE:
+- case GEU:
+- case LE:
+- case LEU:
+- /* Try GT/GTU/LT/LTU OR EQ */
++ switch (rcode)
+ {
+- rtx c_rtx, eq_rtx;
+- enum insn_code ior_code;
+- enum rtx_code new_code;
+-
+- switch (rcode)
+- {
+- case GE:
+- new_code = GT;
+- break;
+-
+- case GEU:
+- new_code = GTU;
+- break;
++ case GE:
++ new_code = GT;
++ break;
+
+- case LE:
+- new_code = LT;
+- break;
++ case GEU:
++ new_code = GTU;
++ break;
+
+- case LEU:
+- new_code = LTU;
+- break;
++ case LE:
++ new_code = LT;
++ break;
+
+- default:
+- gcc_unreachable ();
+- }
++ case LEU:
++ new_code = LTU;
++ break;
+
+- c_rtx = rs6000_emit_vector_compare (new_code,
+- op0, op1, dest_mode);
+- eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
+- dest_mode);
+-
+- ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code;
+- gcc_assert (ior_code != CODE_FOR_nothing);
+- emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
+- if (dmode != dest_mode)
+- {
+- rtx temp = gen_reg_rtx (dest_mode);
+- convert_move (temp, mask, 0);
+- return temp;
+- }
+- return mask;
++ default:
++ gcc_unreachable ();
+ }
+- break;
+- default:
+- gcc_unreachable ();
+- }
+
+- if (try_again)
+- {
+- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
+- /* You only get two chances. */
+- gcc_assert (vec_cmp_insn != INSN_NOT_AVAILABLE);
+- }
++ c_rtx = rs6000_emit_vector_compare (new_code,
++ op0, op1, dmode);
++ eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
++ dmode);
++
++ ior_code = optab_handler (ior_optab, (int)dmode)->insn_code;
++ gcc_assert (ior_code != CODE_FOR_nothing);
++ emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
++ return mask;
++ }
++ break;
++ default:
++ gcc_unreachable ();
++ }
+
++ if (try_again)
++ {
+ if (swap_operands)
+ {
+ rtx tmp;
+@@ -13485,69 +14203,23 @@ rs6000_emit_vector_compare (enum rtx_cod
+ op0 = op1;
+ op1 = tmp;
+ }
+- }
+-
+- emit_insn (gen_rtx_SET (VOIDmode, mask,
+- gen_rtx_UNSPEC (dest_mode,
+- gen_rtvec (2, op0, op1),
+- vec_cmp_insn)));
+- if (dmode != dest_mode)
+- {
+- rtx temp = gen_reg_rtx (dest_mode);
+- convert_move (temp, mask, 0);
+- return temp;
+- }
+- return mask;
+-}
+-
+-/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
+- valid insn doesn exist for given mode. */
+
+-static int
+-get_vsel_insn (enum machine_mode mode)
+-{
+- switch (mode)
+- {
+- case V4SImode:
+- return UNSPEC_VSEL4SI;
+- break;
+- case V4SFmode:
+- return UNSPEC_VSEL4SF;
+- break;
+- case V8HImode:
+- return UNSPEC_VSEL8HI;
+- break;
+- case V16QImode:
+- return UNSPEC_VSEL16QI;
+- break;
+- default:
+- return INSN_NOT_AVAILABLE;
+- break;
++ if (TARGET_VSX && VSX_VECTOR_MODE (dmode))
++ {
++ rtx vsx = rs6000_emit_vector_compare_vsx (rcode, mask, op0, op1);
++ if (vsx)
++ return vsx;
++ }
++ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dmode))
++ {
++ rtx av = rs6000_emit_vector_compare_altivec (rcode, mask, op0, op1);
++ if (av)
++ return av;
++ }
+ }
+- return INSN_NOT_AVAILABLE;
+-}
+-
+-/* Emit vector select insn where DEST is destination using
+- operands OP1, OP2 and MASK. */
+-
+-static void
+-rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
+-{
+- rtx t, temp;
+- enum machine_mode dest_mode = GET_MODE (dest);
+- int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
+
+- temp = gen_reg_rtx (dest_mode);
+-
+- /* For each vector element, select op1 when mask is 1 otherwise
+- select op2. */
+- t = gen_rtx_SET (VOIDmode, temp,
+- gen_rtx_UNSPEC (dest_mode,
+- gen_rtvec (3, op2, op1, mask),
+- vsel_insn_index));
+- emit_insn (t);
+- emit_move_insn (dest, temp);
+- return;
++ /* You only get two chances. */
++ gcc_unreachable ();
+ }
+
+ /* Emit vector conditional expression.
+@@ -13562,15 +14234,29 @@ rs6000_emit_vector_cond_expr (rtx dest,
+ enum rtx_code rcode = GET_CODE (cond);
+ rtx mask;
+
+- if (!TARGET_ALTIVEC)
++ if (!TARGET_ALTIVEC && !TARGET_VSX)
+ return 0;
+
+ /* Get the vector mask for the given relational operations. */
+ mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
+
+- rs6000_emit_vector_select (dest, op1, op2, mask);
++ if (!mask)
++ return 0;
+
+- return 1;
++ if ((TARGET_VSX && VSX_VECTOR_MOVE_MODE (dest_mode))
++ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dest_mode)))
++ {
++ rtx cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx);
++ emit_insn (gen_rtx_SET (VOIDmode,
++ dest,
++ gen_rtx_IF_THEN_ELSE (dest_mode,
++ cond2,
++ op1,
++ op2)));
++ return 1;
++ }
++
++ return 0;
+ }
+
+ /* Emit a conditional move: move TRUE_COND to DEST if OP of the
+@@ -13766,8 +14452,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
+ {
+ rtx condition_rtx, cr;
+
+- /* All isel implementations thus far are 32-bits. */
+- if (GET_MODE (rs6000_compare_op0) != SImode)
++ if (GET_MODE (rs6000_compare_op0) != SImode
++ && (!TARGET_POWERPC64 || GET_MODE (rs6000_compare_op0) != DImode))
+ return 0;
+
+ /* We still have to do the compare, because isel doesn't do a
+@@ -13776,12 +14462,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
+ condition_rtx = rs6000_generate_compare (GET_CODE (op));
+ cr = XEXP (condition_rtx, 0);
+
+- if (GET_MODE (cr) == CCmode)
+- emit_insn (gen_isel_signed (dest, condition_rtx,
+- true_cond, false_cond, cr));
++ if (GET_MODE (rs6000_compare_op0) == SImode)
++ {
++ if (GET_MODE (cr) == CCmode)
++ emit_insn (gen_isel_signed_si (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ else
++ emit_insn (gen_isel_unsigned_si (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ }
+ else
+- emit_insn (gen_isel_unsigned (dest, condition_rtx,
+- true_cond, false_cond, cr));
++ {
++ if (GET_MODE (cr) == CCmode)
++ emit_insn (gen_isel_signed_di (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ else
++ emit_insn (gen_isel_unsigned_di (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ }
+
+ return 1;
+ }
+@@ -13808,6 +14506,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c
+ enum rtx_code c;
+ rtx target;
+
++ /* VSX/altivec have direct min/max insns. */
++ if ((code == SMAX || code == SMIN) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
++ {
++ emit_insn (gen_rtx_SET (VOIDmode,
++ dest,
++ gen_rtx_fmt_ee (code, mode, op0, op1)));
++ return;
++ }
++
+ if (code == SMAX || code == SMIN)
+ c = GE;
+ else
+@@ -15785,6 +16492,7 @@ emit_frame_save (rtx frame_reg, rtx fram
+
+ /* Some cases that need register indexed addressing. */
+ if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
++ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode)
+ || (TARGET_SPE_ABI
+ && SPE_VECTOR_MODE (mode)
+@@ -19320,6 +20028,7 @@ rs6000_issue_rate (void)
+ case CPU_POWER4:
+ case CPU_POWER5:
+ case CPU_POWER6:
++ case CPU_POWER7:
+ return 5;
+ default:
+ return 1;
+@@ -19921,6 +20630,41 @@ insn_must_be_first_in_group (rtx insn)
+ break;
+ }
+ break;
++ case PROCESSOR_POWER7:
++ type = get_attr_type (insn);
++
++ switch (type)
++ {
++ case TYPE_CR_LOGICAL:
++ case TYPE_MFCR:
++ case TYPE_MFCRF:
++ case TYPE_MTCR:
++ case TYPE_IDIV:
++ case TYPE_LDIV:
++ case TYPE_COMPARE:
++ case TYPE_DELAYED_COMPARE:
++ case TYPE_VAR_DELAYED_COMPARE:
++ case TYPE_ISYNC:
++ case TYPE_LOAD_L:
++ case TYPE_STORE_C:
++ case TYPE_LOAD_U:
++ case TYPE_LOAD_UX:
++ case TYPE_LOAD_EXT:
++ case TYPE_LOAD_EXT_U:
++ case TYPE_LOAD_EXT_UX:
++ case TYPE_STORE_U:
++ case TYPE_STORE_UX:
++ case TYPE_FPLOAD_U:
++ case TYPE_FPLOAD_UX:
++ case TYPE_FPSTORE_U:
++ case TYPE_FPSTORE_UX:
++ case TYPE_MFJMPR:
++ case TYPE_MTJMPR:
++ return true;
++ default:
++ break;
++ }
++ break;
+ default:
+ break;
+ }
+@@ -19982,6 +20726,23 @@ insn_must_be_last_in_group (rtx insn)
+ break;
+ }
+ break;
++ case PROCESSOR_POWER7:
++ type = get_attr_type (insn);
++
++ switch (type)
++ {
++ case TYPE_ISYNC:
++ case TYPE_SYNC:
++ case TYPE_LOAD_L:
++ case TYPE_STORE_C:
++ case TYPE_LOAD_EXT_U:
++ case TYPE_LOAD_EXT_UX:
++ case TYPE_STORE_UX:
++ return true;
++ default:
++ break;
++ }
++ break;
+ default:
+ break;
+ }
+@@ -20554,8 +21315,8 @@ rs6000_handle_altivec_attribute (tree *n
+ 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");
++ else if (type == double_type_node && !TARGET_VSX)
++ 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)
+@@ -20581,6 +21342,7 @@ rs6000_handle_altivec_attribute (tree *n
+ 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. */
+@@ -22116,7 +22878,7 @@ rs6000_register_move_cost (enum machine_
+ if (! reg_classes_intersect_p (to, GENERAL_REGS))
+ from = to;
+
+- if (from == FLOAT_REGS || from == ALTIVEC_REGS)
++ if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS)
+ return (rs6000_memory_move_cost (mode, from, 0)
+ + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
+
+@@ -22136,6 +22898,12 @@ rs6000_register_move_cost (enum machine_
+ return 2 * hard_regno_nregs[0][mode];
+ }
+
++ /* If we have VSX, we can easily move between FPR or Altivec registers. */
++ else if (TARGET_VSX
++ && ((from == VSX_REGS || from == FLOAT_REGS || from == ALTIVEC_REGS)
++ || (to == VSX_REGS || to == FLOAT_REGS || to == ALTIVEC_REGS)))
++ return 2;
++
+ /* Moving between two similar registers is just one instruction. */
+ else if (reg_classes_intersect_p (to, from))
+ return (mode == TFmode || mode == TDmode) ? 4 : 2;
+@@ -22376,8 +23144,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src)
+ emit_label (XEXP (label, 0));
+ }
+
+-/* Emit popcount intrinsic on TARGET_POPCNTB targets. DST is the
+- target, and SRC is the argument operand. */
++/* Emit popcount intrinsic on TARGET_POPCNTB (Power5) and TARGET_POPCNTD
++ (Power7) targets. DST is the target, and SRC is the argument operand. */
+
+ void
+ rs6000_emit_popcount (rtx dst, rtx src)
+@@ -22385,6 +23153,16 @@ rs6000_emit_popcount (rtx dst, rtx src)
+ enum machine_mode mode = GET_MODE (dst);
+ rtx tmp1, tmp2;
+
++ /* Use the PPC ISA 2.06 popcnt{w,d} instruction if we can. */
++ if (TARGET_POPCNTD)
++ {
++ if (mode == SImode)
++ emit_insn (gen_popcntwsi2 (dst, src));
++ else
++ emit_insn (gen_popcntddi2 (dst, src));
++ return;
++ }
++
+ tmp1 = gen_reg_rtx (mode);
+
+ if (mode == SImode)
+@@ -22797,7 +23575,7 @@ rs6000_vector_mode_supported_p (enum mac
+ if (TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return true;
+
+- else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
++ else if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
+ return true;
+
+ else
+--- gcc/config/rs6000/vsx.md (.../trunk) (revision 0)
++++ gcc/config/rs6000/vsx.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,864 @@
++;; 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 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])
++
++;; 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")
++ (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")
++ (TI "sp")])
++
++;; Map into the register class used
++(define_mode_attr VSr [(V16QI "v")
++ (V8HI "v")
++ (V4SI "v")
++ (V4SF "wf")
++ (V2DI "wd")
++ (V2DF "wd")
++ (TI "wd")])
++
++;; Same size integer type for floating point data
++(define_mode_attr VSi [(V4SF "v4si")
++ (V2DF "v2di")])
++
++(define_mode_attr VSI [(V4SF "V4SI")
++ (V2DF "V2DI")])
++
++;; Word size for same size conversion
++(define_mode_attr VSc [(V4SF "w")
++ (V2DF "d")])
++
++;; Bitsize for DF load with update
++(define_mode_attr VSbit [(SI "32")
++ (DI "64")])
++
++(define_constants
++ [(UNSPEC_VSX_CONCAT_V2DF 500)])
++
++;; VSX moves
++(define_insn "*vsx_mov<mode>"
++ [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v")
++ (match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W"))]
++ "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 "xvmov<VSs> %x0,%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);
++
++ default:
++ gcc_unreachable ();
++ }
++}
++ [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,store,load,*,vecsimple,vecsimple,*")])
++
++;; Load/store with update
++;; Define insns that do load or store with update. Because VSX only has
++;; reg+reg addressing, pre-decrement or pre-inrement 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<mode>_update64"
++ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
++ (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
++ (match_operand:DI 2 "gpc_reg_operand" "r,r"))))
++ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
++ (plus:DI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "lx<VSm>ux %x3,%0,%2"
++ [(set_attr "type" "vecload")])
++
++(define_insn "*vsx_load<mode>_update32"
++ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
++ (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
++ (match_operand:SI 2 "gpc_reg_operand" "r,r"))))
++ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
++ (plus:SI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "lx<VSm>ux %x3,%0,%2"
++ [(set_attr "type" "vecload")])
++
++(define_insn "*vsx_store<mode>_update64"
++ [(set (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
++ (match_operand:DI 2 "gpc_reg_operand" "r,r")))
++ (match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
++ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
++ (plus:DI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "stx<VSm>ux %x3,%0,%1"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "*vsx_store<mode>_update32"
++ [(set (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
++ (match_operand:SI 2 "gpc_reg_operand" "r,r")))
++ (match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
++ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
++ (plus:SI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "stx<VSm>ux %x3,%0,%1"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "*vsx_loaddf_update<VSbit>"
++ [(set (match_operand:DF 3 "vsx_register_operand" "=ws,?wa")
++ (mem:DF (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)))]
++ "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
++ "lxsdux %x3,%0,%2"
++ [(set_attr "type" "vecload")])
++
++(define_insn "*vsx_storedf_update<VSbit>"
++ [(set (mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
++ (match_operand:P 2 "gpc_reg_operand" "r,r")))
++ (match_operand:DF 3 "gpc_reg_operand" "ws,?wa"))
++ (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
++ (plus:P (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
++ "stxsdux %x3,%0,%1"
++ [(set_attr "type" "vecstore")])
++
++;; We may need to have a varient on the pattern for use in the prologue
++;; that doesn't depend on TARGET_UPDATE.
++
++\f
++;; VSX vector floating point arithmetic instructions
++(define_insn "*vsx_add<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvadd<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_sub<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvsub<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_mul<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvmul<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_div<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvdiv<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfdiv")])
++
++(define_insn "*vsx_fre<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")]
++ UNSPEC_FRES))]
++ "flag_finite_math_only && VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvre<VSs> %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_neg<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvneg<VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_abs<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvabs<VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_nabs<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (neg:VSX_F
++ (abs:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvnabs<VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_smax<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvmax<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_smin<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvmin<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_sqrt<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvsqrt<VSs> %x0,%x1"
++ [(set_attr "type" "vecfdiv")])
++
++;; Fused vector multiply/add instructions
++(define_insn "*vsx_fmadd<mode>4"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (plus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "gpc_reg_operand" "0,<VSr>")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xvmadda<VSs> %x0,%x1,%x2
++ xvmaddm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fmsub<mode>4"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (minus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xvmsuba<VSs> %x0,%x1,%x2
++ xvmsubm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmadd<mode>4_1"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (neg:VSX_F
++ (plus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmadda<VSs> %x0,%x1,%x2
++ xvnmaddm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmadd<mode>4_2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (minus:VSX_F
++ (mult:VSX_F
++ (neg:VSX_F
++ (match_operand:VSX_F 1 "gpc_reg_operand" "%<VSr>,<VSr>"))
++ (match_operand:VSX_F 2 "gpc_reg_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmadda<VSs> %x0,%x1,%x2
++ xvnmaddm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmsub<mode>4_1"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (neg:VSX_F
++ (minus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmsuba<VSs> %x0,%x1,%x2
++ xvnmsubm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmsub<mode>4_2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (minus:VSX_F
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmsuba<VSs> %x0,%x1,%x2
++ xvnmsubm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++;; Vector conditional expressions
++(define_insn "*vsx_eq<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcmpeq<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_gt<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcmpgt<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_ge<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcmpge<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "vsx_vsel<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (const_int 0))
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_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_F 0 "vsx_register_operand" "=<VSr>")
++ (if_then_else:VSX_F
++ (ge:VSX_F (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
++ (const_int 0))
++ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))
++ (neg:VSX_F (abs:VSX_F (match_dup 1)))))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcpsgn<VSs> %x0,%x2,%x1"
++ [(set_attr "type" "vecsimple")])
++
++(define_insn "*vsx_ftrunc<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvr<VSs>piz %x0,%x1"
++ [(set_attr "type" "vecperm")])
++
++(define_insn "*vsx_float<VSi><mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcvsx<VSc><VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_floatuns<VSi><mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (unsigned_float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcvux<VSc><VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fix_trunc<mode><VSi>2"
++ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
++ (fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcv<VSs>sx<VSc>s %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fixuns_trunc<mode><VSi>2"
++ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
++ (unsigned_fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcv<VSs>ux<VSc>s %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++\f
++;; VSX scalar double precision floating point operations
++(define_insn"*vsx_adddf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (plus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsadddp %x0,%x1,%x2"
++ [(set_attr "type" "fp")
++ (set_attr "fp_type" "fp_addsub_d")])
++
++(define_insn"*vsx_subdf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (minus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xssubdp %x0,%x1,%x2"
++ [(set_attr "type" "fp")
++ (set_attr "fp_type" "fp_addsub_d")])
++
++(define_insn"*vsx_muldf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (mult:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsmuldp %x0,%x1,%x2"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_mul_d")])
++
++(define_insn"*vsx_divdf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (div:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsdivdp %x0,%x1,%x2"
++ [(set_attr "type" "ddiv")])
++
++(define_insn "*vsx_fredf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRES))]
++ "flag_finite_math_only && VECTOR_UNIT_VSX_P (DFmode)"
++ "xsredp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_sqrtdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (sqrt:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xssqrtdp %x0,%x1"
++ [(set_attr "type" "dsqrt")])
++
++(define_insn"*vsx_negdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (neg:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsnegdp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn"vsx_absdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsabsdp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn"*vsx_nabsdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (neg:DF (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsnabsdp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_smaxdf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (smax:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsmaxdp %x0,%x1,%x2"
++ [(set_attr "type" "fp")])
++
++
++(define_insn "*vsx_smindf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (smin:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsmindp %x0,%x1,%x2"
++ [(set_attr "type" "fp")])
++
++;; Fused vector multiply/add instructions
++(define_insn "*vsx_fmadddf4"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "gpc_reg_operand" "0,ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xsmaddadp %x0,%x1,%x2
++ xsmaddmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fmsubdf4"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (minus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xsmsubadp %x0,%x1,%x2
++ xsmsubmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmadddf4_1"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (neg:DF
++ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmaddadp %x0,%x1,%x2
++ xsnmaddmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmadddf4_2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (minus:DF (mult:DF (neg:DF
++ (match_operand:DF 1 "gpc_reg_operand" "%ws,ws"))
++ (match_operand:DF 2 "gpc_reg_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmaddadp %x0,%x1,%x2
++ xsnmaddmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmsubdf4_1"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (neg:DF
++ (minus:DF
++ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmsubadp %x0,%x1,%x2
++ xsnmsubmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmsubdf4_2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (minus:DF
++ (match_operand:DF 3 "vsx_register_operand" "0,ws")
++ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmsubadp %x0,%x1,%x2
++ xsnmsubmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++;; For the conversions, limit the register class for the integer value to be
++;; the fprs. 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_floatdidf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xscvsxddp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_floatunsdidf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unsigned_float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
++ "TARGET_HARD_FLOAT && TARGET_VSX"
++ "xscvuxddp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_fix_truncdfdi2"
++ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
++ (fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xscvdpsxds %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_fixuns_truncdfdi2"
++ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
++ (unsigned_fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "TARGET_HARD_FLOAT && TARGET_VSX"
++ "xscvdpuxds %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_btruncdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRIZ))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdpiz %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_floordf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRIM))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdpim %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_ceildf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRIP))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdpip %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "vsx_copysigndf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (if_then_else:DF (ge:DF (match_operand:DF 2 "vsx_register_operand" "ws")
++ (const_int 0))
++ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))
++ (neg:DF (abs:DF (match_dup 1)))))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xscpsgndp %x0,%x2,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_ftruncdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (fix:DF (match_operand:DF 1 "register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdppiz %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++\f
++;; 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")])
++
++\f
++;; Permute operations
++
++(define_insn "vsx_concat_v2df"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
++ (unspec:V2DF
++ [(match_operand:DF 1 "vsx_register_operand" "f,wa")
++ (match_operand:DF 2 "vsx_register_operand" "f,wa")]
++ UNSPEC_VSX_CONCAT_V2DF))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++ "xxpermdi %x0,%x1,%x2,0"
++ [(set_attr "type" "vecperm")])
++
++;; Set a double into one element
++(define_insn "vsx_set_v2df"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
++ (vec_merge:V2DF
++ (match_operand:V2DF 1 "vsx_register_operand" "wd")
++ (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws"))
++ (match_operand:QI 3 "u5bit_cint_operand" "i")))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++{
++ operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
++ return \"xxpermdi %x0,%x1,%x2,%3\";
++}
++ [(set_attr "type" "vecperm")])
++
++;; Extract a DF element from V2DF
++(define_insn "vsx_extract_v2df"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
++ (parallel
++ [(match_operand:QI 2 "u5bit_cint_operand" "i")])))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++{
++ operands[3] = GEN_INT (INTVAL (operands[2]) & 1);
++ return \"xxpermdi %x0,%x1,%x1,%3\";
++}
++ [(set_attr "type" "vecperm")])
++
++;; General V2DF permute
++(define_insn "vsx_xxpermdi"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
++ (vec_concat:V2DF
++ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
++ (parallel
++ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
++ (vec_select:DF (match_operand:V2DF 3 "vsx_register_operand" "wd")
++ (parallel
++ [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++{
++ operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
++ | (INTVAL (operands[4]) & 1));
++ return \"xxpermdi %x0,%x1,%x3,%5\";
++}
++ [(set_attr "type" "vecperm")])
++
++;; V2DF splat
++(define_insn "vsx_splatv2df"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd")
++ (vec_duplicate:V2DF
++ (match_operand:DF 1 "input_operand" "ws,Z")))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++ "@
++ xxpermdi %x0,%x1,%x1,0
++ lxvdsx %x0,%y1"
++ [(set_attr "type" "vecperm,vecload")])
++
++;; V4SF splat
++(define_insn "*vsx_xxspltw"
++ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf")
++ (vec_duplicate:V4SF
++ (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf")
++ (parallel
++ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
++ "VECTOR_UNIT_VSX_P (V4SFmode)"
++ "xxspltw %x0,%x1,%2"
++ [(set_attr "type" "vecperm")])
++
++;; V4SF interleave
++(define_insn "*vsx_xxmrghw"
++ [(set (match_operand:V4SF 0 "register_operand" "=v")
++ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_VSX_P (V4SFmode)"
++ "xxmrghw %x0,%x1,%x2"
++ [(set_attr "type" "vecperm")])
++
++(define_insn "*vsx_xxmrglw"
++ [(set (match_operand:V4SF 0 "register_operand" "=v")
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_VSX_P (V4SFmode)"
++ "xxmrglw %x0,%x1,%x2"
++ [(set_attr "type" "vecperm")])
+--- gcc/config/rs6000/rs6000.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -1,6 +1,6 @@
+ /* Definitions of target machine for GNU compiler, for IBM RS/6000.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
++ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
+ Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+@@ -72,14 +72,16 @@
+ #define ASM_CPU_POWER6_SPEC "-mpower4 -maltivec"
+ #endif
+
+-#ifdef HAVE_AS_VSX
++#ifdef HAVE_AS_POPCNTD
+ #define ASM_CPU_POWER7_SPEC "-mpower7"
+ #else
+ #define ASM_CPU_POWER7_SPEC "-mpower4 -maltivec"
+ #endif
+
+-/* Common ASM definitions used by ASM_SPEC among the various targets
+- for handling -mcpu=xxx switches. */
++/* Common ASM definitions used by ASM_SPEC among the various targets for
++ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
++ provide the default assembler options if the user uses -mcpu=native, so if
++ you make changes here, make them also there. */
+ #define ASM_CPU_SPEC \
+ "%{!mcpu*: \
+ %{mpower: %{!mpower2: -mpwr}} \
+@@ -88,6 +90,7 @@
+ %{!mpowerpc64*: %{mpowerpc*: -mppc}} \
+ %{mno-power: %{!mpowerpc*: -mcom}} \
+ %{!mno-power: %{!mpower*: %(asm_default)}}} \
++%{mcpu=native: %(asm_cpu_native)} \
+ %{mcpu=common: -mcom} \
+ %{mcpu=cell: -mcell} \
+ %{mcpu=power: -mpwr} \
+@@ -163,6 +166,7 @@
+ #define EXTRA_SPECS \
+ { "cpp_default", CPP_DEFAULT_SPEC }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
++ { "asm_cpu_native", ASM_CPU_NATIVE_SPEC }, \
+ { "asm_default", ASM_DEFAULT_SPEC }, \
+ { "cc1_cpu", CC1_CPU_SPEC }, \
+ { "asm_cpu_power5", ASM_CPU_POWER5_SPEC }, \
+@@ -179,6 +183,10 @@ extern const char *host_detect_local_cpu
+ #define EXTRA_SPEC_FUNCTIONS \
+ { "local_cpu_detect", host_detect_local_cpu },
+ #define HAVE_LOCAL_CPU_DETECT
++#define ASM_CPU_NATIVE_SPEC "%:local_cpu_detect(asm)"
++
++#else
++#define ASM_CPU_NATIVE_SPEC "%(asm_default)"
+ #endif
+
+ #ifndef CC1_CPU_SPEC
+@@ -240,6 +248,14 @@ extern const char *host_detect_local_cpu
+ #define TARGET_DFP 0
+ #endif
+
++/* Define TARGET_POPCNTD if the target assembler does not support the
++ popcount word and double word instructions. */
++
++#ifndef HAVE_AS_POPCNTD
++#undef TARGET_POPCNTD
++#define TARGET_POPCNTD 0
++#endif
++
+ #ifndef TARGET_SECURE_PLT
+ #define TARGET_SECURE_PLT 0
+ #endif
+@@ -295,6 +311,7 @@ enum processor_type
+ PROCESSOR_POWER4,
+ PROCESSOR_POWER5,
+ PROCESSOR_POWER6,
++ PROCESSOR_POWER7,
+ PROCESSOR_CELL
+ };
+
+@@ -388,9 +405,13 @@ extern struct rs6000_cpu_select rs6000_s
+ extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
+ extern int rs6000_debug_stack; /* debug stack applications */
+ extern int rs6000_debug_arg; /* debug argument handling */
++extern int rs6000_debug_reg; /* debug register handling */
++extern int rs6000_debug_addr; /* debug memory addressing */
+
+ #define TARGET_DEBUG_STACK rs6000_debug_stack
+ #define TARGET_DEBUG_ARG rs6000_debug_arg
++#define TARGET_DEBUG_REG rs6000_debug_reg
++#define TARGET_DEBUG_ADDR rs6000_debug_addr
+
+ extern const char *rs6000_traceback_name; /* Type of traceback table. */
+
+@@ -401,13 +422,65 @@ extern int rs6000_ieeequad;
+ extern int rs6000_altivec_abi;
+ extern int rs6000_spe_abi;
+ extern int rs6000_spe;
+-extern int rs6000_isel;
+ extern int rs6000_float_gprs;
+ extern int rs6000_alignment_flags;
+ extern const char *rs6000_sched_insert_nops_str;
+ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
+ extern int rs6000_xilinx_fpu;
+
++/* Describe which vector unit to use for a given machine mode. */
++enum rs6000_vector {
++ VECTOR_NONE, /* Type is not a vector or not supported */
++ VECTOR_ALTIVEC, /* Use altivec for vector processing */
++ VECTOR_VSX, /* Use VSX for vector processing */
++ VECTOR_PAIRED, /* Use paired floating point for vectors */
++ VECTOR_SPE, /* Use SPE for vector processing */
++ VECTOR_OTHER /* Some other vector unit */
++};
++
++extern enum rs6000_vector rs6000_vector_unit[];
++
++#define VECTOR_UNIT_NONE_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_NONE)
++
++#define VECTOR_UNIT_VSX_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_VSX)
++
++#define VECTOR_UNIT_ALTIVEC_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC)
++
++#define VECTOR_UNIT_ALTIVEC_OR_VSX_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC \
++ || rs6000_vector_unit[(MODE)] == VECTOR_VSX)
++
++/* Describe whether to use VSX loads or Altivec loads. For now, just use the
++ same unit as the vector unit we are using, but we may want to migrate to
++ using VSX style loads even for types handled by altivec. */
++extern enum rs6000_vector rs6000_vector_mem[];
++
++#define VECTOR_MEM_NONE_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_NONE)
++
++#define VECTOR_MEM_VSX_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_VSX)
++
++#define VECTOR_MEM_ALTIVEC_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC)
++
++#define VECTOR_MEM_ALTIVEC_OR_VSX_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC \
++ || rs6000_vector_mem[(MODE)] == VECTOR_VSX)
++
++/* Return the alignment of a given vector type, which is set based on the
++ vector unit use. VSX for instance can load 32 or 64 bit aligned words
++ without problems, while Altivec requires 128-bit aligned vectors. */
++extern int rs6000_vector_align[];
++
++#define VECTOR_ALIGN(MODE) \
++ ((rs6000_vector_align[(MODE)] != 0) \
++ ? rs6000_vector_align[(MODE)] \
++ : (int)GET_MODE_BITSIZE ((MODE)))
++
+ /* Alignment options for fields in structures for sub-targets following
+ AIX-like ABI.
+ ALIGN_POWER word-aligns FP doubles (default AIX ABI).
+@@ -432,7 +505,7 @@ extern int rs6000_xilinx_fpu;
+ #define TARGET_SPE_ABI 0
+ #define TARGET_SPE 0
+ #define TARGET_E500 0
+-#define TARGET_ISEL rs6000_isel
++#define TARGET_ISEL64 (TARGET_ISEL && TARGET_POWERPC64)
+ #define TARGET_FPRS 1
+ #define TARGET_E500_SINGLE 0
+ #define TARGET_E500_DOUBLE 0
+@@ -530,6 +603,7 @@ extern int rs6000_xilinx_fpu;
+ #endif
+ #define UNITS_PER_FP_WORD 8
+ #define UNITS_PER_ALTIVEC_WORD 16
++#define UNITS_PER_VSX_WORD 16
+ #define UNITS_PER_SPE_WORD 8
+ #define UNITS_PER_PAIRED_WORD 8
+
+@@ -600,8 +674,9 @@ extern int rs6000_xilinx_fpu;
+ #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
+
+ /* Boundary (in *bits*) on which stack pointer should be aligned. */
+-#define STACK_BOUNDARY \
+- ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI) ? 64 : 128)
++#define STACK_BOUNDARY \
++ ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI && !TARGET_VSX) \
++ ? 64 : 128)
+
+ /* Allocation boundary (in *bits*) for the code of a function. */
+ #define FUNCTION_BOUNDARY 32
+@@ -613,10 +688,11 @@ extern int rs6000_xilinx_fpu;
+ local store. TYPE is the data type, and ALIGN is the alignment
+ that the object would ordinarily have. */
+ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+- ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
++ (((TARGET_ALTIVEC || TARGET_VSX) \
++ && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
+ (TARGET_E500_DOUBLE \
+- && TYPE_MODE (TYPE) == DFmode) ? 64 : \
+- ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
++ && TYPE_MODE (TYPE) == DFmode) ? 64 : \
++ ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
+ && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
+ && TREE_CODE (TYPE) == VECTOR_TYPE \
+ && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN)
+@@ -674,15 +750,17 @@ extern int rs6000_xilinx_fpu;
+ /* Define this macro to be the value 1 if unaligned accesses have a cost
+ many times greater than aligned accesses, for example if they are
+ emulated in a trap handler. */
+-/* Altivec vector memory instructions simply ignore the low bits; SPE
+- vector memory instructions trap on unaligned accesses. */
++/* Altivec vector memory instructions simply ignore the low bits; SPE vector
++ memory instructions trap on unaligned accesses; VSX memory instructions are
++ aligned to 4 or 8 bytes. */
+ #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \
+ (STRICT_ALIGNMENT \
+ || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \
+ || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode \
+ || (MODE) == DImode) \
+ && (ALIGN) < 32) \
+- || (VECTOR_MODE_P ((MODE)) && (ALIGN) < GET_MODE_BITSIZE ((MODE))))
++ || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))
++
+ \f
+ /* Standard register usage. */
+
+@@ -909,16 +987,60 @@ extern int rs6000_xilinx_fpu;
+ /* True if register is an AltiVec register. */
+ #define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO)
+
++/* True if register is a VSX register. */
++#define VSX_REGNO_P(N) (FP_REGNO_P (N) || ALTIVEC_REGNO_P (N))
++
++/* Alternate name for any vector register supporting floating point, no matter
++ which instruction set(s) are available. */
++#define VFLOAT_REGNO_P(N) \
++ (ALTIVEC_REGNO_P (N) || (TARGET_VSX && FP_REGNO_P (N)))
++
++/* Alternate name for any vector register supporting integer, no matter which
++ instruction set(s) are available. */
++#define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N)
++
++/* Alternate name for any vector register supporting logical operations, no
++ matter which instruction set(s) are available. */
++#define VLOGICAL_REGNO_P(N) VFLOAT_REGNO_P (N)
++
+ /* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE. */
+
+-#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs ((REGNO), (MODE))
++#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)]
+
+ #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
+ ((TARGET_32BIT && TARGET_POWERPC64 \
+ && (GET_MODE_SIZE (MODE) > 4) \
+ && INT_REGNO_P (REGNO)) ? 1 : 0)
+
++#define VSX_VECTOR_MODE(MODE) \
++ ((MODE) == V4SFmode \
++ || (MODE) == V2DFmode) \
++
++#define VSX_VECTOR_MOVE_MODE(MODE) \
++ ((MODE) == V16QImode \
++ || (MODE) == V8HImode \
++ || (MODE) == V4SImode \
++ || (MODE) == V2DImode \
++ || (MODE) == V4SFmode \
++ || (MODE) == V2DFmode) \
++
++#define VSX_SCALAR_MODE(MODE) \
++ ((MODE) == DFmode)
++
++#define VSX_MODE(MODE) \
++ (VSX_VECTOR_MODE (MODE) \
++ || VSX_SCALAR_MODE (MODE))
++
++#define VSX_MOVE_MODE(MODE) \
++ (VSX_VECTOR_MOVE_MODE (MODE) \
++ || VSX_SCALAR_MODE(MODE) \
++ || (MODE) == V16QImode \
++ || (MODE) == V8HImode \
++ || (MODE) == V4SImode \
++ || (MODE) == V2DImode \
++ || (MODE) == TImode)
++
+ #define ALTIVEC_VECTOR_MODE(MODE) \
+ ((MODE) == V16QImode \
+ || (MODE) == V8HImode \
+@@ -934,10 +1056,12 @@ extern int rs6000_xilinx_fpu;
+ #define PAIRED_VECTOR_MODE(MODE) \
+ ((MODE) == V2SFmode)
+
+-#define UNITS_PER_SIMD_WORD(MODE) \
+- (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
+- : (TARGET_SPE ? UNITS_PER_SPE_WORD : (TARGET_PAIRED_FLOAT ? \
+- UNITS_PER_PAIRED_WORD : UNITS_PER_WORD)))
++#define UNITS_PER_SIMD_WORD(MODE) \
++ (TARGET_VSX ? UNITS_PER_VSX_WORD \
++ : (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
++ : (TARGET_SPE ? UNITS_PER_SPE_WORD \
++ : (TARGET_PAIRED_FLOAT ? UNITS_PER_PAIRED_WORD \
++ : UNITS_PER_WORD))))
+
+ /* Value is TRUE if hard register REGNO can hold a value of
+ machine-mode MODE. */
+@@ -965,6 +1089,10 @@ extern int rs6000_xilinx_fpu;
+ ? ALTIVEC_VECTOR_MODE (MODE2) \
+ : ALTIVEC_VECTOR_MODE (MODE2) \
+ ? ALTIVEC_VECTOR_MODE (MODE1) \
++ : VSX_VECTOR_MODE (MODE1) \
++ ? VSX_VECTOR_MODE (MODE2) \
++ : VSX_VECTOR_MODE (MODE2) \
++ ? VSX_VECTOR_MODE (MODE1) \
+ : 1)
+
+ /* Post-reload, we can't use any new AltiVec registers, as we already
+@@ -1056,9 +1184,10 @@ extern int rs6000_xilinx_fpu;
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+-/* The RS/6000 has three types of registers, fixed-point, floating-point,
+- and condition registers, plus three special registers, MQ, CTR, and the
+- link register. AltiVec adds a vector register class.
++/* The RS/6000 has three types of registers, fixed-point, floating-point, and
++ condition registers, plus three special registers, MQ, CTR, and the link
++ register. AltiVec adds a vector register class. VSX registers overlap the
++ FPR registers and the Altivec registers.
+
+ However, r0 is special in that it cannot be used as a base register.
+ So make a class for registers valid as base registers.
+@@ -1073,6 +1202,7 @@ enum reg_class
+ GENERAL_REGS,
+ FLOAT_REGS,
+ ALTIVEC_REGS,
++ VSX_REGS,
+ VRSAVE_REGS,
+ VSCR_REGS,
+ SPE_ACC_REGS,
+@@ -1103,6 +1233,7 @@ enum reg_class
+ "GENERAL_REGS", \
+ "FLOAT_REGS", \
+ "ALTIVEC_REGS", \
++ "VSX_REGS", \
+ "VRSAVE_REGS", \
+ "VSCR_REGS", \
+ "SPE_ACC_REGS", \
+@@ -1132,6 +1263,7 @@ enum reg_class
+ { 0xffffffff, 0x00000000, 0x00000008, 0x00020000 }, /* GENERAL_REGS */ \
+ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */ \
+ { 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */ \
++ { 0x00000000, 0xffffffff, 0xffffe000, 0x00001fff }, /* VSX_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \
+@@ -1179,8 +1311,8 @@ enum reg_class
+ : (REGNO) == CR0_REGNO ? CR0_REGS \
+ : CR_REGNO_P (REGNO) ? CR_REGS \
+ : (REGNO) == MQ_REGNO ? MQ_REGS \
+- : (REGNO) == LR_REGNO ? LINK_REGS \
+- : (REGNO) == CTR_REGNO ? CTR_REGS \
++ : (REGNO) == LR_REGNO ? LINK_REGS \
++ : (REGNO) == CTR_REGNO ? CTR_REGS \
+ : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \
+ : (REGNO) == XER_REGNO ? XER_REGS \
+ : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \
+@@ -1190,10 +1322,18 @@ enum reg_class
+ : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \
+ : NO_REGS)
+
++/* VSX register classes. */
++extern enum reg_class rs6000_vector_reg_class[];
++extern enum reg_class rs6000_vsx_reg_class;
++
+ /* The class value for index registers, and the one for base regs. */
+ #define INDEX_REG_CLASS GENERAL_REGS
+ #define BASE_REG_CLASS BASE_REGS
+
++/* Return whether a given register class can hold VSX objects. */
++#define VSX_REG_CLASS_P(CLASS) \
++ ((CLASS) == VSX_REGS || (CLASS) == FLOAT_REGS || (CLASS) == ALTIVEC_REGS)
++
+ /* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+@@ -1213,13 +1353,7 @@ enum reg_class
+ */
+
+ #define PREFERRED_RELOAD_CLASS(X,CLASS) \
+- ((CONSTANT_P (X) \
+- && reg_classes_intersect_p ((CLASS), FLOAT_REGS)) \
+- ? NO_REGS \
+- : (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
+- && (CLASS) == NON_SPECIAL_REGS) \
+- ? GENERAL_REGS \
+- : (CLASS))
++ rs6000_preferred_reload_class (X, CLASS)
+
+ /* Return the register class of a scratch register needed to copy IN into
+ or out of a register in CLASS in MODE. If it can be done directly,
+@@ -1234,18 +1368,7 @@ enum reg_class
+ are available.*/
+
+ #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
+- ((CLASS1) != (CLASS2) && (((CLASS1) == FLOAT_REGS \
+- && (!TARGET_MFPGPR || !TARGET_POWERPC64 \
+- || ((MODE != DFmode) \
+- && (MODE != DDmode) \
+- && (MODE != DImode)))) \
+- || ((CLASS2) == FLOAT_REGS \
+- && (!TARGET_MFPGPR || !TARGET_POWERPC64 \
+- || ((MODE != DFmode) \
+- && (MODE != DDmode) \
+- && (MODE != DImode)))) \
+- || (CLASS1) == ALTIVEC_REGS \
+- || (CLASS2) == ALTIVEC_REGS))
++ rs6000_secondary_memory_needed (CLASS1, CLASS2, MODE)
+
+ /* For cpus that cannot load/store SDmode values from the 64-bit
+ FP registers without using a full 64-bit load/store, we need
+@@ -1257,32 +1380,15 @@ enum reg_class
+ /* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS.
+
+- On RS/6000, this is the size of MODE in words,
+- except in the FP regs, where a single reg is enough for two words. */
+-#define CLASS_MAX_NREGS(CLASS, MODE) \
+- (((CLASS) == FLOAT_REGS) \
+- ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+- : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS \
+- && (MODE) == DFmode) \
+- ? 1 \
+- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
++ On RS/6000, this is the size of MODE in words, except in the FP regs, where
++ a single reg is enough for two words, unless we have VSX, where the FP
++ registers can hold 128 bits. */
++#define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
+
+ /* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
+
+ #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+- ? ((GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8 \
+- || TARGET_IEEEQUAD) \
+- && reg_classes_intersect_p (FLOAT_REGS, CLASS)) \
+- : (((TARGET_E500_DOUBLE \
+- && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \
+- || (((TO) == TFmode) + ((FROM) == TFmode)) == 1 \
+- || (((TO) == DDmode) + ((FROM) == DDmode)) == 1 \
+- || (((TO) == TDmode) + ((FROM) == TDmode)) == 1 \
+- || (((TO) == DImode) + ((FROM) == DImode)) == 1)) \
+- || (TARGET_SPE \
+- && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \
+- && reg_classes_intersect_p (GENERAL_REGS, CLASS)))
++ rs6000_cannot_change_mode_class (FROM, TO, CLASS)
+
+ /* Stack layout; function entry, exit and calling. */
+
+@@ -1343,8 +1449,8 @@ extern enum rs6000_abi rs6000_current_ab
+ #define STARTING_FRAME_OFFSET \
+ (FRAME_GROWS_DOWNWARD \
+ ? 0 \
+- : (RS6000_ALIGN (crtl->outgoing_args_size, \
+- TARGET_ALTIVEC ? 16 : 8) \
++ : (RS6000_ALIGN (crtl->outgoing_args_size, \
++ (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \
+ + RS6000_SAVE_AREA))
+
+ /* Offset from the stack pointer register to an item dynamically
+@@ -1354,8 +1460,8 @@ extern enum rs6000_abi rs6000_current_ab
+ length of the outgoing arguments. The default is correct for most
+ machines. See `function.c' for details. */
+ #define STACK_DYNAMIC_OFFSET(FUNDECL) \
+- (RS6000_ALIGN (crtl->outgoing_args_size, \
+- TARGET_ALTIVEC ? 16 : 8) \
++ (RS6000_ALIGN (crtl->outgoing_args_size, \
++ (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \
+ + (STACK_POINTER_OFFSET))
+
+ /* If we generate an insn to push BYTES bytes,
+@@ -1605,7 +1711,7 @@ typedef struct rs6000_args
+ #define EPILOGUE_USES(REGNO) \
+ ((reload_completed && (REGNO) == LR_REGNO) \
+ || (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO) \
+- || (crtl->calls_eh_return \
++ || (crtl->calls_eh_return \
+ && TARGET_AIX \
+ && (REGNO) == 2))
+
+@@ -2316,7 +2422,24 @@ extern char rs6000_reg_names[][8]; /* re
+ /* no additional names for: mq, lr, ctr, ap */ \
+ {"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \
+ {"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \
+- {"cc", 68}, {"sp", 1}, {"toc", 2} }
++ {"cc", 68}, {"sp", 1}, {"toc", 2}, \
++ /* VSX registers overlaid on top of FR, Altivec registers */ \
++ {"vs0", 32}, {"vs1", 33}, {"vs2", 34}, {"vs3", 35}, \
++ {"vs4", 36}, {"vs5", 37}, {"vs6", 38}, {"vs7", 39}, \
++ {"vs8", 40}, {"vs9", 41}, {"vs10", 42}, {"vs11", 43}, \
++ {"vs12", 44}, {"vs13", 45}, {"vs14", 46}, {"vs15", 47}, \
++ {"vs16", 48}, {"vs17", 49}, {"vs18", 50}, {"vs19", 51}, \
++ {"vs20", 52}, {"vs21", 53}, {"vs22", 54}, {"vs23", 55}, \
++ {"vs24", 56}, {"vs25", 57}, {"vs26", 58}, {"vs27", 59}, \
++ {"vs28", 60}, {"vs29", 61}, {"vs30", 62}, {"vs31", 63}, \
++ {"vs32", 77}, {"vs33", 78}, {"vs34", 79}, {"vs35", 80}, \
++ {"vs36", 81}, {"vs37", 82}, {"vs38", 83}, {"vs39", 84}, \
++ {"vs40", 85}, {"vs41", 86}, {"vs42", 87}, {"vs43", 88}, \
++ {"vs44", 89}, {"vs45", 90}, {"vs46", 91}, {"vs47", 92}, \
++ {"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96}, \
++ {"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100}, \
++ {"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104}, \
++ {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} }
+
+ /* Text to write out after a CALL that may be replaced by glue code by
+ the loader. This depends on the AIX version. */
+@@ -2480,10 +2603,14 @@ enum rs6000_builtins
+ ALTIVEC_BUILTIN_VSEL_4SF,
+ ALTIVEC_BUILTIN_VSEL_8HI,
+ ALTIVEC_BUILTIN_VSEL_16QI,
++ ALTIVEC_BUILTIN_VSEL_2DF, /* needed for VSX */
++ ALTIVEC_BUILTIN_VSEL_2DI, /* needed for VSX */
+ ALTIVEC_BUILTIN_VPERM_4SI,
+ ALTIVEC_BUILTIN_VPERM_4SF,
+ ALTIVEC_BUILTIN_VPERM_8HI,
+ ALTIVEC_BUILTIN_VPERM_16QI,
++ ALTIVEC_BUILTIN_VPERM_2DF, /* needed for VSX */
++ ALTIVEC_BUILTIN_VPERM_2DI, /* needed for VSX */
+ ALTIVEC_BUILTIN_VPKUHUM,
+ ALTIVEC_BUILTIN_VPKUWUM,
+ ALTIVEC_BUILTIN_VPKPX,
+@@ -3110,6 +3237,163 @@ enum rs6000_builtins
+ RS6000_BUILTIN_RECIPF,
+ RS6000_BUILTIN_RSQRTF,
+
++ /* VSX builtins. */
++ VSX_BUILTIN_LXSDUX,
++ VSX_BUILTIN_LXSDX,
++ VSX_BUILTIN_LXVD2UX,
++ VSX_BUILTIN_LXVD2X,
++ VSX_BUILTIN_LXVDSX,
++ VSX_BUILTIN_LXVW4UX,
++ VSX_BUILTIN_LXVW4X,
++ VSX_BUILTIN_STXSDUX,
++ VSX_BUILTIN_STXSDX,
++ VSX_BUILTIN_STXVD2UX,
++ VSX_BUILTIN_STXVD2X,
++ VSX_BUILTIN_STXVW4UX,
++ VSX_BUILTIN_STXVW4X,
++ VSX_BUILTIN_XSABSDP,
++ VSX_BUILTIN_XSADDDP,
++ VSX_BUILTIN_XSCMPODP,
++ VSX_BUILTIN_XSCMPUDP,
++ VSX_BUILTIN_XSCPSGNDP,
++ VSX_BUILTIN_XSCVDPSP,
++ VSX_BUILTIN_XSCVDPSXDS,
++ VSX_BUILTIN_XSCVDPSXWS,
++ VSX_BUILTIN_XSCVDPUXDS,
++ VSX_BUILTIN_XSCVDPUXWS,
++ VSX_BUILTIN_XSCVSPDP,
++ VSX_BUILTIN_XSCVSXDDP,
++ VSX_BUILTIN_XSCVUXDDP,
++ VSX_BUILTIN_XSDIVDP,
++ VSX_BUILTIN_XSMADDADP,
++ VSX_BUILTIN_XSMADDMDP,
++ VSX_BUILTIN_XSMAXDP,
++ VSX_BUILTIN_XSMINDP,
++ VSX_BUILTIN_XSMOVDP,
++ VSX_BUILTIN_XSMSUBADP,
++ VSX_BUILTIN_XSMSUBMDP,
++ VSX_BUILTIN_XSMULDP,
++ VSX_BUILTIN_XSNABSDP,
++ VSX_BUILTIN_XSNEGDP,
++ VSX_BUILTIN_XSNMADDADP,
++ VSX_BUILTIN_XSNMADDMDP,
++ VSX_BUILTIN_XSNMSUBADP,
++ VSX_BUILTIN_XSNMSUBMDP,
++ VSX_BUILTIN_XSRDPI,
++ VSX_BUILTIN_XSRDPIC,
++ VSX_BUILTIN_XSRDPIM,
++ VSX_BUILTIN_XSRDPIP,
++ VSX_BUILTIN_XSRDPIZ,
++ VSX_BUILTIN_XSREDP,
++ VSX_BUILTIN_XSRSQRTEDP,
++ VSX_BUILTIN_XSSQRTDP,
++ VSX_BUILTIN_XSSUBDP,
++ VSX_BUILTIN_XSTDIVDP,
++ VSX_BUILTIN_XSTSQRTDP,
++ VSX_BUILTIN_XVABSDP,
++ VSX_BUILTIN_XVABSSP,
++ VSX_BUILTIN_XVADDDP,
++ VSX_BUILTIN_XVADDSP,
++ VSX_BUILTIN_XVCMPEQDP,
++ VSX_BUILTIN_XVCMPEQSP,
++ VSX_BUILTIN_XVCMPGEDP,
++ VSX_BUILTIN_XVCMPGESP,
++ VSX_BUILTIN_XVCMPGTDP,
++ VSX_BUILTIN_XVCMPGTSP,
++ VSX_BUILTIN_XVCPSGNDP,
++ VSX_BUILTIN_XVCPSGNSP,
++ VSX_BUILTIN_XVCVDPSP,
++ VSX_BUILTIN_XVCVDPSXDS,
++ VSX_BUILTIN_XVCVDPSXWS,
++ VSX_BUILTIN_XVCVDPUXDS,
++ VSX_BUILTIN_XVCVDPUXWS,
++ VSX_BUILTIN_XVCVSPDP,
++ VSX_BUILTIN_XVCVSPSXDS,
++ VSX_BUILTIN_XVCVSPSXWS,
++ VSX_BUILTIN_XVCVSPUXDS,
++ VSX_BUILTIN_XVCVSPUXWS,
++ VSX_BUILTIN_XVCVSXDDP,
++ VSX_BUILTIN_XVCVSXDSP,
++ VSX_BUILTIN_XVCVSXWDP,
++ VSX_BUILTIN_XVCVSXWSP,
++ VSX_BUILTIN_XVCVUXDDP,
++ VSX_BUILTIN_XVCVUXDSP,
++ VSX_BUILTIN_XVCVUXWDP,
++ VSX_BUILTIN_XVCVUXWSP,
++ VSX_BUILTIN_XVDIVDP,
++ VSX_BUILTIN_XVDIVSP,
++ VSX_BUILTIN_XVMADDADP,
++ VSX_BUILTIN_XVMADDASP,
++ VSX_BUILTIN_XVMADDMDP,
++ VSX_BUILTIN_XVMADDMSP,
++ VSX_BUILTIN_XVMAXDP,
++ VSX_BUILTIN_XVMAXSP,
++ VSX_BUILTIN_XVMINDP,
++ VSX_BUILTIN_XVMINSP,
++ VSX_BUILTIN_XVMOVDP,
++ VSX_BUILTIN_XVMOVSP,
++ VSX_BUILTIN_XVMSUBADP,
++ VSX_BUILTIN_XVMSUBASP,
++ VSX_BUILTIN_XVMSUBMDP,
++ VSX_BUILTIN_XVMSUBMSP,
++ VSX_BUILTIN_XVMULDP,
++ VSX_BUILTIN_XVMULSP,
++ VSX_BUILTIN_XVNABSDP,
++ VSX_BUILTIN_XVNABSSP,
++ VSX_BUILTIN_XVNEGDP,
++ VSX_BUILTIN_XVNEGSP,
++ VSX_BUILTIN_XVNMADDADP,
++ VSX_BUILTIN_XVNMADDASP,
++ VSX_BUILTIN_XVNMADDMDP,
++ VSX_BUILTIN_XVNMADDMSP,
++ VSX_BUILTIN_XVNMSUBADP,
++ VSX_BUILTIN_XVNMSUBASP,
++ VSX_BUILTIN_XVNMSUBMDP,
++ VSX_BUILTIN_XVNMSUBMSP,
++ VSX_BUILTIN_XVRDPI,
++ VSX_BUILTIN_XVRDPIC,
++ VSX_BUILTIN_XVRDPIM,
++ VSX_BUILTIN_XVRDPIP,
++ VSX_BUILTIN_XVRDPIZ,
++ VSX_BUILTIN_XVREDP,
++ VSX_BUILTIN_XVRESP,
++ VSX_BUILTIN_XVRSPI,
++ VSX_BUILTIN_XVRSPIC,
++ VSX_BUILTIN_XVRSPIM,
++ VSX_BUILTIN_XVRSPIP,
++ VSX_BUILTIN_XVRSPIZ,
++ VSX_BUILTIN_XVRSQRTEDP,
++ VSX_BUILTIN_XVRSQRTESP,
++ VSX_BUILTIN_XVSQRTDP,
++ VSX_BUILTIN_XVSQRTSP,
++ VSX_BUILTIN_XVSUBDP,
++ VSX_BUILTIN_XVSUBSP,
++ VSX_BUILTIN_XVTDIVDP,
++ VSX_BUILTIN_XVTDIVSP,
++ VSX_BUILTIN_XVTSQRTDP,
++ VSX_BUILTIN_XVTSQRTSP,
++ VSX_BUILTIN_XXLAND,
++ VSX_BUILTIN_XXLANDC,
++ VSX_BUILTIN_XXLNOR,
++ VSX_BUILTIN_XXLOR,
++ VSX_BUILTIN_XXLXOR,
++ VSX_BUILTIN_XXMRGHD,
++ VSX_BUILTIN_XXMRGHW,
++ VSX_BUILTIN_XXMRGLD,
++ VSX_BUILTIN_XXMRGLW,
++ VSX_BUILTIN_XXPERMDI,
++ VSX_BUILTIN_XXSEL,
++ VSX_BUILTIN_XXSLDWI,
++ VSX_BUILTIN_XXSPLTD,
++ VSX_BUILTIN_XXSPLTW,
++ VSX_BUILTIN_XXSWAPD,
++
++ /* Combine VSX/Altivec builtins. */
++ VECTOR_BUILTIN_FLOAT_V4SI_V4SF,
++ VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,
++ VECTOR_BUILTIN_FIX_V4SF_V4SI,
++ VECTOR_BUILTIN_FIXUNS_V4SF_V4SI,
++
+ RS6000_BUILTIN_COUNT
+ };
+
+@@ -3123,6 +3407,8 @@ enum rs6000_builtin_type_index
+ RS6000_BTI_V16QI,
+ RS6000_BTI_V2SI,
+ RS6000_BTI_V2SF,
++ RS6000_BTI_V2DI,
++ RS6000_BTI_V2DF,
+ RS6000_BTI_V4HI,
+ RS6000_BTI_V4SI,
+ RS6000_BTI_V4SF,
+@@ -3146,7 +3432,10 @@ enum rs6000_builtin_type_index
+ RS6000_BTI_UINTHI, /* unsigned_intHI_type_node */
+ RS6000_BTI_INTSI, /* intSI_type_node */
+ RS6000_BTI_UINTSI, /* unsigned_intSI_type_node */
++ RS6000_BTI_INTDI, /* intDI_type_node */
++ RS6000_BTI_UINTDI, /* unsigned_intDI_type_node */
+ RS6000_BTI_float, /* float_type_node */
++ RS6000_BTI_double, /* double_type_node */
+ RS6000_BTI_void, /* void_type_node */
+ RS6000_BTI_MAX
+ };
+@@ -3157,6 +3446,8 @@ enum rs6000_builtin_type_index
+ #define opaque_p_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI])
+ #define opaque_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V4SI])
+ #define V16QI_type_node (rs6000_builtin_types[RS6000_BTI_V16QI])
++#define V2DI_type_node (rs6000_builtin_types[RS6000_BTI_V2DI])
++#define V2DF_type_node (rs6000_builtin_types[RS6000_BTI_V2DF])
+ #define V2SI_type_node (rs6000_builtin_types[RS6000_BTI_V2SI])
+ #define V2SF_type_node (rs6000_builtin_types[RS6000_BTI_V2SF])
+ #define V4HI_type_node (rs6000_builtin_types[RS6000_BTI_V4HI])
+@@ -3183,7 +3474,10 @@ enum rs6000_builtin_type_index
+ #define uintHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTHI])
+ #define intSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTSI])
+ #define uintSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTSI])
++#define intDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTDI])
++#define uintDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTDI])
+ #define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
++#define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double])
+ #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
+
+ extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
+--- gcc/config/rs6000/altivec.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/altivec.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -21,18 +21,7 @@
+
+ (define_constants
+ [(UNSPEC_VCMPBFP 50)
+- (UNSPEC_VCMPEQUB 51)
+- (UNSPEC_VCMPEQUH 52)
+- (UNSPEC_VCMPEQUW 53)
+- (UNSPEC_VCMPEQFP 54)
+- (UNSPEC_VCMPGEFP 55)
+- (UNSPEC_VCMPGTUB 56)
+- (UNSPEC_VCMPGTSB 57)
+- (UNSPEC_VCMPGTUH 58)
+- (UNSPEC_VCMPGTSH 59)
+- (UNSPEC_VCMPGTUW 60)
+- (UNSPEC_VCMPGTSW 61)
+- (UNSPEC_VCMPGTFP 62)
++ ;; 51-62 deleted
+ (UNSPEC_VMSUMU 65)
+ (UNSPEC_VMSUMM 66)
+ (UNSPEC_VMSUMSHM 68)
+@@ -87,10 +76,7 @@ (define_constants
+ (UNSPEC_VEXPTEFP 156)
+ (UNSPEC_VRSQRTEFP 157)
+ (UNSPEC_VREFP 158)
+- (UNSPEC_VSEL4SI 159)
+- (UNSPEC_VSEL4SF 160)
+- (UNSPEC_VSEL8HI 161)
+- (UNSPEC_VSEL16QI 162)
++ ;; 159-162 deleted
+ (UNSPEC_VLSDOI 163)
+ (UNSPEC_VUPKHSB 167)
+ (UNSPEC_VUPKHPX 168)
+@@ -125,11 +111,11 @@ (define_constants
+ (UNSPEC_INTERHI_V4SI 228)
+ (UNSPEC_INTERHI_V8HI 229)
+ (UNSPEC_INTERHI_V16QI 230)
+- (UNSPEC_INTERHI_V4SF 231)
++ ;; delete 231
+ (UNSPEC_INTERLO_V4SI 232)
+ (UNSPEC_INTERLO_V8HI 233)
+ (UNSPEC_INTERLO_V16QI 234)
+- (UNSPEC_INTERLO_V4SF 235)
++ ;; delete 235
+ (UNSPEC_LVLX 236)
+ (UNSPEC_LVLXL 237)
+ (UNSPEC_LVRX 238)
+@@ -176,39 +162,17 @@ (define_mode_iterator VIshort [V8HI V16Q
+ (define_mode_iterator VF [V4SF])
+ ;; Vec modes, pity mode iterators are not composable
+ (define_mode_iterator V [V4SI V8HI V16QI V4SF])
++;; Vec modes for move/logical/permute ops, include vector types for move not
++;; otherwise handled by altivec (v2df, v2di, ti)
++(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI TI])
+
+ (define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
+
+-;; Generic LVX load instruction.
+-(define_insn "altivec_lvx_<mode>"
+- [(set (match_operand:V 0 "altivec_register_operand" "=v")
+- (match_operand:V 1 "memory_operand" "Z"))]
+- "TARGET_ALTIVEC"
+- "lvx %0,%y1"
+- [(set_attr "type" "vecload")])
+-
+-;; Generic STVX store instruction.
+-(define_insn "altivec_stvx_<mode>"
+- [(set (match_operand:V 0 "memory_operand" "=Z")
+- (match_operand:V 1 "altivec_register_operand" "v"))]
+- "TARGET_ALTIVEC"
+- "stvx %1,%y0"
+- [(set_attr "type" "vecstore")])
+-
+ ;; Vector move instructions.
+-(define_expand "mov<mode>"
+- [(set (match_operand:V 0 "nonimmediate_operand" "")
+- (match_operand:V 1 "any_operand" ""))]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_emit_move (operands[0], operands[1], <MODE>mode);
+- DONE;
+-})
+-
+-(define_insn "*mov<mode>_internal"
+- [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,o,r,r,v")
+- (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,W"))]
+- "TARGET_ALTIVEC
++(define_insn "*altivec_mov<mode>"
++ [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v")
++ (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,j,W"))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
+ && (register_operand (operands[0], <MODE>mode)
+ || register_operand (operands[1], <MODE>mode))"
+ {
+@@ -220,52 +184,17 @@ (define_insn "*mov<mode>_internal"
+ case 3: return "#";
+ case 4: return "#";
+ case 5: return "#";
+- case 6: return output_vec_const_move (operands);
++ case 6: return "vxor %0,%0,%0";
++ case 7: return output_vec_const_move (operands);
+ default: gcc_unreachable ();
+ }
+ }
+- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+-
+-(define_split
+- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+- (match_operand:V4SI 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{
+- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+-})
+-
+-(define_split
+- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+- (match_operand:V8HI 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
++ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
+
+ (define_split
+- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+- (match_operand:V16QI 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
+-
+-(define_split
+- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+- (match_operand:V4SF 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{
+- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+-})
+-
+-(define_split
+- [(set (match_operand:V 0 "altivec_register_operand" "")
+- (match_operand:V 1 "easy_vector_constant_add_self" ""))]
+- "TARGET_ALTIVEC && reload_completed"
++ [(set (match_operand:VM 0 "altivec_register_operand" "")
++ (match_operand:VM 1 "easy_vector_constant_add_self" ""))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && reload_completed"
+ [(set (match_dup 0) (match_dup 3))
+ (set (match_dup 0) (match_dup 4))]
+ {
+@@ -346,11 +275,11 @@ (define_insn "add<mode>3"
+ "vaddu<VI_char>m %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "addv4sf3"
++(define_insn "*altivec_addv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vaddfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+@@ -392,11 +321,11 @@ (define_insn "sub<mode>3"
+ "vsubu<VI_char>m %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "subv4sf3"
++(define_insn "*altivec_subv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vsubfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+@@ -457,131 +386,81 @@ (define_insn "altivec_vcmpbfp"
+ "vcmpbfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpequb"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")]
+- UNSPEC_VCMPEQUB))]
++(define_insn "*altivec_eq<mode>"
++ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
++ (eq:VI (match_operand:VI 1 "altivec_register_operand" "v")
++ (match_operand:VI 2 "altivec_register_operand" "v")))]
+ "TARGET_ALTIVEC"
+- "vcmpequb %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
++ "vcmpequ<VI_char> %0,%1,%2"
++ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpequh"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")]
+- UNSPEC_VCMPEQUH))]
++(define_insn "*altivec_gt<mode>"
++ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
++ (gt:VI (match_operand:VI 1 "altivec_register_operand" "v")
++ (match_operand:VI 2 "altivec_register_operand" "v")))]
+ "TARGET_ALTIVEC"
+- "vcmpequh %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
++ "vcmpgts<VI_char> %0,%1,%2"
++ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpequw"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")]
+- UNSPEC_VCMPEQUW))]
++(define_insn "*altivec_gtu<mode>"
++ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
++ (gtu:VI (match_operand:VI 1 "altivec_register_operand" "v")
++ (match_operand:VI 2 "altivec_register_operand" "v")))]
+ "TARGET_ALTIVEC"
+- "vcmpequw %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
++ "vcmpgtu<VI_char> %0,%1,%2"
++ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpeqfp"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")]
+- UNSPEC_VCMPEQFP))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_eqv4sf"
++ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
++ (eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
++ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpeqfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpgefp"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")]
+- UNSPEC_VCMPGEFP))]
+- "TARGET_ALTIVEC"
+- "vcmpgefp %0,%1,%2"
++(define_insn "*altivec_gtv4sf"
++ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
++ (gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
++ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
++ "vcmpgtfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpgtub"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTUB))]
+- "TARGET_ALTIVEC"
+- "vcmpgtub %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtsb"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTSB))]
+- "TARGET_ALTIVEC"
+- "vcmpgtsb %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtuh"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTUH))]
+- "TARGET_ALTIVEC"
+- "vcmpgtuh %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtsh"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTSH))]
+- "TARGET_ALTIVEC"
+- "vcmpgtsh %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtuw"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTUW))]
+- "TARGET_ALTIVEC"
+- "vcmpgtuw %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtsw"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTSW))]
+- "TARGET_ALTIVEC"
+- "vcmpgtsw %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtfp"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")]
+- UNSPEC_VCMPGTFP))]
+- "TARGET_ALTIVEC"
+- "vcmpgtfp %0,%1,%2"
++(define_insn "*altivec_gev4sf"
++ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
++ (ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
++ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
++ "vcmpgefp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
++(define_insn "altivec_vsel<mode>"
++ [(set (match_operand:VM 0 "altivec_register_operand" "=v")
++ (if_then_else:VM (ne (match_operand:VM 1 "altivec_register_operand" "v")
++ (const_int 0))
++ (match_operand:VM 2 "altivec_register_operand" "v")
++ (match_operand:VM 3 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "vsel %0,%3,%2,%1"
++ [(set_attr "type" "vecperm")])
++
+ ;; Fused multiply add
+ (define_insn "altivec_vmaddfp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 3 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmaddfp %0,%1,%2,%3"
+ [(set_attr "type" "vecfloat")])
+
+ ;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
+
+-(define_expand "mulv4sf3"
++(define_expand "altivec_mulv4sf3"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))
+ (use (match_operand:V4SF 2 "register_operand" ""))]
+- "TARGET_ALTIVEC && TARGET_FUSED_MADD"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode) && TARGET_FUSED_MADD"
+ "
+ {
+ rtx neg0;
+@@ -684,7 +563,7 @@ (define_insn "altivec_vnmsubfp"
+ (neg:V4SF (minus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 3 "register_operand" "v"))))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vnmsubfp %0,%1,%2,%3"
+ [(set_attr "type" "vecfloat")])
+
+@@ -758,11 +637,11 @@ (define_insn "smax<mode>3"
+ "vmaxs<VI_char> %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "smaxv4sf3"
++(define_insn "*altivec_smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmaxfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+@@ -782,11 +661,11 @@ (define_insn "smin<mode>3"
+ "vmins<VI_char> %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "sminv4sf3"
++(define_insn "*altivec_sminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vminfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+@@ -905,7 +784,7 @@ (define_insn "altivec_vmrghw"
+ "vmrghw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+-(define_insn "altivec_vmrghsf"
++(define_insn "*altivec_vmrghsf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (parallel [(const_int 0)
+@@ -918,7 +797,7 @@ (define_insn "altivec_vmrghsf"
+ (const_int 3)
+ (const_int 1)]))
+ (const_int 5)))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmrghw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+@@ -990,35 +869,37 @@ (define_insn "altivec_vmrglh"
+
+ (define_insn "altivec_vmrglw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
+- (parallel [(const_int 2)
+- (const_int 0)
+- (const_int 3)
+- (const_int 1)]))
+- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
+- (parallel [(const_int 0)
+- (const_int 2)
+- (const_int 1)
+- (const_int 3)]))
+- (const_int 5)))]
++ (vec_merge:V4SI
++ (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
+ "TARGET_ALTIVEC"
+ "vmrglw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+-(define_insn "altivec_vmrglsf"
++(define_insn "*altivec_vmrglsf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
+- (parallel [(const_int 2)
+- (const_int 0)
+- (const_int 3)
+- (const_int 1)]))
+- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
+- (parallel [(const_int 0)
+- (const_int 2)
+- (const_int 1)
+- (const_int 3)]))
+- (const_int 5)))]
+- "TARGET_ALTIVEC"
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmrglw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+@@ -1095,68 +976,53 @@ (define_insn "altivec_vmulosh"
+ [(set_attr "type" "veccomplex")])
+
+
+-;; logical ops
++;; logical ops. Have the logical ops follow the memory ops in
++;; terms of whether to prefer VSX or Altivec
+
+-(define_insn "and<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (and:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_and<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (and:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vand %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "ior<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (ior:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_ior<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (ior:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "xor<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (xor:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_xor<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (xor:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "xorv4sf3"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (xor:V4SF (match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "vxor %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "one_cmpl<mode>2"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (not:VI (match_operand:VI 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_one_cmpl<mode>2"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (not:VM (match_operand:VM 1 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vnor %0,%1,%1"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "altivec_nor<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (not:VI (ior:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v"))))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_nor<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (not:VM (ior:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v"))))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vnor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "andc<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (and:VI (not:VI (match_operand:VI 2 "register_operand" "v"))
+- (match_operand:VI 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "vandc %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "*andc3_v4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (and:V4SF (not:V4SF (match_operand:V4SF 2 "register_operand" "v"))
+- (match_operand:V4SF 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_andc<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (and:VM (not:VM (match_operand:VM 2 "register_operand" "v"))
++ (match_operand:VM 1 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vandc %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+@@ -1392,7 +1258,7 @@ (define_insn "*altivec_vspltsf"
+ (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vspltw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+@@ -1404,19 +1270,19 @@ (define_insn "altivec_vspltis<VI_char>"
+ "vspltis<VI_char> %0,%1"
+ [(set_attr "type" "vecperm")])
+
+-(define_insn "ftruncv4sf2"
++(define_insn "*altivec_ftruncv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vrfiz %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+ (define_insn "altivec_vperm_<mode>"
+- [(set (match_operand:V 0 "register_operand" "=v")
+- (unspec:V [(match_operand:V 1 "register_operand" "v")
+- (match_operand:V 2 "register_operand" "v")
+- (match_operand:V16QI 3 "register_operand" "v")]
+- UNSPEC_VPERM))]
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")
++ (match_operand:V16QI 3 "register_operand" "v")]
++ UNSPEC_VPERM))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+@@ -1515,180 +1381,6 @@ (define_insn "altivec_vrefp"
+ "vrefp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+-(define_expand "vcondv4si"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (if_then_else:V4SI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V4SI 4 "register_operand" "v")
+- (match_operand:V4SI 5 "register_operand" "v")])
+- (match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vconduv4si"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (if_then_else:V4SI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V4SI 4 "register_operand" "v")
+- (match_operand:V4SI 5 "register_operand" "v")])
+- (match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vcondv4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (if_then_else:V4SF
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V4SF 4 "register_operand" "v")
+- (match_operand:V4SF 5 "register_operand" "v")])
+- (match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vcondv8hi"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (if_then_else:V8HI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V8HI 4 "register_operand" "v")
+- (match_operand:V8HI 5 "register_operand" "v")])
+- (match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vconduv8hi"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (if_then_else:V8HI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V8HI 4 "register_operand" "v")
+- (match_operand:V8HI 5 "register_operand" "v")])
+- (match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vcondv16qi"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (if_then_else:V16QI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V16QI 4 "register_operand" "v")
+- (match_operand:V16QI 5 "register_operand" "v")])
+- (match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vconduv16qi"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (if_then_else:V16QI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V16QI 4 "register_operand" "v")
+- (match_operand:V16QI 5 "register_operand" "v")])
+- (match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-
+-(define_insn "altivec_vsel_v4si"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")
+- (match_operand:V4SI 3 "register_operand" "v")]
+- UNSPEC_VSEL4SI))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+-(define_insn "altivec_vsel_v4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")
+- (match_operand:V4SI 3 "register_operand" "v")]
+- UNSPEC_VSEL4SF))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+-(define_insn "altivec_vsel_v8hi"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")
+- (match_operand:V8HI 3 "register_operand" "v")]
+- UNSPEC_VSEL8HI))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+-(define_insn "altivec_vsel_v16qi"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")
+- (match_operand:V16QI 3 "register_operand" "v")]
+- UNSPEC_VSEL16QI))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+ (define_insn "altivec_vsldoi_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+@@ -1878,6 +1570,14 @@ (define_expand "build_vector_mask_for_lo
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+
+ addr = XEXP (operands[1], 0);
++ if (VECTOR_MEM_VSX_P (GET_MODE (operands[1])))
++ {
++ /* VSX doesn't and off the bottom address bits, and memory
++ operations are aligned to the natural data type. */
++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
++ DONE;
++ }
++
+ temp = gen_reg_rtx (GET_MODE (addr));
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_NEG (GET_MODE (addr), addr)));
+@@ -1959,95 +1659,6 @@ (define_insn "*altivec_stvesfx"
+ "stvewx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
+-(define_expand "vec_init<mode>"
+- [(match_operand:V 0 "register_operand" "")
+- (match_operand 1 "" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_init (operands[0], operands[1]);
+- DONE;
+-})
+-
+-(define_expand "vec_setv4si"
+- [(match_operand:V4SI 0 "register_operand" "")
+- (match_operand:SI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_setv8hi"
+- [(match_operand:V8HI 0 "register_operand" "")
+- (match_operand:HI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_setv16qi"
+- [(match_operand:V16QI 0 "register_operand" "")
+- (match_operand:QI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_setv4sf"
+- [(match_operand:V4SF 0 "register_operand" "")
+- (match_operand:SF 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv4si"
+- [(match_operand:SI 0 "register_operand" "")
+- (match_operand:V4SI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv8hi"
+- [(match_operand:HI 0 "register_operand" "")
+- (match_operand:V8HI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv16qi"
+- [(match_operand:QI 0 "register_operand" "")
+- (match_operand:V16QI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv4sf"
+- [(match_operand:SF 0 "register_operand" "")
+- (match_operand:V4SF 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+ ;; Generate
+ ;; vspltis? SCRATCH0,0
+ ;; vsubu?m SCRATCH2,SCRATCH1,%1
+@@ -2069,7 +1680,7 @@ (define_expand "abs<mode>2"
+ ;; vspltisw SCRATCH1,-1
+ ;; vslw SCRATCH2,SCRATCH1,SCRATCH1
+ ;; vandc %0,%1,SCRATCH2
+-(define_expand "absv4sf2"
++(define_expand "altivec_absv4sf2"
+ [(set (match_dup 2)
+ (vec_duplicate:V4SI (const_int -1)))
+ (set (match_dup 3)
+@@ -2132,7 +1743,7 @@ (define_expand "vec_shl_<mode>"
+ DONE;
+ }")
+
+-;; Vector shift left in bits. Currently supported ony for shift
++;; Vector shift right in bits. Currently supported ony for shift
+ ;; amounts that can be expressed as byte shifts (divisible by 8).
+ ;; General shift amounts can be supported using vsro + vsr. We're
+ ;; not expecting to see these yet (the vectorizer currently
+@@ -2665,7 +2276,7 @@ (define_expand "vec_pack_trunc_v4si"
+ DONE;
+ }")
+
+-(define_expand "negv4sf2"
++(define_expand "altivec_negv4sf2"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+@@ -2994,29 +2605,6 @@ (define_expand "vec_extract_oddv16qi"
+ emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2]));
+ DONE;
+ }")
+-(define_expand "vec_interleave_highv4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "")
+- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
+- (match_operand:V4SF 2 "register_operand" "")]
+- UNSPEC_INTERHI_V4SF))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- emit_insn (gen_altivec_vmrghsf (operands[0], operands[1], operands[2]));
+- DONE;
+-}")
+-
+-(define_expand "vec_interleave_lowv4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "")
+- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
+- (match_operand:V4SF 2 "register_operand" "")]
+- UNSPEC_INTERLO_V4SF))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- emit_insn (gen_altivec_vmrglsf (operands[0], operands[1], operands[2]));
+- DONE;
+-}")
+
+ (define_expand "vec_interleave_high<mode>"
+ [(set (match_operand:VI 0 "register_operand" "")
+--- gcc/config/rs6000/aix61.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/aix61.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -57,20 +57,24 @@ do { \
+ #undef ASM_SPEC
+ #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
+
+-/* Common ASM definitions used by ASM_SPEC amongst the various targets
+- for handling -mcpu=xxx switches. */
++/* Common ASM definitions used by ASM_SPEC amongst the various targets for
++ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
++ provide the default assembler options if the user uses -mcpu=native, so if
++ you make changes here, make them there also. */
+ #undef ASM_CPU_SPEC
+ #define ASM_CPU_SPEC \
+ "%{!mcpu*: %{!maix64: \
+ %{mpowerpc64: -mppc64} \
+ %{maltivec: -m970} \
+ %{!maltivec: %{!mpower64: %(asm_default)}}}} \
++%{mcpu=native: %(asm_cpu_native)} \
+ %{mcpu=power3: -m620} \
+ %{mcpu=power4: -mpwr4} \
+ %{mcpu=power5: -mpwr5} \
+ %{mcpu=power5+: -mpwr5x} \
+ %{mcpu=power6: -mpwr6} \
+ %{mcpu=power6x: -mpwr6} \
++%{mcpu=power7: -mpwr7} \
+ %{mcpu=powerpc: -mppc} \
+ %{mcpu=rs64a: -mppc} \
+ %{mcpu=603: -m603} \
+--- gcc/config/rs6000/rs6000.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -138,7 +138,7 @@ (define_attr "length" ""
+ ;; Processor type -- this attribute must exactly match the processor_type
+ ;; enumeration in rs6000.h.
+
+-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,cell"
++(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell"
+ (const (symbol_ref "rs6000_cpu_attr")))
+
+
+@@ -167,6 +167,7 @@ (define_attr "cell_micro" "not,condition
+ (include "power4.md")
+ (include "power5.md")
+ (include "power6.md")
++(include "power7.md")
+ (include "cell.md")
+ (include "xfpu.md")
+
+@@ -218,6 +219,9 @@ (define_mode_attr wd [(QI "b") (HI "h")
+ ; DImode bits
+ (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
+
++;; ISEL/ISEL64 target selection
++(define_mode_attr sel [(SI "") (DI "64")])
++
+ \f
+ ;; Start with fixed-point load and store insns. Here we put only the more
+ ;; complex forms. Basic data transfer is done later.
+@@ -520,7 +524,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %2,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -546,7 +550,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %0,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -687,7 +691,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %2,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -713,7 +717,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %0,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -856,7 +860,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %2,%1,0xffff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -882,7 +886,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %0,%1,0xffff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -1670,7 +1674,7 @@ (define_insn ""
+ "@
+ nor. %2,%1,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -1696,7 +1700,7 @@ (define_insn ""
+ "@
+ nor. %0,%1,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -2221,10 +2225,22 @@ (define_insn "popcntb<mode>2"
+ "TARGET_POPCNTB"
+ "popcntb %0,%1")
+
++(define_insn "popcntwsi2"
++ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
++ (popcount:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
++ "TARGET_POPCNTD"
++ "popcntw %0,%1")
++
++(define_insn "popcntddi2"
++ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
++ (popcount:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
++ "TARGET_POPCNTD && TARGET_POWERPC64"
++ "popcntd %0,%1")
++
+ (define_expand "popcount<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
+- "TARGET_POPCNTB"
++ "TARGET_POPCNTB || TARGET_POPCNTD"
+ {
+ rs6000_emit_popcount (operands[0], operands[1]);
+ DONE;
+@@ -2852,7 +2868,7 @@ (define_insn "andsi3_mc"
+ {rlinm|rlwinm} %0,%1,0,%m2,%M2
+ {andil.|andi.} %0,%1,%b2
+ {andiu.|andis.} %0,%1,%u2"
+- [(set_attr "type" "*,*,compare,compare")])
++ [(set_attr "type" "*,*,fast_compare,fast_compare")])
+
+ (define_insn "andsi3_nomc"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+@@ -2895,7 +2911,8 @@ (define_insn "*andsi3_internal2_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
++ compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,8,8,8,8")])
+
+ (define_insn "*andsi3_internal3_mc"
+@@ -2915,7 +2932,8 @@ (define_insn "*andsi3_internal3_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
++ compare,compare,compare")
+ (set_attr "length" "8,4,4,4,8,8,8,8")])
+
+ (define_split
+@@ -2974,7 +2992,8 @@ (define_insn "*andsi3_internal4"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
++ compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,8,8,8,8")])
+
+ (define_insn "*andsi3_internal5_mc"
+@@ -2996,7 +3015,8 @@ (define_insn "*andsi3_internal5_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
++ compare,compare,compare")
+ (set_attr "length" "8,4,4,4,8,8,8,8")])
+
+ (define_insn "*andsi3_internal5_nomc"
+@@ -3141,7 +3161,7 @@ (define_insn "*boolsi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -3170,7 +3190,7 @@ (define_insn "*boolsi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -3295,7 +3315,7 @@ (define_insn "*boolccsi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -3324,7 +3344,7 @@ (define_insn "*boolccsi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -5317,7 +5337,7 @@ (define_insn "fres"
+ "fres %0,%1"
+ [(set_attr "type" "fp")])
+
+-(define_insn ""
++(define_insn "*fmaddsf4_powerpc"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5328,7 +5348,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fmaddsf4_power"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5337,7 +5357,7 @@ (define_insn ""
+ "{fma|fmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fmsubsf4_powerpc"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5348,7 +5368,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fmsubsf4_power"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5357,7 +5377,7 @@ (define_insn ""
+ "{fms|fmsub} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_powerpc_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5368,7 +5388,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_powerpc_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5379,7 +5399,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_power_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5388,7 +5408,7 @@ (define_insn ""
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_power_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5398,7 +5418,7 @@ (define_insn ""
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_powerpc_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5409,7 +5429,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_powerpc_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+@@ -5420,7 +5440,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_power_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5429,7 +5449,7 @@ (define_insn ""
+ "{fnms|fnmsub} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_power_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+@@ -5510,9 +5530,18 @@ (define_expand "copysigndf3"
+ (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]));
++ DONE;
++ }
+ operands[3] = gen_reg_rtx (DFmode);
+ operands[4] = gen_reg_rtx (DFmode);
+ operands[5] = CONST0_RTX (DFmode);
+@@ -5556,12 +5585,12 @@ (define_split
+ DONE;
+ }")
+
+-(define_expand "movsicc"
+- [(set (match_operand:SI 0 "gpc_reg_operand" "")
+- (if_then_else:SI (match_operand 1 "comparison_operator" "")
+- (match_operand:SI 2 "gpc_reg_operand" "")
+- (match_operand:SI 3 "gpc_reg_operand" "")))]
+- "TARGET_ISEL"
++(define_expand "mov<mode>cc"
++ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
++ (if_then_else:GPR (match_operand 1 "comparison_operator" "")
++ (match_operand:GPR 2 "gpc_reg_operand" "")
++ (match_operand:GPR 3 "gpc_reg_operand" "")))]
++ "TARGET_ISEL<sel>"
+ "
+ {
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+@@ -5578,28 +5607,28 @@ (define_expand "movsicc"
+ ;; leave out the mode in operand 4 and use one pattern, but reload can
+ ;; change the mode underneath our feet and then gets confused trying
+ ;; to reload the value.
+-(define_insn "isel_signed"
+- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (if_then_else:SI
++(define_insn "isel_signed_<mode>"
++ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
++ (if_then_else:GPR
+ (match_operator 1 "comparison_operator"
+ [(match_operand:CC 4 "cc_reg_operand" "y")
+ (const_int 0)])
+- (match_operand:SI 2 "gpc_reg_operand" "b")
+- (match_operand:SI 3 "gpc_reg_operand" "b")))]
+- "TARGET_ISEL"
++ (match_operand:GPR 2 "gpc_reg_operand" "b")
++ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
++ "TARGET_ISEL<sel>"
+ "*
+ { return output_isel (operands); }"
+ [(set_attr "length" "4")])
+
+-(define_insn "isel_unsigned"
+- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (if_then_else:SI
++(define_insn "isel_unsigned_<mode>"
++ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
++ (if_then_else:GPR
+ (match_operator 1 "comparison_operator"
+ [(match_operand:CCUNS 4 "cc_reg_operand" "y")
+ (const_int 0)])
+- (match_operand:SI 2 "gpc_reg_operand" "b")
+- (match_operand:SI 3 "gpc_reg_operand" "b")))]
+- "TARGET_ISEL"
++ (match_operand:GPR 2 "gpc_reg_operand" "b")
++ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
++ "TARGET_ISEL<sel>"
+ "*
+ { return output_isel (operands); }"
+ [(set_attr "length" "4")])
+@@ -5647,7 +5676,8 @@ (define_expand "negdf2"
+ (define_insn "*negdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+- "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")])
+
+@@ -5660,14 +5690,16 @@ (define_expand "absdf2"
+ (define_insn "*absdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+- "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" "=f")
+ (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
+- "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")])
+
+@@ -5682,7 +5714,8 @@ (define_insn "*adddf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+@@ -5698,7 +5731,8 @@ (define_insn "*subdf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+@@ -5714,7 +5748,8 @@ (define_insn "*muldf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+@@ -5732,7 +5767,8 @@ (define_insn "*divdf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+
+@@ -5748,73 +5784,81 @@ (define_expand "recipdf3"
+ DONE;
+ })
+
+-(define_insn "fred"
++(define_expand "fred"
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
++ "(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"
++ "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" "=f")
+ (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+- "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" "=f")
+ (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+- "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" "=f")
+ (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f"))))]
+ "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" "=f")
+ (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f"))
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+ "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" "=f")
+ (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f"))))]
+ "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" "=f")
+ (minus:DF (match_operand:DF 3 "gpc_reg_operand" "f")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))))]
+ "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")])
+@@ -5823,7 +5867,8 @@ (define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+ "(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")])
+
+@@ -5912,6 +5957,18 @@ (define_expand "fix_truncsfsi2"
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
+ "")
+
++(define_expand "fixuns_truncdfsi2"
++ [(set (match_operand:SI 0 "gpc_reg_operand" "")
++ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
++ "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,
+@@ -6153,10 +6210,17 @@ (define_insn "fctiwz"
+ "{fcirz|fctiwz} %0,%1"
+ [(set_attr "type" "fp")])
+
+-(define_insn "btruncdf2"
++(define_expand "btruncdf2"
+ [(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"
++ "")
++
++(define_insn "*btruncdf2_fprs"
++ [(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")])
+
+@@ -6167,10 +6231,17 @@ (define_insn "btruncsf2"
+ "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_fprs"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] 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")])
+
+@@ -6181,10 +6252,17 @@ (define_insn "ceilsf2"
+ "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_fprs"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] 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")])
+
+@@ -6195,6 +6273,7 @@ (define_insn "floorsf2"
+ "frim %0,%1"
+ [(set_attr "type" "fp")])
+
++;; No VSX equivalent to frin
+ (define_insn "rounddf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
+@@ -6209,6 +6288,12 @@ (define_insn "roundsf2"
+ "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")
+@@ -6224,17 +6309,40 @@ (define_expand "floatsisf2"
+ "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" "=f")
+ (float:DF (match_operand:DI 1 "gpc_reg_operand" "!f#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" "=!f#r")
+ (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))]
+- "(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")])
+
+@@ -7623,7 +7731,7 @@ (define_insn "anddi3_mc"
+ andi. %0,%1,%b2
+ andis. %0,%1,%u2
+ #"
+- [(set_attr "type" "*,*,*,compare,compare,*")
++ [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
+ (set_attr "length" "4,4,4,4,4,8")])
+
+ (define_insn "anddi3_nomc"
+@@ -7681,7 +7789,9 @@ (define_insn "*anddi3_internal2_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
++ fast_compare,compare,compare,compare,compare,compare,\
++ compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
+
+ (define_insn "*anddi3_internal2_nomc"
+@@ -7744,7 +7854,9 @@ (define_insn "*anddi3_internal3_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
++ fast_compare,compare,compare,compare,compare,compare,\
++ compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
+
+ (define_insn "*anddi3_internal3_nomc"
+@@ -7896,7 +8008,7 @@ (define_insn "*booldi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -7925,7 +8037,7 @@ (define_insn "*booldi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -7996,7 +8108,7 @@ (define_insn "*boolcdi3_internal2"
+ "@
+ %q4. %3,%2,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8025,7 +8137,7 @@ (define_insn "*boolcdi3_internal3"
+ "@
+ %q4. %0,%2,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8062,7 +8174,7 @@ (define_insn "*boolccdi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8091,7 +8203,7 @@ (define_insn "*boolccdi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8108,6 +8220,51 @@ (define_split
+ (compare:CC (match_dup 0)
+ (const_int 0)))]
+ "")
++
++(define_expand "smindi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
++ DONE;
++}")
++
++(define_expand "smaxdi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
++ DONE;
++}")
++
++(define_expand "umindi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]);
++ DONE;
++}")
++
++(define_expand "umaxdi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]);
++ DONE;
++}")
++
+ \f
+ ;; Now define ways of moving data around.
+
+@@ -8511,8 +8668,8 @@ (define_split
+ ;; 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,f,f,m,!r,!r,!r")
+- (match_operand:DF 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r, ??r, m, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, !r, !r, !r")
++ (match_operand:DF 1 "input_operand" "r, m, r, ws, wa, Z, Z, ws, wa, f, m, f, 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))"
+@@ -8591,19 +8748,30 @@ (define_insn "*movdf_hardfloat32"
+ return \"\";
+ }
+ case 3:
+- return \"fmr %0,%1\";
+ case 4:
+- return \"lfd%U1%X1 %0,%1\";
++ return \"xscpsgndp %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")
+@@ -8651,19 +8819,26 @@ (define_insn "*movdf_softfloat32"
+ ; 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,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
+- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y, r, !r, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, *c*l, !r, *h, !r, !r, !r, r, f")
++ (match_operand:DF 1 "input_operand" "r, Y, r, ws, ?wa, Z, Z, ws, wa, f, m, f, j, r, h, 0, G, H, F, f, 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
++ xscpsgndp %x0,%x1,%x1
++ xscpsgndp %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}
+@@ -8672,33 +8847,40 @@ (define_insn "*movdf_hardfloat64_mfpgpr"
+ #
+ 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,f,f,m,*c*l,!r,*h,!r,!r,!r")
+- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y, r, !r, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, *c*l, !r, *h, !r, !r, !r")
++ (match_operand:DF 1 "input_operand" "r, Y, r, ws, wa, Z, Z, ws, wa, f, m, f, 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
++ xscpsgndp %x0,%x1,%x1
++ xscpsgndp %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")
+@@ -9275,15 +9457,16 @@ (define_insn "*movti_string"
+ (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" "*,load,store")])
+
+ (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))]
+ "
+@@ -9309,7 +9492,7 @@ (define_split
+ (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; })
+@@ -14929,6 +15112,8 @@ (define_insn "prefetch"
+ \f
+
+ (include "sync.md")
++(include "vector.md")
++(include "vsx.md")
+ (include "altivec.md")
+ (include "spe.md")
+ (include "dfp.md")
+--- gcc/config/rs6000/e500.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/e500.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -37,6 +37,8 @@
+ { \
+ if (TARGET_ALTIVEC) \
+ error ("AltiVec and E500 instructions cannot coexist"); \
++ if (TARGET_VSX) \
++ error ("VSX and E500 instructions cannot coexist"); \
+ if (TARGET_64BIT) \
+ error ("64-bit E500 not supported"); \
+ if (TARGET_HARD_FLOAT && TARGET_FPRS) \
+--- gcc/config/rs6000/driver-rs6000.c (.../trunk) (revision 144557)
++++ gcc/config/rs6000/driver-rs6000.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -343,11 +343,115 @@ detect_processor_aix (void)
+ #endif /* _AIX */
+
+
++/*
++ * Array to map -mcpu=native names to the switches passed to the assembler.
++ * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
++ * should be made there as well.
++ */
++
++struct asm_name {
++ const char *cpu;
++ const char *asm_sw;
++};
++
++static const
++struct asm_name asm_names[] = {
++#if defined (_AIX)
++ { "power3", "-m620" },
++ { "power4", "-mpwr4" },
++ { "power5", "-mpwr5" },
++ { "power5+", "-mpwr5x" },
++ { "power6", "-mpwr6" },
++ { "power6x", "-mpwr6" },
++ { "power7", "-mpwr7" },
++ { "powerpc", "-mppc" },
++ { "rs64a", "-mppc" },
++ { "603", "-m603" },
++ { "603e", "-m603" },
++ { "604", "-m604" },
++ { "604e", "-m604" },
++ { "620", "-m620" },
++ { "630", "-m620" },
++ { "970", "-m970" },
++ { "G5", "-m970" },
++ { NULL, "\
++%{!maix64: \
++%{mpowerpc64: -mppc64} \
++%{maltivec: -m970} \
++%{!maltivec: %{!mpower64: %(asm_default)}}}" },
++
++#else
++ { "common", "-mcom" },
++ { "cell", "-mcell" },
++ { "power", "-mpwr" },
++ { "power2", "-mpwrx" },
++ { "power3", "-mppc64" },
++ { "power4", "-mpower4" },
++ { "power5", "%(asm_cpu_power5)" },
++ { "power5+", "%(asm_cpu_power5)" },
++ { "power6", "%(asm_cpu_power6) -maltivec" },
++ { "power6x", "%(asm_cpu_power6) -maltivec" },
++ { "power7", "%(asm_cpu_power7)" },
++ { "powerpc", "-mppc" },
++ { "rios", "-mpwr" },
++ { "rios1", "-mpwr" },
++ { "rios2", "-mpwrx" },
++ { "rsc", "-mpwr" },
++ { "rsc1", "-mpwr" },
++ { "rs64a", "-mppc64" },
++ { "401", "-mppc" },
++ { "403", "-m403" },
++ { "405", "-m405" },
++ { "405fp", "-m405" },
++ { "440", "-m440" },
++ { "440fp", "-m440" },
++ { "464", "-m440" },
++ { "464fp", "-m440" },
++ { "505", "-mppc" },
++ { "601", "-m601" },
++ { "602", "-mppc" },
++ { "603", "-mppc" },
++ { "603e", "-mppc" },
++ { "ec603e", "-mppc" },
++ { "604", "-mppc" },
++ { "604e", "-mppc" },
++ { "620", "-mppc64" },
++ { "630", "-mppc64" },
++ { "740", "-mppc" },
++ { "750", "-mppc" },
++ { "G3", "-mppc" },
++ { "7400", "-mppc -maltivec" },
++ { "7450", "-mppc -maltivec" },
++ { "G4", "-mppc -maltivec" },
++ { "801", "-mppc" },
++ { "821", "-mppc" },
++ { "823", "-mppc" },
++ { "860", "-mppc" },
++ { "970", "-mpower4 -maltivec" },
++ { "G5", "-mpower4 -maltivec" },
++ { "8540", "-me500" },
++ { "8548", "-me500" },
++ { "e300c2", "-me300" },
++ { "e300c3", "-me300" },
++ { "e500mc", "-me500mc" },
++ { NULL, "\
++%{mpower: %{!mpower2: -mpwr}} \
++%{mpower2: -mpwrx} \
++%{mpowerpc64*: -mppc64} \
++%{!mpowerpc64*: %{mpowerpc*: -mppc}} \
++%{mno-power: %{!mpowerpc*: -mcom}} \
++%{!mno-power: %{!mpower*: %(asm_default)}}" },
++#endif
++};
++
+ /* This will be called by the spec parser in gcc.c when it sees
+ a %:local_cpu_detect(args) construct. Currently it will be called
+ with either "arch" or "tune" as argument depending on if -march=native
+ or -mtune=native is to be substituted.
+
++ Additionally it will be called with "asm" to select the appropriate flags
++ for the assembler.
++
+ It returns a string containing new command line parameters to be
+ put at the place of the above two options, depending on what CPU
+ this is executed.
+@@ -361,29 +465,35 @@ const char
+ const char *cache = "";
+ const char *options = "";
+ bool arch;
++ bool assembler;
++ size_t i;
+
+ if (argc < 1)
+ return NULL;
+
+ arch = strcmp (argv[0], "cpu") == 0;
+- if (!arch && strcmp (argv[0], "tune"))
++ assembler = (!arch && strcmp (argv[0], "asm") == 0);
++ if (!arch && !assembler && strcmp (argv[0], "tune"))
+ return NULL;
+
++ if (! assembler)
++ {
+ #if defined (_AIX)
+- cache = detect_caches_aix ();
++ cache = detect_caches_aix ();
+ #elif defined (__APPLE__)
+- cache = detect_caches_darwin ();
++ cache = detect_caches_darwin ();
+ #elif defined (__FreeBSD__)
+- cache = detect_caches_freebsd ();
+- /* FreeBSD PPC does not provide any cache information yet. */
+- cache = "";
++ cache = detect_caches_freebsd ();
++ /* FreeBSD PPC does not provide any cache information yet. */
++ cache = "";
+ #elif defined (__linux__)
+- cache = detect_caches_linux ();
+- /* PPC Linux does not provide any cache information yet. */
+- cache = "";
++ cache = detect_caches_linux ();
++ /* PPC Linux does not provide any cache information yet. */
++ cache = "";
+ #else
+- cache = "";
++ cache = "";
+ #endif
++ }
+
+ #if defined (_AIX)
+ cpu = detect_processor_aix ();
+@@ -397,6 +507,17 @@ const char
+ cpu = "powerpc";
+ #endif
+
++ if (assembler)
++ {
++ for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++)
++ {
++ if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu))
++ return asm_names[i].asm_sw;
++ }
++
++ return NULL;
++ }
++
+ return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
+ }
+
+--- gcc/config/rs6000/sysv4.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/sysv4.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -119,9 +119,9 @@ do { \
+ else if (!strcmp (rs6000_abi_name, "i960-old")) \
+ { \
+ rs6000_current_abi = ABI_V4; \
+- target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI \
+- | MASK_NO_BITFIELD_WORD); \
++ target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI); \
+ target_flags &= ~MASK_STRICT_ALIGN; \
++ TARGET_NO_BITFIELD_WORD = 1; \
+ } \
+ else \
+ { \
+
diff --git a/gcc44-pr39358.patch b/gcc44-pr39358.patch
deleted file mode 100644
index c0bc2cf..0000000
--- a/gcc44-pr39358.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-2009-03-04 Richard Guenther <rguenther@suse.de>
-
- PR tree-optimization/39358
- * tree-ssa-structalias.c (do_sd_constraint): Fix check for
- escaped_id and callused_id.
- (solve_graph): Likewise.
-
- * g++.dg/warn/Wstrict-aliasing-bogus-escape-2.C: New testcase.
- * g++.dg/warn/Wstrict-aliasing-bogus-escape-3.C: Likewise.
-
---- gcc/tree-ssa-structalias.c (revision 144601)
-+++ gcc/tree-ssa-structalias.c (revision 144602)
-@@ -1524,8 +1524,8 @@ do_sd_constraint (constraint_graph_t gra
- of a variable can also reach all other fields of the variable
- we simply have to expand the solution to contain all sub-fields
- if one sub-field is contained. */
-- if (c->rhs.var == escaped_id
-- || c->rhs.var == callused_id)
-+ if (c->rhs.var == find (escaped_id)
-+ || c->rhs.var == find (callused_id))
- {
- bitmap vars = NULL;
- /* In a first pass record all variables we need to add all
-@@ -1594,9 +1594,10 @@ do_sd_constraint (constraint_graph_t gra
- /* Merging the solution from ESCAPED needlessly increases
- the set. Use ESCAPED as representative instead.
- Same for CALLUSED. */
-- else if (get_varinfo (t)->id == escaped_id
-- || get_varinfo (t)->id == callused_id)
-- flag |= bitmap_set_bit (sol, get_varinfo (t)->id);
-+ else if (get_varinfo (t)->id == find (escaped_id))
-+ flag |= bitmap_set_bit (sol, escaped_id);
-+ else if (get_varinfo (t)->id == find (callused_id))
-+ flag |= bitmap_set_bit (sol, callused_id);
- else if (add_graph_edge (graph, lhs, t))
- flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
- }
-@@ -2516,8 +2517,8 @@ solve_graph (constraint_graph_t graph)
-
- if (!solution_empty
- /* Do not propagate the ESCAPED/CALLUSED solutions. */
-- && i != escaped_id
-- && i != callused_id)
-+ && i != find (escaped_id)
-+ && i != find (callused_id))
- {
- bitmap_iterator bi;
-
---- gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-escape-2.C (revision 0)
-+++ gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-escape-2.C (revision 144602)
-@@ -0,0 +1,19 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -Wstrict-aliasing" } */
-+
-+#include<list>
-+
-+struct A
-+{
-+ virtual ~A();
-+};
-+
-+A* foo();
-+
-+void bar(std::list<int> x)
-+{
-+ std::list<int> y = x;
-+ if (*y.rbegin())
-+ delete foo();
-+}
-+
---- gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-escape-3.C (revision 0)
-+++ gcc/testsuite/g++.dg/warn/Wstrict-aliasing-bogus-escape-3.C (revision 144602)
-@@ -0,0 +1,35 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -Wstrict-aliasing" } */
-+
-+struct Node_base {};
-+
-+struct Node : Node_base
-+{
-+ int data;
-+};
-+
-+struct List
-+{
-+ Node_base node, *prev;
-+
-+ List() : prev(&node) { xyz(); }
-+
-+ void xyz();
-+
-+ int back() { return static_cast<Node*>(prev)->data; }
-+};
-+
-+struct A
-+{
-+ virtual ~A();
-+};
-+
-+A* foo();
-+
-+void bar()
-+{
-+ List y;
-+ if (y.back())
-+ delete foo();
-+}
-+
diff --git a/power7.patch b/power7.patch
deleted file mode 100644
index a9c1948..0000000
--- a/power7.patch
+++ /dev/null
@@ -1,9506 +0,0 @@
-2009-03-06 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * doc/invoke.texi (-mvsx-scalar-memory): New switch, to switch to
- use VSX reg+reg addressing for all scalar double precision
- floating point.
- * config/rs6000/rs6000.opt (-vsx-scalar-memory): Ditto.
-
- * configure.ac (gcc_cv_as_powerpc_mfpgpr): Set binutils version to
- 2.19.2.
- (gcc_cv_as_powerpc_cmpb): Ditto.
- (gcc_cv_as_powerpc_dfp): Ditto.
- (gcc_cv_as_powerpc_vsx): Ditto.
- (gcc_cv_as_powerpc_popcntd): Ditto.
- * configure: Regenerate.
-
- * config/rs6000/vector.md (VEC_int): New mode attribute for vector
- conversions.
- (VEC_INT): Ditto.
- (ftrunc<mode>2): Make this a define_expand.
- (float<VEC_int><mode>2): New vector conversion support to add VSX
- 32 bit int/32 bit floating point convert and 64 bit int/64 bit
- floating point vector instructions.
- (unsigned_float<VEC_int><mode>2): Ditto.
- (fix_trunc<mode><VEC_int>2): Ditto.
- (fixuns_trunc<mode><VEC_int>2): Ditto.
-
- * config/rs6000/predicates.md (easy_fp_constant): 0.0 is an easy
- constant under VSX.
- (indexed_or_indirect_operand): Add VSX load/store with update
- support.
-
- * config/rs6000/rs6000.c (rs6000_debug_addr): New global for
- -mdebug=addr.
- (rs6000_init_hard_regno_mode_ok): Add -mvsx-scalar-memory
- support.
- (rs6000_override_options): Add -mdebug=addr support.
- (rs6000_builtin_conversion): Add VSX same size conversions.
- (rs6000_legitimize_address): Add -mdebug=addr support. Add
- support for VSX load/store with update instructions.
- (rs6000_legitimize_reload_address): Ditto.
- (rs6000_legitimate_address): Ditto.
- (rs6000_mode_dependent_address): Ditto.
- (print_operand): Ditto.
- (bdesc_1arg): Add builtins for conversion that calls either the
- VSX or Altivec insn pattern.
- (rs6000_common_init_builtins): Ditto.
-
- * config/rs6000/vsx.md (VSX_I): Delete, no longer used.
- (VSi): New mode attribute for conversions.
- (VSI): Ditto.
- (VSc): Ditto.
- (vsx_mov<mode>): Add load/store with update support.
- (vsx_load<mode>_update*): New insns for load/store with update
- support.
- (vsx_store<mode>_update*): Ditto.
- (vsx_fmadd<mode>4): Generate correct code for V4SF.
- (vsx_fmsub<mode>4): Ditto.
- (vsx_fnmadd<mode>4_*): Ditto.
- (vsx_fnmsub<mode>4_*): Ditto.
- (vsx_float<VSi><mode>2): New insn for vector conversion.
- (vsx_floatuns<VSi><mode>2): Ditto.
- (vsx_fix_trunc<mode><VSi>2): Ditto.
- (vsx_fixuns_trunc<mode><VSi>2): Ditto.
- (vsx_xxmrghw): New insn for V4SF interleave.
- (vsx_xxmrglw): Ditto.
-
- * config/rs6000/rs6000.h (rs6000_debug_addr): -mdebug=addr
- support.
- (TARGET_DEBUG_ADDR): Ditto.
- (rs6000_builtins): Add VSX instructions for eventual VSX
- builtins.
-
- * config/rs6000/altivec.md (altivec_vmrghsf): Don't do the altivec
- instruction if VSX.
- (altivec_vmrglsf): Ditto.
-
- * config/rs6000/rs6000.md (movdf_hardfloat32): Add support for
- using xxlxor to zero a floating register if VSX.
- (movdf_hardfloat64_mfpgpr): Ditto.
- (movdf_hardfloat64): Ditto.
-
-2009-03-03 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/vsx.md (vsx_xxmrglw): Delete for now, use Altivec.
- (vsx_xxmrghw): Ditto.
-
- * config/rs6000/altivec.md (altivec_vmrghsf): Use this insn even
- on VSX systems.
- (altivec_vmrglsf): Ditto.
-
- * config/rs6000/rs6000.h (ASM_CPU_NATIVE_SPEC): Use %(asm_default)
- if we are running as a cross compiler.
-
- * config/rs6000/vector.md (vec_interleave_highv4sf): Use correct
- constants for the extraction.
- (vec_interleave_lowv4sf): Ditto.
-
- * config/rs6000/rs6000.md (floordf2): Fix typo, make this a
- define_expand, not define_insn.
-
- * config/rs6000/aix53.h (ASM_CPU_SPEC): If -mcpu=native, call
- %:local_cpu_detect(asm) to get the appropriate assembler flags for
- the machine.
- * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto.
- * config/rs6000/rs6000.h (ASM_CPU_SPEC): Ditto.
- (ASM_CPU_NATIVE_SPEC): New spec to get asm options if
- -mcpu=native.
- (EXTRA_SPECS): Add ASM_CPU_NATIVE_SPEC.
-
- * config/rs6000/driver-rs6000.c (asm_names): New static array to
- give the appropriate asm switches if -mcpu=native.
- (host_detect_local_cpu): Add support for "asm".
-
- * config/rs6000/rs6000.c (processor_target_table): Don't turn on
- -misel by default for power7.
-
-2009-03-02 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/rs6000.c (rs6000_emit_swdivdf): Revert last
- change, since we reverted the floating multiply/add changes.
-
- * doc/md.texi (Machine Constraints): Update rs6000 constraints.
-
- * config/rs6000/vector.md (neg<mode>2): Fix typo to enable
- vectorized negation.
- (ftrunc<mode>2): Move ftrunc expander here from altivec.md, and
- add V2DF case.
- (vec_interleave_highv4sf): Correct type to be V4SF, not V4SI.
- (vec_extract_evenv2df): Add expander.
- (vec_extract_oddv2df): Ditto.
-
- * config/rs6000/vsx.md (vsx_ftrunc<mode>2): New VSX pattern for
- truncate.
- (vsx_ftruncdf2): Ditto.
- (vsx_xxspltw): New instruction for word splat.
- (vsx_xxmrglw): Whitespace changes. Fix typo from V4SI to v4SF.
- (vsx_xxmrghw): Ditto.
-
- * config/rs6000/altivec.md (altivec_vmrghsf): Whitespace changes.
- (altivec_vmrglsf): Ditto.
- (altivec_vspltsf): Disable if we have VSX.
- (altivec_ftruncv4sf2): Move expander to vector.md, rename insn.
-
- * config/rs6000/rs6000.md (ftruncdf2): Add expander for VSX.
-
- * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok):
- Reenable vectorizing V4SF under altivec.
- (rs6000_hard_regno_mode_ok): Don't allow floating values in LR,
- CTR, MQ. Also, VRSAVE/VSCR are both 32-bits.
- (rs6000_init_hard_regno_mode_ok): Print some of the special
- registers if -mdebug=reg.
-
- * config/rs6000/rs6000.md (floating multiply/add insns): Go back
- to the original semantics for multiply add/subtract, particularly
- with -ffast-math.
-
- * config/rs6000/vsx.md (floating multiply/add insns): Mirror the
- rs6000 floating point multiply/add insns in VSX.
-
-2009-03-01 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/vector.md (VEC_L): At TImode.
- (VEC_M): Like VEC_L, except no TImode.
- (VEC_base): Add TImode support.
- (mov<mode>): Use VEC_M, not VEC_L. If there is no extra
- optimization for the move, just generate the standard move.
- (vector_store_<mode>): Ditto.
- (vector_load_<mode>): Ditto.
- (vec_init<mode>): Use vec_init_operand predicate.
-
- * config/rs6000/predicates.md (vec_init_operand): New predicate.
-
- * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow mode
- in a VSX register if there is a move operation.
- (rs6000_vector_reg_class): Add internal register number to the
- debug output.
- (rs6000_init_hard_regno_mode_ok): Reorganize so all of the code
- for a given type is located together. If not -mvsx, make "ws"
- constraint become NO_REGS, not FLOAT_REGS. Change -mdebug=reg
- output.
- (rs6000_expand_vector_init): Before calling gen_vsx_concat_v2df,
- make sure the two float arguments are copied into registers.
- (rs6000_legitimate_offset_address_p): If no vsx or altivec, don't
- disallow offset addressing. Add V2DImode. If TImode is handled
- by the vector unit, allow indexed addressing. Change default case
- to be a fatal_insn instead of gcc_unreachable.
- (rs6000_handle_altivec_attribute): Add support for vector double
- if -mvsx.
- (rs6000_register_move_cost): Add support for VSX_REGS. Know that
- under VSX, you can move between float and altivec registers
- cheaply.
- (rs6000_emit_swdivdf): Change the pattern of the negate multiply
- and subtract operation.
-
- * config/rs6000/vsx.md (VSX_I): Add TImode.
- (VSX_L): Add TImode.
- (VSm): Ditto.
- (VSs): Ditto.
- (VSr): Ditto.
- (UNSPEC_VSX_CONCAT_V2DF): New constant.
- (vsx_fre<mode>2): Add reciprocal estimate.
- (vsx_freDF2): Ditto.
- (vsx_fnmadd<mode>4): Rework pattern so it matches the
- canonicalization that the compiler does.
- (vsx_fnmsub<mode>4): Ditto.
- (vsx_fnmaddDF4): Ditto.
- (vsx_fnmsubDF4): Ditto.
- (vsx_vsel<mode>): Use vsx_register_operand, not register_operand.
- (vsx_adddf3): Ditto.
- (vsx_subdf3): Ditto.
- (vsx_muldf3): Ditto.
- (vsx_divdf3): Ditto.
- (vsx_negdf3): Ditto.
- (vsx_absdf2): Ditto.
- (vsx_nabsdf2): Ditto.
- (vsx_copysign<mode>3): Add copysign support.
- (vsx_copysignDF3): Ditto.
- (vsx_concat_v2df): Rewrite to use an UNSPEC.
- (vsx_set_v2df): Use "ws" constraint for scalar float.
- (vsx_splatv2df): Ditto.
-
- * config/rs6000/rs6000.h (VECTOR_UNIT_NONE_P): New macro to say no
- vector support.
- (VECTOR_MEM_NONE_P): Ditto.
- (VSX_MOVE_MODE): Add V2DImode, TImode.
-
- * config/rs6000/altivec.md (VM): Add V2DI, TI.
- (build_vector_mask_for_load): Fix thinko in VSX case.
-
- * config/rs6000/rs6000.md (fmaddsf4_powerpc): Name previously
- unnamed pattern. Fix insns so combine will generate the negative
- multiply and subtract operations.
- (fmaddsf4_power): Ditto.
- (fmsubsf4_powerpc): Ditto.
- (fmsubsf4_power): Ditto.
- (fnmaddsf4_powerpc): Ditto.
- (fnmaddsf4_power): Ditto.
- (fnmsubsf4_powerpc): Ditto.
- (fnmsubsf4_power): Ditto.
- (fnsubsf4_powerpc2): Ditto.
- (fnsubsf4_power2): Ditto.
- (fmadddf4_powerpc): Ditto.
- (fmadddf4_power): Ditto.
- (fmsubdf4_powerpc): Ditto.
- (fmsubdf4_power): Ditto.
- (fnmadddf4_powerpc): Ditto.
- (fnmadddf4_power): Ditto.
- (fnmsubdf4_powerpc): Ditto.
- (fnmsubdf4_power): Ditto.
- (copysigndf3): If VSX, call the VSX copysign.
- (fred): Split into an expander and insn. On insn, disable if
- VSX.
- (movdf_hardfloat32): Rework VSX support.
- (movdf_hardfloat64_mfpgpr): Ditto.
- (movdf_hardfloat64): Ditto.
- (movti_ppc64): If vector unit is handling TImode, disable this
- pattern.
-
-2009-02-28 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/ppc-asm.h: If __VSX__ define the additional scalar
- floating point registers that overlap with th Altivec registers.
-
-2009-02-27 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/spe.md (spe_fixuns_truncdfsi2): Rename from
- fixuns_truncdfsi2, and move fixuns_truncdfsi2 into rs6000.md.
-
- * config/rs6000/ppc-asm.h: If __ALTIVEC__ is defined, define the
- Altivec registers. If __VSX__ is defined, define the VSX
- registers.
-
- * config/rs6000/rs6000.opt (-mvsx-scalar-double): Make this on by
- default.
- (-misel): Make this a target mask instead of a variable.
-
- * config/rs6000/rs6000.c (rs6000_isel): Delete global variable.
- (rs6000_explicit_options): Delete isel field.
- (POWERPC_MASKS): Add MASK_ISEL.
- (processor_target_table): Add MASK_ISEL to 8540, 8548, e500mc, and
- power7 processors.
- (rs6000_override_options): Move -misel to a target mask.
- (rs6000_handle_option): Ditto.
- (rs6000_emit_int_cmove): Add support for 64-bit isel.
-
- * config/rs6000/vsx.md (vsx_floatdidf2): New scalar floating point
- pattern to support VSX conversion and rounding instructions.
- (vsx_floatunsdidf2): Ditto.
- (vsx_fix_trundfdi2): Ditto.
- (vsx_fixuns_trundfdi2): Ditto.
- (vsx_btrundf2): Ditto.
- (vsx_floordf2): Ditto.
- (vsx_ceildf2): Ditto.
-
- * config/rs6000/rs6000.h (rs6000_isel): Delete global.
- (TARGET_ISEL): Delete, since -misel is now a target mask.
- (TARGET_ISEL64): New target option for -misel on 64-bit systems.
-
- * config/rs6000/altivec.md (altivec_gtu<mode>): Use gtu, not geu.
-
- * config/rs6000/rs6000.md (sel): New mode attribute for 64-bit
- ISEL support.
- (mov<mode>cc): Add 64-bit ISEL support.
- (isel_signed_<mode>): Ditto.
- (isel_unsigned_<mode>): Ditto.
- (fixuns_truncdfsi2): Move expander here from spe.md.
- (fixuns_truncdfdi2): New expander for unsigned floating point
- conversion on power7.
- (btruncdf2): Split into expander and insn. On the insn, disallow
- on VSX, so the VSX instruction will be generated.
- (ceildf2): Ditto.
- (floordf2): Ditto.
- (floatdidf2): Ditto.
- (fix_truncdfdi2): Ditto.
- (smindi3): Define if we have -misel on 64-bit systems.
- (smaxdi3): Ditto.
- (umindi3): Ditto.
- (umaxdi3): Ditto.
-
- * config/rs6000/e500.h (CHECK_E500_OPTIONS): Disable -mvsx on
- E500.
-
-2009-02-26 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/constraints.md ("wd" constraint): Change the
- variable that holds the register class to use.
- ("wf" constraint): Ditto.
- ("ws" constraint): Ditto.
- ("wa" constraint): Ditto.
-
- * config/rs6000/rs6000.opt (-mvsx-vector-memory): Make this on by
- default.
- (-mvsx-vector-float): Ditto.
-
- * config/rs6000/rs6000.c (rs6000_vector_reg_class): New global to
- hold the register classes for the vector modes.
- (rs6000_vsx_v4sf_regclass): Delete, move into
- rs6000_vector_reg_class.
- (rs6000_vsx_v2df_regclass): Ditto.
- (rs6000_vsx_df_regclass): Ditto.
- (rs6000_vsx_reg_class): Rename from rs6000_vsx_any_regclass.
- (rs6000_hard_regno_mode_ok): Rework VSX, Altivec registers.
- (rs6000_init_hard_regno_mode_ok): Setup rs6000_vector_reg_class.
- Drop rs6000_vsx_*_regclass. By default, use all 64 registers for
- V4SF and V2DF. Use VSX_REG_CLASS_P macro instead of separate
- tests. Update -mdebug=reg printout.
- (rs6000_preferred_reload_class): If VSX, prefer FLOAT_REGS for
- scalar floating point and ALTIVEC_REGS for the types that have
- altivec instructions.
- (rs6000_secondary_memory_needed): If VSX, we can copy between FPR
- and Altivec registers without needed memory.
- (rs6000_secondary_reload_class): Delete ATTRIBUTE_UNUSED from an
- argument that is used. If VSX, we can copy between FPR and
- Altivec registers directly.
-
- * config/rs6000/rs6000.h (VSX_MOVE_MODE): Add in the Altivec
- types.
- (rs6000_vsx_v4sf_regclass): Delete.
- (rs6000_vsx_v2df_regclass): Ditto.
- (rs6000_vsx_df_regclass): Ditto.
- (rs6000_vsx_reg_class): Rename from rs6000_vsx_any_reg_class.
- (rs6000_vector_reg_class): New global to map machine mode to the
- preferred register class to use for that mode.
- (VSX_REG_CLASS_P): New macro to return true for all of the
- register classes VSX items can be in.
-
-2009-02-25 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * doc/invoke.texi (-mvsx-vector-memory): Rename from
- -mvsx-vector-move.
- (-mvsx-vector-logical): Delete.
-
- * config/rs6000/aix53.h (ASM_CPU_SPEC): Add power7 support.
- * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto.
-
- * config/rs6000/vector.md (all insns); Change from using
- rs6000_vector_info to VECTOR_MEM_* or VECTOR_UNIT_* macros.
-
- * config/rs6000/constraints.md ("wi" constraint): Delete.
- ("wl" constraint): Ditto.
- ("ws" constraint): Change to use rs6000_vsx_df_regclass.
-
- * config/rs6000/rs6000.opt (-mvsx-vector-memory): Rename from
- -mvsx-vector-move.
- (-mvsx-vector-float): Make default 0, not 1.
- (-mvsx-vector-double): Make default -1, not 1.
- (-mvsx-vector-logical): Delete.
-
- * config/rs6000/rs6000.c (rs6000_vector_info): Delete.
- (rs6000_vector_unit): New global array to say what vector unit is
- used for arithmetic instructions.
- (rs6000_vector_move): New global array to say what vector unit is
- used for memory references.
- (rs6000_vsx_int_regclass): Delete.
- (rs6000_vsx_logical_regclass): Delete.
- (rs6000_hard_regno_nregs_internal): Switch from using
- rs6000_vector_info to rs6000_vector_unit, rs6000_vector_move.
- (rs6000_hard_regno_mode_ok): Ditto. Reformat code somewhat.
- (rs6000_debug_vector_unit): New array to print vector unit
- information if -mdebug=reg.
- (rs6000_init_hard_regno_mode_ok): Rework to better describe VSX
- and Altivec register sets.
- (builtin_mask_for_load): Return 0 if -mvsx.
- (rs6000_legitimize_reload_address): Allow AND in VSX addresses.
- (rs6000_legitimate_address): Ditto.
- (bdesc_3arg): Delete vselv2di builtin.
- (rs6000_emit_minmax): Use rs6000_vector_unit instead of
- rs6000_vector_info.
- (rs6000_vector_mode_supported_p): Ditto.
-
- * config/rs6000/vsx.md (all insns): Change from using
- rs6000_vector_info to VECTOR_MEM_* and VECTOR_UNIT_* macros.
- (VSr): Change to use "v" register class, not "wi".
- (vsx_mov<mode>): Combine floating and integer. Allow prefered
- register class, and then use ?wa for all VSX registers.
- (vsx_fmadddf4): Use ws constraint, not f.
- (vsx_fmsubdf4): Ditto.
- (vsx_fnmadddf4): Ditto.
- (vsx_fnmsubdf4): Ditto.
- (vsx_and<mode>3): Use preferred register class, and then ?wa to
- catch all VSX registers.
- (vsx_ior<mode>3): Ditto.
- (vsx_xor<mode>3): Ditto.
- (vsx_one_cmpl<mode>2): Ditto.
- (vsx_nor<mode>3): Ditto.
- (vsx_andc<mode>3): Ditto.
-
- * config/rs6000/rs6000.h (rs6000_vector_struct): Delete.
- (rs6000_vector_info): Ditto.
- (rs6000_vector_unit): New global array to say whether a machine
- mode arithmetic is handled by a particular vector unit.
- (rs6000_vector_mem): New global array to say which vector unit to
- use for moves.
- (VECTOR_UNIT_*): New macros to say which vector unit to use.
- (VECTOR_MEM_*): Ditto.
- (rs6000_vsx_int_regclass): Delete.
- (rs6000_vsx_logical_regclass): Delete.
-
- * config/rs6000/altivec.md (all insns): Change from using
- rs6000_vector_info to VECTOR_MEM_* and VECTOR_UNIT_* macros.
- (build_vector_mask_for_load): Disable if VSX.
-
- * config/rs6000/rs6000.md (all DF insns): Change how the VSX
- exclusion is done.
-
-2009-02-24 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/rs6000.c (rs6000_debug_reg): New global.
- (rs6000_debug_reg_print): New function to print register classes
- for a given register range.
- (rs6000_init_hard_regno_mode_ok): If -mdebug=reg, print out the
- register class, call used, fixed information for most of the
- registers. Print the vsx register class variables.
- (rs6000_override_options): Add -mdebug=reg support.
-
- * config/rs6000/rs6000.h (rs6000_debug_reg): New global.
- (TARGET_DEBUG_REG): New target switch for -mdebug=reg.
-
-2009-02-23 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * reload.c (subst_reloads): Change gcc_assert into a fatal_insn.
-
- * config/rs6000/vector.md (VEC_I): Reorder iterator.
- (VEC_L): Ditto.
- (VEC_C): New iterator field for vector comparisons.
- (VEC_base): New mode attribute that mapes the vector type to the
- base type.
- (all insns): Switch to use rs6000_vector_info to determine whether
- the insn is valid instead of using TARGET_VSX or TARGET_ALTIVEC.
- (vcond<mode>): Move here from altivec, and add VSX support.
- (vcondu<mode>): Ditto.
- (vector_eq<mode>): New expander for vector comparisons.
- (vector_gt<mode>): Ditto.
- (vector_ge<mode>): Ditto.
- (vector_gtu<mode>): Ditto.
- (vector_geu<mode>): Ditto.
- (vector_vsel<mode>): New expander for vector select.
- (vec_init<mode>): Move expander from altivec.md and generalize for
- VSX.
- (vec_set<mode>): Ditto.
- (vec_extract<mode>): Ditto.
- (vec_interleave_highv4sf): Ditto.
- (vec_interleave_lowv4sf): Ditto.
- (vec_interleave_highv2df): New expander for VSX.
- (vec_interleave_lowv2df): Ditto.
-
- * config/rs6000/contraints.md (toplevel): Add comment on the
- available constraint letters.
- ("w" constraint): Delete, in favor of using "w" as a two letter
- constraint.
- ("wd" constraint): New VSX constraint.
- ("wf" constraint): Ditto.
- ("wi" constraint): Ditto.
- ("wl" constraint): Ditto.
- ("ws" constraint): Ditto.
- ("wa" constraint): Ditto.
-
- * config/rs6000/predicates.md (indexed_or_indirect_operand):
- Disable altivec support allowing AND of memory address if -mvsx.
-
- * config/rs6000/rs6000.opt (-mvsx-vector-move): New switches to
- allow finer control over whether VSX, Altivec, or the traditional
- instructions are used.
- (-mvsx-scalar-move): Ditto.
- (-mvsx-vector-float): Ditto.
- (-mvsx-vector-double): Ditto.
- (-mvsx-vector-logical): Ditto.
- (-mvsx-scalar-double): Ditto.
-
- * config/rs6000/rs6000.c (rs6000_vector_info): New global to hold
- various information about which vector instruction set to use, and
- the alignment of data.
- (rs6000_vsx_v4sf_regclass): New global to hold VSX register
- class.
- (rs6000_vsx_v2df_regclass): Ditto.
- (rs6000_vsx_df_regclass): Ditto.
- (rs6000_vsx_int_regclass): Ditto.
- (rs6000_vsx_logical_regclass): Ditto.
- (rs6000_vsx_any_regclass): Ditto.
- (rs6000_hard_regno_nregs_internal): Rewrite to fine tune
- VSX/Altivec register selection.
- (rs6000_hard_regno_mode_ok): Ditto.
- (rs6000_init_hard_regno_mode_ok): Set up the vector information
- globals based on the -mvsx-* switches.
- (rs6000_override_options): Add warnings for -mvsx and
- -mlittle-endian or -mavoid-indexed-addresses.
- (rs6000_builtin_vec_perm): Add V2DF/V2DI support.
- (rs6000_expand_vector_init): Add V2DF support.
- (rs6000_expand_vector_set): Ditto.
- (rs6000_expand_vector_extract): Ditto.
- (avoiding_indexed_address_p): Add VSX support.
- (rs6000_legitimize_address): Ditto.
- (rs6000_legitimize_reload_address): Ditto.
- (rs6000_legitimite_address): Ditto.
- (USE_ALTIVEC_FOR_ARG_P): Ditto.
- (function_arg_boundary): Ditto.
- (function_arg_advance): Ditto.
- (function_arg): Ditto.
- (get_vec_cmp_insn): Delete.
- (rs6000_emit_vector_vsx): New function for VSX vector compare.
- (rs6000_emit_vector_altivec): New function for Altivec vector
- compare.
- (get_vsel_insn): Delete.
- (rs6000_emit_vector_select): Ditto.
- (rs6000_override_options): If -mvsx, turn on -maltivec by
- default.
- (rs6000_builtin_vec_perm): Add support for V2DI, V2DF modes.
- (bdesc_3arg): Add vector select and vector permute builtins for
- V2DI and V2DF types. Switch to using the vector_* expander
- instead of altivec_*.
- (rs6000_init_builtins): Initialize new type nodes for VSX.
- Initialize __vector double type. Initialize common builtins for
- VSX.
- (rs6000_emit_vector_compare): Add VSX support.
- (rs6000_vector_mode_supported_p): If VSX, support V2DF.
-
- * config/rs6000/vsx.md (VSX_I): New iterator for integer modes.
- (VSX_L): Reorder iterator.
- (lx_<mode>_vsx): Delete, no longer needed.
- (stx_<mode>_vsx): Ditto.
- (all insns): Change to use vsx_<name> instead of <name>_vsx for
- consistancy with the other rs6000 md files. Change to use the new
- "w" constraints for all insns. Change to use rs6000_vector_info
- deciding whether to execute the instruction or not.
- (vsx_mov<mode>): Rewrite constraints so GPR registers are not
- chosen as reload targets. Split integer vector loads into a
- separate insn, and favor the altivec register over the VSX fp
- registers.
- (vsx_fmadd<mode>4): Use <mode>, not <type>.
- (vsx_fmsub<mode>4): Ditto.
- (vsx_eq<mode>): New insns for V2DF/V4SF vector compare.
- (vsx_gt<mode>): Ditto.
- (vsx_ge<mode>): Ditto.
- (vsx_vsel<mode>): New insns for VSX vector select.
- (vsx_xxpermdi): New insn for DF permute.
- (vsx_splatv2df): New insn for DF splat support.
- (vsx_xxmrglw): New insns for DF interleave.
- (vsx_xxmrghw): Ditto.
-
- * config/rs6000/rs000.h (enum rs6000_vector): New enum to
- describe which vector unit is being used.
- (struct rs6000_vector_struct): New struct to describe the various
- aspects about the current vector instruction set.
- (rs6000_vector_info): New global to describe the current vector
- instruction set.
- (SLOW_UNALIGNED_ACCESS): If rs6000_vector_info has alignment
- information for a type, use that.
- (VSX_VECTOR_MOVE_MODE): New macro for all VSX vectors that are
- supported by move instructions.
- (VSX_MOVE_MODE): New macro for all VSX moves.
- (enum rs6000_builtins): Add V2DI/V2DF vector select and permute
- builtins.
- (rs6000_builtin_type_index): Add new types for VSX vectors.
- (rs6000_vsx_v4sf_regclass): New global to hold VSX register
- class.
- (rs6000_vsx_v2df_regclass): Ditto.
- (rs6000_vsx_df_regclass): Ditto.
- (rs6000_vsx_int_regclass): Ditto.
- (rs6000_vsx_logical_regclass): Ditto.
- (rs6000_vsx_any_regclass): Ditto.
-
- * config/rs6000/altivec.md (UNSPEC_VCMP*): Delete unspec
- constants no longer needed.
- (UNSPEC_VSEL*): Ditto.
- (altivec_lvx_<mode>): Delete, no longer needed.
- (altivec_stvx_<mode>): Ditto.
- (all insns): Rewrite to be consistant of altivec_<insn>. Switch
- to use rs6000_vector_info to determine whether to issue to the
- altivec form of the instructions.
- (mov<mode>_altivec): Rewrite constraints so GPR registers are not
- chosen as reload targets.
- (altivec_eq<mode>): Rewrite vector conditionals, permute, select
- to use iterators, and work with VSX.
- (altivec_gt<mode>): Ditto.
- (altivec_ge<mode>): Ditto.
- (altivec_gtu<mode>): Ditto.
- (altivec_geu<mode>): Ditto.
- (altivec_vsel<mode>): Ditto.
- (altivec_vperm_<mode>): Ditto.
- (altivec_vcmp*): Rewrite to not use unspecs any more, and use mode
- iterators, add VSX support.
- (vcondv4si): Move to vector.md.
- (vconduv4si): Ditto.
- (vcondv8hi): Ditto.
- (vconduv8hi): Ditto.
- (vcondv16qi): Ditto.
- (vconduv16qi): Ditto.
-
- * config/rs6000/rs6000.md (negdf2_fpr): Add support for
- -mvsx-scalar-double.
- (absdf2_fpr): Ditto.
- (nabsdf2_fpr): Ditto.
- (adddf3_fpr): Ditto.
- (subdf3_fpr): Ditto.
- (muldf3_fpr): Ditto.
- (divdf3_fpr): Ditto.
- (DF multiply/add patterns): Ditto.
- (sqrtdf2): Ditto.
- (movdf_hardfloat32): Add VSX support.
- (movdf_hardfloat64_mfpgpr): Ditto.
- (movdf_hardfloat64): Ditto.
-
- * doc/invoke.texi (-mvsx-*): Add new vsx switches.
-
-2009-02-13 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config.in: Update two comments.
-
- * config/rs6000/vector.md (VEC_L): Add V2DI type.
- (move<mode>): Use VEC_L to get all vector types, and delete the
- separate integer mode move definitions.
- (vector_load_<mode>): Ditto.
- (vector_store_<mode>): Ditto.
- (vector move splitters): Move GPR register splitters here from
- altivec.md.
-
- * config/rs6000/constraints.md ("j"): Add "j" constraint to match
- the mode's 0 value.
-
- * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Only
- count the FPRs as being 128 bits if the mode is a VSX type.
- (rs6000_hard_regno_mode_ok): Ditto.
- (rs6000_emit_minmax): Use new VSX_MODE instead of separate tests.
-
- * config/rs6000/vsx.md (VSX_L): Add V2DImode.
- (VSm): Rename from VSX_mem, add modes for integer vectors. Change
- all uses.
- (VSs): Rename from VSX_op, add modes for integer vectors. Change
- all uses.
- (VSr): New mode address to give the register class.
- (mov<mode>_vsx): Use VSr to get the register preferences. Add
- explicit 0 option.
- (scalar double precision patterns): Do not use v register
- constraint right now.
- (logical patterns): Use VSr mode attribute for register
- preferences.
-
- * config/rs6000/rs6000.h (VSX_SCALAR_MODE): New macro.
- (VSX_MODE): Ditto.
-
- * config/rs6000/altivec.md (VM): New mode iterator for memory
- operations. Add V2DI mode.
- (mov_altivec_<mode>): Disable if -mvsx for all modes, not just
- V4SFmode.
- (gpr move splitters): Move to vector.md.
- (and<mode>3_altivec): Use VM mode iterator, not V.
- (ior<mode>3_altivec): Ditto.
- (xor<mode>3_altivec): Ditto.
- (one_cmpl<mode>2_altivec): Ditto.
- (nor<mode>3_altivec): Ditto.
- (andc<mode>3_altivec): Ditto.
-
- * config/rs6000/rs6000.md (movdf_hardfloat): Back out vsx changes.
- (movdf_hardfloat64_vsx): Delete.
-
-2009-02-12 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * config/rs6000/vector.md: New file to abstract out the expanders
- for vector operations from alitvec.md.
-
- * config/rs6000/predicates.md (vsx_register_operand): New
- predicate to match VSX registers.
- (vfloat_operand): New predicate to match registers used for vector
- floating point operations.
- (vint_operand): New predicate to match registers used for vector
- integer operations.
- (vlogical_operand): New predicate to match registers used for
- vector logical operations.
-
- * config/rs6000/rs6000-protos.h (rs6000_hard_regno_nregs): Change
- from a function to an array.
- (rs6000_class_max_nregs): Add declaration.
-
- * config/rs6000/t-rs6000 (MD_INCLUDES): Define to include all of
- the .md files included by rs6000.md.
-
- * config/rs6000/rs6000.c (rs6000_class_max_nregs): New global
- array to pre-calculate CLASS_MAX_NREGS.
- (rs6000_hard_regno_nregs): Change from a function to an array to
- pre-calculate HARD_REGNO_NREGS.
- (rs6000_hard_regno_nregs_internal): Rename from
- rs6000_hard_regno_nregs and add VSX support.
- (rs6000_hard_regno_mode_ok): Add VSX support, and switch to use
- lookup table rs6000_hard_regno_nregs.
- (rs6000_init_hard_regno_mode_ok): Add initialization of
- rs6000_hard_regno_nregs, and rs6000_class_max_nregs global
- arrays.
- (rs6000_override_options): Add some warnings for things that are
- incompatible with -mvsx.
- (rs6000_legitimate_offset_address_p): Add V2DFmode.
- (rs6000_conditional_register_usage): Enable altivec registers if
- -mvsx.
- (bdesc_2arg): Change the name of the nor pattern.
- (altivec_expand_ld_builtin): Change the names of the load
- patterns to be the generic vector loads.
- (altivec_expand_st_builtin): Change the names of the store
- patterns to be the generic vector stores.
- (print_operand): Add 'x' to print out a VSX register properly.
- (rs6000_emit_minmax): Directly emit the min/max patterns for VSX
- and Altivec.
-
- * config/rs6000/vsx.md: New file to add all of the VSX specific
- instructions. Add support for load, store, move, add, subtract,
- multiply, multiply/add, divide, negate, absolute value, maximum,
- minimum, sqrt, and, or, xor, and complent, xor, one's complement,
- and nor instructions.
-
- * config/rs6000/rs6000.h (UNITS_PER_VSX_WORD): Define.
- (VSX_REGNO_P): New macro for VSX registers.
- (VFLOAT_REGNO): New macro for vector floating point registers.
- (VINT_REGNO): New macro for vector integer registers.
- (VLOGICAL_REGNO): New macro for vector logical registers.
- (VSX_VECTOR_MODE): New macro for vector modes supported by VSX.
- (HARD_REGNO_NREGS): Switch to using pre-computed table.
- (CLASS_MAX_NREGS): Ditto.
-
- * config/rs6000/altivec.md (altivec_lvx_<mode>): Delete, repalced
- by expanders in vector.md.
- (altivec_stvx_<mode>): Ditto.
- (mov<mode>): Ditto.
- (mov_altivec_<mode>): Rename from mov<mode>_internal, and prefer
- using VSX if available.
- (addv4sf3_altivec): Rename from standard name, and prefer using
- VSX if available.
- (subv4sf3_altivec): Ditto.
- (mulv4sf3_altivec): Ditto.
- (smaxv4sf3_altivec): Ditto.
- (sminv4sf3_altivec): Ditto.
- (and<mode>3_altivec): Ditto.
- (ior<mode>3_altivec): Ditto.
- (xor<mode>3_altivec): Ditto.
- (one_cmpl<mode>2): Ditto.
- (nor<mode>3_altivec): Ditto.
- (andc<mode>3_altivec): Ditto.
- (absv4sf2_altivec): Ditto.
- (vcondv4sf): Move to vector.md.
-
- * config/rs6000/rs6000.md (negdf2_fpr): Add !TARGET_VSX to prefer
- the version in vsx.md if -mvsx is available.
- (absdf2_fpr): Ditto.
- (nabsdf2_fpr): Ditto.
- (adddf3_fpr): Ditto.
- (subdf3_fpr): Ditto.
- (muldf3_fpr): Ditto.
- (multiply/add patterns): Ditto.
- (movdf_hardfloat64): Disable if -mvsx.
- (movdf_hardfloat64_vsx): Clone from movdf_hardfloat64 and add VSX
- support.
- (vector.md): Include new .md file.
- (vsx.md): Ditto.
-
-2009-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * doc/invoke.texi (-mvsx, -mno-vsx): Document new switches.
-
- * config/rs6000/linux64.opt (-mprofile-kernel): Move to being a
- variable to reduce the number of target flag bits.
- * config/rs6000/sysv4.opt (-mbit-align): Ditto.
- (-mbit-word): Ditto.
- (-mregnames): Ditto.
- * config/rs6000/rs6000.opt (-mupdate, -mno-update): Ditto.
- (-mvsx): New switch, enable VSX support.
-
- * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
- __VSX__ if the vector/scalar instruction set is available.
-
- * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Change
- to allow -mprofile-kernel to be a variable.
-
- * config/rs6000/rs6000.c (processor_target_table): Set -mvsx for
- power7 cpus.
- (POWERPC_MASKS): Add -mvsx.
-
- * config/rs6000/rs6000.h (ADDITIONAL_REGISTER_NAMES): Add VSX
- register names for the registers that overlap with the floating
- point and altivec registers.
-
- * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS):
- TARGET_NO_BITFIELD_WORD is now a variable, not a target mask.
-
-2009-02-11 Pat Haugen <pthaugen@us.ibm.com>
- Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * doc/invoke.texi (-mpopcntd, -mno-popcntd): Document new
- switches.
-
- * configure.ac (powerpc*-*-*): Test for the assembler having the
- popcntd instruction.
- * configure: Regenerate.
- * config.in (HAVE_AS_POPCNTD): Add default value for configure
- test.
-
- * config/rs6000/power7.md: New file.
-
- * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
- _ARCH_PWR7 if the popcntd instruction is available.
-
- * config/rs6000/rs6000.opt (-mpopcntd): New switch to
- enable/disable the use of the popcntd and popcntw instructions.
- (-mfused-madd, -mno-fused-madd): Move to being a separate variable
- because we are out of mask bits.
-
- * config/rs6000/rs6000.c (power7_cost): Define.
- (rs6000_override_options): Add Power7 support.
- (rs6000_issue_rate): Ditto.
- (insn_must_be_first_in_group): Ditto.
- (insn_must_be_last_in_group): Ditto.
- (rs6000_emit_popcount): Add support for using the popcntw and
- popcntd instructions.
-
- * config/rs6000/rs6000.h (ASM_CPU_POWER7_SPEC): Switch to using
- popcntd as the test for a power7 assembler instead of vector
- scalar instructions.
- * (TARGET_POPCNTD): If assembler does not support the popcntd
- instruction, disable using it.
- (processor_type): Add Power7 entry.
-
- * config/rs6000/rs6000.md (define_attr "cpu"): Add power7.
- (power7.md): Include it.
- (andi./andis./nor. patterns): Change insn type to fast_compare.
- (popcntwsi2): Add popcntw support.
- (popcntddi2): Add popcntd support.
-
-testsuite/
-2009-03-01 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * gcc.target/powerpc/vsx-vector-1.c: Fix typos.
- * gcc.target/powerpc/vsx-vector-2.c: Ditto.
-
- * gcc.target/powerpc/vsx-vector-3.c: New file, test __vector
- double.
-
- * gcc.target/powerpc/vsx-vector-4.c: New file, test __vector float
- uses VSX instructions if -mvsx.
-
- * gcc.dg/vmx/vmx.exp (DEFAULT_VMXCLFAGS): Add -mno-vsx.
-
- * lib/target-supports.exp (check_vsx_hw_available): New function
- to test for VSX.
- (check_vmx_hw_available): Add -mno-vsx to options.
- (check_effective_target_powerpc_vsx_ok): New function to check if
- the powerpc compiler can support VSX.
-
-2009-02-27 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * gcc.target/powerpc/vsx-vector-1.c: New file to test VSX code
- generation.
- * gcc.target/powerpc/vsx-vector-2.c: Ditto.
-
-2009-02-01 Michael Meissner <meissner@linux.vnet.ibm.com>
-
- * gcc.target/powerpc/popcount-2.c: New file for power7 support.
- * gcc.target/powerpc/popcount-3.c: Ditto.
-
---- gcc/doc/invoke.texi (.../trunk) (revision 144557)
-+++ gcc/doc/invoke.texi (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -712,7 +712,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
-@@ -726,7 +727,9 @@ 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 -mvsx -mvsx-vector-memory @gol
-+-mvsx-vector-float -mvsx-vector-double @gol
-+-mvsx-scalar-double -mvsx-scalar-memory @gol
- -mprioritize-restricted-insns=@var{priority} @gol
- -msched-costly-dep=@var{dependence_type} @gol
- -minsert-sched-nops=@var{scheme} @gol
-@@ -13512,6 +13515,8 @@ These @samp{-m} options are defined for
- @itemx -mno-mfcrf
- @itemx -mpopcntb
- @itemx -mno-popcntb
-+@itemx -mpopcntd
-+@itemx -mno-popcntd
- @itemx -mfprnd
- @itemx -mno-fprnd
- @itemx -mcmpb
-@@ -13536,6 +13541,8 @@ These @samp{-m} options are defined for
- @opindex mno-mfcrf
- @opindex mpopcntb
- @opindex mno-popcntb
-+@opindex mpopcntd
-+@opindex mno-popcntd
- @opindex mfprnd
- @opindex mno-fprnd
- @opindex mcmpb
-@@ -13585,6 +13592,9 @@ The @option{-mpopcntb} option allows GCC
- 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.
-@@ -13663,9 +13673,9 @@ The @option{-mcpu} options automatically
- 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
-@@ -13766,6 +13776,44 @@ 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 -mvsx-vector-memory
-+@itemx -mno-vsx-vector-memory
-+If @option{-mvsx}, use VSX memory reference instructions for vectors
-+instead of the Altivec instructions This option is a temporary switch
-+to tune the compiler, and may not be supported in future versions.
-+
-+@item -mvsx-vector-float
-+@itemx -mno-vsx-vector-float
-+If @option{-mvsx}, use VSX arithmetic instructions for float vectors.
-+This option is a temporary switch to tune the compiler, and may not be
-+supported in future versions.
-+
-+@item -mvsx-vector-double
-+@itemx -mno-vsx-vector-double
-+If @option{-mvsx}, use VSX arithmetic instructions for double
-+vectors. This option is a temporary switch to tune the
-+compiler, and may not be supported in future versions.
-+
-+@item -mvsx-scalar-double
-+@itemx -mno-vsx-scalar-double
-+If @option{-mvsx}, use VSX arithmetic instructions for scalar double.
-+This option is a temporary switch to tune the compiler, and may not be
-+supported in future versions.
-+
-+@item -mvsx-scalar-memory
-+@itemx -mno-vsx-scalar-memory
-+If @option{-mvsx}, use VSX memory reference instructions for scalar
-+double. This option is a temporary switch to tune the compiler, and
-+may not be supported in future versions.
-+
- @item -mfloat-gprs=@var{yes/single/double/no}
- @itemx -mfloat-gprs
- @opindex mfloat-gprs
---- gcc/doc/md.texi (.../trunk) (revision 144557)
-+++ gcc/doc/md.texi (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -1905,7 +1905,19 @@ Address base register
- Floating point register
-
- @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
-@@ -1991,6 +2003,9 @@ AND masks that can be performed by two r
- @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}
---- gcc/reload.c (.../trunk) (revision 144557)
-+++ gcc/reload.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -6255,8 +6255,14 @@ subst_reloads (rtx insn)
- *r->where = reloadreg;
- }
- /* If reload got no reg and isn't optional, something's wrong. */
-- else
-- gcc_assert (rld[r->what].optional);
-+ else if (!rld[r->what].optional)
-+ {
-+ char buffer[100];
-+ sprintf (buffer,
-+ "unable to find register for reload, replacement #%d",
-+ i);
-+ fatal_insn (buffer, insn);
-+ }
- }
- }
- \f
---- gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../trunk) (revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -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);
-+}
---- gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../trunk) (revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -0,0 +1,74 @@
-+/* { 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" } } */
-+
-+#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];
-+}
---- gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../trunk) (revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -0,0 +1,74 @@
-+/* { 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" } } */
-+
-+#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];
-+}
---- gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../trunk) (revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -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;
-+}
---- gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../trunk) (revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -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);
-+}
---- gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../trunk) (revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -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;
-+}
---- gcc/testsuite/gcc.dg/vmx/vmx.exp (.../trunk) (revision 144557)
-+++ gcc/testsuite/gcc.dg/vmx/vmx.exp (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -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
---- gcc/testsuite/lib/target-supports.exp (.../trunk) (revision 144557)
-+++ gcc/testsuite/lib/target-supports.exp (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -873,6 +873,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.
-
-@@ -883,12 +909,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()
-@@ -1519,6 +1546,33 @@ proc check_effective_target_powerpc_alti
- }
- }
-
-+# 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 { } {
---- gcc/config.in (.../trunk) (revision 144557)
-+++ gcc/config.in (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -334,12 +334,18 @@
- #endif
-
-
--/* Define if your assembler supports popcntb field. */
-+/* Define if your assembler supports popcntb instruction. */
- #ifndef USED_FOR_TARGET
- #undef HAVE_AS_POPCNTB
- #endif
-
-
-+/* Define if your assembler supports popcntd instruction. */
-+#ifndef USED_FOR_TARGET
-+#undef HAVE_AS_POPCNTD
-+#endif
-+
-+
- /* Define if your assembler supports .register. */
- #ifndef USED_FOR_TARGET
- #undef HAVE_AS_REGISTER_PSEUDO_OP
---- gcc/configure.ac (.../trunk) (revision 144557)
-+++ gcc/configure.ac (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -2,7 +2,7 @@
- # Process this file with autoconf to generate a configuration script.
-
- # Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
--# 2007, 2008 Free Software Foundation, Inc.
-+# 2007, 2008, 2009 Free Software Foundation, Inc.
-
- #This file is part of GCC.
-
-@@ -3080,7 +3080,7 @@ foo: nop
- esac
-
- gcc_GAS_CHECK_FEATURE([move fp gpr support],
-- gcc_cv_as_powerpc_mfpgpr, [9,99,0],,
-+ gcc_cv_as_powerpc_mfpgpr, [2,19,2],,
- [$conftest_s],,
- [AC_DEFINE(HAVE_AS_MFPGPR, 1,
- [Define if your assembler supports mffgpr and mftgpr.])])
-@@ -3114,7 +3114,7 @@ LCF0:
- esac
-
- gcc_GAS_CHECK_FEATURE([compare bytes support],
-- gcc_cv_as_powerpc_cmpb, [9,99,0], -a32,
-+ gcc_cv_as_powerpc_cmpb, [2,19,2], -a32,
- [$conftest_s],,
- [AC_DEFINE(HAVE_AS_CMPB, 1,
- [Define if your assembler supports cmpb.])])
-@@ -3129,7 +3129,7 @@ LCF0:
- esac
-
- gcc_GAS_CHECK_FEATURE([decimal float support],
-- gcc_cv_as_powerpc_dfp, [9,99,0], -a32,
-+ gcc_cv_as_powerpc_dfp, [2,19,2], -a32,
- [$conftest_s],,
- [AC_DEFINE(HAVE_AS_DFP, 1,
- [Define if your assembler supports DFP instructions.])])
-@@ -3144,11 +3144,26 @@ LCF0:
- esac
-
- gcc_GAS_CHECK_FEATURE([vector-scalar support],
-- gcc_cv_as_powerpc_vsx, [9,99,0], -a32,
-+ gcc_cv_as_powerpc_vsx, [2,19,2], -a32,
- [$conftest_s],,
- [AC_DEFINE(HAVE_AS_VSX, 1,
- [Define if your assembler supports VSX instructions.])])
-
-+ case $target in
-+ *-*-aix*) conftest_s=' .machine "pwr7"
-+ .csect .text[[PR]]
-+ popcntd 3,3';;
-+ *) conftest_s=' .machine power7
-+ .text
-+ popcntd 3,3';;
-+ esac
-+
-+ gcc_GAS_CHECK_FEATURE([popcntd support],
-+ gcc_cv_as_powerpc_popcntd, [2,19,2], -a32,
-+ [$conftest_s],,
-+ [AC_DEFINE(HAVE_AS_POPCNTD, 1,
-+ [Define if your assembler supports POPCNTD instructions.])])
-+
- gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
- gcc_cv_as_powerpc_gnu_attribute, [2,18,0],,
- [.gnu_attribute 4,1],,
---- gcc/configure (.../trunk) (revision 144557)
-+++ gcc/configure (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -23225,7 +23225,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set}
- else
- gcc_cv_as_powerpc_mfpgpr=no
- if test $in_tree_gas = yes; then
-- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
- then gcc_cv_as_powerpc_mfpgpr=yes
- fi
- elif test x$gcc_cv_as != x; then
-@@ -23321,7 +23321,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}"
- else
- gcc_cv_as_powerpc_cmpb=no
- if test $in_tree_gas = yes; then
-- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
- then gcc_cv_as_powerpc_cmpb=yes
- fi
- elif test x$gcc_cv_as != x; then
-@@ -23367,7 +23367,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" =
- else
- gcc_cv_as_powerpc_dfp=no
- if test $in_tree_gas = yes; then
-- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
- then gcc_cv_as_powerpc_dfp=yes
- fi
- elif test x$gcc_cv_as != x; then
-@@ -23413,7 +23413,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" =
- else
- gcc_cv_as_powerpc_vsx=no
- if test $in_tree_gas = yes; then
-- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
- then gcc_cv_as_powerpc_vsx=yes
- fi
- elif test x$gcc_cv_as != x; then
-@@ -23443,6 +23443,52 @@ _ACEOF
-
- fi
-
-+ case $target in
-+ *-*-aix*) conftest_s=' .machine "pwr7"
-+ .csect .text[PR]
-+ popcntd 3,3';;
-+ *) conftest_s=' .machine power7
-+ .text
-+ popcntd 3,3';;
-+ esac
-+
-+ echo "$as_me:$LINENO: checking assembler for popcntd support" >&5
-+echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6
-+if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then
-+ echo $ECHO_N "(cached) $ECHO_C" >&6
-+else
-+ gcc_cv_as_powerpc_popcntd=no
-+ if test $in_tree_gas = yes; then
-+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
-+ then gcc_cv_as_powerpc_popcntd=yes
-+fi
-+ elif test x$gcc_cv_as != x; then
-+ echo "$conftest_s" > conftest.s
-+ if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
-+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-+ (eval $ac_try) 2>&5
-+ ac_status=$?
-+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+ (exit $ac_status); }; }
-+ then
-+ gcc_cv_as_powerpc_popcntd=yes
-+ else
-+ echo "configure: failed program was" >&5
-+ cat conftest.s >&5
-+ fi
-+ rm -f conftest.o conftest.s
-+ fi
-+fi
-+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5
-+echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6
-+if test $gcc_cv_as_powerpc_popcntd = yes; then
-+
-+cat >>confdefs.h <<\_ACEOF
-+#define HAVE_AS_POPCNTD 1
-+_ACEOF
-+
-+fi
-+
- echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5
- echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6
- if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then
---- gcc/config/rs6000/aix53.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/aix53.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -57,20 +57,24 @@ do { \
- #undef ASM_SPEC
- #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
-
--/* Common ASM definitions used by ASM_SPEC amongst the various targets
-- for handling -mcpu=xxx switches. */
-+/* Common ASM definitions used by ASM_SPEC amongst the various targets for
-+ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
-+ provide the default assembler options if the user uses -mcpu=native, so if
-+ you make changes here, make them there also. */
- #undef ASM_CPU_SPEC
- #define ASM_CPU_SPEC \
- "%{!mcpu*: %{!maix64: \
- %{mpowerpc64: -mppc64} \
- %{maltivec: -m970} \
- %{!maltivec: %{!mpower64: %(asm_default)}}}} \
-+%{mcpu=native: %(asm_cpu_native)} \
- %{mcpu=power3: -m620} \
- %{mcpu=power4: -mpwr4} \
- %{mcpu=power5: -mpwr5} \
- %{mcpu=power5+: -mpwr5x} \
- %{mcpu=power6: -mpwr6} \
- %{mcpu=power6x: -mpwr6} \
-+%{mcpu=power7: -mpwr7} \
- %{mcpu=powerpc: -mppc} \
- %{mcpu=rs64a: -mppc} \
- %{mcpu=603: -m603} \
---- gcc/config/rs6000/vector.md (.../trunk) (revision 0)
-+++ gcc/config/rs6000/vector.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -0,0 +1,518 @@
-+;; 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.
-+;; 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/>.
-+
-+
-+;; Vector int modes
-+(define_mode_iterator VEC_I [V16QI V8HI V4SI])
-+
-+;; Vector float modes
-+(define_mode_iterator VEC_F [V4SF V2DF])
-+
-+;; Vector logical modes
-+(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
-+
-+;; Vector modes for moves. Don't do TImode here.
-+(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
-+
-+;; Vector comparison modes
-+(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
-+
-+;; Base type from vector mode
-+(define_mode_attr VEC_base [(V16QI "QI")
-+ (V8HI "HI")
-+ (V4SI "SI")
-+ (V2DI "DI")
-+ (V4SF "SF")
-+ (V2DF "DF")
-+ (TI "TI")])
-+
-+;; Same size integer type for floating point data
-+(define_mode_attr VEC_int [(V4SF "v4si")
-+ (V2DF "v2di")])
-+
-+(define_mode_attr VEC_INT [(V4SF "V4SI")
-+ (V2DF "V2DI")])
-+
-+;; Vector move instructions.
-+(define_expand "mov<mode>"
-+ [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
-+ (match_operand:VEC_M 1 "any_operand" ""))]
-+ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
-+{
-+ /* modes without special handling just generate the normal SET operation. */
-+ if (<MODE>mode != TImode && <MODE>mode != V2DImode && <MODE>mode != V2DFmode)
-+ {
-+ rs6000_emit_move (operands[0], operands[1], <MODE>mode);
-+ DONE;
-+ }
-+ else if (!vlogical_operand (operands[0], <MODE>mode)
-+ && !vlogical_operand (operands[1], <MODE>mode))
-+ operands[1] = force_reg (<MODE>mode, operands[1]);
-+})
-+
-+;; 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_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_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_OR_VSX_P (<MODE>mode)
-+ && reload_completed
-+ && gpr_or_gpr_p (operands[0], operands[1])"
-+ [(pc)]
-+{
-+ rs6000_split_multireg_move (operands[0], operands[1]);
-+ DONE;
-+})
-+
-+\f
-+;; Generic floating point vector arithmetic support
-+(define_expand "add<mode>3"
-+ [(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_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_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_VSX_P (<MODE>mode)
-+ || (VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD))"
-+ "
-+{
-+ 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_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ 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_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ 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_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_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_OR_VSX_P (<MODE>mode)"
-+ "")
-+
-+\f
-+;; Vector comparisons
-+(define_expand "vcond<mode>"
-+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
-+ (if_then_else:VEC_F
-+ (match_operator 3 "comparison_operator"
-+ [(match_operand:VEC_F 4 "vfloat_operand" "")
-+ (match_operand:VEC_F 5 "vfloat_operand" "")])
-+ (match_operand:VEC_F 1 "vfloat_operand" "")
-+ (match_operand:VEC_F 2 "vfloat_operand" "")))]
-+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-+ operands[3], operands[4], operands[5]))
-+ DONE;
-+ else
-+ FAIL;
-+}")
-+
-+(define_expand "vcond<mode>"
-+ [(set (match_operand:VEC_I 0 "vint_operand" "")
-+ (if_then_else:VEC_I
-+ (match_operator 3 "comparison_operator"
-+ [(match_operand:VEC_I 4 "vint_operand" "")
-+ (match_operand:VEC_I 5 "vint_operand" "")])
-+ (match_operand:VEC_I 1 "vint_operand" "")
-+ (match_operand:VEC_I 2 "vint_operand" "")))]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
-+ "
-+{
-+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-+ operands[3], operands[4], operands[5]))
-+ DONE;
-+ else
-+ FAIL;
-+}")
-+
-+(define_expand "vcondu<mode>"
-+ [(set (match_operand:VEC_I 0 "vint_operand" "=v")
-+ (if_then_else:VEC_I
-+ (match_operator 3 "comparison_operator"
-+ [(match_operand:VEC_I 4 "vint_operand" "")
-+ (match_operand:VEC_I 5 "vint_operand" "")])
-+ (match_operand:VEC_I 1 "vint_operand" "")
-+ (match_operand:VEC_I 2 "vint_operand" "")))]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
-+ "
-+{
-+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-+ operands[3], operands[4], operands[5]))
-+ DONE;
-+ else
-+ FAIL;
-+}")
-+
-+(define_expand "vector_eq<mode>"
-+ [(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_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_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_OR_VSX_P (<MODE>mode)"
-+ "")
-+
-+(define_expand "vector_gtu<mode>"
-+ [(set (match_operand:VEC_I 0 "vint_operand" "")
-+ (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
-+ (match_operand:VEC_I 2 "vint_operand" "")))]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
-+ "")
-+
-+(define_expand "vector_geu<mode>"
-+ [(set (match_operand:VEC_I 0 "vint_operand" "")
-+ (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
-+ (match_operand:VEC_I 2 "vint_operand" "")))]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
-+ "")
-+
-+;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
-+;; which is in the reverse order that we want
-+(define_expand "vector_vsel<mode>"
-+ [(match_operand:VEC_F 0 "vlogical_operand" "")
-+ (match_operand:VEC_F 1 "vlogical_operand" "")
-+ (match_operand:VEC_F 2 "vlogical_operand" "")
-+ (match_operand:VEC_F 3 "vlogical_operand" "")]
-+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ if (VECTOR_UNIT_VSX_P (<MODE>mode))
-+ emit_insn (gen_vsx_vsel<mode> (operands[0], operands[3],
-+ operands[2], operands[1]));
-+ else
-+ emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
-+ operands[2], operands[1]));
-+ DONE;
-+}")
-+
-+(define_expand "vector_vsel<mode>"
-+ [(match_operand:VEC_I 0 "vlogical_operand" "")
-+ (match_operand:VEC_I 1 "vlogical_operand" "")
-+ (match_operand:VEC_I 2 "vlogical_operand" "")
-+ (match_operand:VEC_I 3 "vlogical_operand" "")]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
-+ "
-+{
-+ emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
-+ operands[2], operands[1]));
-+ DONE;
-+}")
-+
-+\f
-+;; Vector logical instructions
-+(define_expand "xor<mode>3"
-+ [(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_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_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_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_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_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_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_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ 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_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ 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_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ 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_OR_VSX_P (<MODE>mode)"
-+ "
-+{
-+ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
-+ {
-+ emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
-+ DONE;
-+ }
-+}")
-+
-+\f
-+;; Vector initialization, set, extract
-+(define_expand "vec_init<mode>"
-+ [(match_operand:VEC_C 0 "vlogical_operand" "")
-+ (match_operand:VEC_C 1 "vec_init_operand" "")]
-+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
-+{
-+ rs6000_expand_vector_init (operands[0], operands[1]);
-+ DONE;
-+})
-+
-+(define_expand "vec_set<mode>"
-+ [(match_operand:VEC_C 0 "vlogical_operand" "")
-+ (match_operand:<VEC_base> 1 "register_operand" "")
-+ (match_operand 2 "const_int_operand" "")]
-+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
-+{
-+ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
-+ DONE;
-+})
-+
-+(define_expand "vec_extract<mode>"
-+ [(match_operand:<VEC_base> 0 "register_operand" "")
-+ (match_operand:VEC_C 1 "vlogical_operand" "")
-+ (match_operand 2 "const_int_operand" "")]
-+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
-+{
-+ rs6000_expand_vector_extract (operands[0], operands[1],
-+ INTVAL (operands[2]));
-+ DONE;
-+})
-+
-+;; Interleave patterns
-+(define_expand "vec_interleave_highv4sf"
-+ [(set (match_operand:V4SF 0 "vfloat_operand" "")
-+ (vec_merge:V4SF
-+ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
-+ (parallel [(const_int 0)
-+ (const_int 2)
-+ (const_int 1)
-+ (const_int 3)]))
-+ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
-+ (parallel [(const_int 2)
-+ (const_int 0)
-+ (const_int 3)
-+ (const_int 1)]))
-+ (const_int 5)))]
-+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
-+ "")
-+
-+(define_expand "vec_interleave_lowv4sf"
-+ [(set (match_operand:V4SF 0 "vfloat_operand" "")
-+ (vec_merge:V4SF
-+ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
-+ (parallel [(const_int 2)
-+ (const_int 0)
-+ (const_int 3)
-+ (const_int 1)]))
-+ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
-+ (parallel [(const_int 0)
-+ (const_int 2)
-+ (const_int 1)
-+ (const_int 3)]))
-+ (const_int 5)))]
-+ "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)"
-+ "")
-+
-+;; For 2 element vectors, even/odd is the same as high/low
-+(define_expand "vec_extract_evenv2df"
-+ [(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_extract_oddv2df"
-+ [(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)"
-+ "")
---- gcc/config/rs6000/spe.md (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/spe.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -99,7 +99,7 @@ (define_insn "*divsf3_gpr"
-
- ;; Floating point conversion instructions.
-
--(define_insn "fixuns_truncdfsi2"
-+(define_insn "spe_fixuns_truncdfsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))]
- "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
---- gcc/config/rs6000/constraints.md (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/constraints.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -17,6 +17,8 @@
- ;; along with GCC; see the file COPYING3. If not see
- ;; <http://www.gnu.org/licenses/>.
-
-+;; Available constraint letters: "e", "k", "u", "A", "B", "C", "D"
-+
- ;; Register constraints
-
- (define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS
-@@ -50,6 +52,23 @@ (define_register_constraint "y" "CR_REGS
- (define_register_constraint "z" "XER_REGS"
- "@internal")
-
-+;; Use w as a prefix to add VSX modes
-+;; vector double (V2DF)
-+(define_register_constraint "wd" "rs6000_vector_reg_class[V2DFmode]"
-+ "@internal")
-+
-+;; vector float (V4SF)
-+(define_register_constraint "wf" "rs6000_vector_reg_class[V4SFmode]"
-+ "@internal")
-+
-+;; scalar double (DF)
-+(define_register_constraint "ws" "rs6000_vector_reg_class[DFmode]"
-+ "@internal")
-+
-+;; any VSX register
-+(define_register_constraint "wa" "rs6000_vsx_reg_class"
-+ "@internal")
-+
- ;; Integer constraints
-
- (define_constraint "I"
-@@ -159,3 +178,7 @@ (define_constraint "t"
- (define_constraint "W"
- "vector constant that does not require memory"
- (match_operand 0 "easy_vector_constant"))
-+
-+(define_constraint "j"
-+ "Zero vector constant"
-+ (match_test "(op == const0_rtx || op == CONST0_RTX (GET_MODE (op)))"))
---- gcc/config/rs6000/predicates.md (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/predicates.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -38,6 +38,37 @@ (define_predicate "altivec_register_oper
- || ALTIVEC_REGNO_P (REGNO (op))
- || REGNO (op) > LAST_VIRTUAL_REGISTER")))
-
-+;; Return 1 if op is a VSX register.
-+(define_predicate "vsx_register_operand"
-+ (and (match_operand 0 "register_operand")
-+ (match_test "GET_CODE (op) != REG
-+ || VSX_REGNO_P (REGNO (op))
-+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
-+
-+;; Return 1 if op is a vector register that operates on floating point vectors
-+;; (either altivec or VSX).
-+(define_predicate "vfloat_operand"
-+ (and (match_operand 0 "register_operand")
-+ (match_test "GET_CODE (op) != REG
-+ || VFLOAT_REGNO_P (REGNO (op))
-+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
-+
-+;; Return 1 if op is a vector register that operates on integer vectors
-+;; (only altivec, VSX doesn't support integer vectors)
-+(define_predicate "vint_operand"
-+ (and (match_operand 0 "register_operand")
-+ (match_test "GET_CODE (op) != REG
-+ || VINT_REGNO_P (REGNO (op))
-+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
-+
-+;; Return 1 if op is a vector register to do logical operations on (and, or,
-+;; xor, etc.)
-+(define_predicate "vlogical_operand"
-+ (and (match_operand 0 "register_operand")
-+ (match_test "GET_CODE (op) != REG
-+ || VLOGICAL_REGNO_P (REGNO (op))
-+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
-+
- ;; Return 1 if op is XER register.
- (define_predicate "xer_operand"
- (and (match_code "reg")
-@@ -234,6 +265,10 @@ (define_predicate "easy_fp_constant"
- && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
-
- case DFmode:
-+ /* The constant 0.f is easy under VSX. */
-+ if (op == CONST0_RTX (DFmode) && VECTOR_UNIT_VSX_P (DFmode))
-+ return 1;
-+
- /* Force constants to memory before reload to utilize
- compress_float_constant.
- Avoid this when flag_unsafe_math_optimizations is enabled
-@@ -396,13 +431,16 @@ (define_predicate "indexed_or_indirect_o
- (match_code "mem")
- {
- op = XEXP (op, 0);
-- if (TARGET_ALTIVEC
-- && ALTIVEC_VECTOR_MODE (mode)
-+ if (VECTOR_MEM_ALTIVEC_P (mode)
- && GET_CODE (op) == AND
- && GET_CODE (XEXP (op, 1)) == CONST_INT
- && INTVAL (XEXP (op, 1)) == -16)
- op = XEXP (op, 0);
-
-+ else if (VECTOR_MEM_VSX_P (mode)
-+ && GET_CODE (op) == PRE_MODIFY)
-+ op = XEXP (op, 1);
-+
- return indexed_or_indirect_address (op, mode);
- })
-
-@@ -1336,3 +1374,19 @@ (define_predicate "stmw_operation"
-
- return 1;
- })
-+
-+;; Return true if the operand is a legitimate parallel for vec_init
-+(define_predicate "vec_init_operand"
-+ (match_code "parallel")
-+{
-+ /* Disallow V2DF mode with MEM's unless both are the same under VSX. */
-+ if (mode == V2DFmode && VECTOR_UNIT_VSX_P (mode))
-+ {
-+ rtx op0 = XVECEXP (op, 0, 0);
-+ rtx op1 = XVECEXP (op, 0, 1);
-+ if ((MEM_P (op0) || MEM_P (op1)) && !rtx_equal_p (op0, op1))
-+ return 0;
-+ }
-+
-+ return 1;
-+})
---- gcc/config/rs6000/ppc-asm.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/ppc-asm.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -63,7 +63,7 @@
- #define f16 16
- #define f17 17
- #define f18 18
--#define f19 19
-+#define f19 19
- #define f20 20
- #define f21 21
- #define f22 22
-@@ -77,6 +77,143 @@
- #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.
- */
---- gcc/config/rs6000/linux64.opt (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/linux64.opt (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -20,5 +20,5 @@
- ; <http://www.gnu.org/licenses/>.
-
- mprofile-kernel
--Target Report Mask(PROFILE_KERNEL)
-+Target Report Var(TARGET_PROFILE_KERNEL)
- Call mcount for profiling before a function prologue
---- gcc/config/rs6000/sysv4.opt (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/sysv4.opt (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -32,7 +32,7 @@ Target RejectNegative Joined
- Specify bit size of immediate TLS offsets
-
- mbit-align
--Target Report Mask(NO_BITFIELD_TYPE)
-+Target Report Var(TARGET_NO_BITFIELD_TYPE)
- Align to the base type of the bit-field
-
- mstrict-align
-@@ -87,11 +87,11 @@ Target Report Mask(EABI)
- Use EABI
-
- mbit-word
--Target Report Mask(NO_BITFIELD_WORD)
-+Target Report Var(TARGET_NO_BITFIELD_WORD)
- Allow bit-fields to cross word boundaries
-
- mregnames
--Target Mask(REGNAMES)
-+Target Var(TARGET_REGNAMES)
- Use alternate register names
-
- ;; FIXME: Does nothing.
---- gcc/config/rs6000/rs6000-protos.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/rs6000-protos.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -64,9 +64,14 @@ extern int insvdi_rshift_rlwimi_p (rtx,
- extern int registers_ok_for_quad_peep (rtx, rtx);
- extern int mems_ok_for_quad_peep (rtx, rtx);
- extern bool gpr_or_gpr_p (rtx, rtx);
-+extern enum reg_class rs6000_preferred_reload_class(rtx, enum reg_class);
- extern enum reg_class rs6000_secondary_reload_class (enum reg_class,
- enum machine_mode, rtx);
--
-+extern bool rs6000_secondary_memory_needed (enum reg_class, enum reg_class,
-+ enum machine_mode);
-+extern bool rs6000_cannot_change_mode_class (enum machine_mode,
-+ enum machine_mode,
-+ enum reg_class);
- extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
- rtx, rtx, rtx);
- extern void paired_expand_vector_move (rtx operands[]);
-@@ -170,7 +175,6 @@ extern int rs6000_register_move_cost (en
- enum reg_class, enum reg_class);
- extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
- extern bool rs6000_tls_referenced_p (rtx);
--extern int rs6000_hard_regno_nregs (int, enum machine_mode);
- extern void rs6000_conditional_register_usage (void);
-
- /* Declare functions in rs6000-c.c */
-@@ -189,4 +193,6 @@ const char * rs6000_xcoff_strip_dollar (
- void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands);
-
- extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
-+extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES];
-+extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER];
- #endif /* rs6000-protos.h */
---- gcc/config/rs6000/t-rs6000 (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/t-rs6000 (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -16,3 +16,33 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs60
-
- # The rs6000 backend doesn't cause warnings in these files.
- insn-conditions.o-warn =
-+
-+MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \
-+ $(srcdir)/config/rs6000/rios2.md \
-+ $(srcdir)/config/rs6000/rs64.md \
-+ $(srcdir)/config/rs6000/mpc.md \
-+ $(srcdir)/config/rs6000/40x.md \
-+ $(srcdir)/config/rs6000/440.md \
-+ $(srcdir)/config/rs6000/603.md \
-+ $(srcdir)/config/rs6000/6xx.md \
-+ $(srcdir)/config/rs6000/7xx.md \
-+ $(srcdir)/config/rs6000/7450.md \
-+ $(srcdir)/config/rs6000/8540.md \
-+ $(srcdir)/config/rs6000/e300c2c3.md \
-+ $(srcdir)/config/rs6000/e500mc.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 \
-+ $(srcdir)/config/rs6000/constraints.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 \
-+ $(srcdir)/config/rs6000/paired.md
---- gcc/config/rs6000/power7.md (.../trunk) (revision 0)
-+++ gcc/config/rs6000/power7.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -0,0 +1,320 @@
-+;; 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")
-+
-+
---- gcc/config/rs6000/rs6000-c.c (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/rs6000-c.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -265,6 +265,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
- builtin_define ("_ARCH_PWR6X");
- if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
- builtin_define ("_ARCH_COM");
-+ if (TARGET_POPCNTD)
-+ builtin_define ("_ARCH_PWR7");
- if (TARGET_ALTIVEC)
- {
- builtin_define ("__ALTIVEC__");
-@@ -306,6 +308,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
- /* Used by libstdc++. */
- if (TARGET_NO_LWSYNC)
- builtin_define ("__NO_LWSYNC__");
-+ if (TARGET_VSX)
-+ builtin_define ("__VSX__");
-
- /* May be overridden by target configuration. */
- RS6000_CPU_CPP_ENDIAN_BUILTINS();
---- gcc/config/rs6000/rs6000.opt (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/rs6000.opt (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -111,24 +111,44 @@ mhard-float
- Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
- Use hardware floating point
-
--mno-update
--Target Report RejectNegative Mask(NO_UPDATE)
--Do not generate load/store with update instructions
-+mpopcntd
-+Target Report Mask(POPCNTD)
-+Use PowerPC V2.06 popcntd instruction
-+
-+mvsx
-+Target Report Mask(VSX)
-+Use vector/scalar (VSX) instructions
-+
-+mvsx-vector-memory
-+Target Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
-+If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
-+
-+mvsx-vector-float
-+Target Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
-+If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
-+
-+mvsx-vector-double
-+Target Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
-+If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
-+
-+mvsx-scalar-double
-+Target Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
-+If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
-+
-+mvsx-scalar-memory
-+Target Report Var(TARGET_VSX_SCALAR_MEMORY)
-+If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
-
- mupdate
--Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
-+Target Report Var(TARGET_UPDATE) Init(1)
- Generate load/store with update instructions
-
- mavoid-indexed-addresses
- Target Report Var(TARGET_AVOID_XFORM) Init(-1)
- Avoid generation of indexed load/store instructions when possible
-
--mno-fused-madd
--Target Report RejectNegative Mask(NO_FUSED_MADD)
--Do not generate fused multiply/add instructions
--
- mfused-madd
--Target Report RejectNegative InverseMask(NO_FUSED_MADD, FUSED_MADD)
-+Target Report Var(TARGET_FUSED_MADD) Init(1)
- Generate fused multiply/add instructions
-
- msched-prolog
-@@ -194,7 +214,7 @@ Target RejectNegative Joined
- -mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead
-
- misel
--Target
-+Target Report Mask(ISEL)
- Generate isel instructions
-
- misel=
---- gcc/config/rs6000/linux64.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/linux64.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -114,7 +114,7 @@ extern int dot_symbols;
- error (INVALID_32BIT, "32"); \
- if (TARGET_PROFILE_KERNEL) \
- { \
-- target_flags &= ~MASK_PROFILE_KERNEL; \
-+ SET_PROFILE_KERNEL (0); \
- error (INVALID_32BIT, "profile-kernel"); \
- } \
- } \
---- gcc/config/rs6000/rs6000.c (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/rs6000.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -178,9 +178,6 @@ int rs6000_spe;
- /* Nonzero if we want SPE ABI extensions. */
- int rs6000_spe_abi;
-
--/* Nonzero to use isel instructions. */
--int rs6000_isel;
--
- /* Nonzero if floating point operations are done in the GPRs. */
- int rs6000_float_gprs = 0;
-
-@@ -227,10 +224,18 @@ int dot_symbols;
- const char *rs6000_debug_name;
- int rs6000_debug_stack; /* debug stack applications */
- int rs6000_debug_arg; /* debug argument handling */
-+int rs6000_debug_reg; /* debug register classes */
-+int rs6000_debug_addr; /* debug memory addressing */
-
- /* Value is TRUE if register/mode pair is acceptable. */
- bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
-
-+/* Maximum number of registers needed for a given register class and mode. */
-+unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES];
-+
-+/* How many registers are needed for a given register and mode. */
-+unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
-+
- /* Built in types. */
-
- tree rs6000_builtin_types[RS6000_BTI_MAX];
-@@ -270,7 +275,6 @@ struct {
- bool altivec_abi; /* True if -mabi=altivec/no-altivec used. */
- bool spe; /* True if -mspe= was used. */
- bool float_gprs; /* True if -mfloat-gprs= was used. */
-- bool isel; /* True if -misel was used. */
- bool long_double; /* True if -mlong-double- was used. */
- bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */
- bool vrsave; /* True if -mvrsave was used. */
-@@ -286,6 +290,18 @@ struct builtin_description
- const char *const name;
- const enum rs6000_builtins code;
- };
-+
-+/* Describe the vector unit used for modes. */
-+enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES];
-+enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES];
-+enum reg_class rs6000_vector_reg_class[NUM_MACHINE_MODES];
-+
-+/* Describe the alignment of a vector. */
-+int rs6000_vector_align[NUM_MACHINE_MODES];
-+
-+/* Describe the register classes used by VSX instructions. */
-+enum reg_class rs6000_vsx_reg_class = NO_REGS;
-+
- \f
- /* Target cpu costs. */
-
-@@ -749,6 +765,25 @@ struct processor_costs power6_cost = {
- 16, /* prefetch streams */
- };
-
-+/* Instruction costs on POWER7 processors. */
-+static const
-+struct processor_costs power7_cost = {
-+ COSTS_N_INSNS (2), /* mulsi */
-+ COSTS_N_INSNS (2), /* mulsi_const */
-+ COSTS_N_INSNS (2), /* mulsi_const9 */
-+ COSTS_N_INSNS (2), /* muldi */
-+ COSTS_N_INSNS (18), /* divsi */
-+ COSTS_N_INSNS (34), /* divdi */
-+ COSTS_N_INSNS (3), /* fp */
-+ COSTS_N_INSNS (3), /* dmul */
-+ COSTS_N_INSNS (13), /* sdiv */
-+ COSTS_N_INSNS (16), /* ddiv */
-+ 128, /* cache line size */
-+ 32, /* l1 cache */
-+ 256, /* l2 cache */
-+ 12, /* prefetch streams */
-+};
-+
- \f
- static bool rs6000_function_ok_for_sibcall (tree, tree);
- static const char *rs6000_invalid_within_doloop (const_rtx);
-@@ -963,12 +998,10 @@ static tree rs6000_gimplify_va_arg (tree
- static bool rs6000_must_pass_in_stack (enum machine_mode, const_tree);
- static bool rs6000_scalar_mode_supported_p (enum machine_mode);
- static bool rs6000_vector_mode_supported_p (enum machine_mode);
--static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
-- enum machine_mode);
-+static rtx rs6000_emit_vector_compare_vsx (enum rtx_code, rtx, rtx, rtx);
-+static rtx rs6000_emit_vector_compare_altivec (enum rtx_code, rtx, rtx, rtx);
- static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
- enum machine_mode);
--static int get_vsel_insn (enum machine_mode);
--static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
- static tree rs6000_stack_protect_fail (void);
-
- const int INSN_NOT_AVAILABLE = -1;
-@@ -1045,6 +1078,9 @@ static const char alt_reg_names[][8] =
- #endif
- #ifndef TARGET_PROFILE_KERNEL
- #define TARGET_PROFILE_KERNEL 0
-+#define SET_PROFILE_KERNEL(N)
-+#else
-+#define SET_PROFILE_KERNEL(N) TARGET_PROFILE_KERNEL = (N)
- #endif
-
- /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
-@@ -1299,28 +1335,96 @@ static const char alt_reg_names[][8] =
-
- struct gcc_target targetm = TARGET_INITIALIZER;
- \f
-+/* Return number of consecutive hard regs needed starting at reg REGNO
-+ to hold something of mode MODE.
-+ This is ordinarily the length in words of a value of mode MODE
-+ but can be less for certain modes in special long registers.
-+
-+ For the SPE, GPRs are 64 bits but only 32 bits are visible in
-+ scalar instructions. The upper 32 bits are only available to the
-+ SIMD instructions.
-+
-+ POWER and PowerPC GPRs hold 32 bits worth;
-+ PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
-+
-+static int
-+rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
-+{
-+ unsigned HOST_WIDE_INT reg_size;
-+
-+ if (FP_REGNO_P (regno))
-+ reg_size = (VECTOR_UNIT_VSX_P (mode)
-+ ? UNITS_PER_VSX_WORD
-+ : UNITS_PER_FP_WORD);
-+
-+ else if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
-+ reg_size = UNITS_PER_SPE_WORD;
-+
-+ else if (ALTIVEC_REGNO_P (regno))
-+ reg_size = UNITS_PER_ALTIVEC_WORD;
-+
-+ /* The value returned for SCmode in the E500 double case is 2 for
-+ ABI compatibility; storing an SCmode value in a single register
-+ would require function_arg and rs6000_spe_function_arg to handle
-+ SCmode so as to pass the value correctly in a pair of
-+ registers. */
-+ else if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
-+ && !DECIMAL_FLOAT_MODE_P (mode))
-+ reg_size = UNITS_PER_FP_WORD;
-+
-+ else
-+ reg_size = UNITS_PER_WORD;
-+
-+ return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
-+}
-
- /* Value is 1 if hard register REGNO can hold a value of machine-mode
- MODE. */
- static int
- rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
- {
-+ int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1;
-+
-+ /* VSX registers that overlap the FPR registers are larger than for non-VSX
-+ implementations. Don't allow an item to be split between a FP register
-+ and an Altivec register. */
-+ if (VECTOR_UNIT_VSX_P (mode) || VECTOR_MEM_VSX_P (mode))
-+ {
-+ enum reg_class rclass = rs6000_vector_reg_class[mode];
-+ if (FP_REGNO_P (regno))
-+ return ((rclass == FLOAT_REGS || rclass == VSX_REGS)
-+ && FP_REGNO_P (last_regno));
-+
-+ if (ALTIVEC_REGNO_P (regno))
-+ return ((rclass == ALTIVEC_REGS || rclass == VSX_REGS)
-+ && ALTIVEC_REGNO_P (last_regno));
-+ }
-+
- /* The GPRs can hold any mode, but values bigger than one register
- cannot go past R31. */
- if (INT_REGNO_P (regno))
-- return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
-+ return INT_REGNO_P (last_regno);
-
-- /* The float registers can only hold floating modes and DImode.
-- This excludes the 32-bit decimal float mode for now. */
-+ /* The float registers (except for VSX vector modes) can only hold floating
-+ modes and DImode. This excludes the 32-bit decimal float mode for
-+ now. */
- if (FP_REGNO_P (regno))
-- return
-- ((SCALAR_FLOAT_MODE_P (mode)
-- && (mode != TDmode || (regno % 2) == 0)
-- && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
-- || (GET_MODE_CLASS (mode) == MODE_INT
-+ {
-+ if (SCALAR_FLOAT_MODE_P (mode)
-+ && (mode != TDmode || (regno % 2) == 0)
-+ && FP_REGNO_P (last_regno))
-+ return 1;
-+
-+ if (GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
-- || (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
-- && PAIRED_VECTOR_MODE (mode)));
-+ return 1;
-+
-+ if (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
-+ && PAIRED_VECTOR_MODE (mode))
-+ return 1;
-+
-+ return 0;
-+ }
-
- /* The CR register can only hold CC modes. */
- if (CR_REGNO_P (regno))
-@@ -1331,28 +1435,312 @@ rs6000_hard_regno_mode_ok (int regno, en
-
- /* AltiVec only in AldyVec registers. */
- if (ALTIVEC_REGNO_P (regno))
-- return ALTIVEC_VECTOR_MODE (mode);
-+ return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode);
-
- /* ...but GPRs can hold SIMD data on the SPE in one register. */
- if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
- return 1;
-
-- /* We cannot put TImode anywhere except general register and it must be
-- able to fit within the register set. */
-+ /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. You
-+ really don't want to spill your floating point values to those
-+ registers. Also do it for the old MQ register in the power. */
-+ if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)
-+ return (GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_SIZE (mode) <= UNITS_PER_WORD);
-+
-+ /* The VRSAVE/VSCR registers are 32-bits (they are fixed, but add this for
-+ completeness). */
-+ if (regno == VRSAVE_REGNO || regno == VSCR_REGNO)
-+ return (mode == SImode);
-+
-+ /* We cannot put TImode anywhere except general register and it must be able
-+ to fit within the register set. In the future, allow TImode in the
-+ Altivec or VSX registers. */
-
- return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
- }
-
--/* Initialize rs6000_hard_regno_mode_ok_p table. */
-+/* Print interesting facts about registers. */
- static void
--rs6000_init_hard_regno_mode_ok (void)
-+rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
- {
- int r, m;
-
-+ for (r = first_regno; r <= last_regno; ++r)
-+ {
-+ const char *comma = "";
-+ int len;
-+
-+ if (first_regno == last_regno)
-+ fprintf (stderr, "%s:\t", reg_name);
-+ else
-+ fprintf (stderr, "%s%d:\t", reg_name, r - first_regno);
-+
-+ len = 8;
-+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
-+ if (rs6000_hard_regno_mode_ok_p[m][r] && rs6000_hard_regno_nregs[m][r])
-+ {
-+ if (len > 70)
-+ {
-+ fprintf (stderr, ",\n\t");
-+ len = 8;
-+ comma = "";
-+ }
-+
-+ if (rs6000_hard_regno_nregs[m][r] > 1)
-+ len += fprintf (stderr, "%s%s/%d", comma, GET_MODE_NAME (m),
-+ rs6000_hard_regno_nregs[m][r]);
-+ else
-+ len += fprintf (stderr, "%s%s", comma, GET_MODE_NAME (m));
-+
-+ comma = ", ";
-+ }
-+
-+ if (call_used_regs[r])
-+ {
-+ if (len > 70)
-+ {
-+ fprintf (stderr, ",\n\t");
-+ len = 8;
-+ comma = "";
-+ }
-+
-+ len += fprintf (stderr, "%s%s", comma, "call-used");
-+ comma = ", ";
-+ }
-+
-+ if (fixed_regs[r])
-+ {
-+ if (len > 70)
-+ {
-+ fprintf (stderr, ",\n\t");
-+ len = 8;
-+ comma = "";
-+ }
-+
-+ len += fprintf (stderr, "%s%s", comma, "fixed");
-+ comma = ", ";
-+ }
-+
-+ if (len > 70)
-+ {
-+ fprintf (stderr, ",\n\t");
-+ comma = "";
-+ }
-+
-+ fprintf (stderr, "%sregno = %d\n", comma, r);
-+ }
-+}
-+
-+/* Map enum rs6000_vector to string. */
-+static const char *
-+rs6000_debug_vector_unit[] = {
-+ "none",
-+ "altivec",
-+ "vsx",
-+ "paired",
-+ "spe",
-+ "other"
-+};
-+
-+/* Initialize the various global tables that are based on register size. */
-+static void
-+rs6000_init_hard_regno_mode_ok (void)
-+{
-+ int r, m, c;
-+ enum reg_class vsx_rc = (TARGET_ALTIVEC ? VSX_REGS : FLOAT_REGS);
-+ bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS);
-+
-+ /* Precalculate vector information, this must be set up before the
-+ rs6000_hard_regno_nregs_internal below. */
-+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
-+ {
-+ rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
-+ rs6000_vector_reg_class[m] = NO_REGS;
-+ }
-+
-+ /* TODO, add TI/V2DI mode for moving data if Altivec or VSX. */
-+
-+ /* V2DF mode, VSX only. */
-+ if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE)
-+ {
-+ rs6000_vector_unit[V2DFmode] = VECTOR_VSX;
-+ rs6000_vector_mem[V2DFmode] = VECTOR_VSX;
-+ rs6000_vector_align[V2DFmode] = 64;
-+ }
-+
-+ /* V4SF mode, either VSX or Altivec. */
-+ if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_FLOAT)
-+ {
-+ rs6000_vector_unit[V4SFmode] = VECTOR_VSX;
-+ if (TARGET_VSX_VECTOR_MEMORY || !TARGET_ALTIVEC)
-+ {
-+ rs6000_vector_align[V4SFmode] = 32;
-+ rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
-+ } else {
-+ rs6000_vector_align[V4SFmode] = 128;
-+ rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
-+ }
-+ }
-+ else if (float_p && TARGET_ALTIVEC)
-+ {
-+ rs6000_vector_unit[V4SFmode] = VECTOR_ALTIVEC;
-+ rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
-+ rs6000_vector_align[V4SFmode] = 128;
-+ }
-+
-+ /* V16QImode, V8HImode, V4SImode are Altivec only, but possibly do VSX loads
-+ and stores. */
-+ if (TARGET_ALTIVEC)
-+ {
-+ rs6000_vector_unit[V4SImode] = VECTOR_ALTIVEC;
-+ rs6000_vector_unit[V8HImode] = VECTOR_ALTIVEC;
-+ rs6000_vector_unit[V16QImode] = VECTOR_ALTIVEC;
-+
-+ rs6000_vector_reg_class[V16QImode] = ALTIVEC_REGS;
-+ rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
-+ rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
-+
-+ if (TARGET_VSX && TARGET_VSX_VECTOR_MEMORY)
-+ {
-+ rs6000_vector_mem[V4SImode] = VECTOR_VSX;
-+ rs6000_vector_mem[V8HImode] = VECTOR_VSX;
-+ rs6000_vector_mem[V16QImode] = VECTOR_VSX;
-+ rs6000_vector_align[V4SImode] = 32;
-+ rs6000_vector_align[V8HImode] = 32;
-+ rs6000_vector_align[V16QImode] = 32;
-+ }
-+ else
-+ {
-+ rs6000_vector_mem[V4SImode] = VECTOR_ALTIVEC;
-+ rs6000_vector_mem[V8HImode] = VECTOR_ALTIVEC;
-+ rs6000_vector_mem[V16QImode] = VECTOR_ALTIVEC;
-+ rs6000_vector_align[V4SImode] = 128;
-+ rs6000_vector_align[V8HImode] = 128;
-+ rs6000_vector_align[V16QImode] = 128;
-+ }
-+ }
-+
-+ /* DFmode, see if we want to use the VSX unit. */
-+ if (float_p && TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
-+ {
-+ rs6000_vector_unit[DFmode] = VECTOR_VSX;
-+ rs6000_vector_align[DFmode] = 64;
-+ rs6000_vector_mem[DFmode]
-+ = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
-+ }
-+
-+ /* TODO, add SPE and paired floating point vector support. */
-+
-+ /* Set the VSX register classes. */
-+ rs6000_vector_reg_class[V4SFmode]
-+ = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
-+ ? vsx_rc
-+ : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
-+ ? ALTIVEC_REGS
-+ : NO_REGS));
-+
-+ rs6000_vector_reg_class[V2DFmode]
-+ = (VECTOR_UNIT_VSX_P (V2DFmode) ? vsx_rc : NO_REGS);
-+
-+ rs6000_vector_reg_class[DFmode]
-+ = ((!float_p || !VECTOR_UNIT_VSX_P (DFmode))
-+ ? NO_REGS
-+ : ((TARGET_VSX_SCALAR_MEMORY)
-+ ? vsx_rc
-+ : FLOAT_REGS));
-+
-+ rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
-+
-+ /* Precalculate HARD_REGNO_NREGS. */
-+ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
-+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
-+ rs6000_hard_regno_nregs[m][r] = rs6000_hard_regno_nregs_internal (r, m);
-+
-+ /* Precalculate HARD_REGNO_MODE_OK. */
- for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
- for (m = 0; m < NUM_MACHINE_MODES; ++m)
- if (rs6000_hard_regno_mode_ok (r, m))
- rs6000_hard_regno_mode_ok_p[m][r] = true;
-+
-+ /* Precalculate CLASSS_MAX_NREGS sizes. */
-+ for (c = 0; c < LIM_REG_CLASSES; ++c)
-+ {
-+ int reg_size;
-+
-+ if (TARGET_VSX && VSX_REG_CLASS_P (c))
-+ reg_size = UNITS_PER_VSX_WORD;
-+
-+ else if (c == ALTIVEC_REGS)
-+ reg_size = UNITS_PER_ALTIVEC_WORD;
-+
-+ else if (c == FLOAT_REGS)
-+ reg_size = UNITS_PER_FP_WORD;
-+
-+ else
-+ reg_size = UNITS_PER_WORD;
-+
-+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
-+ rs6000_class_max_nregs[m][c]
-+ = (GET_MODE_SIZE (m) + reg_size - 1) / reg_size;
-+ }
-+
-+ if (TARGET_E500_DOUBLE)
-+ rs6000_class_max_nregs[DFmode][GENERAL_REGS] = 1;
-+
-+ if (TARGET_DEBUG_REG)
-+ {
-+ const char *nl = (const char *)0;
-+
-+ fprintf (stderr, "Register information: (last virtual reg = %d)\n",
-+ LAST_VIRTUAL_REGISTER);
-+ rs6000_debug_reg_print (0, 31, "gr");
-+ rs6000_debug_reg_print (32, 63, "fp");
-+ rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
-+ LAST_ALTIVEC_REGNO,
-+ "vs");
-+ rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
-+ rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
-+ rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
-+ rs6000_debug_reg_print (MQ_REGNO, MQ_REGNO, "mq");
-+ rs6000_debug_reg_print (XER_REGNO, XER_REGNO, "xer");
-+ rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave");
-+ rs6000_debug_reg_print (VSCR_REGNO, VSCR_REGNO, "vscr");
-+ rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a");
-+ rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f");
-+
-+ fprintf (stderr,
-+ "\n"
-+ "V16QI reg_class = %s\n"
-+ "V8HI reg_class = %s\n"
-+ "V4SI reg_class = %s\n"
-+ "V2DI reg_class = %s\n"
-+ "V4SF reg_class = %s\n"
-+ "V2DF reg_class = %s\n"
-+ "DF reg_class = %s\n"
-+ "vsx reg_class = %s\n\n",
-+ reg_class_names[rs6000_vector_reg_class[V16QImode]],
-+ reg_class_names[rs6000_vector_reg_class[V8HImode]],
-+ reg_class_names[rs6000_vector_reg_class[V4SImode]],
-+ reg_class_names[rs6000_vector_reg_class[V2DImode]],
-+ reg_class_names[rs6000_vector_reg_class[V4SFmode]],
-+ reg_class_names[rs6000_vector_reg_class[V2DFmode]],
-+ reg_class_names[rs6000_vector_reg_class[DFmode]],
-+ reg_class_names[rs6000_vsx_reg_class]);
-+
-+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
-+ if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
-+ {
-+ nl = "\n";
-+ fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n",
-+ GET_MODE_NAME (m),
-+ rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
-+ rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]);
-+ }
-+
-+ if (nl)
-+ fputs (nl, stderr);
-+ }
- }
-
- #if TARGET_MACHO
-@@ -1482,12 +1870,15 @@ rs6000_override_options (const char *def
- {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
-- {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN},
-+ {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
-+ | MASK_ISEL},
- /* 8548 has a dummy entry for now. */
-- {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN},
-+ {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
-+ | MASK_ISEL},
- {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
-- {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
-+ {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
-+ | MASK_ISEL},
- {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"970", PROCESSOR_POWER4,
- POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
-@@ -1520,9 +1911,10 @@ rs6000_override_options (const char *def
- POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
- | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
- | MASK_MFPGPR},
-- {"power7", PROCESSOR_POWER5,
-+ {"power7", PROCESSOR_POWER7,
- POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
-- | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP},
-+ | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
-+ | 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},
-@@ -1549,7 +1941,8 @@ rs6000_override_options (const char *def
- POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
- | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
- | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
-- | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP)
-+ | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
-+ | MASK_POPCNTD | MASK_VSX | MASK_ISEL)
- };
-
- set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
-@@ -1594,10 +1987,6 @@ rs6000_override_options (const char *def
- }
- }
-
-- if ((TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
-- && !rs6000_explicit_options.isel)
-- rs6000_isel = 1;
--
- if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
- || rs6000_cpu == PROCESSOR_PPCE500MC)
- {
-@@ -1642,15 +2031,47 @@ rs6000_override_options (const char *def
- }
- }
-
-+ /* Add some warnings for VSX. Enable -maltivec unless the user explicitly
-+ used -mno-altivec */
-+ if (TARGET_VSX)
-+ {
-+ const char *msg = NULL;
-+ if (!TARGET_HARD_FLOAT || !TARGET_FPRS
-+ || !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT)
-+ msg = "-mvsx requires hardware floating point";
-+ else if (TARGET_PAIRED_FLOAT)
-+ msg = "-mvsx and -mpaired are incompatible";
-+ /* The hardware will allow VSX and little endian, but until we make sure
-+ things like vector select, etc. work don't allow VSX on little endian
-+ systems at this point. */
-+ else if (!BYTES_BIG_ENDIAN)
-+ msg = "-mvsx used with little endian code";
-+ else if (TARGET_AVOID_XFORM > 0)
-+ msg = "-mvsx needs indexed addressing";
-+
-+ if (msg)
-+ {
-+ warning (0, msg);
-+ target_flags &= MASK_VSX;
-+ }
-+ else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC) == 0)
-+ target_flags |= MASK_ALTIVEC;
-+ }
-+
- /* Set debug flags */
- if (rs6000_debug_name)
- {
- if (! strcmp (rs6000_debug_name, "all"))
-- rs6000_debug_stack = rs6000_debug_arg = 1;
-+ rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
-+ = rs6000_debug_addr = 1;
- else if (! strcmp (rs6000_debug_name, "stack"))
- rs6000_debug_stack = 1;
- else if (! strcmp (rs6000_debug_name, "arg"))
- rs6000_debug_arg = 1;
-+ else if (! strcmp (rs6000_debug_name, "reg"))
-+ rs6000_debug_reg = 1;
-+ else if (! strcmp (rs6000_debug_name, "addr"))
-+ rs6000_debug_addr = 1;
- else
- error ("unknown -mdebug-%s switch", rs6000_debug_name);
- }
-@@ -1741,8 +2162,8 @@ rs6000_override_options (const char *def
- rs6000_spe = 0;
- if (!rs6000_explicit_options.float_gprs)
- rs6000_float_gprs = 0;
-- if (!rs6000_explicit_options.isel)
-- rs6000_isel = 0;
-+ if (!(target_flags_explicit & MASK_ISEL))
-+ target_flags &= ~MASK_ISEL;
- }
-
- /* Detect invalid option combinations with E500. */
-@@ -1751,12 +2172,14 @@ rs6000_override_options (const char *def
- rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
- && rs6000_cpu != PROCESSOR_POWER5
- && rs6000_cpu != PROCESSOR_POWER6
-+ && rs6000_cpu != PROCESSOR_POWER7
- && rs6000_cpu != PROCESSOR_CELL);
- rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
- || rs6000_cpu == PROCESSOR_POWER5);
- rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
- || rs6000_cpu == PROCESSOR_POWER5
-- || rs6000_cpu == PROCESSOR_POWER6);
-+ || rs6000_cpu == PROCESSOR_POWER6
-+ || rs6000_cpu == PROCESSOR_POWER7);
-
- rs6000_sched_restricted_insns_priority
- = (rs6000_sched_groups ? 1 : 0);
-@@ -1951,6 +2374,10 @@ rs6000_override_options (const char *def
- rs6000_cost = &power6_cost;
- break;
-
-+ case PROCESSOR_POWER7:
-+ rs6000_cost = &power7_cost;
-+ break;
-+
- default:
- gcc_unreachable ();
- }
-@@ -2001,7 +2428,7 @@ rs6000_override_options (const char *def
- static tree
- rs6000_builtin_mask_for_load (void)
- {
-- if (TARGET_ALTIVEC)
-+ if (TARGET_ALTIVEC && !TARGET_VSX)
- return altivec_builtin_mask_for_load;
- else
- return 0;
-@@ -2015,18 +2442,19 @@ rs6000_builtin_mask_for_load (void)
- static tree
- rs6000_builtin_conversion (enum tree_code code, tree type)
- {
-- if (!TARGET_ALTIVEC)
-- return NULL_TREE;
--
- switch (code)
- {
- case FIX_TRUNC_EXPR:
- switch (TYPE_MODE (type))
- {
- case V4SImode:
-+ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
-+ return NULL_TREE;
-+
- return TYPE_UNSIGNED (type)
-- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTUXS]
-- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTSXS];
-+ ? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI]
-+ : rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI];
-+
- default:
- return NULL_TREE;
- }
-@@ -2035,9 +2463,12 @@ rs6000_builtin_conversion (enum tree_cod
- switch (TYPE_MODE (type))
- {
- case V4SImode:
-+ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
-+ return NULL_TREE;
-+
- return TYPE_UNSIGNED (type)
-- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFUX]
-- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
-+ ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
-+ : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
- default:
- return NULL_TREE;
- }
-@@ -2150,6 +2581,14 @@ rs6000_builtin_vec_perm (tree type, tree
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
- break;
-
-+ case V2DFmode:
-+ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DF];
-+ break;
-+
-+ case V2DImode:
-+ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI];
-+ break;
-+
- default:
- return NULL_TREE;
- }
-@@ -2229,6 +2668,7 @@ static bool
- rs6000_handle_option (size_t code, const char *arg, int value)
- {
- enum fpu_type_t fpu_type = FPU_NONE;
-+ int isel;
-
- switch (code)
- {
-@@ -2331,14 +2771,14 @@ rs6000_handle_option (size_t code, const
- rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
- break;
-
-- case OPT_misel:
-- rs6000_explicit_options.isel = true;
-- rs6000_isel = value;
-- break;
--
- case OPT_misel_:
-- rs6000_explicit_options.isel = true;
-- rs6000_parse_yes_no_option ("isel", arg, &(rs6000_isel));
-+ target_flags_explicit |= MASK_ISEL;
-+ isel = 0;
-+ rs6000_parse_yes_no_option ("isel", arg, &isel);
-+ if (isel)
-+ target_flags |= MASK_ISEL;
-+ else
-+ target_flags &= ~MASK_ISEL;
- break;
-
- case OPT_mspe:
-@@ -2967,6 +3407,9 @@ output_vec_const_move (rtx *operands)
- vec = operands[1];
- mode = GET_MODE (dest);
-
-+ if (TARGET_VSX && zero_constant (vec, mode))
-+ return "xxlxor %x0,%x0,%x0";
-+
- if (TARGET_ALTIVEC)
- {
- rtx splat_vec;
-@@ -3190,20 +3633,21 @@ rs6000_expand_vector_init (rtx target, r
- if (n_var == 0)
- {
- rtx const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
-- if (mode != V4SFmode && all_const_zero)
-+ bool int_vector_p = (GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
-+ if ((int_vector_p || TARGET_VSX) && all_const_zero)
- {
- /* Zero register. */
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_XOR (mode, target, target)));
- return;
- }
-- else if (mode != V4SFmode && easy_vector_constant (const_vec, mode))
-+ else if (int_vector_p && easy_vector_constant (const_vec, mode))
- {
- /* Splat immediate. */
- emit_insn (gen_rtx_SET (VOIDmode, target, const_vec));
- return;
- }
-- else if (all_same)
-+ else if (all_same && int_vector_p)
- ; /* Splat vector element. */
- else
- {
-@@ -3213,6 +3657,18 @@ rs6000_expand_vector_init (rtx target, r
- }
- }
-
-+ if (mode == V2DFmode)
-+ {
-+ gcc_assert (TARGET_VSX);
-+ if (all_same)
-+ emit_insn (gen_vsx_splatv2df (target, XVECEXP (vals, 0, 0)));
-+ else
-+ emit_insn (gen_vsx_concat_v2df (target,
-+ copy_to_reg (XVECEXP (vals, 0, 0)),
-+ copy_to_reg (XVECEXP (vals, 0, 1))));
-+ return;
-+ }
-+
- /* Store value to stack temp. Load vector element. Splat. */
- if (all_same)
- {
-@@ -3272,6 +3728,13 @@ rs6000_expand_vector_set (rtx target, rt
- int width = GET_MODE_SIZE (inner_mode);
- int i;
-
-+ if (mode == V2DFmode)
-+ {
-+ gcc_assert (TARGET_VSX);
-+ emit_insn (gen_vsx_set_v2df (target, val, target, 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);
-@@ -3309,6 +3772,13 @@ rs6000_expand_vector_extract (rtx target
- enum machine_mode inner_mode = GET_MODE_INNER (mode);
- rtx mem, x;
-
-+ if (mode == V2DFmode)
-+ {
-+ gcc_assert (TARGET_VSX);
-+ emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt)));
-+ return;
-+ }
-+
- /* Allocate mode-sized buffer. */
- mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
-
-@@ -3627,9 +4097,13 @@ rs6000_legitimate_offset_address_p (enum
- case V8HImode:
- case V4SFmode:
- case V4SImode:
-- /* AltiVec vector modes. Only reg+reg addressing is valid and
-+ case V2DFmode:
-+ case V2DImode:
-+ /* AltiVec/VSX vector modes. Only reg+reg addressing is valid and
- constant offset zero should not occur due to canonicalization. */
-- return false;
-+ if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
-+ return false;
-+ break;
-
- case V4HImode:
- case V2SImode:
-@@ -3646,6 +4120,11 @@ rs6000_legitimate_offset_address_p (enum
- if (TARGET_E500_DOUBLE)
- return SPE_CONST_OFFSET_OK (offset);
-
-+ /* If we are using VSX scalar loads, restrict ourselves to reg+reg
-+ addressing. */
-+ if (VECTOR_MEM_VSX_P (DFmode))
-+ return false;
-+
- case DDmode:
- case DImode:
- /* On e500v2, we may have:
-@@ -3716,7 +4195,9 @@ avoiding_indexed_address_p (enum machine
- {
- /* Avoid indexed addressing for modes that have non-indexed
- load/store instruction forms. */
-- return TARGET_AVOID_XFORM && !ALTIVEC_VECTOR_MODE (mode);
-+ return (TARGET_AVOID_XFORM
-+ && (!TARGET_ALTIVEC || !ALTIVEC_VECTOR_MODE (mode))
-+ && (!TARGET_VSX || !VSX_VECTOR_MODE (mode)));
- }
-
- inline bool
-@@ -3808,25 +4289,30 @@ rtx
- rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode)
- {
-+ rtx ret = NULL_RTX;
-+ rtx orig_x = x;
-+
- if (GET_CODE (x) == SYMBOL_REF)
- {
- enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
- if (model != 0)
-- return rs6000_legitimize_tls_address (x, model);
-+ ret = rs6000_legitimize_tls_address (x, model);
- }
-
-- if (GET_CODE (x) == PLUS
-- && GET_CODE (XEXP (x, 0)) == REG
-- && GET_CODE (XEXP (x, 1)) == CONST_INT
-- && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000
-- && !((TARGET_POWERPC64
-- && (mode == DImode || mode == TImode)
-- && (INTVAL (XEXP (x, 1)) & 3) != 0)
-- || SPE_VECTOR_MODE (mode)
-- || ALTIVEC_VECTOR_MODE (mode)
-- || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-- || mode == DImode || mode == DDmode
-- || mode == TDmode))))
-+ else if (GET_CODE (x) == PLUS
-+ && GET_CODE (XEXP (x, 0)) == REG
-+ && GET_CODE (XEXP (x, 1)) == CONST_INT
-+ && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000)
-+ >= 0x10000)
-+ && !((TARGET_POWERPC64
-+ && (mode == DImode || mode == TImode)
-+ && (INTVAL (XEXP (x, 1)) & 3) != 0)
-+ || (TARGET_SPE && SPE_VECTOR_MODE (mode))
-+ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
-+ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
-+ || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-+ || mode == DImode || mode == DDmode
-+ || mode == TDmode))))
- {
- HOST_WIDE_INT high_int, low_int;
- rtx sum;
-@@ -3834,7 +4320,7 @@ rs6000_legitimize_address (rtx x, rtx ol
- high_int = INTVAL (XEXP (x, 1)) - low_int;
- sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
- GEN_INT (high_int)), 0);
-- return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
-+ ret = gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
- }
- else if (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 0)) == REG
-@@ -3850,32 +4336,29 @@ rs6000_legitimize_address (rtx x, rtx ol
- && mode != TFmode
- && mode != TDmode)
- {
-- return gen_rtx_PLUS (Pmode, XEXP (x, 0),
-- force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
-+ ret = gen_rtx_PLUS (Pmode, XEXP (x, 0),
-+ force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
- }
-- else if (ALTIVEC_VECTOR_MODE (mode))
-+ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
- {
-- rtx reg;
--
- /* Make sure both operands are registers. */
- if (GET_CODE (x) == PLUS)
-- return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
-- force_reg (Pmode, XEXP (x, 1)));
--
-- reg = force_reg (Pmode, x);
-- return reg;
-+ ret = gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
-+ force_reg (Pmode, XEXP (x, 1)));
-+ else
-+ ret = force_reg (Pmode, x);
- }
-- else if (SPE_VECTOR_MODE (mode)
-+ else if ((TARGET_SPE && SPE_VECTOR_MODE (mode))
- || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
- || mode == DDmode || mode == TDmode
- || mode == DImode)))
- {
- if (mode == DImode)
-- return NULL_RTX;
-- /* We accept [reg + reg] and [reg + OFFSET]. */
-+ ret = NULL_RTX;
-
-- if (GET_CODE (x) == PLUS)
-- {
-+ /* We accept [reg + reg] and [reg + OFFSET]. */
-+ else if (GET_CODE (x) == PLUS)
-+ {
- rtx op1 = XEXP (x, 0);
- rtx op2 = XEXP (x, 1);
- rtx y;
-@@ -3894,12 +4377,12 @@ rs6000_legitimize_address (rtx x, rtx ol
- y = gen_rtx_PLUS (Pmode, op1, op2);
-
- if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2))
-- return force_reg (Pmode, y);
-+ ret = force_reg (Pmode, y);
- else
-- return y;
-+ ret = y;
- }
--
-- return force_reg (Pmode, x);
-+ else
-+ ret = force_reg (Pmode, x);
- }
- else if (TARGET_ELF
- && TARGET_32BIT
-@@ -3915,7 +4398,7 @@ rs6000_legitimize_address (rtx x, rtx ol
- {
- rtx reg = gen_reg_rtx (Pmode);
- emit_insn (gen_elf_high (reg, x));
-- return gen_rtx_LO_SUM (Pmode, reg, x);
-+ ret = gen_rtx_LO_SUM (Pmode, reg, x);
- }
- else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
- && ! flag_pic
-@@ -3933,17 +4416,34 @@ rs6000_legitimize_address (rtx x, rtx ol
- {
- rtx reg = gen_reg_rtx (Pmode);
- emit_insn (gen_macho_high (reg, x));
-- return gen_rtx_LO_SUM (Pmode, reg, x);
-+ ret = gen_rtx_LO_SUM (Pmode, reg, x);
- }
- else if (TARGET_TOC
- && GET_CODE (x) == SYMBOL_REF
- && constant_pool_expr_p (x)
- && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
- {
-- return create_TOC_reference (x);
-+ ret = create_TOC_reference (x);
- }
- else
-- return NULL_RTX;
-+ ret = NULL_RTX;
-+
-+ if (TARGET_DEBUG_ADDR)
-+ {
-+ fprintf (stderr,
-+ "\nrs6000_legitimize_address: mode %s, original addr:\n",
-+ GET_MODE_NAME (mode));
-+ debug_rtx (orig_x);
-+ if (ret)
-+ {
-+ fprintf (stderr, "New addr:\n");
-+ debug_rtx (ret);
-+ }
-+ else
-+ fprintf (stderr, "NULL returned\n");
-+ }
-+
-+ return ret;
- }
-
- /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
-@@ -4232,6 +4732,9 @@ rs6000_legitimize_reload_address (rtx x,
- int opnum, int type,
- int ind_levels ATTRIBUTE_UNUSED, int *win)
- {
-+ rtx orig_x = x;
-+ rtx ret = NULL_RTX;
-+
- /* We must recognize output that we have already generated ourselves. */
- if (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 0)) == PLUS
-@@ -4243,17 +4746,17 @@ rs6000_legitimize_reload_address (rtx x,
- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
- *win = 1;
-- return x;
-+ ret = x;
- }
-
- #if TARGET_MACHO
-- if (DEFAULT_ABI == ABI_DARWIN && flag_pic
-- && GET_CODE (x) == LO_SUM
-- && GET_CODE (XEXP (x, 0)) == PLUS
-- && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
-- && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
-- && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
-- && machopic_operand_p (XEXP (x, 1)))
-+ else if (DEFAULT_ABI == ABI_DARWIN && flag_pic
-+ && GET_CODE (x) == LO_SUM
-+ && GET_CODE (XEXP (x, 0)) == PLUS
-+ && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
-+ && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
-+ && machopic_operand_p (XEXP (x, 1)))
- {
- /* Result of previous invocation of this function on Darwin
- floating point constant. */
-@@ -4261,40 +4764,42 @@ rs6000_legitimize_reload_address (rtx x,
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
- *win = 1;
-- return x;
-+ ret = x;
- }
- #endif
-
- /* Force ld/std non-word aligned offset into base register by wrapping
- in offset 0. */
-- if (GET_CODE (x) == PLUS
-- && GET_CODE (XEXP (x, 0)) == REG
-- && REGNO (XEXP (x, 0)) < 32
-- && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
-- && GET_CODE (XEXP (x, 1)) == CONST_INT
-- && (INTVAL (XEXP (x, 1)) & 3) != 0
-- && !ALTIVEC_VECTOR_MODE (mode)
-- && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
-- && TARGET_POWERPC64)
-+ else if (GET_CODE (x) == PLUS
-+ && GET_CODE (XEXP (x, 0)) == REG
-+ && REGNO (XEXP (x, 0)) < 32
-+ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
-+ && GET_CODE (XEXP (x, 1)) == CONST_INT
-+ && (INTVAL (XEXP (x, 1)) & 3) != 0
-+ && !ALTIVEC_VECTOR_MODE (mode)
-+ && !VSX_VECTOR_MODE (mode)
-+ && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
-+ && TARGET_POWERPC64)
- {
- x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
- push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type) type);
- *win = 1;
-- return x;
-+ ret = x;
- }
-
-- if (GET_CODE (x) == PLUS
-- && GET_CODE (XEXP (x, 0)) == REG
-- && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
-- && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
-- && GET_CODE (XEXP (x, 1)) == CONST_INT
-- && !SPE_VECTOR_MODE (mode)
-- && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-- || mode == DDmode || mode == TDmode
-- || mode == DImode))
-- && !ALTIVEC_VECTOR_MODE (mode))
-+ else if (GET_CODE (x) == PLUS
-+ && GET_CODE (XEXP (x, 0)) == REG
-+ && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
-+ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
-+ && GET_CODE (XEXP (x, 1)) == CONST_INT
-+ && !SPE_VECTOR_MODE (mode)
-+ && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-+ || mode == DDmode || mode == TDmode
-+ || mode == DImode))
-+ && !ALTIVEC_VECTOR_MODE (mode)
-+ && !VSX_VECTOR_MODE (mode))
- {
- HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
- HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-@@ -4305,42 +4810,44 @@ rs6000_legitimize_reload_address (rtx x,
- if (high + low != val)
- {
- *win = 0;
-- return x;
-+ ret = x;
- }
-+ else
-+ {
-+ /* Reload the high part into a base reg; leave the low part
-+ in the mem directly. */
-
-- /* Reload the high part into a base reg; leave the low part
-- in the mem directly. */
--
-- x = gen_rtx_PLUS (GET_MODE (x),
-- gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
-- GEN_INT (high)),
-- GEN_INT (low));
-+ x = gen_rtx_PLUS (GET_MODE (x),
-+ gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
-+ GEN_INT (high)),
-+ GEN_INT (low));
-
-- push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
-- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
-- opnum, (enum reload_type)type);
-- *win = 1;
-- return x;
-+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
-+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
-+ opnum, (enum reload_type)type);
-+ *win = 1;
-+ return x;
-+ }
- }
-
-- if (GET_CODE (x) == SYMBOL_REF
-- && !ALTIVEC_VECTOR_MODE (mode)
-- && !SPE_VECTOR_MODE (mode)
-+ else if (GET_CODE (x) == SYMBOL_REF
-+ && VECTOR_MEM_NONE_P (mode)
-+ && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
- #if TARGET_MACHO
-- && DEFAULT_ABI == ABI_DARWIN
-- && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
-+ && DEFAULT_ABI == ABI_DARWIN
-+ && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
- #else
-- && DEFAULT_ABI == ABI_V4
-- && !flag_pic
-+ && DEFAULT_ABI == ABI_V4
-+ && !flag_pic
- #endif
-- /* Don't do this for TFmode or TDmode, since the result isn't offsettable.
-- The same goes for DImode without 64-bit gprs and DFmode and DDmode
-- without fprs. */
-- && mode != TFmode
-- && mode != TDmode
-- && (mode != DImode || TARGET_POWERPC64)
-- && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
-- || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
-+ /* Don't do this for TFmode or TDmode, since the result isn't
-+ offsettable. The same goes for DImode without 64-bit gprs and
-+ DFmode and DDmode without fprs. */
-+ && mode != TFmode
-+ && mode != TDmode
-+ && (mode != DImode || TARGET_POWERPC64)
-+ && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
-+ || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
- {
- #if TARGET_MACHO
- if (flag_pic)
-@@ -4359,37 +4866,61 @@ rs6000_legitimize_reload_address (rtx x,
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
- *win = 1;
-- return x;
-+ ret = x;
- }
-
- /* Reload an offset address wrapped by an AND that represents the
- masking of the lower bits. Strip the outer AND and let reload
- convert the offset address into an indirect address. */
-- if (TARGET_ALTIVEC
-- && ALTIVEC_VECTOR_MODE (mode)
-- && GET_CODE (x) == AND
-- && GET_CODE (XEXP (x, 0)) == PLUS
-- && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
-- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-- && GET_CODE (XEXP (x, 1)) == CONST_INT
-- && INTVAL (XEXP (x, 1)) == -16)
-+ else if (VECTOR_MEM_ALTIVEC_P (mode)
-+ && GET_CODE (x) == AND
-+ && GET_CODE (XEXP (x, 0)) == PLUS
-+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-+ && GET_CODE (XEXP (x, 1)) == CONST_INT
-+ && INTVAL (XEXP (x, 1)) == -16)
- {
- x = XEXP (x, 0);
- *win = 1;
-- return x;
-+ ret = x;
- }
-
-- if (TARGET_TOC
-- && GET_CODE (x) == SYMBOL_REF
-- && constant_pool_expr_p (x)
-- && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
-+ else if (TARGET_TOC
-+ && GET_CODE (x) == SYMBOL_REF
-+ && constant_pool_expr_p (x)
-+ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
- {
- x = create_TOC_reference (x);
- *win = 1;
-- return x;
-+ ret = x;
-+ }
-+
-+ else
-+ {
-+ *win = 0;
-+ ret = x;
- }
-- *win = 0;
-- return x;
-+
-+ if (TARGET_DEBUG_ADDR)
-+ {
-+ fprintf (stderr,
-+ "\nrs6000_legitimize_reload_address: mode = %s, opnum = %d, "
-+ "type = %d, ind_levels = %d, win = %d, original addr:\n",
-+ GET_MODE_NAME (mode), opnum, type, ind_levels, *win);
-+ debug_rtx (orig_x);
-+
-+ if (orig_x == ret)
-+ fprintf (stderr, "Same address returned\n");
-+ else if (!ret)
-+ fprintf (stderr, "NULL returned\n");
-+ else
-+ {
-+ fprintf (stderr, "New address:\n");
-+ debug_rtx (ret);
-+ }
-+ }
-+
-+ return ret;
- }
-
- /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
-@@ -4412,77 +4943,101 @@ rs6000_legitimize_reload_address (rtx x,
- int
- rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
- {
-+ int ret;
-+ rtx orig_x = x;
-+
- /* If this is an unaligned stvx/ldvx type address, discard the outer AND. */
- if (TARGET_ALTIVEC
-- && ALTIVEC_VECTOR_MODE (mode)
-+ && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
- && GET_CODE (x) == AND
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) == -16)
- x = XEXP (x, 0);
-
- if (RS6000_SYMBOL_REF_TLS_P (x))
-- return 0;
-- if (legitimate_indirect_address_p (x, reg_ok_strict))
-- return 1;
-- if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
-- && !ALTIVEC_VECTOR_MODE (mode)
-- && !SPE_VECTOR_MODE (mode)
-- && mode != TFmode
-- && mode != TDmode
-- /* Restrict addressing for DI because of our SUBREG hackery. */
-- && !(TARGET_E500_DOUBLE
-- && (mode == DFmode || mode == DDmode || mode == DImode))
-- && TARGET_UPDATE
-- && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
-- return 1;
-- if (legitimate_small_data_p (mode, x))
-- return 1;
-- if (legitimate_constant_pool_address_p (x))
-- return 1;
-+ ret = 0;
-+ else if (legitimate_indirect_address_p (x, reg_ok_strict))
-+ ret = 1;
-+ else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
-+ && !VECTOR_MEM_ALTIVEC_P (mode)
-+ /* && !VECTOR_MEM_VSX_P (mode) */
-+ && (TARGET_SPE && !SPE_VECTOR_MODE (mode))
-+ && mode != TFmode
-+ && mode != TDmode
-+ /* Restrict addressing for DI because of our SUBREG hackery. */
-+ && !(TARGET_E500_DOUBLE
-+ && (mode == DFmode || mode == DDmode || mode == DImode))
-+ && TARGET_UPDATE
-+ && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
-+ ret = 1;
-+ else if (legitimate_small_data_p (mode, x))
-+ ret = 1;
-+ else if (legitimate_constant_pool_address_p (x))
-+ ret = 1;
- /* If not REG_OK_STRICT (before reload) let pass any stack offset. */
-- if (! reg_ok_strict
-- && GET_CODE (x) == PLUS
-- && GET_CODE (XEXP (x, 0)) == REG
-- && (XEXP (x, 0) == virtual_stack_vars_rtx
-- || XEXP (x, 0) == arg_pointer_rtx)
-- && GET_CODE (XEXP (x, 1)) == CONST_INT)
-- return 1;
-- if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
-- return 1;
-- if (mode != TImode
-- && mode != TFmode
-- && mode != TDmode
-- && ((TARGET_HARD_FLOAT && TARGET_FPRS)
-- || TARGET_POWERPC64
-- || (mode != DFmode && mode != DDmode)
-- || (TARGET_E500_DOUBLE && mode != DDmode))
-- && (TARGET_POWERPC64 || mode != DImode)
-- && !avoiding_indexed_address_p (mode)
-- && legitimate_indexed_address_p (x, reg_ok_strict))
-- return 1;
-- if (GET_CODE (x) == PRE_MODIFY
-- && mode != TImode
-- && mode != TFmode
-- && mode != TDmode
-- && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
-- || TARGET_POWERPC64
-- || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
-- && (TARGET_POWERPC64 || mode != DImode)
-- && !ALTIVEC_VECTOR_MODE (mode)
-- && !SPE_VECTOR_MODE (mode)
-- /* Restrict addressing for DI because of our SUBREG hackery. */
-- && !(TARGET_E500_DOUBLE
-- && (mode == DFmode || mode == DDmode || mode == DImode))
-- && TARGET_UPDATE
-- && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
-- && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
-- || (!avoiding_indexed_address_p (mode)
-- && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
-- && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
-- return 1;
-- if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
-- return 1;
-- return 0;
-+ else if (! reg_ok_strict
-+ && GET_CODE (x) == PLUS
-+ && GET_CODE (XEXP (x, 0)) == REG
-+ && (XEXP (x, 0) == virtual_stack_vars_rtx
-+ || XEXP (x, 0) == arg_pointer_rtx)
-+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
-+ ret = 1;
-+ else if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
-+ ret = 1;
-+ else if (mode != TImode
-+ && mode != TFmode
-+ && mode != TDmode
-+ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
-+ || TARGET_POWERPC64
-+ || (mode != DFmode && mode != DDmode)
-+ || (TARGET_E500_DOUBLE && mode != DDmode))
-+ && (TARGET_POWERPC64 || mode != DImode)
-+ && !avoiding_indexed_address_p (mode)
-+ && legitimate_indexed_address_p (x, reg_ok_strict))
-+ ret = 1;
-+ else if (GET_CODE (x) == PRE_MODIFY
-+ && VECTOR_MEM_VSX_P (mode)
-+ && TARGET_UPDATE
-+ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)
-+ && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
-+ ret = 1;
-+ else if (GET_CODE (x) == PRE_MODIFY
-+ && mode != TImode
-+ && mode != TFmode
-+ && mode != TDmode
-+ && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
-+ || TARGET_POWERPC64
-+ || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
-+ && (TARGET_POWERPC64 || mode != DImode)
-+ && !VECTOR_MEM_ALTIVEC_P (mode)
-+ && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
-+ /* Restrict addressing for DI because of our SUBREG hackery. */
-+ && !(TARGET_E500_DOUBLE
-+ && (mode == DFmode || mode == DDmode || mode == DImode))
-+ && TARGET_UPDATE
-+ && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
-+ && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
-+ || (!avoiding_indexed_address_p (mode)
-+ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
-+ && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
-+ ret = 1;
-+ else if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
-+ ret = 1;
-+ else
-+ ret = 0;
-+
-+ if (TARGET_DEBUG_ADDR)
-+ {
-+ fprintf (stderr,
-+ "\nrs6000_legitimate_address: return = %d, mode = %s, "
-+ "strict = %d\n",
-+ ret,
-+ GET_MODE_NAME (mode),
-+ reg_ok_strict);
-+ debug_rtx (orig_x);
-+ }
-+
-+ return ret;
- }
-
- /* Go to LABEL if ADDR (a legitimate address expression)
-@@ -4499,28 +5054,40 @@ rs6000_legitimate_address (enum machine_
- bool
- rs6000_mode_dependent_address (rtx addr)
- {
-+ bool ret = false;
-+
- switch (GET_CODE (addr))
- {
- case PLUS:
- if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
- {
- unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
-- return val + 12 + 0x8000 >= 0x10000;
-+ ret = (val + 12 + 0x8000 >= 0x10000);
- }
- break;
-
- case LO_SUM:
-- return true;
-+ ret = true;
-+ break;
-
- /* Auto-increment cases are now treated generically in recog.c. */
- case PRE_MODIFY:
-- return TARGET_UPDATE;
-+ ret = (TARGET_UPDATE != 0);
-+ break;
-
- default:
- break;
- }
-
-- return false;
-+ if (TARGET_DEBUG_ADDR)
-+ {
-+ fprintf (stderr,
-+ "\nrs6000_mode_dependent_address: ret = %d\n",
-+ (int)ret);
-+ debug_rtx (addr);
-+ }
-+
-+ return ret;
- }
-
- /* Implement FIND_BASE_TERM. */
-@@ -4571,43 +5138,6 @@ rs6000_offsettable_memref_p (rtx op)
- return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1);
- }
-
--/* Return number of consecutive hard regs needed starting at reg REGNO
-- to hold something of mode MODE.
-- This is ordinarily the length in words of a value of mode MODE
-- but can be less for certain modes in special long registers.
--
-- For the SPE, GPRs are 64 bits but only 32 bits are visible in
-- scalar instructions. The upper 32 bits are only available to the
-- SIMD instructions.
--
-- POWER and PowerPC GPRs hold 32 bits worth;
-- PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
--
--int
--rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
--{
-- if (FP_REGNO_P (regno))
-- return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
--
-- if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
-- return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
--
-- if (ALTIVEC_REGNO_P (regno))
-- return
-- (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
--
-- /* The value returned for SCmode in the E500 double case is 2 for
-- ABI compatibility; storing an SCmode value in a single register
-- would require function_arg and rs6000_spe_function_arg to handle
-- SCmode so as to pass the value correctly in a pair of
-- registers. */
-- if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
-- && !DECIMAL_FLOAT_MODE_P (mode))
-- return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
--
-- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
--}
--
- /* Change register usage conditional on target flags. */
- void
- rs6000_conditional_register_usage (void)
-@@ -4672,14 +5202,14 @@ rs6000_conditional_register_usage (void)
- = call_really_used_regs[14] = 1;
- }
-
-- if (!TARGET_ALTIVEC)
-+ if (!TARGET_ALTIVEC && !TARGET_VSX)
- {
- for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
- fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
- call_really_used_regs[VRSAVE_REGNO] = 1;
- }
-
-- if (TARGET_ALTIVEC)
-+ if (TARGET_ALTIVEC || TARGET_VSX)
- global_regs[VSCR_REGNO] = 1;
-
- if (TARGET_ALTIVEC_ABI)
-@@ -5101,6 +5631,8 @@ rs6000_emit_move (rtx dest, rtx source,
- 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]);
-@@ -5270,6 +5802,9 @@ rs6000_emit_move (rtx dest, rtx source,
- break;
-
- case TImode:
-+ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (TImode))
-+ break;
-+
- rs6000_eliminate_indexed_memrefs (operands);
-
- if (TARGET_POWER)
-@@ -5285,7 +5820,7 @@ rs6000_emit_move (rtx dest, rtx source,
- break;
-
- default:
-- gcc_unreachable ();
-+ fatal_insn ("bad move", gen_rtx_SET (VOIDmode, dest, source));
- }
-
- /* Above, we may have called force_const_mem which may have returned
-@@ -5305,10 +5840,10 @@ rs6000_emit_move (rtx dest, rtx source,
- && TARGET_HARD_FLOAT && TARGET_FPRS)
-
- /* Nonzero if we can use an AltiVec register to pass this arg. */
--#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
-- (ALTIVEC_VECTOR_MODE (MODE) \
-- && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
-- && TARGET_ALTIVEC_ABI \
-+#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
-+ ((ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)) \
-+ && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
-+ && TARGET_ALTIVEC_ABI \
- && (NAMED))
-
- /* Return a nonzero value to say to return the function value in
-@@ -5549,7 +6084,7 @@ function_arg_boundary (enum machine_mode
- && int_size_in_bytes (type) >= 8
- && int_size_in_bytes (type) < 16))
- return 64;
-- else if (ALTIVEC_VECTOR_MODE (mode)
-+ else if ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
- || (type && TREE_CODE (type) == VECTOR_TYPE
- && int_size_in_bytes (type) >= 16))
- return 128;
-@@ -5694,7 +6229,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
- cum->nargs_prototype--;
-
- if (TARGET_ALTIVEC_ABI
-- && (ALTIVEC_VECTOR_MODE (mode)
-+ && ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
- || (type && TREE_CODE (type) == VECTOR_TYPE
- && int_size_in_bytes (type) == 16)))
- {
-@@ -6288,7 +6823,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum
- else
- return gen_rtx_REG (mode, cum->vregno);
- else if (TARGET_ALTIVEC_ABI
-- && (ALTIVEC_VECTOR_MODE (mode)
-+ && ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
- || (type && TREE_CODE (type) == VECTOR_TYPE
- && int_size_in_bytes (type) == 16)))
- {
-@@ -7212,10 +7747,13 @@ static const struct builtin_description
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
-+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
-+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
-+ { MASK_ALTIVEC, CODE_FOR_vector_vselv4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
-+ { MASK_ALTIVEC, CODE_FOR_vector_vselv4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
-+ { MASK_ALTIVEC, CODE_FOR_vector_vselv8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
-+ { MASK_ALTIVEC, CODE_FOR_vector_vselv16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
-+ { MASK_ALTIVEC, CODE_FOR_vector_vselv2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
-@@ -7289,18 +7827,18 @@ static struct builtin_description bdesc_
- { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
-- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
-+ { MASK_ALTIVEC, CODE_FOR_vector_eqv16qi, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
-+ { MASK_ALTIVEC, CODE_FOR_vector_eqv8hi, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
-+ { MASK_ALTIVEC, CODE_FOR_vector_eqv4si, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
-+ { MASK_ALTIVEC, CODE_FOR_vector_eqv4sf, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gev4sf, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtuv16qi, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtuv8hi, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtuv4si, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtv16qi, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtv8hi, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtv4si, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
-+ { MASK_ALTIVEC, CODE_FOR_vector_gtv4sf, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
- { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
-@@ -7331,7 +7869,7 @@ static struct builtin_description bdesc_
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
-- { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
-+ { MASK_ALTIVEC, CODE_FOR_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
- { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
-@@ -7796,6 +8334,11 @@ static struct builtin_description bdesc_
- { 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_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 },
-+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
-+
- /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
- end with SPE_BUILTIN_EVSUBFUSIAAW. */
- { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
-@@ -8352,16 +8895,16 @@ altivec_expand_ld_builtin (tree exp, rtx
- switch (fcode)
- {
- case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
-- icode = CODE_FOR_altivec_lvx_v16qi;
-+ icode = CODE_FOR_vector_load_v16qi;
- break;
- case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
-- icode = CODE_FOR_altivec_lvx_v8hi;
-+ icode = CODE_FOR_vector_load_v8hi;
- break;
- case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
-- icode = CODE_FOR_altivec_lvx_v4si;
-+ icode = CODE_FOR_vector_load_v4si;
- break;
- case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
-- icode = CODE_FOR_altivec_lvx_v4sf;
-+ icode = CODE_FOR_vector_load_v4sf;
- break;
- default:
- *expandedp = false;
-@@ -8405,16 +8948,16 @@ altivec_expand_st_builtin (tree exp, rtx
- switch (fcode)
- {
- case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
-- icode = CODE_FOR_altivec_stvx_v16qi;
-+ icode = CODE_FOR_vector_store_v16qi;
- break;
- case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
-- icode = CODE_FOR_altivec_stvx_v8hi;
-+ icode = CODE_FOR_vector_store_v8hi;
- break;
- case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
-- icode = CODE_FOR_altivec_stvx_v4si;
-+ icode = CODE_FOR_vector_store_v4si;
- break;
- case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
-- icode = CODE_FOR_altivec_stvx_v4sf;
-+ icode = CODE_FOR_vector_store_v4sf;
- break;
- default:
- *expandedp = false;
-@@ -9372,6 +9915,8 @@ rs6000_init_builtins (void)
- {
- V2SI_type_node = build_vector_type (intSI_type_node, 2);
- V2SF_type_node = build_vector_type (float_type_node, 2);
-+ V2DI_type_node = build_vector_type (intDI_type_node, 2);
-+ V2DF_type_node = build_vector_type (double_type_node, 2);
- V4HI_type_node = build_vector_type (intHI_type_node, 4);
- V4SI_type_node = build_vector_type (intSI_type_node, 4);
- V4SF_type_node = build_vector_type (float_type_node, 4);
-@@ -9404,7 +9949,10 @@ rs6000_init_builtins (void)
- uintHI_type_internal_node = unsigned_intHI_type_node;
- intSI_type_internal_node = intSI_type_node;
- uintSI_type_internal_node = unsigned_intSI_type_node;
-+ intDI_type_internal_node = intDI_type_node;
-+ uintDI_type_internal_node = unsigned_intDI_type_node;
- float_type_internal_node = float_type_node;
-+ double_type_internal_node = float_type_node;
- void_type_internal_node = void_type_node;
-
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-@@ -9462,13 +10010,18 @@ rs6000_init_builtins (void)
- get_identifier ("__vector __pixel"),
- pixel_V8HI_type_node));
-
-+ if (TARGET_VSX)
-+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-+ get_identifier ("__vector double"),
-+ V2DF_type_node));
-+
- if (TARGET_PAIRED_FLOAT)
- paired_init_builtins ();
- if (TARGET_SPE)
- spe_init_builtins ();
- if (TARGET_ALTIVEC)
- altivec_init_builtins ();
-- if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT)
-+ if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT || TARGET_VSX)
- rs6000_common_init_builtins ();
- if (TARGET_PPC_GFXOPT)
- {
-@@ -10407,6 +10960,26 @@ rs6000_common_init_builtins (void)
- tree int_ftype_v8hi_v8hi
- = build_function_type_list (integer_type_node,
- V8HI_type_node, V8HI_type_node, NULL_TREE);
-+ tree v2df_ftype_v2df_v2df_v2df
-+ = build_function_type_list (V2DF_type_node,
-+ V2DF_type_node, V2DF_type_node,
-+ V2DF_type_node, NULL_TREE);
-+ tree v2di_ftype_v2di_v2di_v2di
-+ = build_function_type_list (V2DI_type_node,
-+ V2DI_type_node, V2DI_type_node,
-+ V2DI_type_node, NULL_TREE);
-+ tree v2df_ftype_v2df_v2df_v16qi
-+ = build_function_type_list (V2DF_type_node,
-+ V2DF_type_node, V2DF_type_node,
-+ V16QI_type_node, NULL_TREE);
-+ tree v2di_ftype_v2di_v2di_v16qi
-+ = build_function_type_list (V2DI_type_node,
-+ V2DI_type_node, V2DI_type_node,
-+ V16QI_type_node, NULL_TREE);
-+ tree v4sf_ftype_v4si
-+ = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
-+ tree v4si_ftype_v4sf
-+ = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
-
- /* Add the simple ternary operators. */
- d = bdesc_3arg;
-@@ -10443,6 +11016,12 @@ rs6000_common_init_builtins (void)
- case VOIDmode:
- type = opaque_ftype_opaque_opaque_opaque;
- break;
-+ case V2DImode:
-+ type = v2di_ftype_v2di_v2di_v2di;
-+ break;
-+ case V2DFmode:
-+ type = v2df_ftype_v2df_v2df_v2df;
-+ break;
- case V4SImode:
- type = v4si_ftype_v4si_v4si_v4si;
- break;
-@@ -10466,6 +11045,12 @@ rs6000_common_init_builtins (void)
- {
- switch (mode0)
- {
-+ case V2DImode:
-+ type = v2di_ftype_v2di_v2di_v16qi;
-+ break;
-+ case V2DFmode:
-+ type = v2df_ftype_v2df_v2df_v16qi;
-+ break;
- case V4SImode:
- type = v4si_ftype_v4si_v4si_v16qi;
- break;
-@@ -10721,6 +11306,10 @@ rs6000_common_init_builtins (void)
- type = v2si_ftype_v2sf;
- else if (mode0 == V2SImode && mode1 == QImode)
- type = v2si_ftype_char;
-+ else if (mode0 == V4SImode && mode1 == V4SFmode)
-+ type = v4si_ftype_v4sf;
-+ else if (mode0 == V4SFmode && mode1 == V4SImode)
-+ type = v4sf_ftype_v4si;
- else
- gcc_unreachable ();
-
-@@ -11601,13 +12190,101 @@ rs6000_instantiate_decls (void)
- instantiate_decl_rtl (cfun->machine->sdmode_stack_slot);
- }
-
-+/* Given an rtx X being reloaded into a reg required to be
-+ in class CLASS, return the class of reg to actually use.
-+ In general this is just CLASS; but on some machines
-+ in some cases it is preferable to use a more restrictive class.
-+
-+ On the RS/6000, we have to return NO_REGS when we want to reload a
-+ floating-point CONST_DOUBLE to force it to be copied to memory.
-+
-+ We also don't want to reload integer values into floating-point
-+ registers if we can at all help it. In fact, this can
-+ cause reload to die, if it tries to generate a reload of CTR
-+ into a FP register and discovers it doesn't have the memory location
-+ required.
-+
-+ ??? Would it be a good idea to have reload do the converse, that is
-+ try to reload floating modes into FP registers if possible?
-+ */
-+
-+enum reg_class
-+rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
-+{
-+ enum machine_mode mode = GET_MODE (x);
-+
-+ if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
-+ && VSX_REG_CLASS_P (rclass))
-+ return rclass;
-+
-+ if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS
-+ && easy_vector_constant (x, mode))
-+ return rclass;
-+
-+ if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
-+ return NO_REGS;
-+
-+ if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
-+ return GENERAL_REGS;
-+
-+ /* For VSX, prefer the traditional registers. */
-+ if (rclass == VSX_REGS)
-+ {
-+ if (mode == DFmode)
-+ return FLOAT_REGS;
-+
-+ if (ALTIVEC_VECTOR_MODE (mode))
-+ return ALTIVEC_REGS;
-+ }
-+
-+ return rclass;
-+}
-+
-+/* If we are copying between FP or AltiVec registers and anything else, we need
-+ a memory location. The exception is when we are targeting ppc64 and the
-+ move to/from fpr to gpr instructions are available. Also, under VSX, you
-+ can copy vector registers from the FP register set to the Altivec register
-+ set and vice versa. */
-+
-+bool
-+rs6000_secondary_memory_needed (enum reg_class class1,
-+ enum reg_class class2,
-+ enum machine_mode mode)
-+{
-+ if (class1 == class2)
-+ return false;
-+
-+ if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1)
-+ && VSX_REG_CLASS_P (class2))
-+ return false;
-+
-+ if (class1 == FLOAT_REGS
-+ && (!TARGET_MFPGPR || !TARGET_POWERPC64
-+ || ((mode != DFmode)
-+ && (mode != DDmode)
-+ && (mode != DImode))))
-+ return true;
-+
-+ if (class2 == FLOAT_REGS
-+ && (!TARGET_MFPGPR || !TARGET_POWERPC64
-+ || ((mode != DFmode)
-+ && (mode != DDmode)
-+ && (mode != DImode))))
-+ return true;
-+
-+ if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
-+ return true;
-+
-+ return false;
-+}
-+
- /* Return the register class of a scratch register needed to copy IN into
- or out of a register in RCLASS in MODE. If it can be done directly,
- NO_REGS is returned. */
-
- enum reg_class
- rs6000_secondary_reload_class (enum reg_class rclass,
-- enum machine_mode mode ATTRIBUTE_UNUSED,
-+ enum machine_mode mode,
- rtx in)
- {
- int regno;
-@@ -11663,6 +12340,13 @@ rs6000_secondary_reload_class (enum reg_
- && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
- return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
-
-+ /* Memory, and FP/altivec registers can go into fp/altivec registers under
-+ VSX. */
-+ if (TARGET_VSX
-+ && (regno == -1 || VSX_REGNO_P (regno))
-+ && VSX_REG_CLASS_P (rclass))
-+ return NO_REGS;
-+
- /* Memory, and AltiVec registers can go into AltiVec registers. */
- if ((regno == -1 || ALTIVEC_REGNO_P (regno))
- && rclass == ALTIVEC_REGS)
-@@ -11676,6 +12360,28 @@ rs6000_secondary_reload_class (enum reg_
- /* Otherwise, we need GENERAL_REGS. */
- return GENERAL_REGS;
- }
-+
-+/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
-+
-+bool
-+rs6000_cannot_change_mode_class (enum machine_mode from,
-+ enum machine_mode to,
-+ enum reg_class rclass)
-+{
-+ return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
-+ ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
-+ || TARGET_IEEEQUAD)
-+ && reg_classes_intersect_p (FLOAT_REGS, rclass))
-+ : (((TARGET_E500_DOUBLE
-+ && ((((to) == DFmode) + ((from) == DFmode)) == 1
-+ || (((to) == TFmode) + ((from) == TFmode)) == 1
-+ || (((to) == DDmode) + ((from) == DDmode)) == 1
-+ || (((to) == TDmode) + ((from) == TDmode)) == 1
-+ || (((to) == DImode) + ((from) == DImode)) == 1))
-+ || (TARGET_SPE
-+ && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
-+ && reg_classes_intersect_p (GENERAL_REGS, rclass)));
-+}
- \f
- /* Given a comparison operation, return the bit number in CCR to test. We
- know this is a valid comparison.
-@@ -12406,6 +13112,26 @@ print_operand (FILE *file, rtx x, int co
- fprintf (file, "%d", i + 1);
- return;
-
-+ case 'x':
-+ /* X is a FPR or Altivec register used in a VSX context. */
-+ if (GET_CODE (x) != REG || !VSX_REGNO_P (REGNO (x)))
-+ output_operand_lossage ("invalid %%x value");
-+ else
-+ {
-+ int reg = REGNO (x);
-+ int vsx_reg = (FP_REGNO_P (reg)
-+ ? reg - 32
-+ : reg - FIRST_ALTIVEC_REGNO + 32);
-+
-+#ifdef TARGET_REGNAMES
-+ if (TARGET_REGNAMES)
-+ fprintf (file, "%%vs%d", vsx_reg);
-+ else
-+#endif
-+ fprintf (file, "%d", vsx_reg);
-+ }
-+ return;
-+
- case 'X':
- if (GET_CODE (x) == MEM
- && (legitimate_indexed_address_p (XEXP (x, 0), 0)
-@@ -12518,13 +13244,16 @@ print_operand (FILE *file, rtx x, int co
-
- /* Fall through. Must be [reg+reg]. */
- }
-- if (TARGET_ALTIVEC
-+ if (VECTOR_MEM_ALTIVEC_P (GET_MODE (x))
- && GET_CODE (tmp) == AND
- && GET_CODE (XEXP (tmp, 1)) == CONST_INT
- && INTVAL (XEXP (tmp, 1)) == -16)
- tmp = XEXP (tmp, 0);
-+ else if (VECTOR_MEM_VSX_P (GET_MODE (x))
-+ && GET_CODE (tmp) == PRE_MODIFY)
-+ tmp = XEXP (tmp, 1);
- if (GET_CODE (tmp) == REG)
-- fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
-+ fprintf (file, "%s,%s", reg_names[0], reg_names[REGNO (tmp)]);
- else
- {
- if (!GET_CODE (tmp) == PLUS
-@@ -13296,55 +14025,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr
- return string;
- }
-
--/* Return insn index for the vector compare instruction for given CODE,
-- and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is
-- not available. */
-+/* Return insn for VSX comparisons. */
-
--static int
--get_vec_cmp_insn (enum rtx_code code,
-- enum machine_mode dest_mode,
-- enum machine_mode op_mode)
-+static rtx
-+rs6000_emit_vector_compare_vsx (enum rtx_code code,
-+ rtx mask,
-+ rtx op0,
-+ rtx op1)
- {
-- if (!TARGET_ALTIVEC)
-- return INSN_NOT_AVAILABLE;
--
- switch (code)
- {
-+ default:
-+ break;
-+
- case EQ:
-- if (dest_mode == V16QImode && op_mode == V16QImode)
-- return UNSPEC_VCMPEQUB;
-- if (dest_mode == V8HImode && op_mode == V8HImode)
-- return UNSPEC_VCMPEQUH;
-- if (dest_mode == V4SImode && op_mode == V4SImode)
-- return UNSPEC_VCMPEQUW;
-- if (dest_mode == V4SImode && op_mode == V4SFmode)
-- return UNSPEC_VCMPEQFP;
-+ case GT:
-+ case GE:
-+ emit_insn (gen_rtx_SET (VOIDmode,
-+ mask,
-+ gen_rtx_fmt_ee (code, GET_MODE (mask),
-+ op0,
-+ op1)));
-+ return mask;
-+ }
-+
-+ return NULL_RTX;
-+}
-+
-+/* Return insn for Altivec comparisons. */
-+
-+static rtx
-+rs6000_emit_vector_compare_altivec (enum rtx_code code,
-+ rtx mask,
-+ rtx op0,
-+ rtx op1)
-+{
-+ switch (code)
-+ {
-+ default:
- break;
-+
- case GE:
-- if (dest_mode == V4SImode && op_mode == V4SFmode)
-- return UNSPEC_VCMPGEFP;
-+ if (GET_MODE (mask) != V4SFmode)
-+ return NULL_RTX;
-+ /* fall through */
-+ case EQ:
- case GT:
-- if (dest_mode == V16QImode && op_mode == V16QImode)
-- return UNSPEC_VCMPGTSB;
-- if (dest_mode == V8HImode && op_mode == V8HImode)
-- return UNSPEC_VCMPGTSH;
-- if (dest_mode == V4SImode && op_mode == V4SImode)
-- return UNSPEC_VCMPGTSW;
-- if (dest_mode == V4SImode && op_mode == V4SFmode)
-- return UNSPEC_VCMPGTFP;
-- break;
- case GTU:
-- if (dest_mode == V16QImode && op_mode == V16QImode)
-- return UNSPEC_VCMPGTUB;
-- if (dest_mode == V8HImode && op_mode == V8HImode)
-- return UNSPEC_VCMPGTUH;
-- if (dest_mode == V4SImode && op_mode == V4SImode)
-- return UNSPEC_VCMPGTUW;
-- break;
-- default:
-- break;
-+ emit_insn (gen_rtx_SET (VOIDmode,
-+ mask,
-+ gen_rtx_fmt_ee (code, GET_MODE (mask),
-+ op0,
-+ op1)));
-+ return mask;
- }
-- return INSN_NOT_AVAILABLE;
-+
-+ return NULL_RTX;
- }
-
- /* Emit vector compare for operands OP0 and OP1 using code RCODE.
-@@ -13355,129 +14091,111 @@ rs6000_emit_vector_compare (enum rtx_cod
- rtx op0, rtx op1,
- enum machine_mode dmode)
- {
-- int vec_cmp_insn;
- rtx mask;
-- enum machine_mode dest_mode;
-- enum machine_mode op_mode = GET_MODE (op1);
-+ bool swap_operands = false;
-+ bool try_again = false;
-
-- gcc_assert (TARGET_ALTIVEC);
-+ gcc_assert (TARGET_ALTIVEC || TARGET_VSX);
- gcc_assert (GET_MODE (op0) == GET_MODE (op1));
-
-- /* Floating point vector compare instructions uses destination V4SImode.
-- Move destination to appropriate mode later. */
-- if (dmode == V4SFmode)
-- dest_mode = V4SImode;
-- else
-- dest_mode = dmode;
-+ mask = gen_reg_rtx (dmode);
-
-- mask = gen_reg_rtx (dest_mode);
-- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
-+ /* Try for VSX before Altivec. */
-+ if (TARGET_VSX && VSX_VECTOR_MODE (dmode))
-+ {
-+ rtx vsx = rs6000_emit_vector_compare_vsx (rcode, mask, op0, op1);
-+ if (vsx)
-+ return vsx;
-+ }
-+ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dmode))
-+ {
-+ rtx av = rs6000_emit_vector_compare_altivec (rcode, mask, op0, op1);
-+ if (av)
-+ return av;
-+ }
-
-- if (vec_cmp_insn == INSN_NOT_AVAILABLE)
-+ switch (rcode)
- {
-- bool swap_operands = false;
-- bool try_again = false;
-- switch (rcode)
-- {
-- case LT:
-- rcode = GT;
-- swap_operands = true;
-- try_again = true;
-- break;
-- case LTU:
-- rcode = GTU;
-- swap_operands = true;
-- try_again = true;
-- break;
-- case NE:
-- case UNLE:
-- case UNLT:
-- case UNGE:
-- case UNGT:
-- /* Invert condition and try again.
-- e.g., A != B becomes ~(A==B). */
-- {
-- enum rtx_code rev_code;
-- enum insn_code nor_code;
-- rtx eq_rtx;
--
-- rev_code = reverse_condition_maybe_unordered (rcode);
-- eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1,
-- dest_mode);
--
-- nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code;
-- gcc_assert (nor_code != CODE_FOR_nothing);
-- emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
-+ case LT:
-+ rcode = GT;
-+ swap_operands = true;
-+ try_again = true;
-+ break;
-+ case LTU:
-+ rcode = GTU;
-+ swap_operands = true;
-+ try_again = true;
-+ break;
-+ case NE:
-+ case UNLE:
-+ case UNLT:
-+ case UNGE:
-+ case UNGT:
-+ /* Invert condition and try again.
-+ e.g., A != B becomes ~(A==B). */
-+ {
-+ enum rtx_code rev_code;
-+ enum insn_code nor_code;
-+ rtx eq_rtx;
-+
-+ rev_code = reverse_condition_maybe_unordered (rcode);
-+ eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, dmode);
-+
-+ nor_code = optab_handler (one_cmpl_optab, (int)dmode)->insn_code;
-+ gcc_assert (nor_code != CODE_FOR_nothing);
-+ emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
-+ return mask;
-+ }
-+ break;
-+ case GE:
-+ case GEU:
-+ case LE:
-+ case LEU:
-+ /* Try GT/GTU/LT/LTU OR EQ */
-+ {
-+ rtx c_rtx, eq_rtx;
-+ enum insn_code ior_code;
-+ enum rtx_code new_code;
-
-- if (dmode != dest_mode)
-- {
-- rtx temp = gen_reg_rtx (dest_mode);
-- convert_move (temp, mask, 0);
-- return temp;
-- }
-- return mask;
-- }
-- break;
-- case GE:
-- case GEU:
-- case LE:
-- case LEU:
-- /* Try GT/GTU/LT/LTU OR EQ */
-+ switch (rcode)
- {
-- rtx c_rtx, eq_rtx;
-- enum insn_code ior_code;
-- enum rtx_code new_code;
--
-- switch (rcode)
-- {
-- case GE:
-- new_code = GT;
-- break;
--
-- case GEU:
-- new_code = GTU;
-- break;
-+ case GE:
-+ new_code = GT;
-+ break;
-
-- case LE:
-- new_code = LT;
-- break;
-+ case GEU:
-+ new_code = GTU;
-+ break;
-
-- case LEU:
-- new_code = LTU;
-- break;
-+ case LE:
-+ new_code = LT;
-+ break;
-
-- default:
-- gcc_unreachable ();
-- }
-+ case LEU:
-+ new_code = LTU;
-+ break;
-
-- c_rtx = rs6000_emit_vector_compare (new_code,
-- op0, op1, dest_mode);
-- eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
-- dest_mode);
--
-- ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code;
-- gcc_assert (ior_code != CODE_FOR_nothing);
-- emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
-- if (dmode != dest_mode)
-- {
-- rtx temp = gen_reg_rtx (dest_mode);
-- convert_move (temp, mask, 0);
-- return temp;
-- }
-- return mask;
-+ default:
-+ gcc_unreachable ();
- }
-- break;
-- default:
-- gcc_unreachable ();
-- }
-
-- if (try_again)
-- {
-- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
-- /* You only get two chances. */
-- gcc_assert (vec_cmp_insn != INSN_NOT_AVAILABLE);
-- }
-+ c_rtx = rs6000_emit_vector_compare (new_code,
-+ op0, op1, dmode);
-+ eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
-+ dmode);
-+
-+ ior_code = optab_handler (ior_optab, (int)dmode)->insn_code;
-+ gcc_assert (ior_code != CODE_FOR_nothing);
-+ emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
-+ return mask;
-+ }
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-
-+ if (try_again)
-+ {
- if (swap_operands)
- {
- rtx tmp;
-@@ -13485,69 +14203,23 @@ rs6000_emit_vector_compare (enum rtx_cod
- op0 = op1;
- op1 = tmp;
- }
-- }
--
-- emit_insn (gen_rtx_SET (VOIDmode, mask,
-- gen_rtx_UNSPEC (dest_mode,
-- gen_rtvec (2, op0, op1),
-- vec_cmp_insn)));
-- if (dmode != dest_mode)
-- {
-- rtx temp = gen_reg_rtx (dest_mode);
-- convert_move (temp, mask, 0);
-- return temp;
-- }
-- return mask;
--}
--
--/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
-- valid insn doesn exist for given mode. */
-
--static int
--get_vsel_insn (enum machine_mode mode)
--{
-- switch (mode)
-- {
-- case V4SImode:
-- return UNSPEC_VSEL4SI;
-- break;
-- case V4SFmode:
-- return UNSPEC_VSEL4SF;
-- break;
-- case V8HImode:
-- return UNSPEC_VSEL8HI;
-- break;
-- case V16QImode:
-- return UNSPEC_VSEL16QI;
-- break;
-- default:
-- return INSN_NOT_AVAILABLE;
-- break;
-+ if (TARGET_VSX && VSX_VECTOR_MODE (dmode))
-+ {
-+ rtx vsx = rs6000_emit_vector_compare_vsx (rcode, mask, op0, op1);
-+ if (vsx)
-+ return vsx;
-+ }
-+ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dmode))
-+ {
-+ rtx av = rs6000_emit_vector_compare_altivec (rcode, mask, op0, op1);
-+ if (av)
-+ return av;
-+ }
- }
-- return INSN_NOT_AVAILABLE;
--}
--
--/* Emit vector select insn where DEST is destination using
-- operands OP1, OP2 and MASK. */
--
--static void
--rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
--{
-- rtx t, temp;
-- enum machine_mode dest_mode = GET_MODE (dest);
-- int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
-
-- temp = gen_reg_rtx (dest_mode);
--
-- /* For each vector element, select op1 when mask is 1 otherwise
-- select op2. */
-- t = gen_rtx_SET (VOIDmode, temp,
-- gen_rtx_UNSPEC (dest_mode,
-- gen_rtvec (3, op2, op1, mask),
-- vsel_insn_index));
-- emit_insn (t);
-- emit_move_insn (dest, temp);
-- return;
-+ /* You only get two chances. */
-+ gcc_unreachable ();
- }
-
- /* Emit vector conditional expression.
-@@ -13562,15 +14234,29 @@ rs6000_emit_vector_cond_expr (rtx dest,
- enum rtx_code rcode = GET_CODE (cond);
- rtx mask;
-
-- if (!TARGET_ALTIVEC)
-+ if (!TARGET_ALTIVEC && !TARGET_VSX)
- return 0;
-
- /* Get the vector mask for the given relational operations. */
- mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
-
-- rs6000_emit_vector_select (dest, op1, op2, mask);
-+ if (!mask)
-+ return 0;
-
-- return 1;
-+ if ((TARGET_VSX && VSX_VECTOR_MOVE_MODE (dest_mode))
-+ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dest_mode)))
-+ {
-+ rtx cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx);
-+ emit_insn (gen_rtx_SET (VOIDmode,
-+ dest,
-+ gen_rtx_IF_THEN_ELSE (dest_mode,
-+ cond2,
-+ op1,
-+ op2)));
-+ return 1;
-+ }
-+
-+ return 0;
- }
-
- /* Emit a conditional move: move TRUE_COND to DEST if OP of the
-@@ -13766,8 +14452,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
- {
- rtx condition_rtx, cr;
-
-- /* All isel implementations thus far are 32-bits. */
-- if (GET_MODE (rs6000_compare_op0) != SImode)
-+ if (GET_MODE (rs6000_compare_op0) != SImode
-+ && (!TARGET_POWERPC64 || GET_MODE (rs6000_compare_op0) != DImode))
- return 0;
-
- /* We still have to do the compare, because isel doesn't do a
-@@ -13776,12 +14462,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
- condition_rtx = rs6000_generate_compare (GET_CODE (op));
- cr = XEXP (condition_rtx, 0);
-
-- if (GET_MODE (cr) == CCmode)
-- emit_insn (gen_isel_signed (dest, condition_rtx,
-- true_cond, false_cond, cr));
-+ if (GET_MODE (rs6000_compare_op0) == SImode)
-+ {
-+ if (GET_MODE (cr) == CCmode)
-+ emit_insn (gen_isel_signed_si (dest, condition_rtx,
-+ true_cond, false_cond, cr));
-+ else
-+ emit_insn (gen_isel_unsigned_si (dest, condition_rtx,
-+ true_cond, false_cond, cr));
-+ }
- else
-- emit_insn (gen_isel_unsigned (dest, condition_rtx,
-- true_cond, false_cond, cr));
-+ {
-+ if (GET_MODE (cr) == CCmode)
-+ emit_insn (gen_isel_signed_di (dest, condition_rtx,
-+ true_cond, false_cond, cr));
-+ else
-+ emit_insn (gen_isel_unsigned_di (dest, condition_rtx,
-+ true_cond, false_cond, cr));
-+ }
-
- return 1;
- }
-@@ -13808,6 +14506,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c
- enum rtx_code c;
- rtx target;
-
-+ /* VSX/altivec have direct min/max insns. */
-+ if ((code == SMAX || code == SMIN) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
-+ {
-+ emit_insn (gen_rtx_SET (VOIDmode,
-+ dest,
-+ gen_rtx_fmt_ee (code, mode, op0, op1)));
-+ return;
-+ }
-+
- if (code == SMAX || code == SMIN)
- c = GE;
- else
-@@ -15785,6 +16492,7 @@ emit_frame_save (rtx frame_reg, rtx fram
-
- /* Some cases that need register indexed addressing. */
- if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
-+ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
- || (TARGET_E500_DOUBLE && mode == DFmode)
- || (TARGET_SPE_ABI
- && SPE_VECTOR_MODE (mode)
-@@ -19320,6 +20028,7 @@ rs6000_issue_rate (void)
- case CPU_POWER4:
- case CPU_POWER5:
- case CPU_POWER6:
-+ case CPU_POWER7:
- return 5;
- default:
- return 1;
-@@ -19921,6 +20630,41 @@ insn_must_be_first_in_group (rtx insn)
- break;
- }
- break;
-+ case PROCESSOR_POWER7:
-+ type = get_attr_type (insn);
-+
-+ switch (type)
-+ {
-+ case TYPE_CR_LOGICAL:
-+ case TYPE_MFCR:
-+ case TYPE_MFCRF:
-+ case TYPE_MTCR:
-+ case TYPE_IDIV:
-+ case TYPE_LDIV:
-+ case TYPE_COMPARE:
-+ case TYPE_DELAYED_COMPARE:
-+ case TYPE_VAR_DELAYED_COMPARE:
-+ case TYPE_ISYNC:
-+ case TYPE_LOAD_L:
-+ case TYPE_STORE_C:
-+ case TYPE_LOAD_U:
-+ case TYPE_LOAD_UX:
-+ case TYPE_LOAD_EXT:
-+ case TYPE_LOAD_EXT_U:
-+ case TYPE_LOAD_EXT_UX:
-+ case TYPE_STORE_U:
-+ case TYPE_STORE_UX:
-+ case TYPE_FPLOAD_U:
-+ case TYPE_FPLOAD_UX:
-+ case TYPE_FPSTORE_U:
-+ case TYPE_FPSTORE_UX:
-+ case TYPE_MFJMPR:
-+ case TYPE_MTJMPR:
-+ return true;
-+ default:
-+ break;
-+ }
-+ break;
- default:
- break;
- }
-@@ -19982,6 +20726,23 @@ insn_must_be_last_in_group (rtx insn)
- break;
- }
- break;
-+ case PROCESSOR_POWER7:
-+ type = get_attr_type (insn);
-+
-+ switch (type)
-+ {
-+ case TYPE_ISYNC:
-+ case TYPE_SYNC:
-+ case TYPE_LOAD_L:
-+ case TYPE_STORE_C:
-+ case TYPE_LOAD_EXT_U:
-+ case TYPE_LOAD_EXT_UX:
-+ case TYPE_STORE_UX:
-+ return true;
-+ default:
-+ break;
-+ }
-+ break;
- default:
- break;
- }
-@@ -20554,8 +21315,8 @@ rs6000_handle_altivec_attribute (tree *n
- 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");
-+ else if (type == double_type_node && !TARGET_VSX)
-+ 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)
-@@ -20581,6 +21342,7 @@ rs6000_handle_altivec_attribute (tree *n
- 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. */
-@@ -22116,7 +22878,7 @@ rs6000_register_move_cost (enum machine_
- if (! reg_classes_intersect_p (to, GENERAL_REGS))
- from = to;
-
-- if (from == FLOAT_REGS || from == ALTIVEC_REGS)
-+ if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS)
- return (rs6000_memory_move_cost (mode, from, 0)
- + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
-
-@@ -22136,6 +22898,12 @@ rs6000_register_move_cost (enum machine_
- return 2 * hard_regno_nregs[0][mode];
- }
-
-+ /* If we have VSX, we can easily move between FPR or Altivec registers. */
-+ else if (TARGET_VSX
-+ && ((from == VSX_REGS || from == FLOAT_REGS || from == ALTIVEC_REGS)
-+ || (to == VSX_REGS || to == FLOAT_REGS || to == ALTIVEC_REGS)))
-+ return 2;
-+
- /* Moving between two similar registers is just one instruction. */
- else if (reg_classes_intersect_p (to, from))
- return (mode == TFmode || mode == TDmode) ? 4 : 2;
-@@ -22376,8 +23144,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src)
- emit_label (XEXP (label, 0));
- }
-
--/* Emit popcount intrinsic on TARGET_POPCNTB targets. DST is the
-- target, and SRC is the argument operand. */
-+/* Emit popcount intrinsic on TARGET_POPCNTB (Power5) and TARGET_POPCNTD
-+ (Power7) targets. DST is the target, and SRC is the argument operand. */
-
- void
- rs6000_emit_popcount (rtx dst, rtx src)
-@@ -22385,6 +23153,16 @@ rs6000_emit_popcount (rtx dst, rtx src)
- enum machine_mode mode = GET_MODE (dst);
- rtx tmp1, tmp2;
-
-+ /* Use the PPC ISA 2.06 popcnt{w,d} instruction if we can. */
-+ if (TARGET_POPCNTD)
-+ {
-+ if (mode == SImode)
-+ emit_insn (gen_popcntwsi2 (dst, src));
-+ else
-+ emit_insn (gen_popcntddi2 (dst, src));
-+ return;
-+ }
-+
- tmp1 = gen_reg_rtx (mode);
-
- if (mode == SImode)
-@@ -22797,7 +23575,7 @@ rs6000_vector_mode_supported_p (enum mac
- if (TARGET_SPE && SPE_VECTOR_MODE (mode))
- return true;
-
-- else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
-+ else if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
- return true;
-
- else
---- gcc/config/rs6000/vsx.md (.../trunk) (revision 0)
-+++ gcc/config/rs6000/vsx.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -0,0 +1,864 @@
-+;; 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 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])
-+
-+;; 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")
-+ (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")
-+ (TI "sp")])
-+
-+;; Map into the register class used
-+(define_mode_attr VSr [(V16QI "v")
-+ (V8HI "v")
-+ (V4SI "v")
-+ (V4SF "wf")
-+ (V2DI "wd")
-+ (V2DF "wd")
-+ (TI "wd")])
-+
-+;; Same size integer type for floating point data
-+(define_mode_attr VSi [(V4SF "v4si")
-+ (V2DF "v2di")])
-+
-+(define_mode_attr VSI [(V4SF "V4SI")
-+ (V2DF "V2DI")])
-+
-+;; Word size for same size conversion
-+(define_mode_attr VSc [(V4SF "w")
-+ (V2DF "d")])
-+
-+;; Bitsize for DF load with update
-+(define_mode_attr VSbit [(SI "32")
-+ (DI "64")])
-+
-+(define_constants
-+ [(UNSPEC_VSX_CONCAT_V2DF 500)])
-+
-+;; VSX moves
-+(define_insn "*vsx_mov<mode>"
-+ [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v")
-+ (match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W"))]
-+ "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 "xvmov<VSs> %x0,%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);
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+ [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,store,load,*,vecsimple,vecsimple,*")])
-+
-+;; Load/store with update
-+;; Define insns that do load or store with update. Because VSX only has
-+;; reg+reg addressing, pre-decrement or pre-inrement 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<mode>_update64"
-+ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
-+ (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
-+ (match_operand:DI 2 "gpc_reg_operand" "r,r"))))
-+ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
-+ (plus:DI (match_dup 1)
-+ (match_dup 2)))]
-+ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+ "lx<VSm>ux %x3,%0,%2"
-+ [(set_attr "type" "vecload")])
-+
-+(define_insn "*vsx_load<mode>_update32"
-+ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
-+ (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
-+ (match_operand:SI 2 "gpc_reg_operand" "r,r"))))
-+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
-+ (plus:SI (match_dup 1)
-+ (match_dup 2)))]
-+ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+ "lx<VSm>ux %x3,%0,%2"
-+ [(set_attr "type" "vecload")])
-+
-+(define_insn "*vsx_store<mode>_update64"
-+ [(set (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
-+ (match_operand:DI 2 "gpc_reg_operand" "r,r")))
-+ (match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
-+ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
-+ (plus:DI (match_dup 1)
-+ (match_dup 2)))]
-+ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+ "stx<VSm>ux %x3,%0,%1"
-+ [(set_attr "type" "vecstore")])
-+
-+(define_insn "*vsx_store<mode>_update32"
-+ [(set (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
-+ (match_operand:SI 2 "gpc_reg_operand" "r,r")))
-+ (match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
-+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
-+ (plus:SI (match_dup 1)
-+ (match_dup 2)))]
-+ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+ "stx<VSm>ux %x3,%0,%1"
-+ [(set_attr "type" "vecstore")])
-+
-+(define_insn "*vsx_loaddf_update<VSbit>"
-+ [(set (match_operand:DF 3 "vsx_register_operand" "=ws,?wa")
-+ (mem:DF (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)))]
-+ "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
-+ "lxsdux %x3,%0,%2"
-+ [(set_attr "type" "vecload")])
-+
-+(define_insn "*vsx_storedf_update<VSbit>"
-+ [(set (mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
-+ (match_operand:P 2 "gpc_reg_operand" "r,r")))
-+ (match_operand:DF 3 "gpc_reg_operand" "ws,?wa"))
-+ (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
-+ (plus:P (match_dup 1)
-+ (match_dup 2)))]
-+ "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
-+ "stxsdux %x3,%0,%1"
-+ [(set_attr "type" "vecstore")])
-+
-+;; We may need to have a varient on the pattern for use in the prologue
-+;; that doesn't depend on TARGET_UPDATE.
-+
-+\f
-+;; VSX vector floating point arithmetic instructions
-+(define_insn "*vsx_add<mode>3"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvadd<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_sub<mode>3"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvsub<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_mul<mode>3"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvmul<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_div<mode>3"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvdiv<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "vecfdiv")])
-+
-+(define_insn "*vsx_fre<mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")]
-+ UNSPEC_FRES))]
-+ "flag_finite_math_only && VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvre<VSs> %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_neg<mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvneg<VSs> %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_abs<mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvabs<VSs> %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_nabs<mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (neg:VSX_F
-+ (abs:VSX_F
-+ (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvnabs<VSs> %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_smax<mode>3"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvmax<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "veccmp")])
-+
-+(define_insn "*vsx_smin<mode>3"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvmin<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "veccmp")])
-+
-+(define_insn "*vsx_sqrt<mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvsqrt<VSs> %x0,%x1"
-+ [(set_attr "type" "vecfdiv")])
-+
-+;; Fused vector multiply/add instructions
-+(define_insn "*vsx_fmadd<mode>4"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+ (plus:VSX_F
-+ (mult:VSX_F
-+ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+ (match_operand:VSX_F 3 "gpc_reg_operand" "0,<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
-+ "@
-+ xvmadda<VSs> %x0,%x1,%x2
-+ xvmaddm<VSs> %x0,%x1,%x3"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fmsub<mode>4"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+ (minus:VSX_F
-+ (mult:VSX_F
-+ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
-+ "@
-+ xvmsuba<VSs> %x0,%x1,%x2
-+ xvmsubm<VSs> %x0,%x1,%x3"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fnmadd<mode>4_1"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+ (neg:VSX_F
-+ (plus:VSX_F
-+ (mult:VSX_F
-+ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xvnmadda<VSs> %x0,%x1,%x2
-+ xvnmaddm<VSs> %x0,%x1,%x3"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fnmadd<mode>4_2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+ (minus:VSX_F
-+ (mult:VSX_F
-+ (neg:VSX_F
-+ (match_operand:VSX_F 1 "gpc_reg_operand" "%<VSr>,<VSr>"))
-+ (match_operand:VSX_F 2 "gpc_reg_operand" "<VSr>,0"))
-+ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && !HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xvnmadda<VSs> %x0,%x1,%x2
-+ xvnmaddm<VSs> %x0,%x1,%x3"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fnmsub<mode>4_1"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+ (neg:VSX_F
-+ (minus:VSX_F
-+ (mult:VSX_F
-+ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xvnmsuba<VSs> %x0,%x1,%x2
-+ xvnmsubm<VSs> %x0,%x1,%x3"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fnmsub<mode>4_2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+ (minus:VSX_F
-+ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")
-+ (mult:VSX_F
-+ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && !HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xvnmsuba<VSs> %x0,%x1,%x2
-+ xvnmsubm<VSs> %x0,%x1,%x3"
-+ [(set_attr "type" "vecfloat")])
-+
-+;; Vector conditional expressions
-+(define_insn "*vsx_eq<mode>"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcmpeq<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "veccmp")])
-+
-+(define_insn "*vsx_gt<mode>"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcmpgt<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "veccmp")])
-+
-+(define_insn "*vsx_ge<mode>"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcmpge<VSs> %x0,%x1,%x2"
-+ [(set_attr "type" "veccmp")])
-+
-+(define_insn "vsx_vsel<mode>"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+ (const_int 0))
-+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
-+ (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_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_F 0 "vsx_register_operand" "=<VSr>")
-+ (if_then_else:VSX_F
-+ (ge:VSX_F (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
-+ (const_int 0))
-+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))
-+ (neg:VSX_F (abs:VSX_F (match_dup 1)))))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcpsgn<VSs> %x0,%x2,%x1"
-+ [(set_attr "type" "vecsimple")])
-+
-+(define_insn "*vsx_ftrunc<mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvr<VSs>piz %x0,%x1"
-+ [(set_attr "type" "vecperm")])
-+
-+(define_insn "*vsx_float<VSi><mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcvsx<VSc><VSs> %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_floatuns<VSi><mode>2"
-+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+ (unsigned_float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcvux<VSc><VSs> %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fix_trunc<mode><VSi>2"
-+ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
-+ (fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcv<VSs>sx<VSc>s %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fixuns_trunc<mode><VSi>2"
-+ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
-+ (unsigned_fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
-+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+ "xvcv<VSs>ux<VSc>s %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+\f
-+;; VSX scalar double precision floating point operations
-+(define_insn"*vsx_adddf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (plus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsadddp %x0,%x1,%x2"
-+ [(set_attr "type" "fp")
-+ (set_attr "fp_type" "fp_addsub_d")])
-+
-+(define_insn"*vsx_subdf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (minus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xssubdp %x0,%x1,%x2"
-+ [(set_attr "type" "fp")
-+ (set_attr "fp_type" "fp_addsub_d")])
-+
-+(define_insn"*vsx_muldf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (mult:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsmuldp %x0,%x1,%x2"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_mul_d")])
-+
-+(define_insn"*vsx_divdf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (div:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsdivdp %x0,%x1,%x2"
-+ [(set_attr "type" "ddiv")])
-+
-+(define_insn "*vsx_fredf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+ UNSPEC_FRES))]
-+ "flag_finite_math_only && VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsredp %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_sqrtdf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (sqrt:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xssqrtdp %x0,%x1"
-+ [(set_attr "type" "dsqrt")])
-+
-+(define_insn"*vsx_negdf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (neg:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsnegdp %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn"vsx_absdf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsabsdp %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn"*vsx_nabsdf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (neg:DF (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsnabsdp %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_smaxdf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (smax:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsmaxdp %x0,%x1,%x2"
-+ [(set_attr "type" "fp")])
-+
-+
-+(define_insn "*vsx_smindf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (smin:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsmindp %x0,%x1,%x2"
-+ [(set_attr "type" "fp")])
-+
-+;; Fused vector multiply/add instructions
-+(define_insn "*vsx_fmadddf4"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+ (match_operand:DF 3 "gpc_reg_operand" "0,ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
-+ "@
-+ xsmaddadp %x0,%x1,%x2
-+ xsmaddmdp %x0,%x1,%x3"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fmsubdf4"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+ (minus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+ (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
-+ "@
-+ xsmsubadp %x0,%x1,%x2
-+ xsmsubmdp %x0,%x1,%x3"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmadddf4_1"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+ (neg:DF
-+ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xsnmaddadp %x0,%x1,%x2
-+ xsnmaddmdp %x0,%x1,%x3"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmadddf4_2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+ (minus:DF (mult:DF (neg:DF
-+ (match_operand:DF 1 "gpc_reg_operand" "%ws,ws"))
-+ (match_operand:DF 2 "gpc_reg_operand" "ws,0"))
-+ (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && !HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xsnmaddadp %x0,%x1,%x2
-+ xsnmaddmdp %x0,%x1,%x3"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmsubdf4_1"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+ (neg:DF
-+ (minus:DF
-+ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xsnmsubadp %x0,%x1,%x2
-+ xsnmsubmdp %x0,%x1,%x3"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmsubdf4_2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+ (minus:DF
-+ (match_operand:DF 3 "vsx_register_operand" "0,ws")
-+ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+ (match_operand:DF 2 "vsx_register_operand" "ws,0"))))]
-+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+ && !HONOR_SIGNED_ZEROS (DFmode)"
-+ "@
-+ xsnmsubadp %x0,%x1,%x2
-+ xsnmsubmdp %x0,%x1,%x3"
-+ [(set_attr "type" "dmul")
-+ (set_attr "fp_type" "fp_maddsub_d")])
-+
-+;; For the conversions, limit the register class for the integer value to be
-+;; the fprs. 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_floatdidf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xscvsxddp %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_floatunsdidf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (unsigned_float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
-+ "TARGET_HARD_FLOAT && TARGET_VSX"
-+ "xscvuxddp %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_fix_truncdfdi2"
-+ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
-+ (fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xscvdpsxds %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_fixuns_truncdfdi2"
-+ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
-+ (unsigned_fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+ "TARGET_HARD_FLOAT && TARGET_VSX"
-+ "xscvdpuxds %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_btruncdf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+ UNSPEC_FRIZ))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsrdpiz %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_floordf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+ UNSPEC_FRIM))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsrdpim %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_ceildf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+ UNSPEC_FRIP))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsrdpip %x0,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "vsx_copysigndf3"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (if_then_else:DF (ge:DF (match_operand:DF 2 "vsx_register_operand" "ws")
-+ (const_int 0))
-+ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))
-+ (neg:DF (abs:DF (match_dup 1)))))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xscpsgndp %x0,%x2,%x1"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_ftruncdf2"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (fix:DF (match_operand:DF 1 "register_operand" "ws")))]
-+ "VECTOR_UNIT_VSX_P (DFmode)"
-+ "xsrdppiz %x0,%x1"
-+ [(set_attr "type" "vecfloat")])
-+
-+\f
-+;; 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")])
-+
-+\f
-+;; Permute operations
-+
-+(define_insn "vsx_concat_v2df"
-+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
-+ (unspec:V2DF
-+ [(match_operand:DF 1 "vsx_register_operand" "f,wa")
-+ (match_operand:DF 2 "vsx_register_operand" "f,wa")]
-+ UNSPEC_VSX_CONCAT_V2DF))]
-+ "VECTOR_UNIT_VSX_P (V2DFmode)"
-+ "xxpermdi %x0,%x1,%x2,0"
-+ [(set_attr "type" "vecperm")])
-+
-+;; Set a double into one element
-+(define_insn "vsx_set_v2df"
-+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
-+ (vec_merge:V2DF
-+ (match_operand:V2DF 1 "vsx_register_operand" "wd")
-+ (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws"))
-+ (match_operand:QI 3 "u5bit_cint_operand" "i")))]
-+ "VECTOR_UNIT_VSX_P (V2DFmode)"
-+{
-+ operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
-+ return \"xxpermdi %x0,%x1,%x2,%3\";
-+}
-+ [(set_attr "type" "vecperm")])
-+
-+;; Extract a DF element from V2DF
-+(define_insn "vsx_extract_v2df"
-+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
-+ (parallel
-+ [(match_operand:QI 2 "u5bit_cint_operand" "i")])))]
-+ "VECTOR_UNIT_VSX_P (V2DFmode)"
-+{
-+ operands[3] = GEN_INT (INTVAL (operands[2]) & 1);
-+ return \"xxpermdi %x0,%x1,%x1,%3\";
-+}
-+ [(set_attr "type" "vecperm")])
-+
-+;; General V2DF permute
-+(define_insn "vsx_xxpermdi"
-+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
-+ (vec_concat:V2DF
-+ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
-+ (parallel
-+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
-+ (vec_select:DF (match_operand:V2DF 3 "vsx_register_operand" "wd")
-+ (parallel
-+ [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
-+ "VECTOR_UNIT_VSX_P (V2DFmode)"
-+{
-+ operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
-+ | (INTVAL (operands[4]) & 1));
-+ return \"xxpermdi %x0,%x1,%x3,%5\";
-+}
-+ [(set_attr "type" "vecperm")])
-+
-+;; V2DF splat
-+(define_insn "vsx_splatv2df"
-+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd")
-+ (vec_duplicate:V2DF
-+ (match_operand:DF 1 "input_operand" "ws,Z")))]
-+ "VECTOR_UNIT_VSX_P (V2DFmode)"
-+ "@
-+ xxpermdi %x0,%x1,%x1,0
-+ lxvdsx %x0,%y1"
-+ [(set_attr "type" "vecperm,vecload")])
-+
-+;; V4SF splat
-+(define_insn "*vsx_xxspltw"
-+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf")
-+ (vec_duplicate:V4SF
-+ (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf")
-+ (parallel
-+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
-+ "VECTOR_UNIT_VSX_P (V4SFmode)"
-+ "xxspltw %x0,%x1,%2"
-+ [(set_attr "type" "vecperm")])
-+
-+;; V4SF interleave
-+(define_insn "*vsx_xxmrghw"
-+ [(set (match_operand:V4SF 0 "register_operand" "=v")
-+ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+ (parallel [(const_int 0)
-+ (const_int 2)
-+ (const_int 1)
-+ (const_int 3)]))
-+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-+ (parallel [(const_int 2)
-+ (const_int 0)
-+ (const_int 3)
-+ (const_int 1)]))
-+ (const_int 5)))]
-+ "VECTOR_UNIT_VSX_P (V4SFmode)"
-+ "xxmrghw %x0,%x1,%x2"
-+ [(set_attr "type" "vecperm")])
-+
-+(define_insn "*vsx_xxmrglw"
-+ [(set (match_operand:V4SF 0 "register_operand" "=v")
-+ (vec_merge:V4SF
-+ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+ (parallel [(const_int 2)
-+ (const_int 0)
-+ (const_int 3)
-+ (const_int 1)]))
-+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-+ (parallel [(const_int 0)
-+ (const_int 2)
-+ (const_int 1)
-+ (const_int 3)]))
-+ (const_int 5)))]
-+ "VECTOR_UNIT_VSX_P (V4SFmode)"
-+ "xxmrglw %x0,%x1,%x2"
-+ [(set_attr "type" "vecperm")])
---- gcc/config/rs6000/rs6000.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/rs6000.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -1,6 +1,6 @@
- /* Definitions of target machine for GNU compiler, for IBM RS/6000.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
- Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
-
-@@ -72,14 +72,16 @@
- #define ASM_CPU_POWER6_SPEC "-mpower4 -maltivec"
- #endif
-
--#ifdef HAVE_AS_VSX
-+#ifdef HAVE_AS_POPCNTD
- #define ASM_CPU_POWER7_SPEC "-mpower7"
- #else
- #define ASM_CPU_POWER7_SPEC "-mpower4 -maltivec"
- #endif
-
--/* Common ASM definitions used by ASM_SPEC among the various targets
-- for handling -mcpu=xxx switches. */
-+/* Common ASM definitions used by ASM_SPEC among the various targets for
-+ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
-+ provide the default assembler options if the user uses -mcpu=native, so if
-+ you make changes here, make them also there. */
- #define ASM_CPU_SPEC \
- "%{!mcpu*: \
- %{mpower: %{!mpower2: -mpwr}} \
-@@ -88,6 +90,7 @@
- %{!mpowerpc64*: %{mpowerpc*: -mppc}} \
- %{mno-power: %{!mpowerpc*: -mcom}} \
- %{!mno-power: %{!mpower*: %(asm_default)}}} \
-+%{mcpu=native: %(asm_cpu_native)} \
- %{mcpu=common: -mcom} \
- %{mcpu=cell: -mcell} \
- %{mcpu=power: -mpwr} \
-@@ -163,6 +166,7 @@
- #define EXTRA_SPECS \
- { "cpp_default", CPP_DEFAULT_SPEC }, \
- { "asm_cpu", ASM_CPU_SPEC }, \
-+ { "asm_cpu_native", ASM_CPU_NATIVE_SPEC }, \
- { "asm_default", ASM_DEFAULT_SPEC }, \
- { "cc1_cpu", CC1_CPU_SPEC }, \
- { "asm_cpu_power5", ASM_CPU_POWER5_SPEC }, \
-@@ -179,6 +183,10 @@ extern const char *host_detect_local_cpu
- #define EXTRA_SPEC_FUNCTIONS \
- { "local_cpu_detect", host_detect_local_cpu },
- #define HAVE_LOCAL_CPU_DETECT
-+#define ASM_CPU_NATIVE_SPEC "%:local_cpu_detect(asm)"
-+
-+#else
-+#define ASM_CPU_NATIVE_SPEC "%(asm_default)"
- #endif
-
- #ifndef CC1_CPU_SPEC
-@@ -240,6 +248,14 @@ extern const char *host_detect_local_cpu
- #define TARGET_DFP 0
- #endif
-
-+/* Define TARGET_POPCNTD if the target assembler does not support the
-+ popcount word and double word instructions. */
-+
-+#ifndef HAVE_AS_POPCNTD
-+#undef TARGET_POPCNTD
-+#define TARGET_POPCNTD 0
-+#endif
-+
- #ifndef TARGET_SECURE_PLT
- #define TARGET_SECURE_PLT 0
- #endif
-@@ -295,6 +311,7 @@ enum processor_type
- PROCESSOR_POWER4,
- PROCESSOR_POWER5,
- PROCESSOR_POWER6,
-+ PROCESSOR_POWER7,
- PROCESSOR_CELL
- };
-
-@@ -388,9 +405,13 @@ extern struct rs6000_cpu_select rs6000_s
- extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
- extern int rs6000_debug_stack; /* debug stack applications */
- extern int rs6000_debug_arg; /* debug argument handling */
-+extern int rs6000_debug_reg; /* debug register handling */
-+extern int rs6000_debug_addr; /* debug memory addressing */
-
- #define TARGET_DEBUG_STACK rs6000_debug_stack
- #define TARGET_DEBUG_ARG rs6000_debug_arg
-+#define TARGET_DEBUG_REG rs6000_debug_reg
-+#define TARGET_DEBUG_ADDR rs6000_debug_addr
-
- extern const char *rs6000_traceback_name; /* Type of traceback table. */
-
-@@ -401,13 +422,65 @@ extern int rs6000_ieeequad;
- extern int rs6000_altivec_abi;
- extern int rs6000_spe_abi;
- extern int rs6000_spe;
--extern int rs6000_isel;
- extern int rs6000_float_gprs;
- extern int rs6000_alignment_flags;
- extern const char *rs6000_sched_insert_nops_str;
- extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
- extern int rs6000_xilinx_fpu;
-
-+/* Describe which vector unit to use for a given machine mode. */
-+enum rs6000_vector {
-+ VECTOR_NONE, /* Type is not a vector or not supported */
-+ VECTOR_ALTIVEC, /* Use altivec for vector processing */
-+ VECTOR_VSX, /* Use VSX for vector processing */
-+ VECTOR_PAIRED, /* Use paired floating point for vectors */
-+ VECTOR_SPE, /* Use SPE for vector processing */
-+ VECTOR_OTHER /* Some other vector unit */
-+};
-+
-+extern enum rs6000_vector rs6000_vector_unit[];
-+
-+#define VECTOR_UNIT_NONE_P(MODE) \
-+ (rs6000_vector_unit[(MODE)] == VECTOR_NONE)
-+
-+#define VECTOR_UNIT_VSX_P(MODE) \
-+ (rs6000_vector_unit[(MODE)] == VECTOR_VSX)
-+
-+#define VECTOR_UNIT_ALTIVEC_P(MODE) \
-+ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC)
-+
-+#define VECTOR_UNIT_ALTIVEC_OR_VSX_P(MODE) \
-+ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC \
-+ || rs6000_vector_unit[(MODE)] == VECTOR_VSX)
-+
-+/* Describe whether to use VSX loads or Altivec loads. For now, just use the
-+ same unit as the vector unit we are using, but we may want to migrate to
-+ using VSX style loads even for types handled by altivec. */
-+extern enum rs6000_vector rs6000_vector_mem[];
-+
-+#define VECTOR_MEM_NONE_P(MODE) \
-+ (rs6000_vector_mem[(MODE)] == VECTOR_NONE)
-+
-+#define VECTOR_MEM_VSX_P(MODE) \
-+ (rs6000_vector_mem[(MODE)] == VECTOR_VSX)
-+
-+#define VECTOR_MEM_ALTIVEC_P(MODE) \
-+ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC)
-+
-+#define VECTOR_MEM_ALTIVEC_OR_VSX_P(MODE) \
-+ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC \
-+ || rs6000_vector_mem[(MODE)] == VECTOR_VSX)
-+
-+/* Return the alignment of a given vector type, which is set based on the
-+ vector unit use. VSX for instance can load 32 or 64 bit aligned words
-+ without problems, while Altivec requires 128-bit aligned vectors. */
-+extern int rs6000_vector_align[];
-+
-+#define VECTOR_ALIGN(MODE) \
-+ ((rs6000_vector_align[(MODE)] != 0) \
-+ ? rs6000_vector_align[(MODE)] \
-+ : (int)GET_MODE_BITSIZE ((MODE)))
-+
- /* Alignment options for fields in structures for sub-targets following
- AIX-like ABI.
- ALIGN_POWER word-aligns FP doubles (default AIX ABI).
-@@ -432,7 +505,7 @@ extern int rs6000_xilinx_fpu;
- #define TARGET_SPE_ABI 0
- #define TARGET_SPE 0
- #define TARGET_E500 0
--#define TARGET_ISEL rs6000_isel
-+#define TARGET_ISEL64 (TARGET_ISEL && TARGET_POWERPC64)
- #define TARGET_FPRS 1
- #define TARGET_E500_SINGLE 0
- #define TARGET_E500_DOUBLE 0
-@@ -530,6 +603,7 @@ extern int rs6000_xilinx_fpu;
- #endif
- #define UNITS_PER_FP_WORD 8
- #define UNITS_PER_ALTIVEC_WORD 16
-+#define UNITS_PER_VSX_WORD 16
- #define UNITS_PER_SPE_WORD 8
- #define UNITS_PER_PAIRED_WORD 8
-
-@@ -600,8 +674,9 @@ extern int rs6000_xilinx_fpu;
- #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
-
- /* Boundary (in *bits*) on which stack pointer should be aligned. */
--#define STACK_BOUNDARY \
-- ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI) ? 64 : 128)
-+#define STACK_BOUNDARY \
-+ ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI && !TARGET_VSX) \
-+ ? 64 : 128)
-
- /* Allocation boundary (in *bits*) for the code of a function. */
- #define FUNCTION_BOUNDARY 32
-@@ -613,10 +688,11 @@ extern int rs6000_xilinx_fpu;
- local store. TYPE is the data type, and ALIGN is the alignment
- that the object would ordinarily have. */
- #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
-- ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
-+ (((TARGET_ALTIVEC || TARGET_VSX) \
-+ && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
- (TARGET_E500_DOUBLE \
-- && TYPE_MODE (TYPE) == DFmode) ? 64 : \
-- ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
-+ && TYPE_MODE (TYPE) == DFmode) ? 64 : \
-+ ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
- && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
- && TREE_CODE (TYPE) == VECTOR_TYPE \
- && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN)
-@@ -674,15 +750,17 @@ extern int rs6000_xilinx_fpu;
- /* Define this macro to be the value 1 if unaligned accesses have a cost
- many times greater than aligned accesses, for example if they are
- emulated in a trap handler. */
--/* Altivec vector memory instructions simply ignore the low bits; SPE
-- vector memory instructions trap on unaligned accesses. */
-+/* Altivec vector memory instructions simply ignore the low bits; SPE vector
-+ memory instructions trap on unaligned accesses; VSX memory instructions are
-+ aligned to 4 or 8 bytes. */
- #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \
- (STRICT_ALIGNMENT \
- || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \
- || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode \
- || (MODE) == DImode) \
- && (ALIGN) < 32) \
-- || (VECTOR_MODE_P ((MODE)) && (ALIGN) < GET_MODE_BITSIZE ((MODE))))
-+ || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))
-+
- \f
- /* Standard register usage. */
-
-@@ -909,16 +987,60 @@ extern int rs6000_xilinx_fpu;
- /* True if register is an AltiVec register. */
- #define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO)
-
-+/* True if register is a VSX register. */
-+#define VSX_REGNO_P(N) (FP_REGNO_P (N) || ALTIVEC_REGNO_P (N))
-+
-+/* Alternate name for any vector register supporting floating point, no matter
-+ which instruction set(s) are available. */
-+#define VFLOAT_REGNO_P(N) \
-+ (ALTIVEC_REGNO_P (N) || (TARGET_VSX && FP_REGNO_P (N)))
-+
-+/* Alternate name for any vector register supporting integer, no matter which
-+ instruction set(s) are available. */
-+#define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N)
-+
-+/* Alternate name for any vector register supporting logical operations, no
-+ matter which instruction set(s) are available. */
-+#define VLOGICAL_REGNO_P(N) VFLOAT_REGNO_P (N)
-+
- /* Return number of consecutive hard regs needed starting at reg REGNO
- to hold something of mode MODE. */
-
--#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs ((REGNO), (MODE))
-+#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)]
-
- #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
- ((TARGET_32BIT && TARGET_POWERPC64 \
- && (GET_MODE_SIZE (MODE) > 4) \
- && INT_REGNO_P (REGNO)) ? 1 : 0)
-
-+#define VSX_VECTOR_MODE(MODE) \
-+ ((MODE) == V4SFmode \
-+ || (MODE) == V2DFmode) \
-+
-+#define VSX_VECTOR_MOVE_MODE(MODE) \
-+ ((MODE) == V16QImode \
-+ || (MODE) == V8HImode \
-+ || (MODE) == V4SImode \
-+ || (MODE) == V2DImode \
-+ || (MODE) == V4SFmode \
-+ || (MODE) == V2DFmode) \
-+
-+#define VSX_SCALAR_MODE(MODE) \
-+ ((MODE) == DFmode)
-+
-+#define VSX_MODE(MODE) \
-+ (VSX_VECTOR_MODE (MODE) \
-+ || VSX_SCALAR_MODE (MODE))
-+
-+#define VSX_MOVE_MODE(MODE) \
-+ (VSX_VECTOR_MOVE_MODE (MODE) \
-+ || VSX_SCALAR_MODE(MODE) \
-+ || (MODE) == V16QImode \
-+ || (MODE) == V8HImode \
-+ || (MODE) == V4SImode \
-+ || (MODE) == V2DImode \
-+ || (MODE) == TImode)
-+
- #define ALTIVEC_VECTOR_MODE(MODE) \
- ((MODE) == V16QImode \
- || (MODE) == V8HImode \
-@@ -934,10 +1056,12 @@ extern int rs6000_xilinx_fpu;
- #define PAIRED_VECTOR_MODE(MODE) \
- ((MODE) == V2SFmode)
-
--#define UNITS_PER_SIMD_WORD(MODE) \
-- (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
-- : (TARGET_SPE ? UNITS_PER_SPE_WORD : (TARGET_PAIRED_FLOAT ? \
-- UNITS_PER_PAIRED_WORD : UNITS_PER_WORD)))
-+#define UNITS_PER_SIMD_WORD(MODE) \
-+ (TARGET_VSX ? UNITS_PER_VSX_WORD \
-+ : (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
-+ : (TARGET_SPE ? UNITS_PER_SPE_WORD \
-+ : (TARGET_PAIRED_FLOAT ? UNITS_PER_PAIRED_WORD \
-+ : UNITS_PER_WORD))))
-
- /* Value is TRUE if hard register REGNO can hold a value of
- machine-mode MODE. */
-@@ -965,6 +1089,10 @@ extern int rs6000_xilinx_fpu;
- ? ALTIVEC_VECTOR_MODE (MODE2) \
- : ALTIVEC_VECTOR_MODE (MODE2) \
- ? ALTIVEC_VECTOR_MODE (MODE1) \
-+ : VSX_VECTOR_MODE (MODE1) \
-+ ? VSX_VECTOR_MODE (MODE2) \
-+ : VSX_VECTOR_MODE (MODE2) \
-+ ? VSX_VECTOR_MODE (MODE1) \
- : 1)
-
- /* Post-reload, we can't use any new AltiVec registers, as we already
-@@ -1056,9 +1184,10 @@ extern int rs6000_xilinx_fpu;
- For any two classes, it is very desirable that there be another
- class that represents their union. */
-
--/* The RS/6000 has three types of registers, fixed-point, floating-point,
-- and condition registers, plus three special registers, MQ, CTR, and the
-- link register. AltiVec adds a vector register class.
-+/* The RS/6000 has three types of registers, fixed-point, floating-point, and
-+ condition registers, plus three special registers, MQ, CTR, and the link
-+ register. AltiVec adds a vector register class. VSX registers overlap the
-+ FPR registers and the Altivec registers.
-
- However, r0 is special in that it cannot be used as a base register.
- So make a class for registers valid as base registers.
-@@ -1073,6 +1202,7 @@ enum reg_class
- GENERAL_REGS,
- FLOAT_REGS,
- ALTIVEC_REGS,
-+ VSX_REGS,
- VRSAVE_REGS,
- VSCR_REGS,
- SPE_ACC_REGS,
-@@ -1103,6 +1233,7 @@ enum reg_class
- "GENERAL_REGS", \
- "FLOAT_REGS", \
- "ALTIVEC_REGS", \
-+ "VSX_REGS", \
- "VRSAVE_REGS", \
- "VSCR_REGS", \
- "SPE_ACC_REGS", \
-@@ -1132,6 +1263,7 @@ enum reg_class
- { 0xffffffff, 0x00000000, 0x00000008, 0x00020000 }, /* GENERAL_REGS */ \
- { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */ \
- { 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */ \
-+ { 0x00000000, 0xffffffff, 0xffffe000, 0x00001fff }, /* VSX_REGS */ \
- { 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */ \
- { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \
- { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \
-@@ -1179,8 +1311,8 @@ enum reg_class
- : (REGNO) == CR0_REGNO ? CR0_REGS \
- : CR_REGNO_P (REGNO) ? CR_REGS \
- : (REGNO) == MQ_REGNO ? MQ_REGS \
-- : (REGNO) == LR_REGNO ? LINK_REGS \
-- : (REGNO) == CTR_REGNO ? CTR_REGS \
-+ : (REGNO) == LR_REGNO ? LINK_REGS \
-+ : (REGNO) == CTR_REGNO ? CTR_REGS \
- : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \
- : (REGNO) == XER_REGNO ? XER_REGS \
- : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \
-@@ -1190,10 +1322,18 @@ enum reg_class
- : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \
- : NO_REGS)
-
-+/* VSX register classes. */
-+extern enum reg_class rs6000_vector_reg_class[];
-+extern enum reg_class rs6000_vsx_reg_class;
-+
- /* The class value for index registers, and the one for base regs. */
- #define INDEX_REG_CLASS GENERAL_REGS
- #define BASE_REG_CLASS BASE_REGS
-
-+/* Return whether a given register class can hold VSX objects. */
-+#define VSX_REG_CLASS_P(CLASS) \
-+ ((CLASS) == VSX_REGS || (CLASS) == FLOAT_REGS || (CLASS) == ALTIVEC_REGS)
-+
- /* Given an rtx X being reloaded into a reg required to be
- in class CLASS, return the class of reg to actually use.
- In general this is just CLASS; but on some machines
-@@ -1213,13 +1353,7 @@ enum reg_class
- */
-
- #define PREFERRED_RELOAD_CLASS(X,CLASS) \
-- ((CONSTANT_P (X) \
-- && reg_classes_intersect_p ((CLASS), FLOAT_REGS)) \
-- ? NO_REGS \
-- : (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
-- && (CLASS) == NON_SPECIAL_REGS) \
-- ? GENERAL_REGS \
-- : (CLASS))
-+ rs6000_preferred_reload_class (X, CLASS)
-
- /* Return the register class of a scratch register needed to copy IN into
- or out of a register in CLASS in MODE. If it can be done directly,
-@@ -1234,18 +1368,7 @@ enum reg_class
- are available.*/
-
- #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
-- ((CLASS1) != (CLASS2) && (((CLASS1) == FLOAT_REGS \
-- && (!TARGET_MFPGPR || !TARGET_POWERPC64 \
-- || ((MODE != DFmode) \
-- && (MODE != DDmode) \
-- && (MODE != DImode)))) \
-- || ((CLASS2) == FLOAT_REGS \
-- && (!TARGET_MFPGPR || !TARGET_POWERPC64 \
-- || ((MODE != DFmode) \
-- && (MODE != DDmode) \
-- && (MODE != DImode)))) \
-- || (CLASS1) == ALTIVEC_REGS \
-- || (CLASS2) == ALTIVEC_REGS))
-+ rs6000_secondary_memory_needed (CLASS1, CLASS2, MODE)
-
- /* For cpus that cannot load/store SDmode values from the 64-bit
- FP registers without using a full 64-bit load/store, we need
-@@ -1257,32 +1380,15 @@ enum reg_class
- /* Return the maximum number of consecutive registers
- needed to represent mode MODE in a register of class CLASS.
-
-- On RS/6000, this is the size of MODE in words,
-- except in the FP regs, where a single reg is enough for two words. */
--#define CLASS_MAX_NREGS(CLASS, MODE) \
-- (((CLASS) == FLOAT_REGS) \
-- ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
-- : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS \
-- && (MODE) == DFmode) \
-- ? 1 \
-- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-+ On RS/6000, this is the size of MODE in words, except in the FP regs, where
-+ a single reg is enough for two words, unless we have VSX, where the FP
-+ registers can hold 128 bits. */
-+#define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
-
- /* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
-
- #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
-- ? ((GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8 \
-- || TARGET_IEEEQUAD) \
-- && reg_classes_intersect_p (FLOAT_REGS, CLASS)) \
-- : (((TARGET_E500_DOUBLE \
-- && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \
-- || (((TO) == TFmode) + ((FROM) == TFmode)) == 1 \
-- || (((TO) == DDmode) + ((FROM) == DDmode)) == 1 \
-- || (((TO) == TDmode) + ((FROM) == TDmode)) == 1 \
-- || (((TO) == DImode) + ((FROM) == DImode)) == 1)) \
-- || (TARGET_SPE \
-- && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \
-- && reg_classes_intersect_p (GENERAL_REGS, CLASS)))
-+ rs6000_cannot_change_mode_class (FROM, TO, CLASS)
-
- /* Stack layout; function entry, exit and calling. */
-
-@@ -1343,8 +1449,8 @@ extern enum rs6000_abi rs6000_current_ab
- #define STARTING_FRAME_OFFSET \
- (FRAME_GROWS_DOWNWARD \
- ? 0 \
-- : (RS6000_ALIGN (crtl->outgoing_args_size, \
-- TARGET_ALTIVEC ? 16 : 8) \
-+ : (RS6000_ALIGN (crtl->outgoing_args_size, \
-+ (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \
- + RS6000_SAVE_AREA))
-
- /* Offset from the stack pointer register to an item dynamically
-@@ -1354,8 +1460,8 @@ extern enum rs6000_abi rs6000_current_ab
- length of the outgoing arguments. The default is correct for most
- machines. See `function.c' for details. */
- #define STACK_DYNAMIC_OFFSET(FUNDECL) \
-- (RS6000_ALIGN (crtl->outgoing_args_size, \
-- TARGET_ALTIVEC ? 16 : 8) \
-+ (RS6000_ALIGN (crtl->outgoing_args_size, \
-+ (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \
- + (STACK_POINTER_OFFSET))
-
- /* If we generate an insn to push BYTES bytes,
-@@ -1605,7 +1711,7 @@ typedef struct rs6000_args
- #define EPILOGUE_USES(REGNO) \
- ((reload_completed && (REGNO) == LR_REGNO) \
- || (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO) \
-- || (crtl->calls_eh_return \
-+ || (crtl->calls_eh_return \
- && TARGET_AIX \
- && (REGNO) == 2))
-
-@@ -2316,7 +2422,24 @@ extern char rs6000_reg_names[][8]; /* re
- /* no additional names for: mq, lr, ctr, ap */ \
- {"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \
- {"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \
-- {"cc", 68}, {"sp", 1}, {"toc", 2} }
-+ {"cc", 68}, {"sp", 1}, {"toc", 2}, \
-+ /* VSX registers overlaid on top of FR, Altivec registers */ \
-+ {"vs0", 32}, {"vs1", 33}, {"vs2", 34}, {"vs3", 35}, \
-+ {"vs4", 36}, {"vs5", 37}, {"vs6", 38}, {"vs7", 39}, \
-+ {"vs8", 40}, {"vs9", 41}, {"vs10", 42}, {"vs11", 43}, \
-+ {"vs12", 44}, {"vs13", 45}, {"vs14", 46}, {"vs15", 47}, \
-+ {"vs16", 48}, {"vs17", 49}, {"vs18", 50}, {"vs19", 51}, \
-+ {"vs20", 52}, {"vs21", 53}, {"vs22", 54}, {"vs23", 55}, \
-+ {"vs24", 56}, {"vs25", 57}, {"vs26", 58}, {"vs27", 59}, \
-+ {"vs28", 60}, {"vs29", 61}, {"vs30", 62}, {"vs31", 63}, \
-+ {"vs32", 77}, {"vs33", 78}, {"vs34", 79}, {"vs35", 80}, \
-+ {"vs36", 81}, {"vs37", 82}, {"vs38", 83}, {"vs39", 84}, \
-+ {"vs40", 85}, {"vs41", 86}, {"vs42", 87}, {"vs43", 88}, \
-+ {"vs44", 89}, {"vs45", 90}, {"vs46", 91}, {"vs47", 92}, \
-+ {"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96}, \
-+ {"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100}, \
-+ {"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104}, \
-+ {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} }
-
- /* Text to write out after a CALL that may be replaced by glue code by
- the loader. This depends on the AIX version. */
-@@ -2480,10 +2603,14 @@ enum rs6000_builtins
- ALTIVEC_BUILTIN_VSEL_4SF,
- ALTIVEC_BUILTIN_VSEL_8HI,
- ALTIVEC_BUILTIN_VSEL_16QI,
-+ ALTIVEC_BUILTIN_VSEL_2DF, /* needed for VSX */
-+ ALTIVEC_BUILTIN_VSEL_2DI, /* needed for VSX */
- ALTIVEC_BUILTIN_VPERM_4SI,
- ALTIVEC_BUILTIN_VPERM_4SF,
- ALTIVEC_BUILTIN_VPERM_8HI,
- ALTIVEC_BUILTIN_VPERM_16QI,
-+ ALTIVEC_BUILTIN_VPERM_2DF, /* needed for VSX */
-+ ALTIVEC_BUILTIN_VPERM_2DI, /* needed for VSX */
- ALTIVEC_BUILTIN_VPKUHUM,
- ALTIVEC_BUILTIN_VPKUWUM,
- ALTIVEC_BUILTIN_VPKPX,
-@@ -3110,6 +3237,163 @@ enum rs6000_builtins
- RS6000_BUILTIN_RECIPF,
- RS6000_BUILTIN_RSQRTF,
-
-+ /* VSX builtins. */
-+ VSX_BUILTIN_LXSDUX,
-+ VSX_BUILTIN_LXSDX,
-+ VSX_BUILTIN_LXVD2UX,
-+ VSX_BUILTIN_LXVD2X,
-+ VSX_BUILTIN_LXVDSX,
-+ VSX_BUILTIN_LXVW4UX,
-+ VSX_BUILTIN_LXVW4X,
-+ VSX_BUILTIN_STXSDUX,
-+ VSX_BUILTIN_STXSDX,
-+ VSX_BUILTIN_STXVD2UX,
-+ VSX_BUILTIN_STXVD2X,
-+ VSX_BUILTIN_STXVW4UX,
-+ VSX_BUILTIN_STXVW4X,
-+ VSX_BUILTIN_XSABSDP,
-+ VSX_BUILTIN_XSADDDP,
-+ VSX_BUILTIN_XSCMPODP,
-+ VSX_BUILTIN_XSCMPUDP,
-+ VSX_BUILTIN_XSCPSGNDP,
-+ VSX_BUILTIN_XSCVDPSP,
-+ VSX_BUILTIN_XSCVDPSXDS,
-+ VSX_BUILTIN_XSCVDPSXWS,
-+ VSX_BUILTIN_XSCVDPUXDS,
-+ VSX_BUILTIN_XSCVDPUXWS,
-+ VSX_BUILTIN_XSCVSPDP,
-+ VSX_BUILTIN_XSCVSXDDP,
-+ VSX_BUILTIN_XSCVUXDDP,
-+ VSX_BUILTIN_XSDIVDP,
-+ VSX_BUILTIN_XSMADDADP,
-+ VSX_BUILTIN_XSMADDMDP,
-+ VSX_BUILTIN_XSMAXDP,
-+ VSX_BUILTIN_XSMINDP,
-+ VSX_BUILTIN_XSMOVDP,
-+ VSX_BUILTIN_XSMSUBADP,
-+ VSX_BUILTIN_XSMSUBMDP,
-+ VSX_BUILTIN_XSMULDP,
-+ VSX_BUILTIN_XSNABSDP,
-+ VSX_BUILTIN_XSNEGDP,
-+ VSX_BUILTIN_XSNMADDADP,
-+ VSX_BUILTIN_XSNMADDMDP,
-+ VSX_BUILTIN_XSNMSUBADP,
-+ VSX_BUILTIN_XSNMSUBMDP,
-+ VSX_BUILTIN_XSRDPI,
-+ VSX_BUILTIN_XSRDPIC,
-+ VSX_BUILTIN_XSRDPIM,
-+ VSX_BUILTIN_XSRDPIP,
-+ VSX_BUILTIN_XSRDPIZ,
-+ VSX_BUILTIN_XSREDP,
-+ VSX_BUILTIN_XSRSQRTEDP,
-+ VSX_BUILTIN_XSSQRTDP,
-+ VSX_BUILTIN_XSSUBDP,
-+ VSX_BUILTIN_XSTDIVDP,
-+ VSX_BUILTIN_XSTSQRTDP,
-+ VSX_BUILTIN_XVABSDP,
-+ VSX_BUILTIN_XVABSSP,
-+ VSX_BUILTIN_XVADDDP,
-+ VSX_BUILTIN_XVADDSP,
-+ VSX_BUILTIN_XVCMPEQDP,
-+ VSX_BUILTIN_XVCMPEQSP,
-+ VSX_BUILTIN_XVCMPGEDP,
-+ VSX_BUILTIN_XVCMPGESP,
-+ VSX_BUILTIN_XVCMPGTDP,
-+ VSX_BUILTIN_XVCMPGTSP,
-+ VSX_BUILTIN_XVCPSGNDP,
-+ VSX_BUILTIN_XVCPSGNSP,
-+ VSX_BUILTIN_XVCVDPSP,
-+ VSX_BUILTIN_XVCVDPSXDS,
-+ VSX_BUILTIN_XVCVDPSXWS,
-+ VSX_BUILTIN_XVCVDPUXDS,
-+ VSX_BUILTIN_XVCVDPUXWS,
-+ VSX_BUILTIN_XVCVSPDP,
-+ VSX_BUILTIN_XVCVSPSXDS,
-+ VSX_BUILTIN_XVCVSPSXWS,
-+ VSX_BUILTIN_XVCVSPUXDS,
-+ VSX_BUILTIN_XVCVSPUXWS,
-+ VSX_BUILTIN_XVCVSXDDP,
-+ VSX_BUILTIN_XVCVSXDSP,
-+ VSX_BUILTIN_XVCVSXWDP,
-+ VSX_BUILTIN_XVCVSXWSP,
-+ VSX_BUILTIN_XVCVUXDDP,
-+ VSX_BUILTIN_XVCVUXDSP,
-+ VSX_BUILTIN_XVCVUXWDP,
-+ VSX_BUILTIN_XVCVUXWSP,
-+ VSX_BUILTIN_XVDIVDP,
-+ VSX_BUILTIN_XVDIVSP,
-+ VSX_BUILTIN_XVMADDADP,
-+ VSX_BUILTIN_XVMADDASP,
-+ VSX_BUILTIN_XVMADDMDP,
-+ VSX_BUILTIN_XVMADDMSP,
-+ VSX_BUILTIN_XVMAXDP,
-+ VSX_BUILTIN_XVMAXSP,
-+ VSX_BUILTIN_XVMINDP,
-+ VSX_BUILTIN_XVMINSP,
-+ VSX_BUILTIN_XVMOVDP,
-+ VSX_BUILTIN_XVMOVSP,
-+ VSX_BUILTIN_XVMSUBADP,
-+ VSX_BUILTIN_XVMSUBASP,
-+ VSX_BUILTIN_XVMSUBMDP,
-+ VSX_BUILTIN_XVMSUBMSP,
-+ VSX_BUILTIN_XVMULDP,
-+ VSX_BUILTIN_XVMULSP,
-+ VSX_BUILTIN_XVNABSDP,
-+ VSX_BUILTIN_XVNABSSP,
-+ VSX_BUILTIN_XVNEGDP,
-+ VSX_BUILTIN_XVNEGSP,
-+ VSX_BUILTIN_XVNMADDADP,
-+ VSX_BUILTIN_XVNMADDASP,
-+ VSX_BUILTIN_XVNMADDMDP,
-+ VSX_BUILTIN_XVNMADDMSP,
-+ VSX_BUILTIN_XVNMSUBADP,
-+ VSX_BUILTIN_XVNMSUBASP,
-+ VSX_BUILTIN_XVNMSUBMDP,
-+ VSX_BUILTIN_XVNMSUBMSP,
-+ VSX_BUILTIN_XVRDPI,
-+ VSX_BUILTIN_XVRDPIC,
-+ VSX_BUILTIN_XVRDPIM,
-+ VSX_BUILTIN_XVRDPIP,
-+ VSX_BUILTIN_XVRDPIZ,
-+ VSX_BUILTIN_XVREDP,
-+ VSX_BUILTIN_XVRESP,
-+ VSX_BUILTIN_XVRSPI,
-+ VSX_BUILTIN_XVRSPIC,
-+ VSX_BUILTIN_XVRSPIM,
-+ VSX_BUILTIN_XVRSPIP,
-+ VSX_BUILTIN_XVRSPIZ,
-+ VSX_BUILTIN_XVRSQRTEDP,
-+ VSX_BUILTIN_XVRSQRTESP,
-+ VSX_BUILTIN_XVSQRTDP,
-+ VSX_BUILTIN_XVSQRTSP,
-+ VSX_BUILTIN_XVSUBDP,
-+ VSX_BUILTIN_XVSUBSP,
-+ VSX_BUILTIN_XVTDIVDP,
-+ VSX_BUILTIN_XVTDIVSP,
-+ VSX_BUILTIN_XVTSQRTDP,
-+ VSX_BUILTIN_XVTSQRTSP,
-+ VSX_BUILTIN_XXLAND,
-+ VSX_BUILTIN_XXLANDC,
-+ VSX_BUILTIN_XXLNOR,
-+ VSX_BUILTIN_XXLOR,
-+ VSX_BUILTIN_XXLXOR,
-+ VSX_BUILTIN_XXMRGHD,
-+ VSX_BUILTIN_XXMRGHW,
-+ VSX_BUILTIN_XXMRGLD,
-+ VSX_BUILTIN_XXMRGLW,
-+ VSX_BUILTIN_XXPERMDI,
-+ VSX_BUILTIN_XXSEL,
-+ VSX_BUILTIN_XXSLDWI,
-+ VSX_BUILTIN_XXSPLTD,
-+ VSX_BUILTIN_XXSPLTW,
-+ VSX_BUILTIN_XXSWAPD,
-+
-+ /* Combine VSX/Altivec builtins. */
-+ VECTOR_BUILTIN_FLOAT_V4SI_V4SF,
-+ VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,
-+ VECTOR_BUILTIN_FIX_V4SF_V4SI,
-+ VECTOR_BUILTIN_FIXUNS_V4SF_V4SI,
-+
- RS6000_BUILTIN_COUNT
- };
-
-@@ -3123,6 +3407,8 @@ enum rs6000_builtin_type_index
- RS6000_BTI_V16QI,
- RS6000_BTI_V2SI,
- RS6000_BTI_V2SF,
-+ RS6000_BTI_V2DI,
-+ RS6000_BTI_V2DF,
- RS6000_BTI_V4HI,
- RS6000_BTI_V4SI,
- RS6000_BTI_V4SF,
-@@ -3146,7 +3432,10 @@ enum rs6000_builtin_type_index
- RS6000_BTI_UINTHI, /* unsigned_intHI_type_node */
- RS6000_BTI_INTSI, /* intSI_type_node */
- RS6000_BTI_UINTSI, /* unsigned_intSI_type_node */
-+ RS6000_BTI_INTDI, /* intDI_type_node */
-+ RS6000_BTI_UINTDI, /* unsigned_intDI_type_node */
- RS6000_BTI_float, /* float_type_node */
-+ RS6000_BTI_double, /* double_type_node */
- RS6000_BTI_void, /* void_type_node */
- RS6000_BTI_MAX
- };
-@@ -3157,6 +3446,8 @@ enum rs6000_builtin_type_index
- #define opaque_p_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI])
- #define opaque_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V4SI])
- #define V16QI_type_node (rs6000_builtin_types[RS6000_BTI_V16QI])
-+#define V2DI_type_node (rs6000_builtin_types[RS6000_BTI_V2DI])
-+#define V2DF_type_node (rs6000_builtin_types[RS6000_BTI_V2DF])
- #define V2SI_type_node (rs6000_builtin_types[RS6000_BTI_V2SI])
- #define V2SF_type_node (rs6000_builtin_types[RS6000_BTI_V2SF])
- #define V4HI_type_node (rs6000_builtin_types[RS6000_BTI_V4HI])
-@@ -3183,7 +3474,10 @@ enum rs6000_builtin_type_index
- #define uintHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTHI])
- #define intSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTSI])
- #define uintSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTSI])
-+#define intDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTDI])
-+#define uintDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTDI])
- #define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
-+#define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double])
- #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
-
- extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
---- gcc/config/rs6000/altivec.md (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/altivec.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -21,18 +21,7 @@
-
- (define_constants
- [(UNSPEC_VCMPBFP 50)
-- (UNSPEC_VCMPEQUB 51)
-- (UNSPEC_VCMPEQUH 52)
-- (UNSPEC_VCMPEQUW 53)
-- (UNSPEC_VCMPEQFP 54)
-- (UNSPEC_VCMPGEFP 55)
-- (UNSPEC_VCMPGTUB 56)
-- (UNSPEC_VCMPGTSB 57)
-- (UNSPEC_VCMPGTUH 58)
-- (UNSPEC_VCMPGTSH 59)
-- (UNSPEC_VCMPGTUW 60)
-- (UNSPEC_VCMPGTSW 61)
-- (UNSPEC_VCMPGTFP 62)
-+ ;; 51-62 deleted
- (UNSPEC_VMSUMU 65)
- (UNSPEC_VMSUMM 66)
- (UNSPEC_VMSUMSHM 68)
-@@ -87,10 +76,7 @@ (define_constants
- (UNSPEC_VEXPTEFP 156)
- (UNSPEC_VRSQRTEFP 157)
- (UNSPEC_VREFP 158)
-- (UNSPEC_VSEL4SI 159)
-- (UNSPEC_VSEL4SF 160)
-- (UNSPEC_VSEL8HI 161)
-- (UNSPEC_VSEL16QI 162)
-+ ;; 159-162 deleted
- (UNSPEC_VLSDOI 163)
- (UNSPEC_VUPKHSB 167)
- (UNSPEC_VUPKHPX 168)
-@@ -125,11 +111,11 @@ (define_constants
- (UNSPEC_INTERHI_V4SI 228)
- (UNSPEC_INTERHI_V8HI 229)
- (UNSPEC_INTERHI_V16QI 230)
-- (UNSPEC_INTERHI_V4SF 231)
-+ ;; delete 231
- (UNSPEC_INTERLO_V4SI 232)
- (UNSPEC_INTERLO_V8HI 233)
- (UNSPEC_INTERLO_V16QI 234)
-- (UNSPEC_INTERLO_V4SF 235)
-+ ;; delete 235
- (UNSPEC_LVLX 236)
- (UNSPEC_LVLXL 237)
- (UNSPEC_LVRX 238)
-@@ -176,39 +162,17 @@ (define_mode_iterator VIshort [V8HI V16Q
- (define_mode_iterator VF [V4SF])
- ;; Vec modes, pity mode iterators are not composable
- (define_mode_iterator V [V4SI V8HI V16QI V4SF])
-+;; Vec modes for move/logical/permute ops, include vector types for move not
-+;; otherwise handled by altivec (v2df, v2di, ti)
-+(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI TI])
-
- (define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
-
--;; Generic LVX load instruction.
--(define_insn "altivec_lvx_<mode>"
-- [(set (match_operand:V 0 "altivec_register_operand" "=v")
-- (match_operand:V 1 "memory_operand" "Z"))]
-- "TARGET_ALTIVEC"
-- "lvx %0,%y1"
-- [(set_attr "type" "vecload")])
--
--;; Generic STVX store instruction.
--(define_insn "altivec_stvx_<mode>"
-- [(set (match_operand:V 0 "memory_operand" "=Z")
-- (match_operand:V 1 "altivec_register_operand" "v"))]
-- "TARGET_ALTIVEC"
-- "stvx %1,%y0"
-- [(set_attr "type" "vecstore")])
--
- ;; Vector move instructions.
--(define_expand "mov<mode>"
-- [(set (match_operand:V 0 "nonimmediate_operand" "")
-- (match_operand:V 1 "any_operand" ""))]
-- "TARGET_ALTIVEC"
--{
-- rs6000_emit_move (operands[0], operands[1], <MODE>mode);
-- DONE;
--})
--
--(define_insn "*mov<mode>_internal"
-- [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,o,r,r,v")
-- (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,W"))]
-- "TARGET_ALTIVEC
-+(define_insn "*altivec_mov<mode>"
-+ [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v")
-+ (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,j,W"))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- {
-@@ -220,52 +184,17 @@ (define_insn "*mov<mode>_internal"
- case 3: return "#";
- case 4: return "#";
- case 5: return "#";
-- case 6: return output_vec_const_move (operands);
-+ case 6: return "vxor %0,%0,%0";
-+ case 7: return output_vec_const_move (operands);
- default: gcc_unreachable ();
- }
- }
-- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
--
--(define_split
-- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
-- (match_operand:V4SI 1 "input_operand" ""))]
-- "TARGET_ALTIVEC && reload_completed
-- && gpr_or_gpr_p (operands[0], operands[1])"
-- [(pc)]
--{
-- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
--})
--
--(define_split
-- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
-- (match_operand:V8HI 1 "input_operand" ""))]
-- "TARGET_ALTIVEC && reload_completed
-- && gpr_or_gpr_p (operands[0], operands[1])"
-- [(pc)]
--{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
-
- (define_split
-- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
-- (match_operand:V16QI 1 "input_operand" ""))]
-- "TARGET_ALTIVEC && reload_completed
-- && gpr_or_gpr_p (operands[0], operands[1])"
-- [(pc)]
--{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
--
--(define_split
-- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
-- (match_operand:V4SF 1 "input_operand" ""))]
-- "TARGET_ALTIVEC && reload_completed
-- && gpr_or_gpr_p (operands[0], operands[1])"
-- [(pc)]
--{
-- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
--})
--
--(define_split
-- [(set (match_operand:V 0 "altivec_register_operand" "")
-- (match_operand:V 1 "easy_vector_constant_add_self" ""))]
-- "TARGET_ALTIVEC && reload_completed"
-+ [(set (match_operand:VM 0 "altivec_register_operand" "")
-+ (match_operand:VM 1 "easy_vector_constant_add_self" ""))]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && reload_completed"
- [(set (match_dup 0) (match_dup 3))
- (set (match_dup 0) (match_dup 4))]
- {
-@@ -346,11 +275,11 @@ (define_insn "add<mode>3"
- "vaddu<VI_char>m %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "addv4sf3"
-+(define_insn "*altivec_addv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vaddfp %0,%1,%2"
- [(set_attr "type" "vecfloat")])
-
-@@ -392,11 +321,11 @@ (define_insn "sub<mode>3"
- "vsubu<VI_char>m %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "subv4sf3"
-+(define_insn "*altivec_subv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vsubfp %0,%1,%2"
- [(set_attr "type" "vecfloat")])
-
-@@ -457,131 +386,81 @@ (define_insn "altivec_vcmpbfp"
- "vcmpbfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
--(define_insn "altivec_vcmpequb"
-- [(set (match_operand:V16QI 0 "register_operand" "=v")
-- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
-- (match_operand:V16QI 2 "register_operand" "v")]
-- UNSPEC_VCMPEQUB))]
-+(define_insn "*altivec_eq<mode>"
-+ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
-+ (eq:VI (match_operand:VI 1 "altivec_register_operand" "v")
-+ (match_operand:VI 2 "altivec_register_operand" "v")))]
- "TARGET_ALTIVEC"
-- "vcmpequb %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
-+ "vcmpequ<VI_char> %0,%1,%2"
-+ [(set_attr "type" "veccmp")])
-
--(define_insn "altivec_vcmpequh"
-- [(set (match_operand:V8HI 0 "register_operand" "=v")
-- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
-- (match_operand:V8HI 2 "register_operand" "v")]
-- UNSPEC_VCMPEQUH))]
-+(define_insn "*altivec_gt<mode>"
-+ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
-+ (gt:VI (match_operand:VI 1 "altivec_register_operand" "v")
-+ (match_operand:VI 2 "altivec_register_operand" "v")))]
- "TARGET_ALTIVEC"
-- "vcmpequh %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
-+ "vcmpgts<VI_char> %0,%1,%2"
-+ [(set_attr "type" "veccmp")])
-
--(define_insn "altivec_vcmpequw"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
-- (match_operand:V4SI 2 "register_operand" "v")]
-- UNSPEC_VCMPEQUW))]
-+(define_insn "*altivec_gtu<mode>"
-+ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
-+ (gtu:VI (match_operand:VI 1 "altivec_register_operand" "v")
-+ (match_operand:VI 2 "altivec_register_operand" "v")))]
- "TARGET_ALTIVEC"
-- "vcmpequw %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
-+ "vcmpgtu<VI_char> %0,%1,%2"
-+ [(set_attr "type" "veccmp")])
-
--(define_insn "altivec_vcmpeqfp"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
-- (match_operand:V4SF 2 "register_operand" "v")]
-- UNSPEC_VCMPEQFP))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_eqv4sf"
-+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
-+ (eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
-+ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vcmpeqfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
--(define_insn "altivec_vcmpgefp"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
-- (match_operand:V4SF 2 "register_operand" "v")]
-- UNSPEC_VCMPGEFP))]
-- "TARGET_ALTIVEC"
-- "vcmpgefp %0,%1,%2"
-+(define_insn "*altivec_gtv4sf"
-+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
-+ (gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
-+ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
-+ "vcmpgtfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
--(define_insn "altivec_vcmpgtub"
-- [(set (match_operand:V16QI 0 "register_operand" "=v")
-- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
-- (match_operand:V16QI 2 "register_operand" "v")]
-- UNSPEC_VCMPGTUB))]
-- "TARGET_ALTIVEC"
-- "vcmpgtub %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "altivec_vcmpgtsb"
-- [(set (match_operand:V16QI 0 "register_operand" "=v")
-- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
-- (match_operand:V16QI 2 "register_operand" "v")]
-- UNSPEC_VCMPGTSB))]
-- "TARGET_ALTIVEC"
-- "vcmpgtsb %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "altivec_vcmpgtuh"
-- [(set (match_operand:V8HI 0 "register_operand" "=v")
-- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
-- (match_operand:V8HI 2 "register_operand" "v")]
-- UNSPEC_VCMPGTUH))]
-- "TARGET_ALTIVEC"
-- "vcmpgtuh %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "altivec_vcmpgtsh"
-- [(set (match_operand:V8HI 0 "register_operand" "=v")
-- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
-- (match_operand:V8HI 2 "register_operand" "v")]
-- UNSPEC_VCMPGTSH))]
-- "TARGET_ALTIVEC"
-- "vcmpgtsh %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "altivec_vcmpgtuw"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
-- (match_operand:V4SI 2 "register_operand" "v")]
-- UNSPEC_VCMPGTUW))]
-- "TARGET_ALTIVEC"
-- "vcmpgtuw %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "altivec_vcmpgtsw"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
-- (match_operand:V4SI 2 "register_operand" "v")]
-- UNSPEC_VCMPGTSW))]
-- "TARGET_ALTIVEC"
-- "vcmpgtsw %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "altivec_vcmpgtfp"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
-- (match_operand:V4SF 2 "register_operand" "v")]
-- UNSPEC_VCMPGTFP))]
-- "TARGET_ALTIVEC"
-- "vcmpgtfp %0,%1,%2"
-+(define_insn "*altivec_gev4sf"
-+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
-+ (ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
-+ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
-+ "vcmpgefp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-+(define_insn "altivec_vsel<mode>"
-+ [(set (match_operand:VM 0 "altivec_register_operand" "=v")
-+ (if_then_else:VM (ne (match_operand:VM 1 "altivec_register_operand" "v")
-+ (const_int 0))
-+ (match_operand:VM 2 "altivec_register_operand" "v")
-+ (match_operand:VM 3 "altivec_register_operand" "v")))]
-+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
-+ "vsel %0,%3,%2,%1"
-+ [(set_attr "type" "vecperm")])
-+
- ;; Fused multiply add
- (define_insn "altivec_vmaddfp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v"))
- (match_operand:V4SF 3 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vmaddfp %0,%1,%2,%3"
- [(set_attr "type" "vecfloat")])
-
- ;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
-
--(define_expand "mulv4sf3"
-+(define_expand "altivec_mulv4sf3"
- [(use (match_operand:V4SF 0 "register_operand" ""))
- (use (match_operand:V4SF 1 "register_operand" ""))
- (use (match_operand:V4SF 2 "register_operand" ""))]
-- "TARGET_ALTIVEC && TARGET_FUSED_MADD"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode) && TARGET_FUSED_MADD"
- "
- {
- rtx neg0;
-@@ -684,7 +563,7 @@ (define_insn "altivec_vnmsubfp"
- (neg:V4SF (minus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v"))
- (match_operand:V4SF 3 "register_operand" "v"))))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vnmsubfp %0,%1,%2,%3"
- [(set_attr "type" "vecfloat")])
-
-@@ -758,11 +637,11 @@ (define_insn "smax<mode>3"
- "vmaxs<VI_char> %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "smaxv4sf3"
-+(define_insn "*altivec_smaxv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vmaxfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-@@ -782,11 +661,11 @@ (define_insn "smin<mode>3"
- "vmins<VI_char> %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "sminv4sf3"
-+(define_insn "*altivec_sminv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vminfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-@@ -905,7 +784,7 @@ (define_insn "altivec_vmrghw"
- "vmrghw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
--(define_insn "altivec_vmrghsf"
-+(define_insn "*altivec_vmrghsf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (parallel [(const_int 0)
-@@ -918,7 +797,7 @@ (define_insn "altivec_vmrghsf"
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vmrghw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-@@ -990,35 +869,37 @@ (define_insn "altivec_vmrglh"
-
- (define_insn "altivec_vmrglw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
-- (parallel [(const_int 2)
-- (const_int 0)
-- (const_int 3)
-- (const_int 1)]))
-- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
-- (parallel [(const_int 0)
-- (const_int 2)
-- (const_int 1)
-- (const_int 3)]))
-- (const_int 5)))]
-+ (vec_merge:V4SI
-+ (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
-+ (parallel [(const_int 2)
-+ (const_int 0)
-+ (const_int 3)
-+ (const_int 1)]))
-+ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
-+ (parallel [(const_int 0)
-+ (const_int 2)
-+ (const_int 1)
-+ (const_int 3)]))
-+ (const_int 5)))]
- "TARGET_ALTIVEC"
- "vmrglw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
--(define_insn "altivec_vmrglsf"
-+(define_insn "*altivec_vmrglsf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
-- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-- (parallel [(const_int 2)
-- (const_int 0)
-- (const_int 3)
-- (const_int 1)]))
-- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-- (parallel [(const_int 0)
-- (const_int 2)
-- (const_int 1)
-- (const_int 3)]))
-- (const_int 5)))]
-- "TARGET_ALTIVEC"
-+ (vec_merge:V4SF
-+ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+ (parallel [(const_int 2)
-+ (const_int 0)
-+ (const_int 3)
-+ (const_int 1)]))
-+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-+ (parallel [(const_int 0)
-+ (const_int 2)
-+ (const_int 1)
-+ (const_int 3)]))
-+ (const_int 5)))]
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vmrglw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-@@ -1095,68 +976,53 @@ (define_insn "altivec_vmulosh"
- [(set_attr "type" "veccomplex")])
-
-
--;; logical ops
-+;; logical ops. Have the logical ops follow the memory ops in
-+;; terms of whether to prefer VSX or Altivec
-
--(define_insn "and<mode>3"
-- [(set (match_operand:VI 0 "register_operand" "=v")
-- (and:VI (match_operand:VI 1 "register_operand" "v")
-- (match_operand:VI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_and<mode>3"
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (and:VM (match_operand:VM 1 "register_operand" "v")
-+ (match_operand:VM 2 "register_operand" "v")))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
- "vand %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "ior<mode>3"
-- [(set (match_operand:VI 0 "register_operand" "=v")
-- (ior:VI (match_operand:VI 1 "register_operand" "v")
-- (match_operand:VI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_ior<mode>3"
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (ior:VM (match_operand:VM 1 "register_operand" "v")
-+ (match_operand:VM 2 "register_operand" "v")))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
- "vor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "xor<mode>3"
-- [(set (match_operand:VI 0 "register_operand" "=v")
-- (xor:VI (match_operand:VI 1 "register_operand" "v")
-- (match_operand:VI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_xor<mode>3"
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (xor:VM (match_operand:VM 1 "register_operand" "v")
-+ (match_operand:VM 2 "register_operand" "v")))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
- "vxor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "xorv4sf3"
-- [(set (match_operand:V4SF 0 "register_operand" "=v")
-- (xor:V4SF (match_operand:V4SF 1 "register_operand" "v")
-- (match_operand:V4SF 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "vxor %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "one_cmpl<mode>2"
-- [(set (match_operand:VI 0 "register_operand" "=v")
-- (not:VI (match_operand:VI 1 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_one_cmpl<mode>2"
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (not:VM (match_operand:VM 1 "register_operand" "v")))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
- "vnor %0,%1,%1"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "altivec_nor<mode>3"
-- [(set (match_operand:VI 0 "register_operand" "=v")
-- (not:VI (ior:VI (match_operand:VI 1 "register_operand" "v")
-- (match_operand:VI 2 "register_operand" "v"))))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_nor<mode>3"
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (not:VM (ior:VM (match_operand:VM 1 "register_operand" "v")
-+ (match_operand:VM 2 "register_operand" "v"))))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
- "vnor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
--(define_insn "andc<mode>3"
-- [(set (match_operand:VI 0 "register_operand" "=v")
-- (and:VI (not:VI (match_operand:VI 2 "register_operand" "v"))
-- (match_operand:VI 1 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "vandc %0,%1,%2"
-- [(set_attr "type" "vecsimple")])
--
--(define_insn "*andc3_v4sf"
-- [(set (match_operand:V4SF 0 "register_operand" "=v")
-- (and:V4SF (not:V4SF (match_operand:V4SF 2 "register_operand" "v"))
-- (match_operand:V4SF 1 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+(define_insn "*altivec_andc<mode>3"
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (and:VM (not:VM (match_operand:VM 2 "register_operand" "v"))
-+ (match_operand:VM 1 "register_operand" "v")))]
-+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
- "vandc %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-@@ -1392,7 +1258,7 @@ (define_insn "*altivec_vspltsf"
- (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
- (parallel
- [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vspltw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-@@ -1404,19 +1270,19 @@ (define_insn "altivec_vspltis<VI_char>"
- "vspltis<VI_char> %0,%1"
- [(set_attr "type" "vecperm")])
-
--(define_insn "ftruncv4sf2"
-+(define_insn "*altivec_ftruncv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vrfiz %0,%1"
- [(set_attr "type" "vecfloat")])
-
- (define_insn "altivec_vperm_<mode>"
-- [(set (match_operand:V 0 "register_operand" "=v")
-- (unspec:V [(match_operand:V 1 "register_operand" "v")
-- (match_operand:V 2 "register_operand" "v")
-- (match_operand:V16QI 3 "register_operand" "v")]
-- UNSPEC_VPERM))]
-+ [(set (match_operand:VM 0 "register_operand" "=v")
-+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
-+ (match_operand:VM 2 "register_operand" "v")
-+ (match_operand:V16QI 3 "register_operand" "v")]
-+ UNSPEC_VPERM))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-@@ -1515,180 +1381,6 @@ (define_insn "altivec_vrefp"
- "vrefp %0,%1"
- [(set_attr "type" "vecfloat")])
-
--(define_expand "vcondv4si"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (if_then_else:V4SI
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V4SI 4 "register_operand" "v")
-- (match_operand:V4SI 5 "register_operand" "v")])
-- (match_operand:V4SI 1 "register_operand" "v")
-- (match_operand:V4SI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--(define_expand "vconduv4si"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (if_then_else:V4SI
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V4SI 4 "register_operand" "v")
-- (match_operand:V4SI 5 "register_operand" "v")])
-- (match_operand:V4SI 1 "register_operand" "v")
-- (match_operand:V4SI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--(define_expand "vcondv4sf"
-- [(set (match_operand:V4SF 0 "register_operand" "=v")
-- (if_then_else:V4SF
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V4SF 4 "register_operand" "v")
-- (match_operand:V4SF 5 "register_operand" "v")])
-- (match_operand:V4SF 1 "register_operand" "v")
-- (match_operand:V4SF 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--(define_expand "vcondv8hi"
-- [(set (match_operand:V8HI 0 "register_operand" "=v")
-- (if_then_else:V8HI
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V8HI 4 "register_operand" "v")
-- (match_operand:V8HI 5 "register_operand" "v")])
-- (match_operand:V8HI 1 "register_operand" "v")
-- (match_operand:V8HI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--(define_expand "vconduv8hi"
-- [(set (match_operand:V8HI 0 "register_operand" "=v")
-- (if_then_else:V8HI
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V8HI 4 "register_operand" "v")
-- (match_operand:V8HI 5 "register_operand" "v")])
-- (match_operand:V8HI 1 "register_operand" "v")
-- (match_operand:V8HI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--(define_expand "vcondv16qi"
-- [(set (match_operand:V16QI 0 "register_operand" "=v")
-- (if_then_else:V16QI
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V16QI 4 "register_operand" "v")
-- (match_operand:V16QI 5 "register_operand" "v")])
-- (match_operand:V16QI 1 "register_operand" "v")
-- (match_operand:V16QI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--(define_expand "vconduv16qi"
-- [(set (match_operand:V16QI 0 "register_operand" "=v")
-- (if_then_else:V16QI
-- (match_operator 3 "comparison_operator"
-- [(match_operand:V16QI 4 "register_operand" "v")
-- (match_operand:V16QI 5 "register_operand" "v")])
-- (match_operand:V16QI 1 "register_operand" "v")
-- (match_operand:V16QI 2 "register_operand" "v")))]
-- "TARGET_ALTIVEC"
-- "
--{
-- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
-- operands[3], operands[4], operands[5]))
-- DONE;
-- else
-- FAIL;
--}
-- ")
--
--
--(define_insn "altivec_vsel_v4si"
-- [(set (match_operand:V4SI 0 "register_operand" "=v")
-- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
-- (match_operand:V4SI 2 "register_operand" "v")
-- (match_operand:V4SI 3 "register_operand" "v")]
-- UNSPEC_VSEL4SI))]
-- "TARGET_ALTIVEC"
-- "vsel %0,%1,%2,%3"
-- [(set_attr "type" "vecperm")])
--
--(define_insn "altivec_vsel_v4sf"
-- [(set (match_operand:V4SF 0 "register_operand" "=v")
-- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
-- (match_operand:V4SF 2 "register_operand" "v")
-- (match_operand:V4SI 3 "register_operand" "v")]
-- UNSPEC_VSEL4SF))]
-- "TARGET_ALTIVEC"
-- "vsel %0,%1,%2,%3"
-- [(set_attr "type" "vecperm")])
--
--(define_insn "altivec_vsel_v8hi"
-- [(set (match_operand:V8HI 0 "register_operand" "=v")
-- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
-- (match_operand:V8HI 2 "register_operand" "v")
-- (match_operand:V8HI 3 "register_operand" "v")]
-- UNSPEC_VSEL8HI))]
-- "TARGET_ALTIVEC"
-- "vsel %0,%1,%2,%3"
-- [(set_attr "type" "vecperm")])
--
--(define_insn "altivec_vsel_v16qi"
-- [(set (match_operand:V16QI 0 "register_operand" "=v")
-- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
-- (match_operand:V16QI 2 "register_operand" "v")
-- (match_operand:V16QI 3 "register_operand" "v")]
-- UNSPEC_VSEL16QI))]
-- "TARGET_ALTIVEC"
-- "vsel %0,%1,%2,%3"
-- [(set_attr "type" "vecperm")])
--
- (define_insn "altivec_vsldoi_<mode>"
- [(set (match_operand:V 0 "register_operand" "=v")
- (unspec:V [(match_operand:V 1 "register_operand" "v")
-@@ -1878,6 +1570,14 @@ (define_expand "build_vector_mask_for_lo
- gcc_assert (GET_CODE (operands[1]) == MEM);
-
- addr = XEXP (operands[1], 0);
-+ if (VECTOR_MEM_VSX_P (GET_MODE (operands[1])))
-+ {
-+ /* VSX doesn't and off the bottom address bits, and memory
-+ operations are aligned to the natural data type. */
-+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-+ DONE;
-+ }
-+
- temp = gen_reg_rtx (GET_MODE (addr));
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- gen_rtx_NEG (GET_MODE (addr), addr)));
-@@ -1959,95 +1659,6 @@ (define_insn "*altivec_stvesfx"
- "stvewx %1,%y0"
- [(set_attr "type" "vecstore")])
-
--(define_expand "vec_init<mode>"
-- [(match_operand:V 0 "register_operand" "")
-- (match_operand 1 "" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_init (operands[0], operands[1]);
-- DONE;
--})
--
--(define_expand "vec_setv4si"
-- [(match_operand:V4SI 0 "register_operand" "")
-- (match_operand:SI 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_setv8hi"
-- [(match_operand:V8HI 0 "register_operand" "")
-- (match_operand:HI 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_setv16qi"
-- [(match_operand:V16QI 0 "register_operand" "")
-- (match_operand:QI 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_setv4sf"
-- [(match_operand:V4SF 0 "register_operand" "")
-- (match_operand:SF 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_extractv4si"
-- [(match_operand:SI 0 "register_operand" "")
-- (match_operand:V4SI 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_extractv8hi"
-- [(match_operand:HI 0 "register_operand" "")
-- (match_operand:V8HI 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_extractv16qi"
-- [(match_operand:QI 0 "register_operand" "")
-- (match_operand:V16QI 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
--(define_expand "vec_extractv4sf"
-- [(match_operand:SF 0 "register_operand" "")
-- (match_operand:V4SF 1 "register_operand" "")
-- (match_operand 2 "const_int_operand" "")]
-- "TARGET_ALTIVEC"
--{
-- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
-- DONE;
--})
--
- ;; Generate
- ;; vspltis? SCRATCH0,0
- ;; vsubu?m SCRATCH2,SCRATCH1,%1
-@@ -2069,7 +1680,7 @@ (define_expand "abs<mode>2"
- ;; vspltisw SCRATCH1,-1
- ;; vslw SCRATCH2,SCRATCH1,SCRATCH1
- ;; vandc %0,%1,SCRATCH2
--(define_expand "absv4sf2"
-+(define_expand "altivec_absv4sf2"
- [(set (match_dup 2)
- (vec_duplicate:V4SI (const_int -1)))
- (set (match_dup 3)
-@@ -2132,7 +1743,7 @@ (define_expand "vec_shl_<mode>"
- DONE;
- }")
-
--;; Vector shift left in bits. Currently supported ony for shift
-+;; Vector shift right in bits. Currently supported ony for shift
- ;; amounts that can be expressed as byte shifts (divisible by 8).
- ;; General shift amounts can be supported using vsro + vsr. We're
- ;; not expecting to see these yet (the vectorizer currently
-@@ -2665,7 +2276,7 @@ (define_expand "vec_pack_trunc_v4si"
- DONE;
- }")
-
--(define_expand "negv4sf2"
-+(define_expand "altivec_negv4sf2"
- [(use (match_operand:V4SF 0 "register_operand" ""))
- (use (match_operand:V4SF 1 "register_operand" ""))]
- "TARGET_ALTIVEC"
-@@ -2994,29 +2605,6 @@ (define_expand "vec_extract_oddv16qi"
- emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2]));
- DONE;
- }")
--(define_expand "vec_interleave_highv4sf"
-- [(set (match_operand:V4SF 0 "register_operand" "")
-- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
-- (match_operand:V4SF 2 "register_operand" "")]
-- UNSPEC_INTERHI_V4SF))]
-- "TARGET_ALTIVEC"
-- "
--{
-- emit_insn (gen_altivec_vmrghsf (operands[0], operands[1], operands[2]));
-- DONE;
--}")
--
--(define_expand "vec_interleave_lowv4sf"
-- [(set (match_operand:V4SF 0 "register_operand" "")
-- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
-- (match_operand:V4SF 2 "register_operand" "")]
-- UNSPEC_INTERLO_V4SF))]
-- "TARGET_ALTIVEC"
-- "
--{
-- emit_insn (gen_altivec_vmrglsf (operands[0], operands[1], operands[2]));
-- DONE;
--}")
-
- (define_expand "vec_interleave_high<mode>"
- [(set (match_operand:VI 0 "register_operand" "")
---- gcc/config/rs6000/aix61.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/aix61.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -57,20 +57,24 @@ do { \
- #undef ASM_SPEC
- #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
-
--/* Common ASM definitions used by ASM_SPEC amongst the various targets
-- for handling -mcpu=xxx switches. */
-+/* Common ASM definitions used by ASM_SPEC amongst the various targets for
-+ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
-+ provide the default assembler options if the user uses -mcpu=native, so if
-+ you make changes here, make them there also. */
- #undef ASM_CPU_SPEC
- #define ASM_CPU_SPEC \
- "%{!mcpu*: %{!maix64: \
- %{mpowerpc64: -mppc64} \
- %{maltivec: -m970} \
- %{!maltivec: %{!mpower64: %(asm_default)}}}} \
-+%{mcpu=native: %(asm_cpu_native)} \
- %{mcpu=power3: -m620} \
- %{mcpu=power4: -mpwr4} \
- %{mcpu=power5: -mpwr5} \
- %{mcpu=power5+: -mpwr5x} \
- %{mcpu=power6: -mpwr6} \
- %{mcpu=power6x: -mpwr6} \
-+%{mcpu=power7: -mpwr7} \
- %{mcpu=powerpc: -mppc} \
- %{mcpu=rs64a: -mppc} \
- %{mcpu=603: -m603} \
---- gcc/config/rs6000/rs6000.md (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/rs6000.md (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -138,7 +138,7 @@ (define_attr "length" ""
- ;; Processor type -- this attribute must exactly match the processor_type
- ;; enumeration in rs6000.h.
-
--(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,cell"
-+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell"
- (const (symbol_ref "rs6000_cpu_attr")))
-
-
-@@ -167,6 +167,7 @@ (define_attr "cell_micro" "not,condition
- (include "power4.md")
- (include "power5.md")
- (include "power6.md")
-+(include "power7.md")
- (include "cell.md")
- (include "xfpu.md")
-
-@@ -218,6 +219,9 @@ (define_mode_attr wd [(QI "b") (HI "h")
- ; DImode bits
- (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
-
-+;; ISEL/ISEL64 target selection
-+(define_mode_attr sel [(SI "") (DI "64")])
-+
- \f
- ;; Start with fixed-point load and store insns. Here we put only the more
- ;; complex forms. Basic data transfer is done later.
-@@ -520,7 +524,7 @@ (define_insn ""
- "@
- {andil.|andi.} %2,%1,0xff
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -546,7 +550,7 @@ (define_insn ""
- "@
- {andil.|andi.} %0,%1,0xff
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -687,7 +691,7 @@ (define_insn ""
- "@
- {andil.|andi.} %2,%1,0xff
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -713,7 +717,7 @@ (define_insn ""
- "@
- {andil.|andi.} %0,%1,0xff
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -856,7 +860,7 @@ (define_insn ""
- "@
- {andil.|andi.} %2,%1,0xffff
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -882,7 +886,7 @@ (define_insn ""
- "@
- {andil.|andi.} %0,%1,0xffff
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -1670,7 +1674,7 @@ (define_insn ""
- "@
- nor. %2,%1,%1
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -1696,7 +1700,7 @@ (define_insn ""
- "@
- nor. %0,%1,%1
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -2221,10 +2225,22 @@ (define_insn "popcntb<mode>2"
- "TARGET_POPCNTB"
- "popcntb %0,%1")
-
-+(define_insn "popcntwsi2"
-+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-+ (popcount:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
-+ "TARGET_POPCNTD"
-+ "popcntw %0,%1")
-+
-+(define_insn "popcntddi2"
-+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-+ (popcount:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
-+ "TARGET_POPCNTD && TARGET_POWERPC64"
-+ "popcntd %0,%1")
-+
- (define_expand "popcount<mode>2"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "")
- (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
-- "TARGET_POPCNTB"
-+ "TARGET_POPCNTB || TARGET_POPCNTD"
- {
- rs6000_emit_popcount (operands[0], operands[1]);
- DONE;
-@@ -2852,7 +2868,7 @@ (define_insn "andsi3_mc"
- {rlinm|rlwinm} %0,%1,0,%m2,%M2
- {andil.|andi.} %0,%1,%b2
- {andiu.|andis.} %0,%1,%u2"
-- [(set_attr "type" "*,*,compare,compare")])
-+ [(set_attr "type" "*,*,fast_compare,fast_compare")])
-
- (define_insn "andsi3_nomc"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-@@ -2895,7 +2911,8 @@ (define_insn "*andsi3_internal2_mc"
- #
- #
- #"
-- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
-+ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
-+ compare,compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8")])
-
- (define_insn "*andsi3_internal3_mc"
-@@ -2915,7 +2932,8 @@ (define_insn "*andsi3_internal3_mc"
- #
- #
- #"
-- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
-+ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
-+ compare,compare,compare")
- (set_attr "length" "8,4,4,4,8,8,8,8")])
-
- (define_split
-@@ -2974,7 +2992,8 @@ (define_insn "*andsi3_internal4"
- #
- #
- #"
-- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
-+ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
-+ compare,compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8")])
-
- (define_insn "*andsi3_internal5_mc"
-@@ -2996,7 +3015,8 @@ (define_insn "*andsi3_internal5_mc"
- #
- #
- #"
-- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
-+ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
-+ compare,compare,compare")
- (set_attr "length" "8,4,4,4,8,8,8,8")])
-
- (define_insn "*andsi3_internal5_nomc"
-@@ -3141,7 +3161,7 @@ (define_insn "*boolsi3_internal2"
- "@
- %q4. %3,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -3170,7 +3190,7 @@ (define_insn "*boolsi3_internal3"
- "@
- %q4. %0,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -3295,7 +3315,7 @@ (define_insn "*boolccsi3_internal2"
- "@
- %q4. %3,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -3324,7 +3344,7 @@ (define_insn "*boolccsi3_internal3"
- "@
- %q4. %0,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -5317,7 +5337,7 @@ (define_insn "fres"
- "fres %0,%1"
- [(set_attr "type" "fp")])
-
--(define_insn ""
-+(define_insn "*fmaddsf4_powerpc"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5328,7 +5348,7 @@ (define_insn ""
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
--(define_insn ""
-+(define_insn "*fmaddsf4_power"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5337,7 +5357,7 @@ (define_insn ""
- "{fma|fmadd} %0,%1,%2,%3"
- [(set_attr "type" "dmul")])
-
--(define_insn ""
-+(define_insn "*fmsubsf4_powerpc"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5348,7 +5368,7 @@ (define_insn ""
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
--(define_insn ""
-+(define_insn "*fmsubsf4_power"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5357,7 +5377,7 @@ (define_insn ""
- "{fms|fmsub} %0,%1,%2,%3"
- [(set_attr "type" "dmul")])
-
--(define_insn ""
-+(define_insn "*fnmaddsf4_powerpc_1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5368,7 +5388,7 @@ (define_insn ""
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
--(define_insn ""
-+(define_insn "*fnmaddsf4_powerpc_2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5379,7 +5399,7 @@ (define_insn ""
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
--(define_insn ""
-+(define_insn "*fnmaddsf4_power_1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5388,7 +5408,7 @@ (define_insn ""
- "{fnma|fnmadd} %0,%1,%2,%3"
- [(set_attr "type" "dmul")])
-
--(define_insn ""
-+(define_insn "*fnmaddsf4_power_2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5398,7 +5418,7 @@ (define_insn ""
- "{fnma|fnmadd} %0,%1,%2,%3"
- [(set_attr "type" "dmul")])
-
--(define_insn ""
-+(define_insn "*fnmsubsf4_powerpc_1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5409,7 +5429,7 @@ (define_insn ""
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
--(define_insn ""
-+(define_insn "*fnmsubsf4_powerpc_2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
-@@ -5420,7 +5440,7 @@ (define_insn ""
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
--(define_insn ""
-+(define_insn "*fnmsubsf4_power_1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5429,7 +5449,7 @@ (define_insn ""
- "{fnms|fnmsub} %0,%1,%2,%3"
- [(set_attr "type" "dmul")])
-
--(define_insn ""
-+(define_insn "*fnmsubsf4_power_2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
-@@ -5510,9 +5530,18 @@ (define_expand "copysigndf3"
- (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]));
-+ DONE;
-+ }
- operands[3] = gen_reg_rtx (DFmode);
- operands[4] = gen_reg_rtx (DFmode);
- operands[5] = CONST0_RTX (DFmode);
-@@ -5556,12 +5585,12 @@ (define_split
- DONE;
- }")
-
--(define_expand "movsicc"
-- [(set (match_operand:SI 0 "gpc_reg_operand" "")
-- (if_then_else:SI (match_operand 1 "comparison_operator" "")
-- (match_operand:SI 2 "gpc_reg_operand" "")
-- (match_operand:SI 3 "gpc_reg_operand" "")))]
-- "TARGET_ISEL"
-+(define_expand "mov<mode>cc"
-+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
-+ (if_then_else:GPR (match_operand 1 "comparison_operator" "")
-+ (match_operand:GPR 2 "gpc_reg_operand" "")
-+ (match_operand:GPR 3 "gpc_reg_operand" "")))]
-+ "TARGET_ISEL<sel>"
- "
- {
- if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
-@@ -5578,28 +5607,28 @@ (define_expand "movsicc"
- ;; leave out the mode in operand 4 and use one pattern, but reload can
- ;; change the mode underneath our feet and then gets confused trying
- ;; to reload the value.
--(define_insn "isel_signed"
-- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-- (if_then_else:SI
-+(define_insn "isel_signed_<mode>"
-+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-+ (if_then_else:GPR
- (match_operator 1 "comparison_operator"
- [(match_operand:CC 4 "cc_reg_operand" "y")
- (const_int 0)])
-- (match_operand:SI 2 "gpc_reg_operand" "b")
-- (match_operand:SI 3 "gpc_reg_operand" "b")))]
-- "TARGET_ISEL"
-+ (match_operand:GPR 2 "gpc_reg_operand" "b")
-+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
-+ "TARGET_ISEL<sel>"
- "*
- { return output_isel (operands); }"
- [(set_attr "length" "4")])
-
--(define_insn "isel_unsigned"
-- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-- (if_then_else:SI
-+(define_insn "isel_unsigned_<mode>"
-+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-+ (if_then_else:GPR
- (match_operator 1 "comparison_operator"
- [(match_operand:CCUNS 4 "cc_reg_operand" "y")
- (const_int 0)])
-- (match_operand:SI 2 "gpc_reg_operand" "b")
-- (match_operand:SI 3 "gpc_reg_operand" "b")))]
-- "TARGET_ISEL"
-+ (match_operand:GPR 2 "gpc_reg_operand" "b")
-+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
-+ "TARGET_ISEL<sel>"
- "*
- { return output_isel (operands); }"
- [(set_attr "length" "4")])
-@@ -5647,7 +5676,8 @@ (define_expand "negdf2"
- (define_insn "*negdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
-- "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")])
-
-@@ -5660,14 +5690,16 @@ (define_expand "absdf2"
- (define_insn "*absdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
-- "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" "=f")
- (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
-- "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")])
-
-@@ -5682,7 +5714,8 @@ (define_insn "*adddf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f")))]
-- "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")])
-@@ -5698,7 +5731,8 @@ (define_insn "*subdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")))]
-- "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")])
-@@ -5714,7 +5748,8 @@ (define_insn "*muldf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f")))]
-- "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")])
-@@ -5732,7 +5767,8 @@ (define_insn "*divdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")))]
-- "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")])
-
-@@ -5748,73 +5784,81 @@ (define_expand "recipdf3"
- DONE;
- })
-
--(define_insn "fred"
-+(define_expand "fred"
-+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
-+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
-+ "(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"
-+ "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" "=f")
- (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f"))
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
-- "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" "=f")
- (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f"))
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
-- "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" "=f")
- (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f"))
- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "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" "=f")
- (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f"))
- (match_operand:DF 2 "gpc_reg_operand" "f"))
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
- "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" "=f")
- (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f"))
- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "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" "=f")
- (minus:DF (match_operand:DF 3 "gpc_reg_operand" "f")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
- (match_operand:DF 2 "gpc_reg_operand" "f"))))]
- "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")])
-@@ -5823,7 +5867,8 @@ (define_insn "sqrtdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "(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")])
-
-@@ -5912,6 +5957,18 @@ (define_expand "fix_truncsfsi2"
- "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "")
-
-+(define_expand "fixuns_truncdfsi2"
-+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
-+ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
-+ "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,
-@@ -6153,10 +6210,17 @@ (define_insn "fctiwz"
- "{fcirz|fctiwz} %0,%1"
- [(set_attr "type" "fp")])
-
--(define_insn "btruncdf2"
-+(define_expand "btruncdf2"
- [(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"
-+ "")
-+
-+(define_insn "*btruncdf2_fprs"
-+ [(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")])
-
-@@ -6167,10 +6231,17 @@ (define_insn "btruncsf2"
- "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_fprs"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] 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")])
-
-@@ -6181,10 +6252,17 @@ (define_insn "ceilsf2"
- "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_fprs"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] 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")])
-
-@@ -6195,6 +6273,7 @@ (define_insn "floorsf2"
- "frim %0,%1"
- [(set_attr "type" "fp")])
-
-+;; No VSX equivalent to frin
- (define_insn "rounddf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
-@@ -6209,6 +6288,12 @@ (define_insn "roundsf2"
- "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")
-@@ -6224,17 +6309,40 @@ (define_expand "floatsisf2"
- "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" "=f")
- (float:DF (match_operand:DI 1 "gpc_reg_operand" "!f#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" "=!f#r")
- (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))]
-- "(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")])
-
-@@ -7623,7 +7731,7 @@ (define_insn "anddi3_mc"
- andi. %0,%1,%b2
- andis. %0,%1,%u2
- #"
-- [(set_attr "type" "*,*,*,compare,compare,*")
-+ [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
- (set_attr "length" "4,4,4,4,4,8")])
-
- (define_insn "anddi3_nomc"
-@@ -7681,7 +7789,9 @@ (define_insn "*anddi3_internal2_mc"
- #
- #
- #"
-- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
-+ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
-+ fast_compare,compare,compare,compare,compare,compare,\
-+ compare,compare")
- (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
-
- (define_insn "*anddi3_internal2_nomc"
-@@ -7744,7 +7854,9 @@ (define_insn "*anddi3_internal3_mc"
- #
- #
- #"
-- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
-+ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
-+ fast_compare,compare,compare,compare,compare,compare,\
-+ compare,compare")
- (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
-
- (define_insn "*anddi3_internal3_nomc"
-@@ -7896,7 +8008,7 @@ (define_insn "*booldi3_internal2"
- "@
- %q4. %3,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -7925,7 +8037,7 @@ (define_insn "*booldi3_internal3"
- "@
- %q4. %0,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -7996,7 +8108,7 @@ (define_insn "*boolcdi3_internal2"
- "@
- %q4. %3,%2,%1
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -8025,7 +8137,7 @@ (define_insn "*boolcdi3_internal3"
- "@
- %q4. %0,%2,%1
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -8062,7 +8174,7 @@ (define_insn "*boolccdi3_internal2"
- "@
- %q4. %3,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -8091,7 +8203,7 @@ (define_insn "*boolccdi3_internal3"
- "@
- %q4. %0,%1,%2
- #"
-- [(set_attr "type" "compare")
-+ [(set_attr "type" "fast_compare,compare")
- (set_attr "length" "4,8")])
-
- (define_split
-@@ -8108,6 +8220,51 @@ (define_split
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-+
-+(define_expand "smindi3"
-+ [(match_operand:DI 0 "gpc_reg_operand" "")
-+ (match_operand:DI 1 "gpc_reg_operand" "")
-+ (match_operand:DI 2 "gpc_reg_operand" "")]
-+ "TARGET_ISEL64"
-+ "
-+{
-+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
-+ DONE;
-+}")
-+
-+(define_expand "smaxdi3"
-+ [(match_operand:DI 0 "gpc_reg_operand" "")
-+ (match_operand:DI 1 "gpc_reg_operand" "")
-+ (match_operand:DI 2 "gpc_reg_operand" "")]
-+ "TARGET_ISEL64"
-+ "
-+{
-+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
-+ DONE;
-+}")
-+
-+(define_expand "umindi3"
-+ [(match_operand:DI 0 "gpc_reg_operand" "")
-+ (match_operand:DI 1 "gpc_reg_operand" "")
-+ (match_operand:DI 2 "gpc_reg_operand" "")]
-+ "TARGET_ISEL64"
-+ "
-+{
-+ rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]);
-+ DONE;
-+}")
-+
-+(define_expand "umaxdi3"
-+ [(match_operand:DI 0 "gpc_reg_operand" "")
-+ (match_operand:DI 1 "gpc_reg_operand" "")
-+ (match_operand:DI 2 "gpc_reg_operand" "")]
-+ "TARGET_ISEL64"
-+ "
-+{
-+ rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]);
-+ DONE;
-+}")
-+
- \f
- ;; Now define ways of moving data around.
-
-@@ -8511,8 +8668,8 @@ (define_split
- ;; 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,f,f,m,!r,!r,!r")
-- (match_operand:DF 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
-+ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r, ??r, m, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, !r, !r, !r")
-+ (match_operand:DF 1 "input_operand" "r, m, r, ws, wa, Z, Z, ws, wa, f, m, f, 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))"
-@@ -8591,19 +8748,30 @@ (define_insn "*movdf_hardfloat32"
- return \"\";
- }
- case 3:
-- return \"fmr %0,%1\";
- case 4:
-- return \"lfd%U1%X1 %0,%1\";
-+ return \"xscpsgndp %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")
-@@ -8651,19 +8819,26 @@ (define_insn "*movdf_softfloat32"
- ; 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,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
-- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
-+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y, r, !r, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, *c*l, !r, *h, !r, !r, !r, r, f")
-+ (match_operand:DF 1 "input_operand" "r, Y, r, ws, ?wa, Z, Z, ws, wa, f, m, f, j, r, h, 0, G, H, F, f, 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
-+ xscpsgndp %x0,%x1,%x1
-+ xscpsgndp %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}
-@@ -8672,33 +8847,40 @@ (define_insn "*movdf_hardfloat64_mfpgpr"
- #
- 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,f,f,m,*c*l,!r,*h,!r,!r,!r")
-- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
-+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y, r, !r, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, *c*l, !r, *h, !r, !r, !r")
-+ (match_operand:DF 1 "input_operand" "r, Y, r, ws, wa, Z, Z, ws, wa, f, m, f, 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
-+ xscpsgndp %x0,%x1,%x1
-+ xscpsgndp %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")
-@@ -9275,15 +9457,16 @@ (define_insn "*movti_string"
- (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" "*,load,store")])
-
- (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))]
- "
-@@ -9309,7 +9492,7 @@ (define_split
- (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; })
-@@ -14929,6 +15112,8 @@ (define_insn "prefetch"
- \f
-
- (include "sync.md")
-+(include "vector.md")
-+(include "vsx.md")
- (include "altivec.md")
- (include "spe.md")
- (include "dfp.md")
---- gcc/config/rs6000/e500.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/e500.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -37,6 +37,8 @@
- { \
- if (TARGET_ALTIVEC) \
- error ("AltiVec and E500 instructions cannot coexist"); \
-+ if (TARGET_VSX) \
-+ error ("VSX and E500 instructions cannot coexist"); \
- if (TARGET_64BIT) \
- error ("64-bit E500 not supported"); \
- if (TARGET_HARD_FLOAT && TARGET_FPRS) \
---- gcc/config/rs6000/driver-rs6000.c (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/driver-rs6000.c (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -343,11 +343,115 @@ detect_processor_aix (void)
- #endif /* _AIX */
-
-
-+/*
-+ * Array to map -mcpu=native names to the switches passed to the assembler.
-+ * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
-+ * should be made there as well.
-+ */
-+
-+struct asm_name {
-+ const char *cpu;
-+ const char *asm_sw;
-+};
-+
-+static const
-+struct asm_name asm_names[] = {
-+#if defined (_AIX)
-+ { "power3", "-m620" },
-+ { "power4", "-mpwr4" },
-+ { "power5", "-mpwr5" },
-+ { "power5+", "-mpwr5x" },
-+ { "power6", "-mpwr6" },
-+ { "power6x", "-mpwr6" },
-+ { "power7", "-mpwr7" },
-+ { "powerpc", "-mppc" },
-+ { "rs64a", "-mppc" },
-+ { "603", "-m603" },
-+ { "603e", "-m603" },
-+ { "604", "-m604" },
-+ { "604e", "-m604" },
-+ { "620", "-m620" },
-+ { "630", "-m620" },
-+ { "970", "-m970" },
-+ { "G5", "-m970" },
-+ { NULL, "\
-+%{!maix64: \
-+%{mpowerpc64: -mppc64} \
-+%{maltivec: -m970} \
-+%{!maltivec: %{!mpower64: %(asm_default)}}}" },
-+
-+#else
-+ { "common", "-mcom" },
-+ { "cell", "-mcell" },
-+ { "power", "-mpwr" },
-+ { "power2", "-mpwrx" },
-+ { "power3", "-mppc64" },
-+ { "power4", "-mpower4" },
-+ { "power5", "%(asm_cpu_power5)" },
-+ { "power5+", "%(asm_cpu_power5)" },
-+ { "power6", "%(asm_cpu_power6) -maltivec" },
-+ { "power6x", "%(asm_cpu_power6) -maltivec" },
-+ { "power7", "%(asm_cpu_power7)" },
-+ { "powerpc", "-mppc" },
-+ { "rios", "-mpwr" },
-+ { "rios1", "-mpwr" },
-+ { "rios2", "-mpwrx" },
-+ { "rsc", "-mpwr" },
-+ { "rsc1", "-mpwr" },
-+ { "rs64a", "-mppc64" },
-+ { "401", "-mppc" },
-+ { "403", "-m403" },
-+ { "405", "-m405" },
-+ { "405fp", "-m405" },
-+ { "440", "-m440" },
-+ { "440fp", "-m440" },
-+ { "464", "-m440" },
-+ { "464fp", "-m440" },
-+ { "505", "-mppc" },
-+ { "601", "-m601" },
-+ { "602", "-mppc" },
-+ { "603", "-mppc" },
-+ { "603e", "-mppc" },
-+ { "ec603e", "-mppc" },
-+ { "604", "-mppc" },
-+ { "604e", "-mppc" },
-+ { "620", "-mppc64" },
-+ { "630", "-mppc64" },
-+ { "740", "-mppc" },
-+ { "750", "-mppc" },
-+ { "G3", "-mppc" },
-+ { "7400", "-mppc -maltivec" },
-+ { "7450", "-mppc -maltivec" },
-+ { "G4", "-mppc -maltivec" },
-+ { "801", "-mppc" },
-+ { "821", "-mppc" },
-+ { "823", "-mppc" },
-+ { "860", "-mppc" },
-+ { "970", "-mpower4 -maltivec" },
-+ { "G5", "-mpower4 -maltivec" },
-+ { "8540", "-me500" },
-+ { "8548", "-me500" },
-+ { "e300c2", "-me300" },
-+ { "e300c3", "-me300" },
-+ { "e500mc", "-me500mc" },
-+ { NULL, "\
-+%{mpower: %{!mpower2: -mpwr}} \
-+%{mpower2: -mpwrx} \
-+%{mpowerpc64*: -mppc64} \
-+%{!mpowerpc64*: %{mpowerpc*: -mppc}} \
-+%{mno-power: %{!mpowerpc*: -mcom}} \
-+%{!mno-power: %{!mpower*: %(asm_default)}}" },
-+#endif
-+};
-+
- /* This will be called by the spec parser in gcc.c when it sees
- a %:local_cpu_detect(args) construct. Currently it will be called
- with either "arch" or "tune" as argument depending on if -march=native
- or -mtune=native is to be substituted.
-
-+ Additionally it will be called with "asm" to select the appropriate flags
-+ for the assembler.
-+
- It returns a string containing new command line parameters to be
- put at the place of the above two options, depending on what CPU
- this is executed.
-@@ -361,29 +465,35 @@ const char
- const char *cache = "";
- const char *options = "";
- bool arch;
-+ bool assembler;
-+ size_t i;
-
- if (argc < 1)
- return NULL;
-
- arch = strcmp (argv[0], "cpu") == 0;
-- if (!arch && strcmp (argv[0], "tune"))
-+ assembler = (!arch && strcmp (argv[0], "asm") == 0);
-+ if (!arch && !assembler && strcmp (argv[0], "tune"))
- return NULL;
-
-+ if (! assembler)
-+ {
- #if defined (_AIX)
-- cache = detect_caches_aix ();
-+ cache = detect_caches_aix ();
- #elif defined (__APPLE__)
-- cache = detect_caches_darwin ();
-+ cache = detect_caches_darwin ();
- #elif defined (__FreeBSD__)
-- cache = detect_caches_freebsd ();
-- /* FreeBSD PPC does not provide any cache information yet. */
-- cache = "";
-+ cache = detect_caches_freebsd ();
-+ /* FreeBSD PPC does not provide any cache information yet. */
-+ cache = "";
- #elif defined (__linux__)
-- cache = detect_caches_linux ();
-- /* PPC Linux does not provide any cache information yet. */
-- cache = "";
-+ cache = detect_caches_linux ();
-+ /* PPC Linux does not provide any cache information yet. */
-+ cache = "";
- #else
-- cache = "";
-+ cache = "";
- #endif
-+ }
-
- #if defined (_AIX)
- cpu = detect_processor_aix ();
-@@ -397,6 +507,17 @@ const char
- cpu = "powerpc";
- #endif
-
-+ if (assembler)
-+ {
-+ for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++)
-+ {
-+ if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu))
-+ return asm_names[i].asm_sw;
-+ }
-+
-+ return NULL;
-+ }
-+
- return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
- }
-
---- gcc/config/rs6000/sysv4.h (.../trunk) (revision 144557)
-+++ gcc/config/rs6000/sysv4.h (.../branches/ibm/power7-meissner) (revision 144692)
-@@ -119,9 +119,9 @@ do { \
- else if (!strcmp (rs6000_abi_name, "i960-old")) \
- { \
- rs6000_current_abi = ABI_V4; \
-- target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI \
-- | MASK_NO_BITFIELD_WORD); \
-+ target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI); \
- target_flags &= ~MASK_STRICT_ALIGN; \
-+ TARGET_NO_BITFIELD_WORD = 1; \
- } \
- else \
- { \
-
diff --git a/sources b/sources
index 2674f42..d78d617 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
2659f09c2e43ef8b7d4406321753f1b2 fastjar-0.97.tar.gz
-75f2e4ab9717342f13146245d58fa160 gcc-4.4.0-20090304.tar.bz2
+79ee98a73c0cbab32938bbf5d85f086b gcc-4.4.0-20090307.tar.bz2
716b7a0823f96c9d02c1703a9c47d387 cloog-ppl-0.15.tar.gz
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [rpms/gcc] rhel-f41-base: 4.4.0-0.23
@ 2026-06-29 12:24 Jakub Jelinek
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2026-06-29 12:24 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/gcc
Branch : rhel-f41-base
Commit : caa5b98426bb85515427b899c65c3a38fb02022f
Author : Jakub Jelinek <jakub@fedoraproject.org>
Date : 2009-03-07T09:16:22+00:00
Stats : +9523/-5 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/gcc/c/caa5b98426bb85515427b899c65c3a38fb02022f?branch=rhel-f41-base
Log:
4.4.0-0.23
---
diff --git a/gcc.spec b/gcc.spec
index cacf788..59b75b8 100644
--- a/gcc.spec
+++ b/gcc.spec
@@ -1,9 +1,9 @@
-%define DATE 20090304
-%define SVNREV 144601
+%define DATE 20090307
+%define SVNREV 144693
%define gcc_version 4.4.0
# Note, gcc_release must be integer, if you want to add suffixes to
# %{release}, append them after %{gcc_release} on Release: line.
-%define gcc_release 0.22
+%define gcc_release 0.23
%define _unpackaged_files_terminate_build 0
%define multilib_64_archs sparc64 ppc64 s390x x86_64
%define include_gappletviewer 1
@@ -145,7 +145,7 @@ Patch21: gcc44-cloog-dl.patch
Patch22: gcc44-raw-string.patch
Patch24: gcc44-atom.patch
Patch25: gcc44-pr39226.patch
-Patch26: gcc44-pr39358.patch
+Patch26: gcc44-power7.patch
Patch1000: fastjar-0.97-segfault.patch
@@ -434,7 +434,7 @@ which are required to compile with the GNAT.
%patch22 -p0 -b .raw-string~
%patch24 -p0 -b .atom~
%patch25 -p0 -b .pr39226~
-%patch26 -p0 -b .pr39358~
+%patch26 -p0 -b .power7~
# This testcase doesn't compile.
rm libjava/testsuite/libjava.lang/PR35020*
@@ -1769,6 +1769,18 @@ fi
%doc rpm.doc/changelogs/libmudflap/ChangeLog*
%changelog
+* Sat Mar 7 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-0.23
+- update from trunk
+ - PRs c++/13549, c++/29469, c++/29607, c++/33492, c++/37520, c++/38908,
+ c++/9634, debug/39372, middle-end/39360, rtl-optimization/39235,
+ testsuite/39357, tree-optimization/39349
+ - emit DW_TAG_imported* even in main or in lexical blocks that
+ contain no automatic variables (#488547, PR debug/39379)
+ - fix DW_AT_decl_line on DW_TAG_imported* (#488771, PR debug/39387)
+ - fix SCCVN with SSA names occurring in abnormal PHIs (#488061,
+ PR tree-optimization/39362)
+- preliminary Power7 support
+
* Wed Mar 4 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-0.22
- update from trunk
- PRs ada/39172, ada/39264, bootstrap/39257, c++/36411, c++/37789,
diff --git a/power7.patch b/power7.patch
new file mode 100644
index 0000000..a9c1948
--- /dev/null
+++ b/power7.patch
@@ -0,0 +1,9506 @@
+2009-03-06 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mvsx-scalar-memory): New switch, to switch to
+ use VSX reg+reg addressing for all scalar double precision
+ floating point.
+ * config/rs6000/rs6000.opt (-vsx-scalar-memory): Ditto.
+
+ * configure.ac (gcc_cv_as_powerpc_mfpgpr): Set binutils version to
+ 2.19.2.
+ (gcc_cv_as_powerpc_cmpb): Ditto.
+ (gcc_cv_as_powerpc_dfp): Ditto.
+ (gcc_cv_as_powerpc_vsx): Ditto.
+ (gcc_cv_as_powerpc_popcntd): Ditto.
+ * configure: Regenerate.
+
+ * config/rs6000/vector.md (VEC_int): New mode attribute for vector
+ conversions.
+ (VEC_INT): Ditto.
+ (ftrunc<mode>2): Make this a define_expand.
+ (float<VEC_int><mode>2): New vector conversion support to add VSX
+ 32 bit int/32 bit floating point convert and 64 bit int/64 bit
+ floating point vector instructions.
+ (unsigned_float<VEC_int><mode>2): Ditto.
+ (fix_trunc<mode><VEC_int>2): Ditto.
+ (fixuns_trunc<mode><VEC_int>2): Ditto.
+
+ * config/rs6000/predicates.md (easy_fp_constant): 0.0 is an easy
+ constant under VSX.
+ (indexed_or_indirect_operand): Add VSX load/store with update
+ support.
+
+ * config/rs6000/rs6000.c (rs6000_debug_addr): New global for
+ -mdebug=addr.
+ (rs6000_init_hard_regno_mode_ok): Add -mvsx-scalar-memory
+ support.
+ (rs6000_override_options): Add -mdebug=addr support.
+ (rs6000_builtin_conversion): Add VSX same size conversions.
+ (rs6000_legitimize_address): Add -mdebug=addr support. Add
+ support for VSX load/store with update instructions.
+ (rs6000_legitimize_reload_address): Ditto.
+ (rs6000_legitimate_address): Ditto.
+ (rs6000_mode_dependent_address): Ditto.
+ (print_operand): Ditto.
+ (bdesc_1arg): Add builtins for conversion that calls either the
+ VSX or Altivec insn pattern.
+ (rs6000_common_init_builtins): Ditto.
+
+ * config/rs6000/vsx.md (VSX_I): Delete, no longer used.
+ (VSi): New mode attribute for conversions.
+ (VSI): Ditto.
+ (VSc): Ditto.
+ (vsx_mov<mode>): Add load/store with update support.
+ (vsx_load<mode>_update*): New insns for load/store with update
+ support.
+ (vsx_store<mode>_update*): Ditto.
+ (vsx_fmadd<mode>4): Generate correct code for V4SF.
+ (vsx_fmsub<mode>4): Ditto.
+ (vsx_fnmadd<mode>4_*): Ditto.
+ (vsx_fnmsub<mode>4_*): Ditto.
+ (vsx_float<VSi><mode>2): New insn for vector conversion.
+ (vsx_floatuns<VSi><mode>2): Ditto.
+ (vsx_fix_trunc<mode><VSi>2): Ditto.
+ (vsx_fixuns_trunc<mode><VSi>2): Ditto.
+ (vsx_xxmrghw): New insn for V4SF interleave.
+ (vsx_xxmrglw): Ditto.
+
+ * config/rs6000/rs6000.h (rs6000_debug_addr): -mdebug=addr
+ support.
+ (TARGET_DEBUG_ADDR): Ditto.
+ (rs6000_builtins): Add VSX instructions for eventual VSX
+ builtins.
+
+ * config/rs6000/altivec.md (altivec_vmrghsf): Don't do the altivec
+ instruction if VSX.
+ (altivec_vmrglsf): Ditto.
+
+ * config/rs6000/rs6000.md (movdf_hardfloat32): Add support for
+ using xxlxor to zero a floating register if VSX.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_hardfloat64): Ditto.
+
+2009-03-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (vsx_xxmrglw): Delete for now, use Altivec.
+ (vsx_xxmrghw): Ditto.
+
+ * config/rs6000/altivec.md (altivec_vmrghsf): Use this insn even
+ on VSX systems.
+ (altivec_vmrglsf): Ditto.
+
+ * config/rs6000/rs6000.h (ASM_CPU_NATIVE_SPEC): Use %(asm_default)
+ if we are running as a cross compiler.
+
+ * config/rs6000/vector.md (vec_interleave_highv4sf): Use correct
+ constants for the extraction.
+ (vec_interleave_lowv4sf): Ditto.
+
+ * config/rs6000/rs6000.md (floordf2): Fix typo, make this a
+ define_expand, not define_insn.
+
+ * config/rs6000/aix53.h (ASM_CPU_SPEC): If -mcpu=native, call
+ %:local_cpu_detect(asm) to get the appropriate assembler flags for
+ the machine.
+ * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto.
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Ditto.
+ (ASM_CPU_NATIVE_SPEC): New spec to get asm options if
+ -mcpu=native.
+ (EXTRA_SPECS): Add ASM_CPU_NATIVE_SPEC.
+
+ * config/rs6000/driver-rs6000.c (asm_names): New static array to
+ give the appropriate asm switches if -mcpu=native.
+ (host_detect_local_cpu): Add support for "asm".
+
+ * config/rs6000/rs6000.c (processor_target_table): Don't turn on
+ -misel by default for power7.
+
+2009-03-02 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_swdivdf): Revert last
+ change, since we reverted the floating multiply/add changes.
+
+ * doc/md.texi (Machine Constraints): Update rs6000 constraints.
+
+ * config/rs6000/vector.md (neg<mode>2): Fix typo to enable
+ vectorized negation.
+ (ftrunc<mode>2): Move ftrunc expander here from altivec.md, and
+ add V2DF case.
+ (vec_interleave_highv4sf): Correct type to be V4SF, not V4SI.
+ (vec_extract_evenv2df): Add expander.
+ (vec_extract_oddv2df): Ditto.
+
+ * config/rs6000/vsx.md (vsx_ftrunc<mode>2): New VSX pattern for
+ truncate.
+ (vsx_ftruncdf2): Ditto.
+ (vsx_xxspltw): New instruction for word splat.
+ (vsx_xxmrglw): Whitespace changes. Fix typo from V4SI to v4SF.
+ (vsx_xxmrghw): Ditto.
+
+ * config/rs6000/altivec.md (altivec_vmrghsf): Whitespace changes.
+ (altivec_vmrglsf): Ditto.
+ (altivec_vspltsf): Disable if we have VSX.
+ (altivec_ftruncv4sf2): Move expander to vector.md, rename insn.
+
+ * config/rs6000/rs6000.md (ftruncdf2): Add expander for VSX.
+
+ * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok):
+ Reenable vectorizing V4SF under altivec.
+ (rs6000_hard_regno_mode_ok): Don't allow floating values in LR,
+ CTR, MQ. Also, VRSAVE/VSCR are both 32-bits.
+ (rs6000_init_hard_regno_mode_ok): Print some of the special
+ registers if -mdebug=reg.
+
+ * config/rs6000/rs6000.md (floating multiply/add insns): Go back
+ to the original semantics for multiply add/subtract, particularly
+ with -ffast-math.
+
+ * config/rs6000/vsx.md (floating multiply/add insns): Mirror the
+ rs6000 floating point multiply/add insns in VSX.
+
+2009-03-01 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (VEC_L): At TImode.
+ (VEC_M): Like VEC_L, except no TImode.
+ (VEC_base): Add TImode support.
+ (mov<mode>): Use VEC_M, not VEC_L. If there is no extra
+ optimization for the move, just generate the standard move.
+ (vector_store_<mode>): Ditto.
+ (vector_load_<mode>): Ditto.
+ (vec_init<mode>): Use vec_init_operand predicate.
+
+ * config/rs6000/predicates.md (vec_init_operand): New predicate.
+
+ * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow mode
+ in a VSX register if there is a move operation.
+ (rs6000_vector_reg_class): Add internal register number to the
+ debug output.
+ (rs6000_init_hard_regno_mode_ok): Reorganize so all of the code
+ for a given type is located together. If not -mvsx, make "ws"
+ constraint become NO_REGS, not FLOAT_REGS. Change -mdebug=reg
+ output.
+ (rs6000_expand_vector_init): Before calling gen_vsx_concat_v2df,
+ make sure the two float arguments are copied into registers.
+ (rs6000_legitimate_offset_address_p): If no vsx or altivec, don't
+ disallow offset addressing. Add V2DImode. If TImode is handled
+ by the vector unit, allow indexed addressing. Change default case
+ to be a fatal_insn instead of gcc_unreachable.
+ (rs6000_handle_altivec_attribute): Add support for vector double
+ if -mvsx.
+ (rs6000_register_move_cost): Add support for VSX_REGS. Know that
+ under VSX, you can move between float and altivec registers
+ cheaply.
+ (rs6000_emit_swdivdf): Change the pattern of the negate multiply
+ and subtract operation.
+
+ * config/rs6000/vsx.md (VSX_I): Add TImode.
+ (VSX_L): Add TImode.
+ (VSm): Ditto.
+ (VSs): Ditto.
+ (VSr): Ditto.
+ (UNSPEC_VSX_CONCAT_V2DF): New constant.
+ (vsx_fre<mode>2): Add reciprocal estimate.
+ (vsx_freDF2): Ditto.
+ (vsx_fnmadd<mode>4): Rework pattern so it matches the
+ canonicalization that the compiler does.
+ (vsx_fnmsub<mode>4): Ditto.
+ (vsx_fnmaddDF4): Ditto.
+ (vsx_fnmsubDF4): Ditto.
+ (vsx_vsel<mode>): Use vsx_register_operand, not register_operand.
+ (vsx_adddf3): Ditto.
+ (vsx_subdf3): Ditto.
+ (vsx_muldf3): Ditto.
+ (vsx_divdf3): Ditto.
+ (vsx_negdf3): Ditto.
+ (vsx_absdf2): Ditto.
+ (vsx_nabsdf2): Ditto.
+ (vsx_copysign<mode>3): Add copysign support.
+ (vsx_copysignDF3): Ditto.
+ (vsx_concat_v2df): Rewrite to use an UNSPEC.
+ (vsx_set_v2df): Use "ws" constraint for scalar float.
+ (vsx_splatv2df): Ditto.
+
+ * config/rs6000/rs6000.h (VECTOR_UNIT_NONE_P): New macro to say no
+ vector support.
+ (VECTOR_MEM_NONE_P): Ditto.
+ (VSX_MOVE_MODE): Add V2DImode, TImode.
+
+ * config/rs6000/altivec.md (VM): Add V2DI, TI.
+ (build_vector_mask_for_load): Fix thinko in VSX case.
+
+ * config/rs6000/rs6000.md (fmaddsf4_powerpc): Name previously
+ unnamed pattern. Fix insns so combine will generate the negative
+ multiply and subtract operations.
+ (fmaddsf4_power): Ditto.
+ (fmsubsf4_powerpc): Ditto.
+ (fmsubsf4_power): Ditto.
+ (fnmaddsf4_powerpc): Ditto.
+ (fnmaddsf4_power): Ditto.
+ (fnmsubsf4_powerpc): Ditto.
+ (fnmsubsf4_power): Ditto.
+ (fnsubsf4_powerpc2): Ditto.
+ (fnsubsf4_power2): Ditto.
+ (fmadddf4_powerpc): Ditto.
+ (fmadddf4_power): Ditto.
+ (fmsubdf4_powerpc): Ditto.
+ (fmsubdf4_power): Ditto.
+ (fnmadddf4_powerpc): Ditto.
+ (fnmadddf4_power): Ditto.
+ (fnmsubdf4_powerpc): Ditto.
+ (fnmsubdf4_power): Ditto.
+ (copysigndf3): If VSX, call the VSX copysign.
+ (fred): Split into an expander and insn. On insn, disable if
+ VSX.
+ (movdf_hardfloat32): Rework VSX support.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_hardfloat64): Ditto.
+ (movti_ppc64): If vector unit is handling TImode, disable this
+ pattern.
+
+2009-02-28 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/ppc-asm.h: If __VSX__ define the additional scalar
+ floating point registers that overlap with th Altivec registers.
+
+2009-02-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/spe.md (spe_fixuns_truncdfsi2): Rename from
+ fixuns_truncdfsi2, and move fixuns_truncdfsi2 into rs6000.md.
+
+ * config/rs6000/ppc-asm.h: If __ALTIVEC__ is defined, define the
+ Altivec registers. If __VSX__ is defined, define the VSX
+ registers.
+
+ * config/rs6000/rs6000.opt (-mvsx-scalar-double): Make this on by
+ default.
+ (-misel): Make this a target mask instead of a variable.
+
+ * config/rs6000/rs6000.c (rs6000_isel): Delete global variable.
+ (rs6000_explicit_options): Delete isel field.
+ (POWERPC_MASKS): Add MASK_ISEL.
+ (processor_target_table): Add MASK_ISEL to 8540, 8548, e500mc, and
+ power7 processors.
+ (rs6000_override_options): Move -misel to a target mask.
+ (rs6000_handle_option): Ditto.
+ (rs6000_emit_int_cmove): Add support for 64-bit isel.
+
+ * config/rs6000/vsx.md (vsx_floatdidf2): New scalar floating point
+ pattern to support VSX conversion and rounding instructions.
+ (vsx_floatunsdidf2): Ditto.
+ (vsx_fix_trundfdi2): Ditto.
+ (vsx_fixuns_trundfdi2): Ditto.
+ (vsx_btrundf2): Ditto.
+ (vsx_floordf2): Ditto.
+ (vsx_ceildf2): Ditto.
+
+ * config/rs6000/rs6000.h (rs6000_isel): Delete global.
+ (TARGET_ISEL): Delete, since -misel is now a target mask.
+ (TARGET_ISEL64): New target option for -misel on 64-bit systems.
+
+ * config/rs6000/altivec.md (altivec_gtu<mode>): Use gtu, not geu.
+
+ * config/rs6000/rs6000.md (sel): New mode attribute for 64-bit
+ ISEL support.
+ (mov<mode>cc): Add 64-bit ISEL support.
+ (isel_signed_<mode>): Ditto.
+ (isel_unsigned_<mode>): Ditto.
+ (fixuns_truncdfsi2): Move expander here from spe.md.
+ (fixuns_truncdfdi2): New expander for unsigned floating point
+ conversion on power7.
+ (btruncdf2): Split into expander and insn. On the insn, disallow
+ on VSX, so the VSX instruction will be generated.
+ (ceildf2): Ditto.
+ (floordf2): Ditto.
+ (floatdidf2): Ditto.
+ (fix_truncdfdi2): Ditto.
+ (smindi3): Define if we have -misel on 64-bit systems.
+ (smaxdi3): Ditto.
+ (umindi3): Ditto.
+ (umaxdi3): Ditto.
+
+ * config/rs6000/e500.h (CHECK_E500_OPTIONS): Disable -mvsx on
+ E500.
+
+2009-02-26 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/constraints.md ("wd" constraint): Change the
+ variable that holds the register class to use.
+ ("wf" constraint): Ditto.
+ ("ws" constraint): Ditto.
+ ("wa" constraint): Ditto.
+
+ * config/rs6000/rs6000.opt (-mvsx-vector-memory): Make this on by
+ default.
+ (-mvsx-vector-float): Ditto.
+
+ * config/rs6000/rs6000.c (rs6000_vector_reg_class): New global to
+ hold the register classes for the vector modes.
+ (rs6000_vsx_v4sf_regclass): Delete, move into
+ rs6000_vector_reg_class.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_reg_class): Rename from rs6000_vsx_any_regclass.
+ (rs6000_hard_regno_mode_ok): Rework VSX, Altivec registers.
+ (rs6000_init_hard_regno_mode_ok): Setup rs6000_vector_reg_class.
+ Drop rs6000_vsx_*_regclass. By default, use all 64 registers for
+ V4SF and V2DF. Use VSX_REG_CLASS_P macro instead of separate
+ tests. Update -mdebug=reg printout.
+ (rs6000_preferred_reload_class): If VSX, prefer FLOAT_REGS for
+ scalar floating point and ALTIVEC_REGS for the types that have
+ altivec instructions.
+ (rs6000_secondary_memory_needed): If VSX, we can copy between FPR
+ and Altivec registers without needed memory.
+ (rs6000_secondary_reload_class): Delete ATTRIBUTE_UNUSED from an
+ argument that is used. If VSX, we can copy between FPR and
+ Altivec registers directly.
+
+ * config/rs6000/rs6000.h (VSX_MOVE_MODE): Add in the Altivec
+ types.
+ (rs6000_vsx_v4sf_regclass): Delete.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_reg_class): Rename from rs6000_vsx_any_reg_class.
+ (rs6000_vector_reg_class): New global to map machine mode to the
+ preferred register class to use for that mode.
+ (VSX_REG_CLASS_P): New macro to return true for all of the
+ register classes VSX items can be in.
+
+2009-02-25 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mvsx-vector-memory): Rename from
+ -mvsx-vector-move.
+ (-mvsx-vector-logical): Delete.
+
+ * config/rs6000/aix53.h (ASM_CPU_SPEC): Add power7 support.
+ * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto.
+
+ * config/rs6000/vector.md (all insns); Change from using
+ rs6000_vector_info to VECTOR_MEM_* or VECTOR_UNIT_* macros.
+
+ * config/rs6000/constraints.md ("wi" constraint): Delete.
+ ("wl" constraint): Ditto.
+ ("ws" constraint): Change to use rs6000_vsx_df_regclass.
+
+ * config/rs6000/rs6000.opt (-mvsx-vector-memory): Rename from
+ -mvsx-vector-move.
+ (-mvsx-vector-float): Make default 0, not 1.
+ (-mvsx-vector-double): Make default -1, not 1.
+ (-mvsx-vector-logical): Delete.
+
+ * config/rs6000/rs6000.c (rs6000_vector_info): Delete.
+ (rs6000_vector_unit): New global array to say what vector unit is
+ used for arithmetic instructions.
+ (rs6000_vector_move): New global array to say what vector unit is
+ used for memory references.
+ (rs6000_vsx_int_regclass): Delete.
+ (rs6000_vsx_logical_regclass): Delete.
+ (rs6000_hard_regno_nregs_internal): Switch from using
+ rs6000_vector_info to rs6000_vector_unit, rs6000_vector_move.
+ (rs6000_hard_regno_mode_ok): Ditto. Reformat code somewhat.
+ (rs6000_debug_vector_unit): New array to print vector unit
+ information if -mdebug=reg.
+ (rs6000_init_hard_regno_mode_ok): Rework to better describe VSX
+ and Altivec register sets.
+ (builtin_mask_for_load): Return 0 if -mvsx.
+ (rs6000_legitimize_reload_address): Allow AND in VSX addresses.
+ (rs6000_legitimate_address): Ditto.
+ (bdesc_3arg): Delete vselv2di builtin.
+ (rs6000_emit_minmax): Use rs6000_vector_unit instead of
+ rs6000_vector_info.
+ (rs6000_vector_mode_supported_p): Ditto.
+
+ * config/rs6000/vsx.md (all insns): Change from using
+ rs6000_vector_info to VECTOR_MEM_* and VECTOR_UNIT_* macros.
+ (VSr): Change to use "v" register class, not "wi".
+ (vsx_mov<mode>): Combine floating and integer. Allow prefered
+ register class, and then use ?wa for all VSX registers.
+ (vsx_fmadddf4): Use ws constraint, not f.
+ (vsx_fmsubdf4): Ditto.
+ (vsx_fnmadddf4): Ditto.
+ (vsx_fnmsubdf4): Ditto.
+ (vsx_and<mode>3): Use preferred register class, and then ?wa to
+ catch all VSX registers.
+ (vsx_ior<mode>3): Ditto.
+ (vsx_xor<mode>3): Ditto.
+ (vsx_one_cmpl<mode>2): Ditto.
+ (vsx_nor<mode>3): Ditto.
+ (vsx_andc<mode>3): Ditto.
+
+ * config/rs6000/rs6000.h (rs6000_vector_struct): Delete.
+ (rs6000_vector_info): Ditto.
+ (rs6000_vector_unit): New global array to say whether a machine
+ mode arithmetic is handled by a particular vector unit.
+ (rs6000_vector_mem): New global array to say which vector unit to
+ use for moves.
+ (VECTOR_UNIT_*): New macros to say which vector unit to use.
+ (VECTOR_MEM_*): Ditto.
+ (rs6000_vsx_int_regclass): Delete.
+ (rs6000_vsx_logical_regclass): Delete.
+
+ * config/rs6000/altivec.md (all insns): Change from using
+ rs6000_vector_info to VECTOR_MEM_* and VECTOR_UNIT_* macros.
+ (build_vector_mask_for_load): Disable if VSX.
+
+ * config/rs6000/rs6000.md (all DF insns): Change how the VSX
+ exclusion is done.
+
+2009-02-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_debug_reg): New global.
+ (rs6000_debug_reg_print): New function to print register classes
+ for a given register range.
+ (rs6000_init_hard_regno_mode_ok): If -mdebug=reg, print out the
+ register class, call used, fixed information for most of the
+ registers. Print the vsx register class variables.
+ (rs6000_override_options): Add -mdebug=reg support.
+
+ * config/rs6000/rs6000.h (rs6000_debug_reg): New global.
+ (TARGET_DEBUG_REG): New target switch for -mdebug=reg.
+
+2009-02-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * reload.c (subst_reloads): Change gcc_assert into a fatal_insn.
+
+ * config/rs6000/vector.md (VEC_I): Reorder iterator.
+ (VEC_L): Ditto.
+ (VEC_C): New iterator field for vector comparisons.
+ (VEC_base): New mode attribute that mapes the vector type to the
+ base type.
+ (all insns): Switch to use rs6000_vector_info to determine whether
+ the insn is valid instead of using TARGET_VSX or TARGET_ALTIVEC.
+ (vcond<mode>): Move here from altivec, and add VSX support.
+ (vcondu<mode>): Ditto.
+ (vector_eq<mode>): New expander for vector comparisons.
+ (vector_gt<mode>): Ditto.
+ (vector_ge<mode>): Ditto.
+ (vector_gtu<mode>): Ditto.
+ (vector_geu<mode>): Ditto.
+ (vector_vsel<mode>): New expander for vector select.
+ (vec_init<mode>): Move expander from altivec.md and generalize for
+ VSX.
+ (vec_set<mode>): Ditto.
+ (vec_extract<mode>): Ditto.
+ (vec_interleave_highv4sf): Ditto.
+ (vec_interleave_lowv4sf): Ditto.
+ (vec_interleave_highv2df): New expander for VSX.
+ (vec_interleave_lowv2df): Ditto.
+
+ * config/rs6000/contraints.md (toplevel): Add comment on the
+ available constraint letters.
+ ("w" constraint): Delete, in favor of using "w" as a two letter
+ constraint.
+ ("wd" constraint): New VSX constraint.
+ ("wf" constraint): Ditto.
+ ("wi" constraint): Ditto.
+ ("wl" constraint): Ditto.
+ ("ws" constraint): Ditto.
+ ("wa" constraint): Ditto.
+
+ * config/rs6000/predicates.md (indexed_or_indirect_operand):
+ Disable altivec support allowing AND of memory address if -mvsx.
+
+ * config/rs6000/rs6000.opt (-mvsx-vector-move): New switches to
+ allow finer control over whether VSX, Altivec, or the traditional
+ instructions are used.
+ (-mvsx-scalar-move): Ditto.
+ (-mvsx-vector-float): Ditto.
+ (-mvsx-vector-double): Ditto.
+ (-mvsx-vector-logical): Ditto.
+ (-mvsx-scalar-double): Ditto.
+
+ * config/rs6000/rs6000.c (rs6000_vector_info): New global to hold
+ various information about which vector instruction set to use, and
+ the alignment of data.
+ (rs6000_vsx_v4sf_regclass): New global to hold VSX register
+ class.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_int_regclass): Ditto.
+ (rs6000_vsx_logical_regclass): Ditto.
+ (rs6000_vsx_any_regclass): Ditto.
+ (rs6000_hard_regno_nregs_internal): Rewrite to fine tune
+ VSX/Altivec register selection.
+ (rs6000_hard_regno_mode_ok): Ditto.
+ (rs6000_init_hard_regno_mode_ok): Set up the vector information
+ globals based on the -mvsx-* switches.
+ (rs6000_override_options): Add warnings for -mvsx and
+ -mlittle-endian or -mavoid-indexed-addresses.
+ (rs6000_builtin_vec_perm): Add V2DF/V2DI support.
+ (rs6000_expand_vector_init): Add V2DF support.
+ (rs6000_expand_vector_set): Ditto.
+ (rs6000_expand_vector_extract): Ditto.
+ (avoiding_indexed_address_p): Add VSX support.
+ (rs6000_legitimize_address): Ditto.
+ (rs6000_legitimize_reload_address): Ditto.
+ (rs6000_legitimite_address): Ditto.
+ (USE_ALTIVEC_FOR_ARG_P): Ditto.
+ (function_arg_boundary): Ditto.
+ (function_arg_advance): Ditto.
+ (function_arg): Ditto.
+ (get_vec_cmp_insn): Delete.
+ (rs6000_emit_vector_vsx): New function for VSX vector compare.
+ (rs6000_emit_vector_altivec): New function for Altivec vector
+ compare.
+ (get_vsel_insn): Delete.
+ (rs6000_emit_vector_select): Ditto.
+ (rs6000_override_options): If -mvsx, turn on -maltivec by
+ default.
+ (rs6000_builtin_vec_perm): Add support for V2DI, V2DF modes.
+ (bdesc_3arg): Add vector select and vector permute builtins for
+ V2DI and V2DF types. Switch to using the vector_* expander
+ instead of altivec_*.
+ (rs6000_init_builtins): Initialize new type nodes for VSX.
+ Initialize __vector double type. Initialize common builtins for
+ VSX.
+ (rs6000_emit_vector_compare): Add VSX support.
+ (rs6000_vector_mode_supported_p): If VSX, support V2DF.
+
+ * config/rs6000/vsx.md (VSX_I): New iterator for integer modes.
+ (VSX_L): Reorder iterator.
+ (lx_<mode>_vsx): Delete, no longer needed.
+ (stx_<mode>_vsx): Ditto.
+ (all insns): Change to use vsx_<name> instead of <name>_vsx for
+ consistancy with the other rs6000 md files. Change to use the new
+ "w" constraints for all insns. Change to use rs6000_vector_info
+ deciding whether to execute the instruction or not.
+ (vsx_mov<mode>): Rewrite constraints so GPR registers are not
+ chosen as reload targets. Split integer vector loads into a
+ separate insn, and favor the altivec register over the VSX fp
+ registers.
+ (vsx_fmadd<mode>4): Use <mode>, not <type>.
+ (vsx_fmsub<mode>4): Ditto.
+ (vsx_eq<mode>): New insns for V2DF/V4SF vector compare.
+ (vsx_gt<mode>): Ditto.
+ (vsx_ge<mode>): Ditto.
+ (vsx_vsel<mode>): New insns for VSX vector select.
+ (vsx_xxpermdi): New insn for DF permute.
+ (vsx_splatv2df): New insn for DF splat support.
+ (vsx_xxmrglw): New insns for DF interleave.
+ (vsx_xxmrghw): Ditto.
+
+ * config/rs6000/rs000.h (enum rs6000_vector): New enum to
+ describe which vector unit is being used.
+ (struct rs6000_vector_struct): New struct to describe the various
+ aspects about the current vector instruction set.
+ (rs6000_vector_info): New global to describe the current vector
+ instruction set.
+ (SLOW_UNALIGNED_ACCESS): If rs6000_vector_info has alignment
+ information for a type, use that.
+ (VSX_VECTOR_MOVE_MODE): New macro for all VSX vectors that are
+ supported by move instructions.
+ (VSX_MOVE_MODE): New macro for all VSX moves.
+ (enum rs6000_builtins): Add V2DI/V2DF vector select and permute
+ builtins.
+ (rs6000_builtin_type_index): Add new types for VSX vectors.
+ (rs6000_vsx_v4sf_regclass): New global to hold VSX register
+ class.
+ (rs6000_vsx_v2df_regclass): Ditto.
+ (rs6000_vsx_df_regclass): Ditto.
+ (rs6000_vsx_int_regclass): Ditto.
+ (rs6000_vsx_logical_regclass): Ditto.
+ (rs6000_vsx_any_regclass): Ditto.
+
+ * config/rs6000/altivec.md (UNSPEC_VCMP*): Delete unspec
+ constants no longer needed.
+ (UNSPEC_VSEL*): Ditto.
+ (altivec_lvx_<mode>): Delete, no longer needed.
+ (altivec_stvx_<mode>): Ditto.
+ (all insns): Rewrite to be consistant of altivec_<insn>. Switch
+ to use rs6000_vector_info to determine whether to issue to the
+ altivec form of the instructions.
+ (mov<mode>_altivec): Rewrite constraints so GPR registers are not
+ chosen as reload targets.
+ (altivec_eq<mode>): Rewrite vector conditionals, permute, select
+ to use iterators, and work with VSX.
+ (altivec_gt<mode>): Ditto.
+ (altivec_ge<mode>): Ditto.
+ (altivec_gtu<mode>): Ditto.
+ (altivec_geu<mode>): Ditto.
+ (altivec_vsel<mode>): Ditto.
+ (altivec_vperm_<mode>): Ditto.
+ (altivec_vcmp*): Rewrite to not use unspecs any more, and use mode
+ iterators, add VSX support.
+ (vcondv4si): Move to vector.md.
+ (vconduv4si): Ditto.
+ (vcondv8hi): Ditto.
+ (vconduv8hi): Ditto.
+ (vcondv16qi): Ditto.
+ (vconduv16qi): Ditto.
+
+ * config/rs6000/rs6000.md (negdf2_fpr): Add support for
+ -mvsx-scalar-double.
+ (absdf2_fpr): Ditto.
+ (nabsdf2_fpr): Ditto.
+ (adddf3_fpr): Ditto.
+ (subdf3_fpr): Ditto.
+ (muldf3_fpr): Ditto.
+ (divdf3_fpr): Ditto.
+ (DF multiply/add patterns): Ditto.
+ (sqrtdf2): Ditto.
+ (movdf_hardfloat32): Add VSX support.
+ (movdf_hardfloat64_mfpgpr): Ditto.
+ (movdf_hardfloat64): Ditto.
+
+ * doc/invoke.texi (-mvsx-*): Add new vsx switches.
+
+2009-02-13 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config.in: Update two comments.
+
+ * config/rs6000/vector.md (VEC_L): Add V2DI type.
+ (move<mode>): Use VEC_L to get all vector types, and delete the
+ separate integer mode move definitions.
+ (vector_load_<mode>): Ditto.
+ (vector_store_<mode>): Ditto.
+ (vector move splitters): Move GPR register splitters here from
+ altivec.md.
+
+ * config/rs6000/constraints.md ("j"): Add "j" constraint to match
+ the mode's 0 value.
+
+ * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Only
+ count the FPRs as being 128 bits if the mode is a VSX type.
+ (rs6000_hard_regno_mode_ok): Ditto.
+ (rs6000_emit_minmax): Use new VSX_MODE instead of separate tests.
+
+ * config/rs6000/vsx.md (VSX_L): Add V2DImode.
+ (VSm): Rename from VSX_mem, add modes for integer vectors. Change
+ all uses.
+ (VSs): Rename from VSX_op, add modes for integer vectors. Change
+ all uses.
+ (VSr): New mode address to give the register class.
+ (mov<mode>_vsx): Use VSr to get the register preferences. Add
+ explicit 0 option.
+ (scalar double precision patterns): Do not use v register
+ constraint right now.
+ (logical patterns): Use VSr mode attribute for register
+ preferences.
+
+ * config/rs6000/rs6000.h (VSX_SCALAR_MODE): New macro.
+ (VSX_MODE): Ditto.
+
+ * config/rs6000/altivec.md (VM): New mode iterator for memory
+ operations. Add V2DI mode.
+ (mov_altivec_<mode>): Disable if -mvsx for all modes, not just
+ V4SFmode.
+ (gpr move splitters): Move to vector.md.
+ (and<mode>3_altivec): Use VM mode iterator, not V.
+ (ior<mode>3_altivec): Ditto.
+ (xor<mode>3_altivec): Ditto.
+ (one_cmpl<mode>2_altivec): Ditto.
+ (nor<mode>3_altivec): Ditto.
+ (andc<mode>3_altivec): Ditto.
+
+ * config/rs6000/rs6000.md (movdf_hardfloat): Back out vsx changes.
+ (movdf_hardfloat64_vsx): Delete.
+
+2009-02-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md: New file to abstract out the expanders
+ for vector operations from alitvec.md.
+
+ * config/rs6000/predicates.md (vsx_register_operand): New
+ predicate to match VSX registers.
+ (vfloat_operand): New predicate to match registers used for vector
+ floating point operations.
+ (vint_operand): New predicate to match registers used for vector
+ integer operations.
+ (vlogical_operand): New predicate to match registers used for
+ vector logical operations.
+
+ * config/rs6000/rs6000-protos.h (rs6000_hard_regno_nregs): Change
+ from a function to an array.
+ (rs6000_class_max_nregs): Add declaration.
+
+ * config/rs6000/t-rs6000 (MD_INCLUDES): Define to include all of
+ the .md files included by rs6000.md.
+
+ * config/rs6000/rs6000.c (rs6000_class_max_nregs): New global
+ array to pre-calculate CLASS_MAX_NREGS.
+ (rs6000_hard_regno_nregs): Change from a function to an array to
+ pre-calculate HARD_REGNO_NREGS.
+ (rs6000_hard_regno_nregs_internal): Rename from
+ rs6000_hard_regno_nregs and add VSX support.
+ (rs6000_hard_regno_mode_ok): Add VSX support, and switch to use
+ lookup table rs6000_hard_regno_nregs.
+ (rs6000_init_hard_regno_mode_ok): Add initialization of
+ rs6000_hard_regno_nregs, and rs6000_class_max_nregs global
+ arrays.
+ (rs6000_override_options): Add some warnings for things that are
+ incompatible with -mvsx.
+ (rs6000_legitimate_offset_address_p): Add V2DFmode.
+ (rs6000_conditional_register_usage): Enable altivec registers if
+ -mvsx.
+ (bdesc_2arg): Change the name of the nor pattern.
+ (altivec_expand_ld_builtin): Change the names of the load
+ patterns to be the generic vector loads.
+ (altivec_expand_st_builtin): Change the names of the store
+ patterns to be the generic vector stores.
+ (print_operand): Add 'x' to print out a VSX register properly.
+ (rs6000_emit_minmax): Directly emit the min/max patterns for VSX
+ and Altivec.
+
+ * config/rs6000/vsx.md: New file to add all of the VSX specific
+ instructions. Add support for load, store, move, add, subtract,
+ multiply, multiply/add, divide, negate, absolute value, maximum,
+ minimum, sqrt, and, or, xor, and complent, xor, one's complement,
+ and nor instructions.
+
+ * config/rs6000/rs6000.h (UNITS_PER_VSX_WORD): Define.
+ (VSX_REGNO_P): New macro for VSX registers.
+ (VFLOAT_REGNO): New macro for vector floating point registers.
+ (VINT_REGNO): New macro for vector integer registers.
+ (VLOGICAL_REGNO): New macro for vector logical registers.
+ (VSX_VECTOR_MODE): New macro for vector modes supported by VSX.
+ (HARD_REGNO_NREGS): Switch to using pre-computed table.
+ (CLASS_MAX_NREGS): Ditto.
+
+ * config/rs6000/altivec.md (altivec_lvx_<mode>): Delete, repalced
+ by expanders in vector.md.
+ (altivec_stvx_<mode>): Ditto.
+ (mov<mode>): Ditto.
+ (mov_altivec_<mode>): Rename from mov<mode>_internal, and prefer
+ using VSX if available.
+ (addv4sf3_altivec): Rename from standard name, and prefer using
+ VSX if available.
+ (subv4sf3_altivec): Ditto.
+ (mulv4sf3_altivec): Ditto.
+ (smaxv4sf3_altivec): Ditto.
+ (sminv4sf3_altivec): Ditto.
+ (and<mode>3_altivec): Ditto.
+ (ior<mode>3_altivec): Ditto.
+ (xor<mode>3_altivec): Ditto.
+ (one_cmpl<mode>2): Ditto.
+ (nor<mode>3_altivec): Ditto.
+ (andc<mode>3_altivec): Ditto.
+ (absv4sf2_altivec): Ditto.
+ (vcondv4sf): Move to vector.md.
+
+ * config/rs6000/rs6000.md (negdf2_fpr): Add !TARGET_VSX to prefer
+ the version in vsx.md if -mvsx is available.
+ (absdf2_fpr): Ditto.
+ (nabsdf2_fpr): Ditto.
+ (adddf3_fpr): Ditto.
+ (subdf3_fpr): Ditto.
+ (muldf3_fpr): Ditto.
+ (multiply/add patterns): Ditto.
+ (movdf_hardfloat64): Disable if -mvsx.
+ (movdf_hardfloat64_vsx): Clone from movdf_hardfloat64 and add VSX
+ support.
+ (vector.md): Include new .md file.
+ (vsx.md): Ditto.
+
+2009-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mvsx, -mno-vsx): Document new switches.
+
+ * config/rs6000/linux64.opt (-mprofile-kernel): Move to being a
+ variable to reduce the number of target flag bits.
+ * config/rs6000/sysv4.opt (-mbit-align): Ditto.
+ (-mbit-word): Ditto.
+ (-mregnames): Ditto.
+ * config/rs6000/rs6000.opt (-mupdate, -mno-update): Ditto.
+ (-mvsx): New switch, enable VSX support.
+
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
+ __VSX__ if the vector/scalar instruction set is available.
+
+ * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Change
+ to allow -mprofile-kernel to be a variable.
+
+ * config/rs6000/rs6000.c (processor_target_table): Set -mvsx for
+ power7 cpus.
+ (POWERPC_MASKS): Add -mvsx.
+
+ * config/rs6000/rs6000.h (ADDITIONAL_REGISTER_NAMES): Add VSX
+ register names for the registers that overlap with the floating
+ point and altivec registers.
+
+ * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS):
+ TARGET_NO_BITFIELD_WORD is now a variable, not a target mask.
+
+2009-02-11 Pat Haugen <pthaugen@us.ibm.com>
+ Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/invoke.texi (-mpopcntd, -mno-popcntd): Document new
+ switches.
+
+ * configure.ac (powerpc*-*-*): Test for the assembler having the
+ popcntd instruction.
+ * configure: Regenerate.
+ * config.in (HAVE_AS_POPCNTD): Add default value for configure
+ test.
+
+ * config/rs6000/power7.md: New file.
+
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
+ _ARCH_PWR7 if the popcntd instruction is available.
+
+ * config/rs6000/rs6000.opt (-mpopcntd): New switch to
+ enable/disable the use of the popcntd and popcntw instructions.
+ (-mfused-madd, -mno-fused-madd): Move to being a separate variable
+ because we are out of mask bits.
+
+ * config/rs6000/rs6000.c (power7_cost): Define.
+ (rs6000_override_options): Add Power7 support.
+ (rs6000_issue_rate): Ditto.
+ (insn_must_be_first_in_group): Ditto.
+ (insn_must_be_last_in_group): Ditto.
+ (rs6000_emit_popcount): Add support for using the popcntw and
+ popcntd instructions.
+
+ * config/rs6000/rs6000.h (ASM_CPU_POWER7_SPEC): Switch to using
+ popcntd as the test for a power7 assembler instead of vector
+ scalar instructions.
+ * (TARGET_POPCNTD): If assembler does not support the popcntd
+ instruction, disable using it.
+ (processor_type): Add Power7 entry.
+
+ * config/rs6000/rs6000.md (define_attr "cpu"): Add power7.
+ (power7.md): Include it.
+ (andi./andis./nor. patterns): Change insn type to fast_compare.
+ (popcntwsi2): Add popcntw support.
+ (popcntddi2): Add popcntd support.
+
+testsuite/
+2009-03-01 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsx-vector-1.c: Fix typos.
+ * gcc.target/powerpc/vsx-vector-2.c: Ditto.
+
+ * gcc.target/powerpc/vsx-vector-3.c: New file, test __vector
+ double.
+
+ * gcc.target/powerpc/vsx-vector-4.c: New file, test __vector float
+ uses VSX instructions if -mvsx.
+
+ * gcc.dg/vmx/vmx.exp (DEFAULT_VMXCLFAGS): Add -mno-vsx.
+
+ * lib/target-supports.exp (check_vsx_hw_available): New function
+ to test for VSX.
+ (check_vmx_hw_available): Add -mno-vsx to options.
+ (check_effective_target_powerpc_vsx_ok): New function to check if
+ the powerpc compiler can support VSX.
+
+2009-02-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsx-vector-1.c: New file to test VSX code
+ generation.
+ * gcc.target/powerpc/vsx-vector-2.c: Ditto.
+
+2009-02-01 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/popcount-2.c: New file for power7 support.
+ * gcc.target/powerpc/popcount-3.c: Ditto.
+
+--- gcc/doc/invoke.texi (.../trunk) (revision 144557)
++++ gcc/doc/invoke.texi (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -712,7 +712,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
+@@ -726,7 +727,9 @@ 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 -mvsx -mvsx-vector-memory @gol
++-mvsx-vector-float -mvsx-vector-double @gol
++-mvsx-scalar-double -mvsx-scalar-memory @gol
+ -mprioritize-restricted-insns=@var{priority} @gol
+ -msched-costly-dep=@var{dependence_type} @gol
+ -minsert-sched-nops=@var{scheme} @gol
+@@ -13512,6 +13515,8 @@ These @samp{-m} options are defined for
+ @itemx -mno-mfcrf
+ @itemx -mpopcntb
+ @itemx -mno-popcntb
++@itemx -mpopcntd
++@itemx -mno-popcntd
+ @itemx -mfprnd
+ @itemx -mno-fprnd
+ @itemx -mcmpb
+@@ -13536,6 +13541,8 @@ These @samp{-m} options are defined for
+ @opindex mno-mfcrf
+ @opindex mpopcntb
+ @opindex mno-popcntb
++@opindex mpopcntd
++@opindex mno-popcntd
+ @opindex mfprnd
+ @opindex mno-fprnd
+ @opindex mcmpb
+@@ -13585,6 +13592,9 @@ The @option{-mpopcntb} option allows GCC
+ 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.
+@@ -13663,9 +13673,9 @@ The @option{-mcpu} options automatically
+ 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
+@@ -13766,6 +13776,44 @@ 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 -mvsx-vector-memory
++@itemx -mno-vsx-vector-memory
++If @option{-mvsx}, use VSX memory reference instructions for vectors
++instead of the Altivec instructions This option is a temporary switch
++to tune the compiler, and may not be supported in future versions.
++
++@item -mvsx-vector-float
++@itemx -mno-vsx-vector-float
++If @option{-mvsx}, use VSX arithmetic instructions for float vectors.
++This option is a temporary switch to tune the compiler, and may not be
++supported in future versions.
++
++@item -mvsx-vector-double
++@itemx -mno-vsx-vector-double
++If @option{-mvsx}, use VSX arithmetic instructions for double
++vectors. This option is a temporary switch to tune the
++compiler, and may not be supported in future versions.
++
++@item -mvsx-scalar-double
++@itemx -mno-vsx-scalar-double
++If @option{-mvsx}, use VSX arithmetic instructions for scalar double.
++This option is a temporary switch to tune the compiler, and may not be
++supported in future versions.
++
++@item -mvsx-scalar-memory
++@itemx -mno-vsx-scalar-memory
++If @option{-mvsx}, use VSX memory reference instructions for scalar
++double. This option is a temporary switch to tune the compiler, and
++may not be supported in future versions.
++
+ @item -mfloat-gprs=@var{yes/single/double/no}
+ @itemx -mfloat-gprs
+ @opindex mfloat-gprs
+--- gcc/doc/md.texi (.../trunk) (revision 144557)
++++ gcc/doc/md.texi (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -1905,7 +1905,19 @@ Address base register
+ Floating point register
+
+ @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
+@@ -1991,6 +2003,9 @@ AND masks that can be performed by two r
+ @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}
+--- gcc/reload.c (.../trunk) (revision 144557)
++++ gcc/reload.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -6255,8 +6255,14 @@ subst_reloads (rtx insn)
+ *r->where = reloadreg;
+ }
+ /* If reload got no reg and isn't optional, something's wrong. */
+- else
+- gcc_assert (rld[r->what].optional);
++ else if (!rld[r->what].optional)
++ {
++ char buffer[100];
++ sprintf (buffer,
++ "unable to find register for reload, replacement #%d",
++ i);
++ fatal_insn (buffer, insn);
++ }
+ }
+ }
+ \f
+--- gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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);
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,74 @@
++/* { 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" } } */
++
++#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];
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,74 @@
++/* { 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" } } */
++
++#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];
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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;
++}
+--- gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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);
++}
+--- gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../trunk) (revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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;
++}
+--- gcc/testsuite/gcc.dg/vmx/vmx.exp (.../trunk) (revision 144557)
++++ gcc/testsuite/gcc.dg/vmx/vmx.exp (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -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
+--- gcc/testsuite/lib/target-supports.exp (.../trunk) (revision 144557)
++++ gcc/testsuite/lib/target-supports.exp (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -873,6 +873,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.
+
+@@ -883,12 +909,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()
+@@ -1519,6 +1546,33 @@ proc check_effective_target_powerpc_alti
+ }
+ }
+
++# 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 { } {
+--- gcc/config.in (.../trunk) (revision 144557)
++++ gcc/config.in (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -334,12 +334,18 @@
+ #endif
+
+
+-/* Define if your assembler supports popcntb field. */
++/* Define if your assembler supports popcntb instruction. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_AS_POPCNTB
+ #endif
+
+
++/* Define if your assembler supports popcntd instruction. */
++#ifndef USED_FOR_TARGET
++#undef HAVE_AS_POPCNTD
++#endif
++
++
+ /* Define if your assembler supports .register. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_AS_REGISTER_PSEUDO_OP
+--- gcc/configure.ac (.../trunk) (revision 144557)
++++ gcc/configure.ac (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -2,7 +2,7 @@
+ # Process this file with autoconf to generate a configuration script.
+
+ # Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+-# 2007, 2008 Free Software Foundation, Inc.
++# 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ #This file is part of GCC.
+
+@@ -3080,7 +3080,7 @@ foo: nop
+ esac
+
+ gcc_GAS_CHECK_FEATURE([move fp gpr support],
+- gcc_cv_as_powerpc_mfpgpr, [9,99,0],,
++ gcc_cv_as_powerpc_mfpgpr, [2,19,2],,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_MFPGPR, 1,
+ [Define if your assembler supports mffgpr and mftgpr.])])
+@@ -3114,7 +3114,7 @@ LCF0:
+ esac
+
+ gcc_GAS_CHECK_FEATURE([compare bytes support],
+- gcc_cv_as_powerpc_cmpb, [9,99,0], -a32,
++ gcc_cv_as_powerpc_cmpb, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_CMPB, 1,
+ [Define if your assembler supports cmpb.])])
+@@ -3129,7 +3129,7 @@ LCF0:
+ esac
+
+ gcc_GAS_CHECK_FEATURE([decimal float support],
+- gcc_cv_as_powerpc_dfp, [9,99,0], -a32,
++ gcc_cv_as_powerpc_dfp, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_DFP, 1,
+ [Define if your assembler supports DFP instructions.])])
+@@ -3144,11 +3144,26 @@ LCF0:
+ esac
+
+ gcc_GAS_CHECK_FEATURE([vector-scalar support],
+- gcc_cv_as_powerpc_vsx, [9,99,0], -a32,
++ gcc_cv_as_powerpc_vsx, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_VSX, 1,
+ [Define if your assembler supports VSX instructions.])])
+
++ case $target in
++ *-*-aix*) conftest_s=' .machine "pwr7"
++ .csect .text[[PR]]
++ popcntd 3,3';;
++ *) conftest_s=' .machine power7
++ .text
++ popcntd 3,3';;
++ esac
++
++ gcc_GAS_CHECK_FEATURE([popcntd support],
++ gcc_cv_as_powerpc_popcntd, [2,19,2], -a32,
++ [$conftest_s],,
++ [AC_DEFINE(HAVE_AS_POPCNTD, 1,
++ [Define if your assembler supports POPCNTD instructions.])])
++
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_powerpc_gnu_attribute, [2,18,0],,
+ [.gnu_attribute 4,1],,
+--- gcc/configure (.../trunk) (revision 144557)
++++ gcc/configure (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -23225,7 +23225,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set}
+ else
+ gcc_cv_as_powerpc_mfpgpr=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_mfpgpr=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23321,7 +23321,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}"
+ else
+ gcc_cv_as_powerpc_cmpb=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_cmpb=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23367,7 +23367,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" =
+ else
+ gcc_cv_as_powerpc_dfp=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_dfp=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23413,7 +23413,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" =
+ else
+ gcc_cv_as_powerpc_vsx=no
+ if test $in_tree_gas = yes; then
+- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_vsx=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+@@ -23443,6 +23443,52 @@ _ACEOF
+
+ fi
+
++ case $target in
++ *-*-aix*) conftest_s=' .machine "pwr7"
++ .csect .text[PR]
++ popcntd 3,3';;
++ *) conftest_s=' .machine power7
++ .text
++ popcntd 3,3';;
++ esac
++
++ echo "$as_me:$LINENO: checking assembler for popcntd support" >&5
++echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6
++if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++ gcc_cv_as_powerpc_popcntd=no
++ if test $in_tree_gas = yes; then
++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
++ then gcc_cv_as_powerpc_popcntd=yes
++fi
++ elif test x$gcc_cv_as != x; then
++ echo "$conftest_s" > conftest.s
++ if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }
++ then
++ gcc_cv_as_powerpc_popcntd=yes
++ else
++ echo "configure: failed program was" >&5
++ cat conftest.s >&5
++ fi
++ rm -f conftest.o conftest.s
++ fi
++fi
++echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5
++echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6
++if test $gcc_cv_as_powerpc_popcntd = yes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_AS_POPCNTD 1
++_ACEOF
++
++fi
++
+ echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5
+ echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6
+ if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then
+--- gcc/config/rs6000/aix53.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/aix53.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -57,20 +57,24 @@ do { \
+ #undef ASM_SPEC
+ #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
+
+-/* Common ASM definitions used by ASM_SPEC amongst the various targets
+- for handling -mcpu=xxx switches. */
++/* Common ASM definitions used by ASM_SPEC amongst the various targets for
++ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
++ provide the default assembler options if the user uses -mcpu=native, so if
++ you make changes here, make them there also. */
+ #undef ASM_CPU_SPEC
+ #define ASM_CPU_SPEC \
+ "%{!mcpu*: %{!maix64: \
+ %{mpowerpc64: -mppc64} \
+ %{maltivec: -m970} \
+ %{!maltivec: %{!mpower64: %(asm_default)}}}} \
++%{mcpu=native: %(asm_cpu_native)} \
+ %{mcpu=power3: -m620} \
+ %{mcpu=power4: -mpwr4} \
+ %{mcpu=power5: -mpwr5} \
+ %{mcpu=power5+: -mpwr5x} \
+ %{mcpu=power6: -mpwr6} \
+ %{mcpu=power6x: -mpwr6} \
++%{mcpu=power7: -mpwr7} \
+ %{mcpu=powerpc: -mppc} \
+ %{mcpu=rs64a: -mppc} \
+ %{mcpu=603: -m603} \
+--- gcc/config/rs6000/vector.md (.../trunk) (revision 0)
++++ gcc/config/rs6000/vector.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,518 @@
++;; 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.
++;; 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/>.
++
++
++;; Vector int modes
++(define_mode_iterator VEC_I [V16QI V8HI V4SI])
++
++;; Vector float modes
++(define_mode_iterator VEC_F [V4SF V2DF])
++
++;; Vector logical modes
++(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
++
++;; Vector modes for moves. Don't do TImode here.
++(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
++
++;; Vector comparison modes
++(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
++
++;; Base type from vector mode
++(define_mode_attr VEC_base [(V16QI "QI")
++ (V8HI "HI")
++ (V4SI "SI")
++ (V2DI "DI")
++ (V4SF "SF")
++ (V2DF "DF")
++ (TI "TI")])
++
++;; Same size integer type for floating point data
++(define_mode_attr VEC_int [(V4SF "v4si")
++ (V2DF "v2di")])
++
++(define_mode_attr VEC_INT [(V4SF "V4SI")
++ (V2DF "V2DI")])
++
++;; Vector move instructions.
++(define_expand "mov<mode>"
++ [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
++ (match_operand:VEC_M 1 "any_operand" ""))]
++ "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ /* modes without special handling just generate the normal SET operation. */
++ if (<MODE>mode != TImode && <MODE>mode != V2DImode && <MODE>mode != V2DFmode)
++ {
++ rs6000_emit_move (operands[0], operands[1], <MODE>mode);
++ DONE;
++ }
++ else if (!vlogical_operand (operands[0], <MODE>mode)
++ && !vlogical_operand (operands[1], <MODE>mode))
++ operands[1] = force_reg (<MODE>mode, operands[1]);
++})
++
++;; 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_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_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_OR_VSX_P (<MODE>mode)
++ && reload_completed
++ && gpr_or_gpr_p (operands[0], operands[1])"
++ [(pc)]
++{
++ rs6000_split_multireg_move (operands[0], operands[1]);
++ DONE;
++})
++
++\f
++;; Generic floating point vector arithmetic support
++(define_expand "add<mode>3"
++ [(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_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_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_VSX_P (<MODE>mode)
++ || (VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD))"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_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_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_OR_VSX_P (<MODE>mode)"
++ "")
++
++\f
++;; Vector comparisons
++(define_expand "vcond<mode>"
++ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
++ (if_then_else:VEC_F
++ (match_operator 3 "comparison_operator"
++ [(match_operand:VEC_F 4 "vfloat_operand" "")
++ (match_operand:VEC_F 5 "vfloat_operand" "")])
++ (match_operand:VEC_F 1 "vfloat_operand" "")
++ (match_operand:VEC_F 2 "vfloat_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++ "
++{
++ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
++ operands[3], operands[4], operands[5]))
++ DONE;
++ else
++ FAIL;
++}")
++
++(define_expand "vcond<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "")
++ (if_then_else:VEC_I
++ (match_operator 3 "comparison_operator"
++ [(match_operand:VEC_I 4 "vint_operand" "")
++ (match_operand:VEC_I 5 "vint_operand" "")])
++ (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "
++{
++ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
++ operands[3], operands[4], operands[5]))
++ DONE;
++ else
++ FAIL;
++}")
++
++(define_expand "vcondu<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "=v")
++ (if_then_else:VEC_I
++ (match_operator 3 "comparison_operator"
++ [(match_operand:VEC_I 4 "vint_operand" "")
++ (match_operand:VEC_I 5 "vint_operand" "")])
++ (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "
++{
++ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
++ operands[3], operands[4], operands[5]))
++ DONE;
++ else
++ FAIL;
++}")
++
++(define_expand "vector_eq<mode>"
++ [(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_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_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_OR_VSX_P (<MODE>mode)"
++ "")
++
++(define_expand "vector_gtu<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "")
++ (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "")
++
++(define_expand "vector_geu<mode>"
++ [(set (match_operand:VEC_I 0 "vint_operand" "")
++ (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
++ (match_operand:VEC_I 2 "vint_operand" "")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "")
++
++;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
++;; which is in the reverse order that we want
++(define_expand "vector_vsel<mode>"
++ [(match_operand:VEC_F 0 "vlogical_operand" "")
++ (match_operand:VEC_F 1 "vlogical_operand" "")
++ (match_operand:VEC_F 2 "vlogical_operand" "")
++ (match_operand:VEC_F 3 "vlogical_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++ "
++{
++ if (VECTOR_UNIT_VSX_P (<MODE>mode))
++ emit_insn (gen_vsx_vsel<mode> (operands[0], operands[3],
++ operands[2], operands[1]));
++ else
++ emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
++ operands[2], operands[1]));
++ DONE;
++}")
++
++(define_expand "vector_vsel<mode>"
++ [(match_operand:VEC_I 0 "vlogical_operand" "")
++ (match_operand:VEC_I 1 "vlogical_operand" "")
++ (match_operand:VEC_I 2 "vlogical_operand" "")
++ (match_operand:VEC_I 3 "vlogical_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "
++{
++ emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
++ operands[2], operands[1]));
++ DONE;
++}")
++
++\f
++;; Vector logical instructions
++(define_expand "xor<mode>3"
++ [(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_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_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_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_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_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_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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ 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_OR_VSX_P (<MODE>mode)"
++ "
++{
++ if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
++ {
++ emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
++ DONE;
++ }
++}")
++
++\f
++;; Vector initialization, set, extract
++(define_expand "vec_init<mode>"
++ [(match_operand:VEC_C 0 "vlogical_operand" "")
++ (match_operand:VEC_C 1 "vec_init_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ rs6000_expand_vector_init (operands[0], operands[1]);
++ DONE;
++})
++
++(define_expand "vec_set<mode>"
++ [(match_operand:VEC_C 0 "vlogical_operand" "")
++ (match_operand:<VEC_base> 1 "register_operand" "")
++ (match_operand 2 "const_int_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
++ DONE;
++})
++
++(define_expand "vec_extract<mode>"
++ [(match_operand:<VEC_base> 0 "register_operand" "")
++ (match_operand:VEC_C 1 "vlogical_operand" "")
++ (match_operand 2 "const_int_operand" "")]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++{
++ rs6000_expand_vector_extract (operands[0], operands[1],
++ INTVAL (operands[2]));
++ DONE;
++})
++
++;; Interleave patterns
++(define_expand "vec_interleave_highv4sf"
++ [(set (match_operand:V4SF 0 "vfloat_operand" "")
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
++ "")
++
++(define_expand "vec_interleave_lowv4sf"
++ [(set (match_operand:V4SF 0 "vfloat_operand" "")
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
++ "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)"
++ "")
++
++;; For 2 element vectors, even/odd is the same as high/low
++(define_expand "vec_extract_evenv2df"
++ [(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_extract_oddv2df"
++ [(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)"
++ "")
+--- gcc/config/rs6000/spe.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/spe.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -99,7 +99,7 @@ (define_insn "*divsf3_gpr"
+
+ ;; Floating point conversion instructions.
+
+-(define_insn "fixuns_truncdfsi2"
++(define_insn "spe_fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+--- gcc/config/rs6000/constraints.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/constraints.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -17,6 +17,8 @@
+ ;; along with GCC; see the file COPYING3. If not see
+ ;; <http://www.gnu.org/licenses/>.
+
++;; Available constraint letters: "e", "k", "u", "A", "B", "C", "D"
++
+ ;; Register constraints
+
+ (define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS
+@@ -50,6 +52,23 @@ (define_register_constraint "y" "CR_REGS
+ (define_register_constraint "z" "XER_REGS"
+ "@internal")
+
++;; Use w as a prefix to add VSX modes
++;; vector double (V2DF)
++(define_register_constraint "wd" "rs6000_vector_reg_class[V2DFmode]"
++ "@internal")
++
++;; vector float (V4SF)
++(define_register_constraint "wf" "rs6000_vector_reg_class[V4SFmode]"
++ "@internal")
++
++;; scalar double (DF)
++(define_register_constraint "ws" "rs6000_vector_reg_class[DFmode]"
++ "@internal")
++
++;; any VSX register
++(define_register_constraint "wa" "rs6000_vsx_reg_class"
++ "@internal")
++
+ ;; Integer constraints
+
+ (define_constraint "I"
+@@ -159,3 +178,7 @@ (define_constraint "t"
+ (define_constraint "W"
+ "vector constant that does not require memory"
+ (match_operand 0 "easy_vector_constant"))
++
++(define_constraint "j"
++ "Zero vector constant"
++ (match_test "(op == const0_rtx || op == CONST0_RTX (GET_MODE (op)))"))
+--- gcc/config/rs6000/predicates.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/predicates.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -38,6 +38,37 @@ (define_predicate "altivec_register_oper
+ || ALTIVEC_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
++;; Return 1 if op is a VSX register.
++(define_predicate "vsx_register_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VSX_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
++;; Return 1 if op is a vector register that operates on floating point vectors
++;; (either altivec or VSX).
++(define_predicate "vfloat_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VFLOAT_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
++;; Return 1 if op is a vector register that operates on integer vectors
++;; (only altivec, VSX doesn't support integer vectors)
++(define_predicate "vint_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VINT_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
++;; Return 1 if op is a vector register to do logical operations on (and, or,
++;; xor, etc.)
++(define_predicate "vlogical_operand"
++ (and (match_operand 0 "register_operand")
++ (match_test "GET_CODE (op) != REG
++ || VLOGICAL_REGNO_P (REGNO (op))
++ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
++
+ ;; Return 1 if op is XER register.
+ (define_predicate "xer_operand"
+ (and (match_code "reg")
+@@ -234,6 +265,10 @@ (define_predicate "easy_fp_constant"
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
+
+ case DFmode:
++ /* The constant 0.f is easy under VSX. */
++ if (op == CONST0_RTX (DFmode) && VECTOR_UNIT_VSX_P (DFmode))
++ return 1;
++
+ /* Force constants to memory before reload to utilize
+ compress_float_constant.
+ Avoid this when flag_unsafe_math_optimizations is enabled
+@@ -396,13 +431,16 @@ (define_predicate "indexed_or_indirect_o
+ (match_code "mem")
+ {
+ op = XEXP (op, 0);
+- if (TARGET_ALTIVEC
+- && ALTIVEC_VECTOR_MODE (mode)
++ if (VECTOR_MEM_ALTIVEC_P (mode)
+ && GET_CODE (op) == AND
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && INTVAL (XEXP (op, 1)) == -16)
+ op = XEXP (op, 0);
+
++ else if (VECTOR_MEM_VSX_P (mode)
++ && GET_CODE (op) == PRE_MODIFY)
++ op = XEXP (op, 1);
++
+ return indexed_or_indirect_address (op, mode);
+ })
+
+@@ -1336,3 +1374,19 @@ (define_predicate "stmw_operation"
+
+ return 1;
+ })
++
++;; Return true if the operand is a legitimate parallel for vec_init
++(define_predicate "vec_init_operand"
++ (match_code "parallel")
++{
++ /* Disallow V2DF mode with MEM's unless both are the same under VSX. */
++ if (mode == V2DFmode && VECTOR_UNIT_VSX_P (mode))
++ {
++ rtx op0 = XVECEXP (op, 0, 0);
++ rtx op1 = XVECEXP (op, 0, 1);
++ if ((MEM_P (op0) || MEM_P (op1)) && !rtx_equal_p (op0, op1))
++ return 0;
++ }
++
++ return 1;
++})
+--- gcc/config/rs6000/ppc-asm.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/ppc-asm.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -63,7 +63,7 @@
+ #define f16 16
+ #define f17 17
+ #define f18 18
+-#define f19 19
++#define f19 19
+ #define f20 20
+ #define f21 21
+ #define f22 22
+@@ -77,6 +77,143 @@
+ #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.
+ */
+--- gcc/config/rs6000/linux64.opt (.../trunk) (revision 144557)
++++ gcc/config/rs6000/linux64.opt (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -20,5 +20,5 @@
+ ; <http://www.gnu.org/licenses/>.
+
+ mprofile-kernel
+-Target Report Mask(PROFILE_KERNEL)
++Target Report Var(TARGET_PROFILE_KERNEL)
+ Call mcount for profiling before a function prologue
+--- gcc/config/rs6000/sysv4.opt (.../trunk) (revision 144557)
++++ gcc/config/rs6000/sysv4.opt (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -32,7 +32,7 @@ Target RejectNegative Joined
+ Specify bit size of immediate TLS offsets
+
+ mbit-align
+-Target Report Mask(NO_BITFIELD_TYPE)
++Target Report Var(TARGET_NO_BITFIELD_TYPE)
+ Align to the base type of the bit-field
+
+ mstrict-align
+@@ -87,11 +87,11 @@ Target Report Mask(EABI)
+ Use EABI
+
+ mbit-word
+-Target Report Mask(NO_BITFIELD_WORD)
++Target Report Var(TARGET_NO_BITFIELD_WORD)
+ Allow bit-fields to cross word boundaries
+
+ mregnames
+-Target Mask(REGNAMES)
++Target Var(TARGET_REGNAMES)
+ Use alternate register names
+
+ ;; FIXME: Does nothing.
+--- gcc/config/rs6000/rs6000-protos.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000-protos.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -64,9 +64,14 @@ extern int insvdi_rshift_rlwimi_p (rtx,
+ extern int registers_ok_for_quad_peep (rtx, rtx);
+ extern int mems_ok_for_quad_peep (rtx, rtx);
+ extern bool gpr_or_gpr_p (rtx, rtx);
++extern enum reg_class rs6000_preferred_reload_class(rtx, enum reg_class);
+ extern enum reg_class rs6000_secondary_reload_class (enum reg_class,
+ enum machine_mode, rtx);
+-
++extern bool rs6000_secondary_memory_needed (enum reg_class, enum reg_class,
++ enum machine_mode);
++extern bool rs6000_cannot_change_mode_class (enum machine_mode,
++ enum machine_mode,
++ enum reg_class);
+ extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
+ rtx, rtx, rtx);
+ extern void paired_expand_vector_move (rtx operands[]);
+@@ -170,7 +175,6 @@ extern int rs6000_register_move_cost (en
+ enum reg_class, enum reg_class);
+ extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
+ extern bool rs6000_tls_referenced_p (rtx);
+-extern int rs6000_hard_regno_nregs (int, enum machine_mode);
+ extern void rs6000_conditional_register_usage (void);
+
+ /* Declare functions in rs6000-c.c */
+@@ -189,4 +193,6 @@ const char * rs6000_xcoff_strip_dollar (
+ void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands);
+
+ extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
++extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES];
++extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER];
+ #endif /* rs6000-protos.h */
+--- gcc/config/rs6000/t-rs6000 (.../trunk) (revision 144557)
++++ gcc/config/rs6000/t-rs6000 (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -16,3 +16,33 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs60
+
+ # The rs6000 backend doesn't cause warnings in these files.
+ insn-conditions.o-warn =
++
++MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \
++ $(srcdir)/config/rs6000/rios2.md \
++ $(srcdir)/config/rs6000/rs64.md \
++ $(srcdir)/config/rs6000/mpc.md \
++ $(srcdir)/config/rs6000/40x.md \
++ $(srcdir)/config/rs6000/440.md \
++ $(srcdir)/config/rs6000/603.md \
++ $(srcdir)/config/rs6000/6xx.md \
++ $(srcdir)/config/rs6000/7xx.md \
++ $(srcdir)/config/rs6000/7450.md \
++ $(srcdir)/config/rs6000/8540.md \
++ $(srcdir)/config/rs6000/e300c2c3.md \
++ $(srcdir)/config/rs6000/e500mc.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 \
++ $(srcdir)/config/rs6000/constraints.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 \
++ $(srcdir)/config/rs6000/paired.md
+--- gcc/config/rs6000/power7.md (.../trunk) (revision 0)
++++ gcc/config/rs6000/power7.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,320 @@
++;; 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")
++
++
+--- gcc/config/rs6000/rs6000-c.c (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000-c.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -265,6 +265,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+ builtin_define ("_ARCH_PWR6X");
+ if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
+ builtin_define ("_ARCH_COM");
++ if (TARGET_POPCNTD)
++ builtin_define ("_ARCH_PWR7");
+ if (TARGET_ALTIVEC)
+ {
+ builtin_define ("__ALTIVEC__");
+@@ -306,6 +308,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+ /* Used by libstdc++. */
+ if (TARGET_NO_LWSYNC)
+ builtin_define ("__NO_LWSYNC__");
++ if (TARGET_VSX)
++ builtin_define ("__VSX__");
+
+ /* May be overridden by target configuration. */
+ RS6000_CPU_CPP_ENDIAN_BUILTINS();
+--- gcc/config/rs6000/rs6000.opt (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.opt (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -111,24 +111,44 @@ mhard-float
+ Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
+ Use hardware floating point
+
+-mno-update
+-Target Report RejectNegative Mask(NO_UPDATE)
+-Do not generate load/store with update instructions
++mpopcntd
++Target Report Mask(POPCNTD)
++Use PowerPC V2.06 popcntd instruction
++
++mvsx
++Target Report Mask(VSX)
++Use vector/scalar (VSX) instructions
++
++mvsx-vector-memory
++Target Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
++If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
++
++mvsx-vector-float
++Target Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
++If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
++
++mvsx-vector-double
++Target Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
++If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
++
++mvsx-scalar-double
++Target Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
++If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
++
++mvsx-scalar-memory
++Target Report Var(TARGET_VSX_SCALAR_MEMORY)
++If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
+
+ mupdate
+-Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
++Target Report Var(TARGET_UPDATE) Init(1)
+ Generate load/store with update instructions
+
+ mavoid-indexed-addresses
+ Target Report Var(TARGET_AVOID_XFORM) Init(-1)
+ Avoid generation of indexed load/store instructions when possible
+
+-mno-fused-madd
+-Target Report RejectNegative Mask(NO_FUSED_MADD)
+-Do not generate fused multiply/add instructions
+-
+ mfused-madd
+-Target Report RejectNegative InverseMask(NO_FUSED_MADD, FUSED_MADD)
++Target Report Var(TARGET_FUSED_MADD) Init(1)
+ Generate fused multiply/add instructions
+
+ msched-prolog
+@@ -194,7 +214,7 @@ Target RejectNegative Joined
+ -mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead
+
+ misel
+-Target
++Target Report Mask(ISEL)
+ Generate isel instructions
+
+ misel=
+--- gcc/config/rs6000/linux64.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/linux64.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -114,7 +114,7 @@ extern int dot_symbols;
+ error (INVALID_32BIT, "32"); \
+ if (TARGET_PROFILE_KERNEL) \
+ { \
+- target_flags &= ~MASK_PROFILE_KERNEL; \
++ SET_PROFILE_KERNEL (0); \
+ error (INVALID_32BIT, "profile-kernel"); \
+ } \
+ } \
+--- gcc/config/rs6000/rs6000.c (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -178,9 +178,6 @@ int rs6000_spe;
+ /* Nonzero if we want SPE ABI extensions. */
+ int rs6000_spe_abi;
+
+-/* Nonzero to use isel instructions. */
+-int rs6000_isel;
+-
+ /* Nonzero if floating point operations are done in the GPRs. */
+ int rs6000_float_gprs = 0;
+
+@@ -227,10 +224,18 @@ int dot_symbols;
+ const char *rs6000_debug_name;
+ int rs6000_debug_stack; /* debug stack applications */
+ int rs6000_debug_arg; /* debug argument handling */
++int rs6000_debug_reg; /* debug register classes */
++int rs6000_debug_addr; /* debug memory addressing */
+
+ /* Value is TRUE if register/mode pair is acceptable. */
+ bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+
++/* Maximum number of registers needed for a given register class and mode. */
++unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES];
++
++/* How many registers are needed for a given register and mode. */
++unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
++
+ /* Built in types. */
+
+ tree rs6000_builtin_types[RS6000_BTI_MAX];
+@@ -270,7 +275,6 @@ struct {
+ bool altivec_abi; /* True if -mabi=altivec/no-altivec used. */
+ bool spe; /* True if -mspe= was used. */
+ bool float_gprs; /* True if -mfloat-gprs= was used. */
+- bool isel; /* True if -misel was used. */
+ bool long_double; /* True if -mlong-double- was used. */
+ bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */
+ bool vrsave; /* True if -mvrsave was used. */
+@@ -286,6 +290,18 @@ struct builtin_description
+ const char *const name;
+ const enum rs6000_builtins code;
+ };
++
++/* Describe the vector unit used for modes. */
++enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES];
++enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES];
++enum reg_class rs6000_vector_reg_class[NUM_MACHINE_MODES];
++
++/* Describe the alignment of a vector. */
++int rs6000_vector_align[NUM_MACHINE_MODES];
++
++/* Describe the register classes used by VSX instructions. */
++enum reg_class rs6000_vsx_reg_class = NO_REGS;
++
+ \f
+ /* Target cpu costs. */
+
+@@ -749,6 +765,25 @@ struct processor_costs power6_cost = {
+ 16, /* prefetch streams */
+ };
+
++/* Instruction costs on POWER7 processors. */
++static const
++struct processor_costs power7_cost = {
++ COSTS_N_INSNS (2), /* mulsi */
++ COSTS_N_INSNS (2), /* mulsi_const */
++ COSTS_N_INSNS (2), /* mulsi_const9 */
++ COSTS_N_INSNS (2), /* muldi */
++ COSTS_N_INSNS (18), /* divsi */
++ COSTS_N_INSNS (34), /* divdi */
++ COSTS_N_INSNS (3), /* fp */
++ COSTS_N_INSNS (3), /* dmul */
++ COSTS_N_INSNS (13), /* sdiv */
++ COSTS_N_INSNS (16), /* ddiv */
++ 128, /* cache line size */
++ 32, /* l1 cache */
++ 256, /* l2 cache */
++ 12, /* prefetch streams */
++};
++
+ \f
+ static bool rs6000_function_ok_for_sibcall (tree, tree);
+ static const char *rs6000_invalid_within_doloop (const_rtx);
+@@ -963,12 +998,10 @@ static tree rs6000_gimplify_va_arg (tree
+ static bool rs6000_must_pass_in_stack (enum machine_mode, const_tree);
+ static bool rs6000_scalar_mode_supported_p (enum machine_mode);
+ static bool rs6000_vector_mode_supported_p (enum machine_mode);
+-static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
+- enum machine_mode);
++static rtx rs6000_emit_vector_compare_vsx (enum rtx_code, rtx, rtx, rtx);
++static rtx rs6000_emit_vector_compare_altivec (enum rtx_code, rtx, rtx, rtx);
+ static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
+ enum machine_mode);
+-static int get_vsel_insn (enum machine_mode);
+-static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
+ static tree rs6000_stack_protect_fail (void);
+
+ const int INSN_NOT_AVAILABLE = -1;
+@@ -1045,6 +1078,9 @@ static const char alt_reg_names[][8] =
+ #endif
+ #ifndef TARGET_PROFILE_KERNEL
+ #define TARGET_PROFILE_KERNEL 0
++#define SET_PROFILE_KERNEL(N)
++#else
++#define SET_PROFILE_KERNEL(N) TARGET_PROFILE_KERNEL = (N)
+ #endif
+
+ /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
+@@ -1299,28 +1335,96 @@ static const char alt_reg_names[][8] =
+
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ \f
++/* Return number of consecutive hard regs needed starting at reg REGNO
++ to hold something of mode MODE.
++ This is ordinarily the length in words of a value of mode MODE
++ but can be less for certain modes in special long registers.
++
++ For the SPE, GPRs are 64 bits but only 32 bits are visible in
++ scalar instructions. The upper 32 bits are only available to the
++ SIMD instructions.
++
++ POWER and PowerPC GPRs hold 32 bits worth;
++ PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
++
++static int
++rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
++{
++ unsigned HOST_WIDE_INT reg_size;
++
++ if (FP_REGNO_P (regno))
++ reg_size = (VECTOR_UNIT_VSX_P (mode)
++ ? UNITS_PER_VSX_WORD
++ : UNITS_PER_FP_WORD);
++
++ else if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
++ reg_size = UNITS_PER_SPE_WORD;
++
++ else if (ALTIVEC_REGNO_P (regno))
++ reg_size = UNITS_PER_ALTIVEC_WORD;
++
++ /* The value returned for SCmode in the E500 double case is 2 for
++ ABI compatibility; storing an SCmode value in a single register
++ would require function_arg and rs6000_spe_function_arg to handle
++ SCmode so as to pass the value correctly in a pair of
++ registers. */
++ else if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
++ && !DECIMAL_FLOAT_MODE_P (mode))
++ reg_size = UNITS_PER_FP_WORD;
++
++ else
++ reg_size = UNITS_PER_WORD;
++
++ return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
++}
+
+ /* Value is 1 if hard register REGNO can hold a value of machine-mode
+ MODE. */
+ static int
+ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
+ {
++ int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1;
++
++ /* VSX registers that overlap the FPR registers are larger than for non-VSX
++ implementations. Don't allow an item to be split between a FP register
++ and an Altivec register. */
++ if (VECTOR_UNIT_VSX_P (mode) || VECTOR_MEM_VSX_P (mode))
++ {
++ enum reg_class rclass = rs6000_vector_reg_class[mode];
++ if (FP_REGNO_P (regno))
++ return ((rclass == FLOAT_REGS || rclass == VSX_REGS)
++ && FP_REGNO_P (last_regno));
++
++ if (ALTIVEC_REGNO_P (regno))
++ return ((rclass == ALTIVEC_REGS || rclass == VSX_REGS)
++ && ALTIVEC_REGNO_P (last_regno));
++ }
++
+ /* The GPRs can hold any mode, but values bigger than one register
+ cannot go past R31. */
+ if (INT_REGNO_P (regno))
+- return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
++ return INT_REGNO_P (last_regno);
+
+- /* The float registers can only hold floating modes and DImode.
+- This excludes the 32-bit decimal float mode for now. */
++ /* The float registers (except for VSX vector modes) can only hold floating
++ modes and DImode. This excludes the 32-bit decimal float mode for
++ now. */
+ if (FP_REGNO_P (regno))
+- return
+- ((SCALAR_FLOAT_MODE_P (mode)
+- && (mode != TDmode || (regno % 2) == 0)
+- && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
+- || (GET_MODE_CLASS (mode) == MODE_INT
++ {
++ if (SCALAR_FLOAT_MODE_P (mode)
++ && (mode != TDmode || (regno % 2) == 0)
++ && FP_REGNO_P (last_regno))
++ return 1;
++
++ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
+- || (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
+- && PAIRED_VECTOR_MODE (mode)));
++ return 1;
++
++ if (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
++ && PAIRED_VECTOR_MODE (mode))
++ return 1;
++
++ return 0;
++ }
+
+ /* The CR register can only hold CC modes. */
+ if (CR_REGNO_P (regno))
+@@ -1331,28 +1435,312 @@ rs6000_hard_regno_mode_ok (int regno, en
+
+ /* AltiVec only in AldyVec registers. */
+ if (ALTIVEC_REGNO_P (regno))
+- return ALTIVEC_VECTOR_MODE (mode);
++ return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode);
+
+ /* ...but GPRs can hold SIMD data on the SPE in one register. */
+ if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return 1;
+
+- /* We cannot put TImode anywhere except general register and it must be
+- able to fit within the register set. */
++ /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. You
++ really don't want to spill your floating point values to those
++ registers. Also do it for the old MQ register in the power. */
++ if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)
++ return (GET_MODE_CLASS (mode) == MODE_INT
++ && GET_MODE_SIZE (mode) <= UNITS_PER_WORD);
++
++ /* The VRSAVE/VSCR registers are 32-bits (they are fixed, but add this for
++ completeness). */
++ if (regno == VRSAVE_REGNO || regno == VSCR_REGNO)
++ return (mode == SImode);
++
++ /* We cannot put TImode anywhere except general register and it must be able
++ to fit within the register set. In the future, allow TImode in the
++ Altivec or VSX registers. */
+
+ return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
+ }
+
+-/* Initialize rs6000_hard_regno_mode_ok_p table. */
++/* Print interesting facts about registers. */
+ static void
+-rs6000_init_hard_regno_mode_ok (void)
++rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
+ {
+ int r, m;
+
++ for (r = first_regno; r <= last_regno; ++r)
++ {
++ const char *comma = "";
++ int len;
++
++ if (first_regno == last_regno)
++ fprintf (stderr, "%s:\t", reg_name);
++ else
++ fprintf (stderr, "%s%d:\t", reg_name, r - first_regno);
++
++ len = 8;
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ if (rs6000_hard_regno_mode_ok_p[m][r] && rs6000_hard_regno_nregs[m][r])
++ {
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ len = 8;
++ comma = "";
++ }
++
++ if (rs6000_hard_regno_nregs[m][r] > 1)
++ len += fprintf (stderr, "%s%s/%d", comma, GET_MODE_NAME (m),
++ rs6000_hard_regno_nregs[m][r]);
++ else
++ len += fprintf (stderr, "%s%s", comma, GET_MODE_NAME (m));
++
++ comma = ", ";
++ }
++
++ if (call_used_regs[r])
++ {
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ len = 8;
++ comma = "";
++ }
++
++ len += fprintf (stderr, "%s%s", comma, "call-used");
++ comma = ", ";
++ }
++
++ if (fixed_regs[r])
++ {
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ len = 8;
++ comma = "";
++ }
++
++ len += fprintf (stderr, "%s%s", comma, "fixed");
++ comma = ", ";
++ }
++
++ if (len > 70)
++ {
++ fprintf (stderr, ",\n\t");
++ comma = "";
++ }
++
++ fprintf (stderr, "%sregno = %d\n", comma, r);
++ }
++}
++
++/* Map enum rs6000_vector to string. */
++static const char *
++rs6000_debug_vector_unit[] = {
++ "none",
++ "altivec",
++ "vsx",
++ "paired",
++ "spe",
++ "other"
++};
++
++/* Initialize the various global tables that are based on register size. */
++static void
++rs6000_init_hard_regno_mode_ok (void)
++{
++ int r, m, c;
++ enum reg_class vsx_rc = (TARGET_ALTIVEC ? VSX_REGS : FLOAT_REGS);
++ bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS);
++
++ /* Precalculate vector information, this must be set up before the
++ rs6000_hard_regno_nregs_internal below. */
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ {
++ rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
++ rs6000_vector_reg_class[m] = NO_REGS;
++ }
++
++ /* TODO, add TI/V2DI mode for moving data if Altivec or VSX. */
++
++ /* V2DF mode, VSX only. */
++ if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE)
++ {
++ rs6000_vector_unit[V2DFmode] = VECTOR_VSX;
++ rs6000_vector_mem[V2DFmode] = VECTOR_VSX;
++ rs6000_vector_align[V2DFmode] = 64;
++ }
++
++ /* V4SF mode, either VSX or Altivec. */
++ if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_FLOAT)
++ {
++ rs6000_vector_unit[V4SFmode] = VECTOR_VSX;
++ if (TARGET_VSX_VECTOR_MEMORY || !TARGET_ALTIVEC)
++ {
++ rs6000_vector_align[V4SFmode] = 32;
++ rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
++ } else {
++ rs6000_vector_align[V4SFmode] = 128;
++ rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
++ }
++ }
++ else if (float_p && TARGET_ALTIVEC)
++ {
++ rs6000_vector_unit[V4SFmode] = VECTOR_ALTIVEC;
++ rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
++ rs6000_vector_align[V4SFmode] = 128;
++ }
++
++ /* V16QImode, V8HImode, V4SImode are Altivec only, but possibly do VSX loads
++ and stores. */
++ if (TARGET_ALTIVEC)
++ {
++ rs6000_vector_unit[V4SImode] = VECTOR_ALTIVEC;
++ rs6000_vector_unit[V8HImode] = VECTOR_ALTIVEC;
++ rs6000_vector_unit[V16QImode] = VECTOR_ALTIVEC;
++
++ rs6000_vector_reg_class[V16QImode] = ALTIVEC_REGS;
++ rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
++ rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
++
++ if (TARGET_VSX && TARGET_VSX_VECTOR_MEMORY)
++ {
++ rs6000_vector_mem[V4SImode] = VECTOR_VSX;
++ rs6000_vector_mem[V8HImode] = VECTOR_VSX;
++ rs6000_vector_mem[V16QImode] = VECTOR_VSX;
++ rs6000_vector_align[V4SImode] = 32;
++ rs6000_vector_align[V8HImode] = 32;
++ rs6000_vector_align[V16QImode] = 32;
++ }
++ else
++ {
++ rs6000_vector_mem[V4SImode] = VECTOR_ALTIVEC;
++ rs6000_vector_mem[V8HImode] = VECTOR_ALTIVEC;
++ rs6000_vector_mem[V16QImode] = VECTOR_ALTIVEC;
++ rs6000_vector_align[V4SImode] = 128;
++ rs6000_vector_align[V8HImode] = 128;
++ rs6000_vector_align[V16QImode] = 128;
++ }
++ }
++
++ /* DFmode, see if we want to use the VSX unit. */
++ if (float_p && TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
++ {
++ rs6000_vector_unit[DFmode] = VECTOR_VSX;
++ rs6000_vector_align[DFmode] = 64;
++ rs6000_vector_mem[DFmode]
++ = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
++ }
++
++ /* TODO, add SPE and paired floating point vector support. */
++
++ /* Set the VSX register classes. */
++ rs6000_vector_reg_class[V4SFmode]
++ = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
++ ? vsx_rc
++ : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
++ ? ALTIVEC_REGS
++ : NO_REGS));
++
++ rs6000_vector_reg_class[V2DFmode]
++ = (VECTOR_UNIT_VSX_P (V2DFmode) ? vsx_rc : NO_REGS);
++
++ rs6000_vector_reg_class[DFmode]
++ = ((!float_p || !VECTOR_UNIT_VSX_P (DFmode))
++ ? NO_REGS
++ : ((TARGET_VSX_SCALAR_MEMORY)
++ ? vsx_rc
++ : FLOAT_REGS));
++
++ rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
++
++ /* Precalculate HARD_REGNO_NREGS. */
++ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ rs6000_hard_regno_nregs[m][r] = rs6000_hard_regno_nregs_internal (r, m);
++
++ /* Precalculate HARD_REGNO_MODE_OK. */
+ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
+ if (rs6000_hard_regno_mode_ok (r, m))
+ rs6000_hard_regno_mode_ok_p[m][r] = true;
++
++ /* Precalculate CLASSS_MAX_NREGS sizes. */
++ for (c = 0; c < LIM_REG_CLASSES; ++c)
++ {
++ int reg_size;
++
++ if (TARGET_VSX && VSX_REG_CLASS_P (c))
++ reg_size = UNITS_PER_VSX_WORD;
++
++ else if (c == ALTIVEC_REGS)
++ reg_size = UNITS_PER_ALTIVEC_WORD;
++
++ else if (c == FLOAT_REGS)
++ reg_size = UNITS_PER_FP_WORD;
++
++ else
++ reg_size = UNITS_PER_WORD;
++
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ rs6000_class_max_nregs[m][c]
++ = (GET_MODE_SIZE (m) + reg_size - 1) / reg_size;
++ }
++
++ if (TARGET_E500_DOUBLE)
++ rs6000_class_max_nregs[DFmode][GENERAL_REGS] = 1;
++
++ if (TARGET_DEBUG_REG)
++ {
++ const char *nl = (const char *)0;
++
++ fprintf (stderr, "Register information: (last virtual reg = %d)\n",
++ LAST_VIRTUAL_REGISTER);
++ rs6000_debug_reg_print (0, 31, "gr");
++ rs6000_debug_reg_print (32, 63, "fp");
++ rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
++ LAST_ALTIVEC_REGNO,
++ "vs");
++ rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
++ rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
++ rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
++ rs6000_debug_reg_print (MQ_REGNO, MQ_REGNO, "mq");
++ rs6000_debug_reg_print (XER_REGNO, XER_REGNO, "xer");
++ rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave");
++ rs6000_debug_reg_print (VSCR_REGNO, VSCR_REGNO, "vscr");
++ rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a");
++ rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f");
++
++ fprintf (stderr,
++ "\n"
++ "V16QI reg_class = %s\n"
++ "V8HI reg_class = %s\n"
++ "V4SI reg_class = %s\n"
++ "V2DI reg_class = %s\n"
++ "V4SF reg_class = %s\n"
++ "V2DF reg_class = %s\n"
++ "DF reg_class = %s\n"
++ "vsx reg_class = %s\n\n",
++ reg_class_names[rs6000_vector_reg_class[V16QImode]],
++ reg_class_names[rs6000_vector_reg_class[V8HImode]],
++ reg_class_names[rs6000_vector_reg_class[V4SImode]],
++ reg_class_names[rs6000_vector_reg_class[V2DImode]],
++ reg_class_names[rs6000_vector_reg_class[V4SFmode]],
++ reg_class_names[rs6000_vector_reg_class[V2DFmode]],
++ reg_class_names[rs6000_vector_reg_class[DFmode]],
++ reg_class_names[rs6000_vsx_reg_class]);
++
++ for (m = 0; m < NUM_MACHINE_MODES; ++m)
++ if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
++ {
++ nl = "\n";
++ fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n",
++ GET_MODE_NAME (m),
++ rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
++ rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]);
++ }
++
++ if (nl)
++ fputs (nl, stderr);
++ }
+ }
+
+ #if TARGET_MACHO
+@@ -1482,12 +1870,15 @@ rs6000_override_options (const char *def
+ {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+- {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN},
++ {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
++ | MASK_ISEL},
+ /* 8548 has a dummy entry for now. */
+- {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN},
++ {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
++ | MASK_ISEL},
+ {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
+- {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
++ {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
++ | MASK_ISEL},
+ {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"970", PROCESSOR_POWER4,
+ POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+@@ -1520,9 +1911,10 @@ rs6000_override_options (const char *def
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
+ | MASK_MFPGPR},
+- {"power7", PROCESSOR_POWER5,
++ {"power7", PROCESSOR_POWER7,
+ POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
+- | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP},
++ | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
++ | 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},
+@@ -1549,7 +1941,8 @@ rs6000_override_options (const char *def
+ POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
+ | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
+- | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP)
++ | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
++ | MASK_POPCNTD | MASK_VSX | MASK_ISEL)
+ };
+
+ set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
+@@ -1594,10 +1987,6 @@ rs6000_override_options (const char *def
+ }
+ }
+
+- if ((TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
+- && !rs6000_explicit_options.isel)
+- rs6000_isel = 1;
+-
+ if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
+ || rs6000_cpu == PROCESSOR_PPCE500MC)
+ {
+@@ -1642,15 +2031,47 @@ rs6000_override_options (const char *def
+ }
+ }
+
++ /* Add some warnings for VSX. Enable -maltivec unless the user explicitly
++ used -mno-altivec */
++ if (TARGET_VSX)
++ {
++ const char *msg = NULL;
++ if (!TARGET_HARD_FLOAT || !TARGET_FPRS
++ || !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT)
++ msg = "-mvsx requires hardware floating point";
++ else if (TARGET_PAIRED_FLOAT)
++ msg = "-mvsx and -mpaired are incompatible";
++ /* The hardware will allow VSX and little endian, but until we make sure
++ things like vector select, etc. work don't allow VSX on little endian
++ systems at this point. */
++ else if (!BYTES_BIG_ENDIAN)
++ msg = "-mvsx used with little endian code";
++ else if (TARGET_AVOID_XFORM > 0)
++ msg = "-mvsx needs indexed addressing";
++
++ if (msg)
++ {
++ warning (0, msg);
++ target_flags &= MASK_VSX;
++ }
++ else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC) == 0)
++ target_flags |= MASK_ALTIVEC;
++ }
++
+ /* Set debug flags */
+ if (rs6000_debug_name)
+ {
+ if (! strcmp (rs6000_debug_name, "all"))
+- rs6000_debug_stack = rs6000_debug_arg = 1;
++ rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
++ = rs6000_debug_addr = 1;
+ else if (! strcmp (rs6000_debug_name, "stack"))
+ rs6000_debug_stack = 1;
+ else if (! strcmp (rs6000_debug_name, "arg"))
+ rs6000_debug_arg = 1;
++ else if (! strcmp (rs6000_debug_name, "reg"))
++ rs6000_debug_reg = 1;
++ else if (! strcmp (rs6000_debug_name, "addr"))
++ rs6000_debug_addr = 1;
+ else
+ error ("unknown -mdebug-%s switch", rs6000_debug_name);
+ }
+@@ -1741,8 +2162,8 @@ rs6000_override_options (const char *def
+ rs6000_spe = 0;
+ if (!rs6000_explicit_options.float_gprs)
+ rs6000_float_gprs = 0;
+- if (!rs6000_explicit_options.isel)
+- rs6000_isel = 0;
++ if (!(target_flags_explicit & MASK_ISEL))
++ target_flags &= ~MASK_ISEL;
+ }
+
+ /* Detect invalid option combinations with E500. */
+@@ -1751,12 +2172,14 @@ rs6000_override_options (const char *def
+ rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
+ && rs6000_cpu != PROCESSOR_POWER5
+ && rs6000_cpu != PROCESSOR_POWER6
++ && rs6000_cpu != PROCESSOR_POWER7
+ && rs6000_cpu != PROCESSOR_CELL);
+ rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
+ || rs6000_cpu == PROCESSOR_POWER5);
+ rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
+ || rs6000_cpu == PROCESSOR_POWER5
+- || rs6000_cpu == PROCESSOR_POWER6);
++ || rs6000_cpu == PROCESSOR_POWER6
++ || rs6000_cpu == PROCESSOR_POWER7);
+
+ rs6000_sched_restricted_insns_priority
+ = (rs6000_sched_groups ? 1 : 0);
+@@ -1951,6 +2374,10 @@ rs6000_override_options (const char *def
+ rs6000_cost = &power6_cost;
+ break;
+
++ case PROCESSOR_POWER7:
++ rs6000_cost = &power7_cost;
++ break;
++
+ default:
+ gcc_unreachable ();
+ }
+@@ -2001,7 +2428,7 @@ rs6000_override_options (const char *def
+ static tree
+ rs6000_builtin_mask_for_load (void)
+ {
+- if (TARGET_ALTIVEC)
++ if (TARGET_ALTIVEC && !TARGET_VSX)
+ return altivec_builtin_mask_for_load;
+ else
+ return 0;
+@@ -2015,18 +2442,19 @@ rs6000_builtin_mask_for_load (void)
+ static tree
+ rs6000_builtin_conversion (enum tree_code code, tree type)
+ {
+- if (!TARGET_ALTIVEC)
+- return NULL_TREE;
+-
+ switch (code)
+ {
+ case FIX_TRUNC_EXPR:
+ switch (TYPE_MODE (type))
+ {
+ case V4SImode:
++ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
++ return NULL_TREE;
++
+ return TYPE_UNSIGNED (type)
+- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTUXS]
+- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTSXS];
++ ? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI]
++ : rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI];
++
+ default:
+ return NULL_TREE;
+ }
+@@ -2035,9 +2463,12 @@ rs6000_builtin_conversion (enum tree_cod
+ switch (TYPE_MODE (type))
+ {
+ case V4SImode:
++ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
++ return NULL_TREE;
++
+ return TYPE_UNSIGNED (type)
+- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFUX]
+- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
++ ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
++ : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
+ default:
+ return NULL_TREE;
+ }
+@@ -2150,6 +2581,14 @@ rs6000_builtin_vec_perm (tree type, tree
+ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
+ break;
+
++ case V2DFmode:
++ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DF];
++ break;
++
++ case V2DImode:
++ d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI];
++ break;
++
+ default:
+ return NULL_TREE;
+ }
+@@ -2229,6 +2668,7 @@ static bool
+ rs6000_handle_option (size_t code, const char *arg, int value)
+ {
+ enum fpu_type_t fpu_type = FPU_NONE;
++ int isel;
+
+ switch (code)
+ {
+@@ -2331,14 +2771,14 @@ rs6000_handle_option (size_t code, const
+ rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
+ break;
+
+- case OPT_misel:
+- rs6000_explicit_options.isel = true;
+- rs6000_isel = value;
+- break;
+-
+ case OPT_misel_:
+- rs6000_explicit_options.isel = true;
+- rs6000_parse_yes_no_option ("isel", arg, &(rs6000_isel));
++ target_flags_explicit |= MASK_ISEL;
++ isel = 0;
++ rs6000_parse_yes_no_option ("isel", arg, &isel);
++ if (isel)
++ target_flags |= MASK_ISEL;
++ else
++ target_flags &= ~MASK_ISEL;
+ break;
+
+ case OPT_mspe:
+@@ -2967,6 +3407,9 @@ output_vec_const_move (rtx *operands)
+ vec = operands[1];
+ mode = GET_MODE (dest);
+
++ if (TARGET_VSX && zero_constant (vec, mode))
++ return "xxlxor %x0,%x0,%x0";
++
+ if (TARGET_ALTIVEC)
+ {
+ rtx splat_vec;
+@@ -3190,20 +3633,21 @@ rs6000_expand_vector_init (rtx target, r
+ if (n_var == 0)
+ {
+ rtx const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+- if (mode != V4SFmode && all_const_zero)
++ bool int_vector_p = (GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
++ if ((int_vector_p || TARGET_VSX) && all_const_zero)
+ {
+ /* Zero register. */
+ emit_insn (gen_rtx_SET (VOIDmode, target,
+ gen_rtx_XOR (mode, target, target)));
+ return;
+ }
+- else if (mode != V4SFmode && easy_vector_constant (const_vec, mode))
++ else if (int_vector_p && easy_vector_constant (const_vec, mode))
+ {
+ /* Splat immediate. */
+ emit_insn (gen_rtx_SET (VOIDmode, target, const_vec));
+ return;
+ }
+- else if (all_same)
++ else if (all_same && int_vector_p)
+ ; /* Splat vector element. */
+ else
+ {
+@@ -3213,6 +3657,18 @@ rs6000_expand_vector_init (rtx target, r
+ }
+ }
+
++ if (mode == V2DFmode)
++ {
++ gcc_assert (TARGET_VSX);
++ if (all_same)
++ emit_insn (gen_vsx_splatv2df (target, XVECEXP (vals, 0, 0)));
++ else
++ emit_insn (gen_vsx_concat_v2df (target,
++ copy_to_reg (XVECEXP (vals, 0, 0)),
++ copy_to_reg (XVECEXP (vals, 0, 1))));
++ return;
++ }
++
+ /* Store value to stack temp. Load vector element. Splat. */
+ if (all_same)
+ {
+@@ -3272,6 +3728,13 @@ rs6000_expand_vector_set (rtx target, rt
+ int width = GET_MODE_SIZE (inner_mode);
+ int i;
+
++ if (mode == V2DFmode)
++ {
++ gcc_assert (TARGET_VSX);
++ emit_insn (gen_vsx_set_v2df (target, val, target, 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);
+@@ -3309,6 +3772,13 @@ rs6000_expand_vector_extract (rtx target
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ rtx mem, x;
+
++ if (mode == V2DFmode)
++ {
++ gcc_assert (TARGET_VSX);
++ emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt)));
++ return;
++ }
++
+ /* Allocate mode-sized buffer. */
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
+
+@@ -3627,9 +4097,13 @@ rs6000_legitimate_offset_address_p (enum
+ case V8HImode:
+ case V4SFmode:
+ case V4SImode:
+- /* AltiVec vector modes. Only reg+reg addressing is valid and
++ case V2DFmode:
++ case V2DImode:
++ /* AltiVec/VSX vector modes. Only reg+reg addressing is valid and
+ constant offset zero should not occur due to canonicalization. */
+- return false;
++ if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
++ return false;
++ break;
+
+ case V4HImode:
+ case V2SImode:
+@@ -3646,6 +4120,11 @@ rs6000_legitimate_offset_address_p (enum
+ if (TARGET_E500_DOUBLE)
+ return SPE_CONST_OFFSET_OK (offset);
+
++ /* If we are using VSX scalar loads, restrict ourselves to reg+reg
++ addressing. */
++ if (VECTOR_MEM_VSX_P (DFmode))
++ return false;
++
+ case DDmode:
+ case DImode:
+ /* On e500v2, we may have:
+@@ -3716,7 +4195,9 @@ avoiding_indexed_address_p (enum machine
+ {
+ /* Avoid indexed addressing for modes that have non-indexed
+ load/store instruction forms. */
+- return TARGET_AVOID_XFORM && !ALTIVEC_VECTOR_MODE (mode);
++ return (TARGET_AVOID_XFORM
++ && (!TARGET_ALTIVEC || !ALTIVEC_VECTOR_MODE (mode))
++ && (!TARGET_VSX || !VSX_VECTOR_MODE (mode)));
+ }
+
+ inline bool
+@@ -3808,25 +4289,30 @@ rtx
+ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+ {
++ rtx ret = NULL_RTX;
++ rtx orig_x = x;
++
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
+ if (model != 0)
+- return rs6000_legitimize_tls_address (x, model);
++ ret = rs6000_legitimize_tls_address (x, model);
+ }
+
+- if (GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000
+- && !((TARGET_POWERPC64
+- && (mode == DImode || mode == TImode)
+- && (INTVAL (XEXP (x, 1)) & 3) != 0)
+- || SPE_VECTOR_MODE (mode)
+- || ALTIVEC_VECTOR_MODE (mode)
+- || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+- || mode == DImode || mode == DDmode
+- || mode == TDmode))))
++ else if (GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000)
++ >= 0x10000)
++ && !((TARGET_POWERPC64
++ && (mode == DImode || mode == TImode)
++ && (INTVAL (XEXP (x, 1)) & 3) != 0)
++ || (TARGET_SPE && SPE_VECTOR_MODE (mode))
++ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
++ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
++ || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
++ || mode == DImode || mode == DDmode
++ || mode == TDmode))))
+ {
+ HOST_WIDE_INT high_int, low_int;
+ rtx sum;
+@@ -3834,7 +4320,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+ high_int = INTVAL (XEXP (x, 1)) - low_int;
+ sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
+ GEN_INT (high_int)), 0);
+- return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
++ ret = gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
+ }
+ else if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+@@ -3850,32 +4336,29 @@ rs6000_legitimize_address (rtx x, rtx ol
+ && mode != TFmode
+ && mode != TDmode)
+ {
+- return gen_rtx_PLUS (Pmode, XEXP (x, 0),
+- force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
++ ret = gen_rtx_PLUS (Pmode, XEXP (x, 0),
++ force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
+ }
+- else if (ALTIVEC_VECTOR_MODE (mode))
++ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+ {
+- rtx reg;
+-
+ /* Make sure both operands are registers. */
+ if (GET_CODE (x) == PLUS)
+- return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
+- force_reg (Pmode, XEXP (x, 1)));
+-
+- reg = force_reg (Pmode, x);
+- return reg;
++ ret = gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
++ force_reg (Pmode, XEXP (x, 1)));
++ else
++ ret = force_reg (Pmode, x);
+ }
+- else if (SPE_VECTOR_MODE (mode)
++ else if ((TARGET_SPE && SPE_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+ || mode == DDmode || mode == TDmode
+ || mode == DImode)))
+ {
+ if (mode == DImode)
+- return NULL_RTX;
+- /* We accept [reg + reg] and [reg + OFFSET]. */
++ ret = NULL_RTX;
+
+- if (GET_CODE (x) == PLUS)
+- {
++ /* We accept [reg + reg] and [reg + OFFSET]. */
++ else if (GET_CODE (x) == PLUS)
++ {
+ rtx op1 = XEXP (x, 0);
+ rtx op2 = XEXP (x, 1);
+ rtx y;
+@@ -3894,12 +4377,12 @@ rs6000_legitimize_address (rtx x, rtx ol
+ y = gen_rtx_PLUS (Pmode, op1, op2);
+
+ if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2))
+- return force_reg (Pmode, y);
++ ret = force_reg (Pmode, y);
+ else
+- return y;
++ ret = y;
+ }
+-
+- return force_reg (Pmode, x);
++ else
++ ret = force_reg (Pmode, x);
+ }
+ else if (TARGET_ELF
+ && TARGET_32BIT
+@@ -3915,7 +4398,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_elf_high (reg, x));
+- return gen_rtx_LO_SUM (Pmode, reg, x);
++ ret = gen_rtx_LO_SUM (Pmode, reg, x);
+ }
+ else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
+ && ! flag_pic
+@@ -3933,17 +4416,34 @@ rs6000_legitimize_address (rtx x, rtx ol
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_macho_high (reg, x));
+- return gen_rtx_LO_SUM (Pmode, reg, x);
++ ret = gen_rtx_LO_SUM (Pmode, reg, x);
+ }
+ else if (TARGET_TOC
+ && GET_CODE (x) == SYMBOL_REF
+ && constant_pool_expr_p (x)
+ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
+ {
+- return create_TOC_reference (x);
++ ret = create_TOC_reference (x);
+ }
+ else
+- return NULL_RTX;
++ ret = NULL_RTX;
++
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_legitimize_address: mode %s, original addr:\n",
++ GET_MODE_NAME (mode));
++ debug_rtx (orig_x);
++ if (ret)
++ {
++ fprintf (stderr, "New addr:\n");
++ debug_rtx (ret);
++ }
++ else
++ fprintf (stderr, "NULL returned\n");
++ }
++
++ return ret;
+ }
+
+ /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
+@@ -4232,6 +4732,9 @@ rs6000_legitimize_reload_address (rtx x,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED, int *win)
+ {
++ rtx orig_x = x;
++ rtx ret = NULL_RTX;
++
+ /* We must recognize output that we have already generated ourselves. */
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+@@ -4243,17 +4746,17 @@ rs6000_legitimize_reload_address (rtx x,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+ #if TARGET_MACHO
+- if (DEFAULT_ABI == ABI_DARWIN && flag_pic
+- && GET_CODE (x) == LO_SUM
+- && GET_CODE (XEXP (x, 0)) == PLUS
+- && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
+- && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+- && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
+- && machopic_operand_p (XEXP (x, 1)))
++ else if (DEFAULT_ABI == ABI_DARWIN && flag_pic
++ && GET_CODE (x) == LO_SUM
++ && GET_CODE (XEXP (x, 0)) == PLUS
++ && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
++ && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
++ && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
++ && machopic_operand_p (XEXP (x, 1)))
+ {
+ /* Result of previous invocation of this function on Darwin
+ floating point constant. */
+@@ -4261,40 +4764,42 @@ rs6000_legitimize_reload_address (rtx x,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+ #endif
+
+ /* Force ld/std non-word aligned offset into base register by wrapping
+ in offset 0. */
+- if (GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && REGNO (XEXP (x, 0)) < 32
+- && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && (INTVAL (XEXP (x, 1)) & 3) != 0
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
+- && TARGET_POWERPC64)
++ else if (GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && REGNO (XEXP (x, 0)) < 32
++ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && (INTVAL (XEXP (x, 1)) & 3) != 0
++ && !ALTIVEC_VECTOR_MODE (mode)
++ && !VSX_VECTOR_MODE (mode)
++ && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
++ && TARGET_POWERPC64)
+ {
+ x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+- if (GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
+- && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && !SPE_VECTOR_MODE (mode)
+- && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+- || mode == DDmode || mode == TDmode
+- || mode == DImode))
+- && !ALTIVEC_VECTOR_MODE (mode))
++ else if (GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
++ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && !SPE_VECTOR_MODE (mode)
++ && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
++ || mode == DDmode || mode == TDmode
++ || mode == DImode))
++ && !ALTIVEC_VECTOR_MODE (mode)
++ && !VSX_VECTOR_MODE (mode))
+ {
+ HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
+ HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
+@@ -4305,42 +4810,44 @@ rs6000_legitimize_reload_address (rtx x,
+ if (high + low != val)
+ {
+ *win = 0;
+- return x;
++ ret = x;
+ }
++ else
++ {
++ /* Reload the high part into a base reg; leave the low part
++ in the mem directly. */
+
+- /* Reload the high part into a base reg; leave the low part
+- in the mem directly. */
+-
+- x = gen_rtx_PLUS (GET_MODE (x),
+- gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+- GEN_INT (high)),
+- GEN_INT (low));
++ x = gen_rtx_PLUS (GET_MODE (x),
++ gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
++ GEN_INT (high)),
++ GEN_INT (low));
+
+- push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+- opnum, (enum reload_type)type);
+- *win = 1;
+- return x;
++ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
++ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
++ opnum, (enum reload_type)type);
++ *win = 1;
++ return x;
++ }
+ }
+
+- if (GET_CODE (x) == SYMBOL_REF
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && !SPE_VECTOR_MODE (mode)
++ else if (GET_CODE (x) == SYMBOL_REF
++ && VECTOR_MEM_NONE_P (mode)
++ && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
+ #if TARGET_MACHO
+- && DEFAULT_ABI == ABI_DARWIN
+- && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
++ && DEFAULT_ABI == ABI_DARWIN
++ && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+ #else
+- && DEFAULT_ABI == ABI_V4
+- && !flag_pic
++ && DEFAULT_ABI == ABI_V4
++ && !flag_pic
+ #endif
+- /* Don't do this for TFmode or TDmode, since the result isn't offsettable.
+- The same goes for DImode without 64-bit gprs and DFmode and DDmode
+- without fprs. */
+- && mode != TFmode
+- && mode != TDmode
+- && (mode != DImode || TARGET_POWERPC64)
+- && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
+- || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
++ /* Don't do this for TFmode or TDmode, since the result isn't
++ offsettable. The same goes for DImode without 64-bit gprs and
++ DFmode and DDmode without fprs. */
++ && mode != TFmode
++ && mode != TDmode
++ && (mode != DImode || TARGET_POWERPC64)
++ && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
++ || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
+ {
+ #if TARGET_MACHO
+ if (flag_pic)
+@@ -4359,37 +4866,61 @@ rs6000_legitimize_reload_address (rtx x,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+ /* Reload an offset address wrapped by an AND that represents the
+ masking of the lower bits. Strip the outer AND and let reload
+ convert the offset address into an indirect address. */
+- if (TARGET_ALTIVEC
+- && ALTIVEC_VECTOR_MODE (mode)
+- && GET_CODE (x) == AND
+- && GET_CODE (XEXP (x, 0)) == PLUS
+- && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+- && GET_CODE (XEXP (x, 1)) == CONST_INT
+- && INTVAL (XEXP (x, 1)) == -16)
++ else if (VECTOR_MEM_ALTIVEC_P (mode)
++ && GET_CODE (x) == AND
++ && GET_CODE (XEXP (x, 0)) == PLUS
++ && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
++ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
++ && GET_CODE (XEXP (x, 1)) == CONST_INT
++ && INTVAL (XEXP (x, 1)) == -16)
+ {
+ x = XEXP (x, 0);
+ *win = 1;
+- return x;
++ ret = x;
+ }
+
+- if (TARGET_TOC
+- && GET_CODE (x) == SYMBOL_REF
+- && constant_pool_expr_p (x)
+- && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
++ else if (TARGET_TOC
++ && GET_CODE (x) == SYMBOL_REF
++ && constant_pool_expr_p (x)
++ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
+ {
+ x = create_TOC_reference (x);
+ *win = 1;
+- return x;
++ ret = x;
++ }
++
++ else
++ {
++ *win = 0;
++ ret = x;
+ }
+- *win = 0;
+- return x;
++
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_legitimize_reload_address: mode = %s, opnum = %d, "
++ "type = %d, ind_levels = %d, win = %d, original addr:\n",
++ GET_MODE_NAME (mode), opnum, type, ind_levels, *win);
++ debug_rtx (orig_x);
++
++ if (orig_x == ret)
++ fprintf (stderr, "Same address returned\n");
++ else if (!ret)
++ fprintf (stderr, "NULL returned\n");
++ else
++ {
++ fprintf (stderr, "New address:\n");
++ debug_rtx (ret);
++ }
++ }
++
++ return ret;
+ }
+
+ /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+@@ -4412,77 +4943,101 @@ rs6000_legitimize_reload_address (rtx x,
+ int
+ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
+ {
++ int ret;
++ rtx orig_x = x;
++
+ /* If this is an unaligned stvx/ldvx type address, discard the outer AND. */
+ if (TARGET_ALTIVEC
+- && ALTIVEC_VECTOR_MODE (mode)
++ && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ && GET_CODE (x) == AND
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) == -16)
+ x = XEXP (x, 0);
+
+ if (RS6000_SYMBOL_REF_TLS_P (x))
+- return 0;
+- if (legitimate_indirect_address_p (x, reg_ok_strict))
+- return 1;
+- if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && !SPE_VECTOR_MODE (mode)
+- && mode != TFmode
+- && mode != TDmode
+- /* Restrict addressing for DI because of our SUBREG hackery. */
+- && !(TARGET_E500_DOUBLE
+- && (mode == DFmode || mode == DDmode || mode == DImode))
+- && TARGET_UPDATE
+- && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
+- return 1;
+- if (legitimate_small_data_p (mode, x))
+- return 1;
+- if (legitimate_constant_pool_address_p (x))
+- return 1;
++ ret = 0;
++ else if (legitimate_indirect_address_p (x, reg_ok_strict))
++ ret = 1;
++ else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
++ && !VECTOR_MEM_ALTIVEC_P (mode)
++ /* && !VECTOR_MEM_VSX_P (mode) */
++ && (TARGET_SPE && !SPE_VECTOR_MODE (mode))
++ && mode != TFmode
++ && mode != TDmode
++ /* Restrict addressing for DI because of our SUBREG hackery. */
++ && !(TARGET_E500_DOUBLE
++ && (mode == DFmode || mode == DDmode || mode == DImode))
++ && TARGET_UPDATE
++ && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
++ ret = 1;
++ else if (legitimate_small_data_p (mode, x))
++ ret = 1;
++ else if (legitimate_constant_pool_address_p (x))
++ ret = 1;
+ /* If not REG_OK_STRICT (before reload) let pass any stack offset. */
+- if (! reg_ok_strict
+- && GET_CODE (x) == PLUS
+- && GET_CODE (XEXP (x, 0)) == REG
+- && (XEXP (x, 0) == virtual_stack_vars_rtx
+- || XEXP (x, 0) == arg_pointer_rtx)
+- && GET_CODE (XEXP (x, 1)) == CONST_INT)
+- return 1;
+- if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
+- return 1;
+- if (mode != TImode
+- && mode != TFmode
+- && mode != TDmode
+- && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+- || TARGET_POWERPC64
+- || (mode != DFmode && mode != DDmode)
+- || (TARGET_E500_DOUBLE && mode != DDmode))
+- && (TARGET_POWERPC64 || mode != DImode)
+- && !avoiding_indexed_address_p (mode)
+- && legitimate_indexed_address_p (x, reg_ok_strict))
+- return 1;
+- if (GET_CODE (x) == PRE_MODIFY
+- && mode != TImode
+- && mode != TFmode
+- && mode != TDmode
+- && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
+- || TARGET_POWERPC64
+- || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
+- && (TARGET_POWERPC64 || mode != DImode)
+- && !ALTIVEC_VECTOR_MODE (mode)
+- && !SPE_VECTOR_MODE (mode)
+- /* Restrict addressing for DI because of our SUBREG hackery. */
+- && !(TARGET_E500_DOUBLE
+- && (mode == DFmode || mode == DDmode || mode == DImode))
+- && TARGET_UPDATE
+- && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
+- && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
+- || (!avoiding_indexed_address_p (mode)
+- && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
+- && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
+- return 1;
+- if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
+- return 1;
+- return 0;
++ else if (! reg_ok_strict
++ && GET_CODE (x) == PLUS
++ && GET_CODE (XEXP (x, 0)) == REG
++ && (XEXP (x, 0) == virtual_stack_vars_rtx
++ || XEXP (x, 0) == arg_pointer_rtx)
++ && GET_CODE (XEXP (x, 1)) == CONST_INT)
++ ret = 1;
++ else if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
++ ret = 1;
++ else if (mode != TImode
++ && mode != TFmode
++ && mode != TDmode
++ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
++ || TARGET_POWERPC64
++ || (mode != DFmode && mode != DDmode)
++ || (TARGET_E500_DOUBLE && mode != DDmode))
++ && (TARGET_POWERPC64 || mode != DImode)
++ && !avoiding_indexed_address_p (mode)
++ && legitimate_indexed_address_p (x, reg_ok_strict))
++ ret = 1;
++ else if (GET_CODE (x) == PRE_MODIFY
++ && VECTOR_MEM_VSX_P (mode)
++ && TARGET_UPDATE
++ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)
++ && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
++ ret = 1;
++ else if (GET_CODE (x) == PRE_MODIFY
++ && mode != TImode
++ && mode != TFmode
++ && mode != TDmode
++ && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
++ || TARGET_POWERPC64
++ || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
++ && (TARGET_POWERPC64 || mode != DImode)
++ && !VECTOR_MEM_ALTIVEC_P (mode)
++ && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
++ /* Restrict addressing for DI because of our SUBREG hackery. */
++ && !(TARGET_E500_DOUBLE
++ && (mode == DFmode || mode == DDmode || mode == DImode))
++ && TARGET_UPDATE
++ && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
++ && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
++ || (!avoiding_indexed_address_p (mode)
++ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
++ && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
++ ret = 1;
++ else if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
++ ret = 1;
++ else
++ ret = 0;
++
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_legitimate_address: return = %d, mode = %s, "
++ "strict = %d\n",
++ ret,
++ GET_MODE_NAME (mode),
++ reg_ok_strict);
++ debug_rtx (orig_x);
++ }
++
++ return ret;
+ }
+
+ /* Go to LABEL if ADDR (a legitimate address expression)
+@@ -4499,28 +5054,40 @@ rs6000_legitimate_address (enum machine_
+ bool
+ rs6000_mode_dependent_address (rtx addr)
+ {
++ bool ret = false;
++
+ switch (GET_CODE (addr))
+ {
+ case PLUS:
+ if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
+- return val + 12 + 0x8000 >= 0x10000;
++ ret = (val + 12 + 0x8000 >= 0x10000);
+ }
+ break;
+
+ case LO_SUM:
+- return true;
++ ret = true;
++ break;
+
+ /* Auto-increment cases are now treated generically in recog.c. */
+ case PRE_MODIFY:
+- return TARGET_UPDATE;
++ ret = (TARGET_UPDATE != 0);
++ break;
+
+ default:
+ break;
+ }
+
+- return false;
++ if (TARGET_DEBUG_ADDR)
++ {
++ fprintf (stderr,
++ "\nrs6000_mode_dependent_address: ret = %d\n",
++ (int)ret);
++ debug_rtx (addr);
++ }
++
++ return ret;
+ }
+
+ /* Implement FIND_BASE_TERM. */
+@@ -4571,43 +5138,6 @@ rs6000_offsettable_memref_p (rtx op)
+ return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1);
+ }
+
+-/* Return number of consecutive hard regs needed starting at reg REGNO
+- to hold something of mode MODE.
+- This is ordinarily the length in words of a value of mode MODE
+- but can be less for certain modes in special long registers.
+-
+- For the SPE, GPRs are 64 bits but only 32 bits are visible in
+- scalar instructions. The upper 32 bits are only available to the
+- SIMD instructions.
+-
+- POWER and PowerPC GPRs hold 32 bits worth;
+- PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
+-
+-int
+-rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
+-{
+- if (FP_REGNO_P (regno))
+- return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+-
+- if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+- return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
+-
+- if (ALTIVEC_REGNO_P (regno))
+- return
+- (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
+-
+- /* The value returned for SCmode in the E500 double case is 2 for
+- ABI compatibility; storing an SCmode value in a single register
+- would require function_arg and rs6000_spe_function_arg to handle
+- SCmode so as to pass the value correctly in a pair of
+- registers. */
+- if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
+- && !DECIMAL_FLOAT_MODE_P (mode))
+- return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+-
+- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+-}
+-
+ /* Change register usage conditional on target flags. */
+ void
+ rs6000_conditional_register_usage (void)
+@@ -4672,14 +5202,14 @@ rs6000_conditional_register_usage (void)
+ = call_really_used_regs[14] = 1;
+ }
+
+- if (!TARGET_ALTIVEC)
++ if (!TARGET_ALTIVEC && !TARGET_VSX)
+ {
+ for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
+ fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
+ call_really_used_regs[VRSAVE_REGNO] = 1;
+ }
+
+- if (TARGET_ALTIVEC)
++ if (TARGET_ALTIVEC || TARGET_VSX)
+ global_regs[VSCR_REGNO] = 1;
+
+ if (TARGET_ALTIVEC_ABI)
+@@ -5101,6 +5631,8 @@ rs6000_emit_move (rtx dest, rtx source,
+ 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]);
+@@ -5270,6 +5802,9 @@ rs6000_emit_move (rtx dest, rtx source,
+ break;
+
+ case TImode:
++ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (TImode))
++ break;
++
+ rs6000_eliminate_indexed_memrefs (operands);
+
+ if (TARGET_POWER)
+@@ -5285,7 +5820,7 @@ rs6000_emit_move (rtx dest, rtx source,
+ break;
+
+ default:
+- gcc_unreachable ();
++ fatal_insn ("bad move", gen_rtx_SET (VOIDmode, dest, source));
+ }
+
+ /* Above, we may have called force_const_mem which may have returned
+@@ -5305,10 +5840,10 @@ rs6000_emit_move (rtx dest, rtx source,
+ && TARGET_HARD_FLOAT && TARGET_FPRS)
+
+ /* Nonzero if we can use an AltiVec register to pass this arg. */
+-#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
+- (ALTIVEC_VECTOR_MODE (MODE) \
+- && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
+- && TARGET_ALTIVEC_ABI \
++#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
++ ((ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)) \
++ && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
++ && TARGET_ALTIVEC_ABI \
+ && (NAMED))
+
+ /* Return a nonzero value to say to return the function value in
+@@ -5549,7 +6084,7 @@ function_arg_boundary (enum machine_mode
+ && int_size_in_bytes (type) >= 8
+ && int_size_in_bytes (type) < 16))
+ return 64;
+- else if (ALTIVEC_VECTOR_MODE (mode)
++ else if ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) >= 16))
+ return 128;
+@@ -5694,7 +6229,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
+ cum->nargs_prototype--;
+
+ if (TARGET_ALTIVEC_ABI
+- && (ALTIVEC_VECTOR_MODE (mode)
++ && ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) == 16)))
+ {
+@@ -6288,7 +6823,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum
+ else
+ return gen_rtx_REG (mode, cum->vregno);
+ else if (TARGET_ALTIVEC_ABI
+- && (ALTIVEC_VECTOR_MODE (mode)
++ && ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) == 16)))
+ {
+@@ -7212,10 +7747,13 @@ static const struct builtin_description
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
++ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
++ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
++ { MASK_ALTIVEC, CODE_FOR_vector_vselv2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
+@@ -7289,18 +7827,18 @@ static struct builtin_description bdesc_
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
+- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv16qi, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv8hi, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv4si, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
++ { MASK_ALTIVEC, CODE_FOR_vector_eqv4sf, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
++ { MASK_ALTIVEC, CODE_FOR_vector_gev4sf, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtuv16qi, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtuv8hi, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtuv4si, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv16qi, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv8hi, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv4si, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
++ { MASK_ALTIVEC, CODE_FOR_vector_gtv4sf, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
+ { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
+@@ -7331,7 +7869,7 @@ static struct builtin_description bdesc_
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
+- { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
++ { MASK_ALTIVEC, CODE_FOR_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
+ { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
+@@ -7796,6 +8334,11 @@ static struct builtin_description bdesc_
+ { 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_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 },
++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
++
+ /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
+ end with SPE_BUILTIN_EVSUBFUSIAAW. */
+ { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
+@@ -8352,16 +8895,16 @@ altivec_expand_ld_builtin (tree exp, rtx
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
+- icode = CODE_FOR_altivec_lvx_v16qi;
++ icode = CODE_FOR_vector_load_v16qi;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
+- icode = CODE_FOR_altivec_lvx_v8hi;
++ icode = CODE_FOR_vector_load_v8hi;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
+- icode = CODE_FOR_altivec_lvx_v4si;
++ icode = CODE_FOR_vector_load_v4si;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
+- icode = CODE_FOR_altivec_lvx_v4sf;
++ icode = CODE_FOR_vector_load_v4sf;
+ break;
+ default:
+ *expandedp = false;
+@@ -8405,16 +8948,16 @@ altivec_expand_st_builtin (tree exp, rtx
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
+- icode = CODE_FOR_altivec_stvx_v16qi;
++ icode = CODE_FOR_vector_store_v16qi;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
+- icode = CODE_FOR_altivec_stvx_v8hi;
++ icode = CODE_FOR_vector_store_v8hi;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
+- icode = CODE_FOR_altivec_stvx_v4si;
++ icode = CODE_FOR_vector_store_v4si;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
+- icode = CODE_FOR_altivec_stvx_v4sf;
++ icode = CODE_FOR_vector_store_v4sf;
+ break;
+ default:
+ *expandedp = false;
+@@ -9372,6 +9915,8 @@ rs6000_init_builtins (void)
+ {
+ V2SI_type_node = build_vector_type (intSI_type_node, 2);
+ V2SF_type_node = build_vector_type (float_type_node, 2);
++ V2DI_type_node = build_vector_type (intDI_type_node, 2);
++ V2DF_type_node = build_vector_type (double_type_node, 2);
+ V4HI_type_node = build_vector_type (intHI_type_node, 4);
+ V4SI_type_node = build_vector_type (intSI_type_node, 4);
+ V4SF_type_node = build_vector_type (float_type_node, 4);
+@@ -9404,7 +9949,10 @@ rs6000_init_builtins (void)
+ uintHI_type_internal_node = unsigned_intHI_type_node;
+ intSI_type_internal_node = intSI_type_node;
+ uintSI_type_internal_node = unsigned_intSI_type_node;
++ intDI_type_internal_node = intDI_type_node;
++ uintDI_type_internal_node = unsigned_intDI_type_node;
+ float_type_internal_node = float_type_node;
++ double_type_internal_node = float_type_node;
+ void_type_internal_node = void_type_node;
+
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+@@ -9462,13 +10010,18 @@ rs6000_init_builtins (void)
+ get_identifier ("__vector __pixel"),
+ pixel_V8HI_type_node));
+
++ if (TARGET_VSX)
++ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
++ get_identifier ("__vector double"),
++ V2DF_type_node));
++
+ if (TARGET_PAIRED_FLOAT)
+ paired_init_builtins ();
+ if (TARGET_SPE)
+ spe_init_builtins ();
+ if (TARGET_ALTIVEC)
+ altivec_init_builtins ();
+- if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT)
++ if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT || TARGET_VSX)
+ rs6000_common_init_builtins ();
+ if (TARGET_PPC_GFXOPT)
+ {
+@@ -10407,6 +10960,26 @@ rs6000_common_init_builtins (void)
+ tree int_ftype_v8hi_v8hi
+ = build_function_type_list (integer_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
++ tree v2df_ftype_v2df_v2df_v2df
++ = build_function_type_list (V2DF_type_node,
++ V2DF_type_node, V2DF_type_node,
++ V2DF_type_node, NULL_TREE);
++ tree v2di_ftype_v2di_v2di_v2di
++ = build_function_type_list (V2DI_type_node,
++ V2DI_type_node, V2DI_type_node,
++ V2DI_type_node, NULL_TREE);
++ tree v2df_ftype_v2df_v2df_v16qi
++ = build_function_type_list (V2DF_type_node,
++ V2DF_type_node, V2DF_type_node,
++ V16QI_type_node, NULL_TREE);
++ tree v2di_ftype_v2di_v2di_v16qi
++ = build_function_type_list (V2DI_type_node,
++ V2DI_type_node, V2DI_type_node,
++ V16QI_type_node, NULL_TREE);
++ tree v4sf_ftype_v4si
++ = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
++ tree v4si_ftype_v4sf
++ = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
+
+ /* Add the simple ternary operators. */
+ d = bdesc_3arg;
+@@ -10443,6 +11016,12 @@ rs6000_common_init_builtins (void)
+ case VOIDmode:
+ type = opaque_ftype_opaque_opaque_opaque;
+ break;
++ case V2DImode:
++ type = v2di_ftype_v2di_v2di_v2di;
++ break;
++ case V2DFmode:
++ type = v2df_ftype_v2df_v2df_v2df;
++ break;
+ case V4SImode:
+ type = v4si_ftype_v4si_v4si_v4si;
+ break;
+@@ -10466,6 +11045,12 @@ rs6000_common_init_builtins (void)
+ {
+ switch (mode0)
+ {
++ case V2DImode:
++ type = v2di_ftype_v2di_v2di_v16qi;
++ break;
++ case V2DFmode:
++ type = v2df_ftype_v2df_v2df_v16qi;
++ break;
+ case V4SImode:
+ type = v4si_ftype_v4si_v4si_v16qi;
+ break;
+@@ -10721,6 +11306,10 @@ rs6000_common_init_builtins (void)
+ type = v2si_ftype_v2sf;
+ else if (mode0 == V2SImode && mode1 == QImode)
+ type = v2si_ftype_char;
++ else if (mode0 == V4SImode && mode1 == V4SFmode)
++ type = v4si_ftype_v4sf;
++ else if (mode0 == V4SFmode && mode1 == V4SImode)
++ type = v4sf_ftype_v4si;
+ else
+ gcc_unreachable ();
+
+@@ -11601,13 +12190,101 @@ rs6000_instantiate_decls (void)
+ instantiate_decl_rtl (cfun->machine->sdmode_stack_slot);
+ }
+
++/* Given an rtx X being reloaded into a reg required to be
++ in class CLASS, return the class of reg to actually use.
++ In general this is just CLASS; but on some machines
++ in some cases it is preferable to use a more restrictive class.
++
++ On the RS/6000, we have to return NO_REGS when we want to reload a
++ floating-point CONST_DOUBLE to force it to be copied to memory.
++
++ We also don't want to reload integer values into floating-point
++ registers if we can at all help it. In fact, this can
++ cause reload to die, if it tries to generate a reload of CTR
++ into a FP register and discovers it doesn't have the memory location
++ required.
++
++ ??? Would it be a good idea to have reload do the converse, that is
++ try to reload floating modes into FP registers if possible?
++ */
++
++enum reg_class
++rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
++{
++ enum machine_mode mode = GET_MODE (x);
++
++ if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
++ && VSX_REG_CLASS_P (rclass))
++ return rclass;
++
++ if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS
++ && easy_vector_constant (x, mode))
++ return rclass;
++
++ if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
++ return NO_REGS;
++
++ if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
++ return GENERAL_REGS;
++
++ /* For VSX, prefer the traditional registers. */
++ if (rclass == VSX_REGS)
++ {
++ if (mode == DFmode)
++ return FLOAT_REGS;
++
++ if (ALTIVEC_VECTOR_MODE (mode))
++ return ALTIVEC_REGS;
++ }
++
++ return rclass;
++}
++
++/* If we are copying between FP or AltiVec registers and anything else, we need
++ a memory location. The exception is when we are targeting ppc64 and the
++ move to/from fpr to gpr instructions are available. Also, under VSX, you
++ can copy vector registers from the FP register set to the Altivec register
++ set and vice versa. */
++
++bool
++rs6000_secondary_memory_needed (enum reg_class class1,
++ enum reg_class class2,
++ enum machine_mode mode)
++{
++ if (class1 == class2)
++ return false;
++
++ if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1)
++ && VSX_REG_CLASS_P (class2))
++ return false;
++
++ if (class1 == FLOAT_REGS
++ && (!TARGET_MFPGPR || !TARGET_POWERPC64
++ || ((mode != DFmode)
++ && (mode != DDmode)
++ && (mode != DImode))))
++ return true;
++
++ if (class2 == FLOAT_REGS
++ && (!TARGET_MFPGPR || !TARGET_POWERPC64
++ || ((mode != DFmode)
++ && (mode != DDmode)
++ && (mode != DImode))))
++ return true;
++
++ if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
++ return true;
++
++ return false;
++}
++
+ /* Return the register class of a scratch register needed to copy IN into
+ or out of a register in RCLASS in MODE. If it can be done directly,
+ NO_REGS is returned. */
+
+ enum reg_class
+ rs6000_secondary_reload_class (enum reg_class rclass,
+- enum machine_mode mode ATTRIBUTE_UNUSED,
++ enum machine_mode mode,
+ rtx in)
+ {
+ int regno;
+@@ -11663,6 +12340,13 @@ rs6000_secondary_reload_class (enum reg_
+ && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
+ return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+
++ /* Memory, and FP/altivec registers can go into fp/altivec registers under
++ VSX. */
++ if (TARGET_VSX
++ && (regno == -1 || VSX_REGNO_P (regno))
++ && VSX_REG_CLASS_P (rclass))
++ return NO_REGS;
++
+ /* Memory, and AltiVec registers can go into AltiVec registers. */
+ if ((regno == -1 || ALTIVEC_REGNO_P (regno))
+ && rclass == ALTIVEC_REGS)
+@@ -11676,6 +12360,28 @@ rs6000_secondary_reload_class (enum reg_
+ /* Otherwise, we need GENERAL_REGS. */
+ return GENERAL_REGS;
+ }
++
++/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
++
++bool
++rs6000_cannot_change_mode_class (enum machine_mode from,
++ enum machine_mode to,
++ enum reg_class rclass)
++{
++ return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
++ ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
++ || TARGET_IEEEQUAD)
++ && reg_classes_intersect_p (FLOAT_REGS, rclass))
++ : (((TARGET_E500_DOUBLE
++ && ((((to) == DFmode) + ((from) == DFmode)) == 1
++ || (((to) == TFmode) + ((from) == TFmode)) == 1
++ || (((to) == DDmode) + ((from) == DDmode)) == 1
++ || (((to) == TDmode) + ((from) == TDmode)) == 1
++ || (((to) == DImode) + ((from) == DImode)) == 1))
++ || (TARGET_SPE
++ && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
++ && reg_classes_intersect_p (GENERAL_REGS, rclass)));
++}
+ \f
+ /* Given a comparison operation, return the bit number in CCR to test. We
+ know this is a valid comparison.
+@@ -12406,6 +13112,26 @@ print_operand (FILE *file, rtx x, int co
+ fprintf (file, "%d", i + 1);
+ return;
+
++ case 'x':
++ /* X is a FPR or Altivec register used in a VSX context. */
++ if (GET_CODE (x) != REG || !VSX_REGNO_P (REGNO (x)))
++ output_operand_lossage ("invalid %%x value");
++ else
++ {
++ int reg = REGNO (x);
++ int vsx_reg = (FP_REGNO_P (reg)
++ ? reg - 32
++ : reg - FIRST_ALTIVEC_REGNO + 32);
++
++#ifdef TARGET_REGNAMES
++ if (TARGET_REGNAMES)
++ fprintf (file, "%%vs%d", vsx_reg);
++ else
++#endif
++ fprintf (file, "%d", vsx_reg);
++ }
++ return;
++
+ case 'X':
+ if (GET_CODE (x) == MEM
+ && (legitimate_indexed_address_p (XEXP (x, 0), 0)
+@@ -12518,13 +13244,16 @@ print_operand (FILE *file, rtx x, int co
+
+ /* Fall through. Must be [reg+reg]. */
+ }
+- if (TARGET_ALTIVEC
++ if (VECTOR_MEM_ALTIVEC_P (GET_MODE (x))
+ && GET_CODE (tmp) == AND
+ && GET_CODE (XEXP (tmp, 1)) == CONST_INT
+ && INTVAL (XEXP (tmp, 1)) == -16)
+ tmp = XEXP (tmp, 0);
++ else if (VECTOR_MEM_VSX_P (GET_MODE (x))
++ && GET_CODE (tmp) == PRE_MODIFY)
++ tmp = XEXP (tmp, 1);
+ if (GET_CODE (tmp) == REG)
+- fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
++ fprintf (file, "%s,%s", reg_names[0], reg_names[REGNO (tmp)]);
+ else
+ {
+ if (!GET_CODE (tmp) == PLUS
+@@ -13296,55 +14025,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr
+ return string;
+ }
+
+-/* Return insn index for the vector compare instruction for given CODE,
+- and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is
+- not available. */
++/* Return insn for VSX comparisons. */
+
+-static int
+-get_vec_cmp_insn (enum rtx_code code,
+- enum machine_mode dest_mode,
+- enum machine_mode op_mode)
++static rtx
++rs6000_emit_vector_compare_vsx (enum rtx_code code,
++ rtx mask,
++ rtx op0,
++ rtx op1)
+ {
+- if (!TARGET_ALTIVEC)
+- return INSN_NOT_AVAILABLE;
+-
+ switch (code)
+ {
++ default:
++ break;
++
+ case EQ:
+- if (dest_mode == V16QImode && op_mode == V16QImode)
+- return UNSPEC_VCMPEQUB;
+- if (dest_mode == V8HImode && op_mode == V8HImode)
+- return UNSPEC_VCMPEQUH;
+- if (dest_mode == V4SImode && op_mode == V4SImode)
+- return UNSPEC_VCMPEQUW;
+- if (dest_mode == V4SImode && op_mode == V4SFmode)
+- return UNSPEC_VCMPEQFP;
++ case GT:
++ case GE:
++ emit_insn (gen_rtx_SET (VOIDmode,
++ mask,
++ gen_rtx_fmt_ee (code, GET_MODE (mask),
++ op0,
++ op1)));
++ return mask;
++ }
++
++ return NULL_RTX;
++}
++
++/* Return insn for Altivec comparisons. */
++
++static rtx
++rs6000_emit_vector_compare_altivec (enum rtx_code code,
++ rtx mask,
++ rtx op0,
++ rtx op1)
++{
++ switch (code)
++ {
++ default:
+ break;
++
+ case GE:
+- if (dest_mode == V4SImode && op_mode == V4SFmode)
+- return UNSPEC_VCMPGEFP;
++ if (GET_MODE (mask) != V4SFmode)
++ return NULL_RTX;
++ /* fall through */
++ case EQ:
+ case GT:
+- if (dest_mode == V16QImode && op_mode == V16QImode)
+- return UNSPEC_VCMPGTSB;
+- if (dest_mode == V8HImode && op_mode == V8HImode)
+- return UNSPEC_VCMPGTSH;
+- if (dest_mode == V4SImode && op_mode == V4SImode)
+- return UNSPEC_VCMPGTSW;
+- if (dest_mode == V4SImode && op_mode == V4SFmode)
+- return UNSPEC_VCMPGTFP;
+- break;
+ case GTU:
+- if (dest_mode == V16QImode && op_mode == V16QImode)
+- return UNSPEC_VCMPGTUB;
+- if (dest_mode == V8HImode && op_mode == V8HImode)
+- return UNSPEC_VCMPGTUH;
+- if (dest_mode == V4SImode && op_mode == V4SImode)
+- return UNSPEC_VCMPGTUW;
+- break;
+- default:
+- break;
++ emit_insn (gen_rtx_SET (VOIDmode,
++ mask,
++ gen_rtx_fmt_ee (code, GET_MODE (mask),
++ op0,
++ op1)));
++ return mask;
+ }
+- return INSN_NOT_AVAILABLE;
++
++ return NULL_RTX;
+ }
+
+ /* Emit vector compare for operands OP0 and OP1 using code RCODE.
+@@ -13355,129 +14091,111 @@ rs6000_emit_vector_compare (enum rtx_cod
+ rtx op0, rtx op1,
+ enum machine_mode dmode)
+ {
+- int vec_cmp_insn;
+ rtx mask;
+- enum machine_mode dest_mode;
+- enum machine_mode op_mode = GET_MODE (op1);
++ bool swap_operands = false;
++ bool try_again = false;
+
+- gcc_assert (TARGET_ALTIVEC);
++ gcc_assert (TARGET_ALTIVEC || TARGET_VSX);
+ gcc_assert (GET_MODE (op0) == GET_MODE (op1));
+
+- /* Floating point vector compare instructions uses destination V4SImode.
+- Move destination to appropriate mode later. */
+- if (dmode == V4SFmode)
+- dest_mode = V4SImode;
+- else
+- dest_mode = dmode;
++ mask = gen_reg_rtx (dmode);
+
+- mask = gen_reg_rtx (dest_mode);
+- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
++ /* Try for VSX before Altivec. */
++ if (TARGET_VSX && VSX_VECTOR_MODE (dmode))
++ {
++ rtx vsx = rs6000_emit_vector_compare_vsx (rcode, mask, op0, op1);
++ if (vsx)
++ return vsx;
++ }
++ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dmode))
++ {
++ rtx av = rs6000_emit_vector_compare_altivec (rcode, mask, op0, op1);
++ if (av)
++ return av;
++ }
+
+- if (vec_cmp_insn == INSN_NOT_AVAILABLE)
++ switch (rcode)
+ {
+- bool swap_operands = false;
+- bool try_again = false;
+- switch (rcode)
+- {
+- case LT:
+- rcode = GT;
+- swap_operands = true;
+- try_again = true;
+- break;
+- case LTU:
+- rcode = GTU;
+- swap_operands = true;
+- try_again = true;
+- break;
+- case NE:
+- case UNLE:
+- case UNLT:
+- case UNGE:
+- case UNGT:
+- /* Invert condition and try again.
+- e.g., A != B becomes ~(A==B). */
+- {
+- enum rtx_code rev_code;
+- enum insn_code nor_code;
+- rtx eq_rtx;
+-
+- rev_code = reverse_condition_maybe_unordered (rcode);
+- eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1,
+- dest_mode);
+-
+- nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code;
+- gcc_assert (nor_code != CODE_FOR_nothing);
+- emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
++ case LT:
++ rcode = GT;
++ swap_operands = true;
++ try_again = true;
++ break;
++ case LTU:
++ rcode = GTU;
++ swap_operands = true;
++ try_again = true;
++ break;
++ case NE:
++ case UNLE:
++ case UNLT:
++ case UNGE:
++ case UNGT:
++ /* Invert condition and try again.
++ e.g., A != B becomes ~(A==B). */
++ {
++ enum rtx_code rev_code;
++ enum insn_code nor_code;
++ rtx eq_rtx;
++
++ rev_code = reverse_condition_maybe_unordered (rcode);
++ eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, dmode);
++
++ nor_code = optab_handler (one_cmpl_optab, (int)dmode)->insn_code;
++ gcc_assert (nor_code != CODE_FOR_nothing);
++ emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
++ return mask;
++ }
++ break;
++ case GE:
++ case GEU:
++ case LE:
++ case LEU:
++ /* Try GT/GTU/LT/LTU OR EQ */
++ {
++ rtx c_rtx, eq_rtx;
++ enum insn_code ior_code;
++ enum rtx_code new_code;
+
+- if (dmode != dest_mode)
+- {
+- rtx temp = gen_reg_rtx (dest_mode);
+- convert_move (temp, mask, 0);
+- return temp;
+- }
+- return mask;
+- }
+- break;
+- case GE:
+- case GEU:
+- case LE:
+- case LEU:
+- /* Try GT/GTU/LT/LTU OR EQ */
++ switch (rcode)
+ {
+- rtx c_rtx, eq_rtx;
+- enum insn_code ior_code;
+- enum rtx_code new_code;
+-
+- switch (rcode)
+- {
+- case GE:
+- new_code = GT;
+- break;
+-
+- case GEU:
+- new_code = GTU;
+- break;
++ case GE:
++ new_code = GT;
++ break;
+
+- case LE:
+- new_code = LT;
+- break;
++ case GEU:
++ new_code = GTU;
++ break;
+
+- case LEU:
+- new_code = LTU;
+- break;
++ case LE:
++ new_code = LT;
++ break;
+
+- default:
+- gcc_unreachable ();
+- }
++ case LEU:
++ new_code = LTU;
++ break;
+
+- c_rtx = rs6000_emit_vector_compare (new_code,
+- op0, op1, dest_mode);
+- eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
+- dest_mode);
+-
+- ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code;
+- gcc_assert (ior_code != CODE_FOR_nothing);
+- emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
+- if (dmode != dest_mode)
+- {
+- rtx temp = gen_reg_rtx (dest_mode);
+- convert_move (temp, mask, 0);
+- return temp;
+- }
+- return mask;
++ default:
++ gcc_unreachable ();
+ }
+- break;
+- default:
+- gcc_unreachable ();
+- }
+
+- if (try_again)
+- {
+- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
+- /* You only get two chances. */
+- gcc_assert (vec_cmp_insn != INSN_NOT_AVAILABLE);
+- }
++ c_rtx = rs6000_emit_vector_compare (new_code,
++ op0, op1, dmode);
++ eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
++ dmode);
++
++ ior_code = optab_handler (ior_optab, (int)dmode)->insn_code;
++ gcc_assert (ior_code != CODE_FOR_nothing);
++ emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
++ return mask;
++ }
++ break;
++ default:
++ gcc_unreachable ();
++ }
+
++ if (try_again)
++ {
+ if (swap_operands)
+ {
+ rtx tmp;
+@@ -13485,69 +14203,23 @@ rs6000_emit_vector_compare (enum rtx_cod
+ op0 = op1;
+ op1 = tmp;
+ }
+- }
+-
+- emit_insn (gen_rtx_SET (VOIDmode, mask,
+- gen_rtx_UNSPEC (dest_mode,
+- gen_rtvec (2, op0, op1),
+- vec_cmp_insn)));
+- if (dmode != dest_mode)
+- {
+- rtx temp = gen_reg_rtx (dest_mode);
+- convert_move (temp, mask, 0);
+- return temp;
+- }
+- return mask;
+-}
+-
+-/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
+- valid insn doesn exist for given mode. */
+
+-static int
+-get_vsel_insn (enum machine_mode mode)
+-{
+- switch (mode)
+- {
+- case V4SImode:
+- return UNSPEC_VSEL4SI;
+- break;
+- case V4SFmode:
+- return UNSPEC_VSEL4SF;
+- break;
+- case V8HImode:
+- return UNSPEC_VSEL8HI;
+- break;
+- case V16QImode:
+- return UNSPEC_VSEL16QI;
+- break;
+- default:
+- return INSN_NOT_AVAILABLE;
+- break;
++ if (TARGET_VSX && VSX_VECTOR_MODE (dmode))
++ {
++ rtx vsx = rs6000_emit_vector_compare_vsx (rcode, mask, op0, op1);
++ if (vsx)
++ return vsx;
++ }
++ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dmode))
++ {
++ rtx av = rs6000_emit_vector_compare_altivec (rcode, mask, op0, op1);
++ if (av)
++ return av;
++ }
+ }
+- return INSN_NOT_AVAILABLE;
+-}
+-
+-/* Emit vector select insn where DEST is destination using
+- operands OP1, OP2 and MASK. */
+-
+-static void
+-rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
+-{
+- rtx t, temp;
+- enum machine_mode dest_mode = GET_MODE (dest);
+- int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
+
+- temp = gen_reg_rtx (dest_mode);
+-
+- /* For each vector element, select op1 when mask is 1 otherwise
+- select op2. */
+- t = gen_rtx_SET (VOIDmode, temp,
+- gen_rtx_UNSPEC (dest_mode,
+- gen_rtvec (3, op2, op1, mask),
+- vsel_insn_index));
+- emit_insn (t);
+- emit_move_insn (dest, temp);
+- return;
++ /* You only get two chances. */
++ gcc_unreachable ();
+ }
+
+ /* Emit vector conditional expression.
+@@ -13562,15 +14234,29 @@ rs6000_emit_vector_cond_expr (rtx dest,
+ enum rtx_code rcode = GET_CODE (cond);
+ rtx mask;
+
+- if (!TARGET_ALTIVEC)
++ if (!TARGET_ALTIVEC && !TARGET_VSX)
+ return 0;
+
+ /* Get the vector mask for the given relational operations. */
+ mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
+
+- rs6000_emit_vector_select (dest, op1, op2, mask);
++ if (!mask)
++ return 0;
+
+- return 1;
++ if ((TARGET_VSX && VSX_VECTOR_MOVE_MODE (dest_mode))
++ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dest_mode)))
++ {
++ rtx cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx);
++ emit_insn (gen_rtx_SET (VOIDmode,
++ dest,
++ gen_rtx_IF_THEN_ELSE (dest_mode,
++ cond2,
++ op1,
++ op2)));
++ return 1;
++ }
++
++ return 0;
+ }
+
+ /* Emit a conditional move: move TRUE_COND to DEST if OP of the
+@@ -13766,8 +14452,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
+ {
+ rtx condition_rtx, cr;
+
+- /* All isel implementations thus far are 32-bits. */
+- if (GET_MODE (rs6000_compare_op0) != SImode)
++ if (GET_MODE (rs6000_compare_op0) != SImode
++ && (!TARGET_POWERPC64 || GET_MODE (rs6000_compare_op0) != DImode))
+ return 0;
+
+ /* We still have to do the compare, because isel doesn't do a
+@@ -13776,12 +14462,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
+ condition_rtx = rs6000_generate_compare (GET_CODE (op));
+ cr = XEXP (condition_rtx, 0);
+
+- if (GET_MODE (cr) == CCmode)
+- emit_insn (gen_isel_signed (dest, condition_rtx,
+- true_cond, false_cond, cr));
++ if (GET_MODE (rs6000_compare_op0) == SImode)
++ {
++ if (GET_MODE (cr) == CCmode)
++ emit_insn (gen_isel_signed_si (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ else
++ emit_insn (gen_isel_unsigned_si (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ }
+ else
+- emit_insn (gen_isel_unsigned (dest, condition_rtx,
+- true_cond, false_cond, cr));
++ {
++ if (GET_MODE (cr) == CCmode)
++ emit_insn (gen_isel_signed_di (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ else
++ emit_insn (gen_isel_unsigned_di (dest, condition_rtx,
++ true_cond, false_cond, cr));
++ }
+
+ return 1;
+ }
+@@ -13808,6 +14506,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c
+ enum rtx_code c;
+ rtx target;
+
++ /* VSX/altivec have direct min/max insns. */
++ if ((code == SMAX || code == SMIN) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
++ {
++ emit_insn (gen_rtx_SET (VOIDmode,
++ dest,
++ gen_rtx_fmt_ee (code, mode, op0, op1)));
++ return;
++ }
++
+ if (code == SMAX || code == SMIN)
+ c = GE;
+ else
+@@ -15785,6 +16492,7 @@ emit_frame_save (rtx frame_reg, rtx fram
+
+ /* Some cases that need register indexed addressing. */
+ if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
++ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode)
+ || (TARGET_SPE_ABI
+ && SPE_VECTOR_MODE (mode)
+@@ -19320,6 +20028,7 @@ rs6000_issue_rate (void)
+ case CPU_POWER4:
+ case CPU_POWER5:
+ case CPU_POWER6:
++ case CPU_POWER7:
+ return 5;
+ default:
+ return 1;
+@@ -19921,6 +20630,41 @@ insn_must_be_first_in_group (rtx insn)
+ break;
+ }
+ break;
++ case PROCESSOR_POWER7:
++ type = get_attr_type (insn);
++
++ switch (type)
++ {
++ case TYPE_CR_LOGICAL:
++ case TYPE_MFCR:
++ case TYPE_MFCRF:
++ case TYPE_MTCR:
++ case TYPE_IDIV:
++ case TYPE_LDIV:
++ case TYPE_COMPARE:
++ case TYPE_DELAYED_COMPARE:
++ case TYPE_VAR_DELAYED_COMPARE:
++ case TYPE_ISYNC:
++ case TYPE_LOAD_L:
++ case TYPE_STORE_C:
++ case TYPE_LOAD_U:
++ case TYPE_LOAD_UX:
++ case TYPE_LOAD_EXT:
++ case TYPE_LOAD_EXT_U:
++ case TYPE_LOAD_EXT_UX:
++ case TYPE_STORE_U:
++ case TYPE_STORE_UX:
++ case TYPE_FPLOAD_U:
++ case TYPE_FPLOAD_UX:
++ case TYPE_FPSTORE_U:
++ case TYPE_FPSTORE_UX:
++ case TYPE_MFJMPR:
++ case TYPE_MTJMPR:
++ return true;
++ default:
++ break;
++ }
++ break;
+ default:
+ break;
+ }
+@@ -19982,6 +20726,23 @@ insn_must_be_last_in_group (rtx insn)
+ break;
+ }
+ break;
++ case PROCESSOR_POWER7:
++ type = get_attr_type (insn);
++
++ switch (type)
++ {
++ case TYPE_ISYNC:
++ case TYPE_SYNC:
++ case TYPE_LOAD_L:
++ case TYPE_STORE_C:
++ case TYPE_LOAD_EXT_U:
++ case TYPE_LOAD_EXT_UX:
++ case TYPE_STORE_UX:
++ return true;
++ default:
++ break;
++ }
++ break;
+ default:
+ break;
+ }
+@@ -20554,8 +21315,8 @@ rs6000_handle_altivec_attribute (tree *n
+ 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");
++ else if (type == double_type_node && !TARGET_VSX)
++ 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)
+@@ -20581,6 +21342,7 @@ rs6000_handle_altivec_attribute (tree *n
+ 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. */
+@@ -22116,7 +22878,7 @@ rs6000_register_move_cost (enum machine_
+ if (! reg_classes_intersect_p (to, GENERAL_REGS))
+ from = to;
+
+- if (from == FLOAT_REGS || from == ALTIVEC_REGS)
++ if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS)
+ return (rs6000_memory_move_cost (mode, from, 0)
+ + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
+
+@@ -22136,6 +22898,12 @@ rs6000_register_move_cost (enum machine_
+ return 2 * hard_regno_nregs[0][mode];
+ }
+
++ /* If we have VSX, we can easily move between FPR or Altivec registers. */
++ else if (TARGET_VSX
++ && ((from == VSX_REGS || from == FLOAT_REGS || from == ALTIVEC_REGS)
++ || (to == VSX_REGS || to == FLOAT_REGS || to == ALTIVEC_REGS)))
++ return 2;
++
+ /* Moving between two similar registers is just one instruction. */
+ else if (reg_classes_intersect_p (to, from))
+ return (mode == TFmode || mode == TDmode) ? 4 : 2;
+@@ -22376,8 +23144,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src)
+ emit_label (XEXP (label, 0));
+ }
+
+-/* Emit popcount intrinsic on TARGET_POPCNTB targets. DST is the
+- target, and SRC is the argument operand. */
++/* Emit popcount intrinsic on TARGET_POPCNTB (Power5) and TARGET_POPCNTD
++ (Power7) targets. DST is the target, and SRC is the argument operand. */
+
+ void
+ rs6000_emit_popcount (rtx dst, rtx src)
+@@ -22385,6 +23153,16 @@ rs6000_emit_popcount (rtx dst, rtx src)
+ enum machine_mode mode = GET_MODE (dst);
+ rtx tmp1, tmp2;
+
++ /* Use the PPC ISA 2.06 popcnt{w,d} instruction if we can. */
++ if (TARGET_POPCNTD)
++ {
++ if (mode == SImode)
++ emit_insn (gen_popcntwsi2 (dst, src));
++ else
++ emit_insn (gen_popcntddi2 (dst, src));
++ return;
++ }
++
+ tmp1 = gen_reg_rtx (mode);
+
+ if (mode == SImode)
+@@ -22797,7 +23575,7 @@ rs6000_vector_mode_supported_p (enum mac
+ if (TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return true;
+
+- else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
++ else if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
+ return true;
+
+ else
+--- gcc/config/rs6000/vsx.md (.../trunk) (revision 0)
++++ gcc/config/rs6000/vsx.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -0,0 +1,864 @@
++;; 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 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])
++
++;; 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")
++ (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")
++ (TI "sp")])
++
++;; Map into the register class used
++(define_mode_attr VSr [(V16QI "v")
++ (V8HI "v")
++ (V4SI "v")
++ (V4SF "wf")
++ (V2DI "wd")
++ (V2DF "wd")
++ (TI "wd")])
++
++;; Same size integer type for floating point data
++(define_mode_attr VSi [(V4SF "v4si")
++ (V2DF "v2di")])
++
++(define_mode_attr VSI [(V4SF "V4SI")
++ (V2DF "V2DI")])
++
++;; Word size for same size conversion
++(define_mode_attr VSc [(V4SF "w")
++ (V2DF "d")])
++
++;; Bitsize for DF load with update
++(define_mode_attr VSbit [(SI "32")
++ (DI "64")])
++
++(define_constants
++ [(UNSPEC_VSX_CONCAT_V2DF 500)])
++
++;; VSX moves
++(define_insn "*vsx_mov<mode>"
++ [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v")
++ (match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W"))]
++ "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 "xvmov<VSs> %x0,%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);
++
++ default:
++ gcc_unreachable ();
++ }
++}
++ [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,store,load,*,vecsimple,vecsimple,*")])
++
++;; Load/store with update
++;; Define insns that do load or store with update. Because VSX only has
++;; reg+reg addressing, pre-decrement or pre-inrement 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<mode>_update64"
++ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
++ (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
++ (match_operand:DI 2 "gpc_reg_operand" "r,r"))))
++ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
++ (plus:DI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "lx<VSm>ux %x3,%0,%2"
++ [(set_attr "type" "vecload")])
++
++(define_insn "*vsx_load<mode>_update32"
++ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
++ (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
++ (match_operand:SI 2 "gpc_reg_operand" "r,r"))))
++ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
++ (plus:SI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "lx<VSm>ux %x3,%0,%2"
++ [(set_attr "type" "vecload")])
++
++(define_insn "*vsx_store<mode>_update64"
++ [(set (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
++ (match_operand:DI 2 "gpc_reg_operand" "r,r")))
++ (match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
++ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
++ (plus:DI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "stx<VSm>ux %x3,%0,%1"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "*vsx_store<mode>_update32"
++ [(set (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
++ (match_operand:SI 2 "gpc_reg_operand" "r,r")))
++ (match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
++ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
++ (plus:SI (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++ "stx<VSm>ux %x3,%0,%1"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "*vsx_loaddf_update<VSbit>"
++ [(set (match_operand:DF 3 "vsx_register_operand" "=ws,?wa")
++ (mem:DF (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)))]
++ "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
++ "lxsdux %x3,%0,%2"
++ [(set_attr "type" "vecload")])
++
++(define_insn "*vsx_storedf_update<VSbit>"
++ [(set (mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
++ (match_operand:P 2 "gpc_reg_operand" "r,r")))
++ (match_operand:DF 3 "gpc_reg_operand" "ws,?wa"))
++ (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
++ (plus:P (match_dup 1)
++ (match_dup 2)))]
++ "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
++ "stxsdux %x3,%0,%1"
++ [(set_attr "type" "vecstore")])
++
++;; We may need to have a varient on the pattern for use in the prologue
++;; that doesn't depend on TARGET_UPDATE.
++
++\f
++;; VSX vector floating point arithmetic instructions
++(define_insn "*vsx_add<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvadd<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_sub<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvsub<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_mul<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvmul<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_div<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvdiv<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "vecfdiv")])
++
++(define_insn "*vsx_fre<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")]
++ UNSPEC_FRES))]
++ "flag_finite_math_only && VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvre<VSs> %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_neg<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvneg<VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_abs<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvabs<VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_nabs<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (neg:VSX_F
++ (abs:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvnabs<VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_smax<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvmax<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_smin<mode>3"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvmin<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_sqrt<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvsqrt<VSs> %x0,%x1"
++ [(set_attr "type" "vecfdiv")])
++
++;; Fused vector multiply/add instructions
++(define_insn "*vsx_fmadd<mode>4"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (plus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "gpc_reg_operand" "0,<VSr>")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xvmadda<VSs> %x0,%x1,%x2
++ xvmaddm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fmsub<mode>4"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (minus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xvmsuba<VSs> %x0,%x1,%x2
++ xvmsubm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmadd<mode>4_1"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (neg:VSX_F
++ (plus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmadda<VSs> %x0,%x1,%x2
++ xvnmaddm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmadd<mode>4_2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (minus:VSX_F
++ (mult:VSX_F
++ (neg:VSX_F
++ (match_operand:VSX_F 1 "gpc_reg_operand" "%<VSr>,<VSr>"))
++ (match_operand:VSX_F 2 "gpc_reg_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmadda<VSs> %x0,%x1,%x2
++ xvnmaddm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmsub<mode>4_1"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (neg:VSX_F
++ (minus:VSX_F
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmsuba<VSs> %x0,%x1,%x2
++ xvnmsubm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fnmsub<mode>4_2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
++ (minus:VSX_F
++ (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")
++ (mult:VSX_F
++ (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xvnmsuba<VSs> %x0,%x1,%x2
++ xvnmsubm<VSs> %x0,%x1,%x3"
++ [(set_attr "type" "vecfloat")])
++
++;; Vector conditional expressions
++(define_insn "*vsx_eq<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcmpeq<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_gt<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcmpgt<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "*vsx_ge<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcmpge<VSs> %x0,%x1,%x2"
++ [(set_attr "type" "veccmp")])
++
++(define_insn "vsx_vsel<mode>"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++ (const_int 0))
++ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
++ (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_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_F 0 "vsx_register_operand" "=<VSr>")
++ (if_then_else:VSX_F
++ (ge:VSX_F (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
++ (const_int 0))
++ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))
++ (neg:VSX_F (abs:VSX_F (match_dup 1)))))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcpsgn<VSs> %x0,%x2,%x1"
++ [(set_attr "type" "vecsimple")])
++
++(define_insn "*vsx_ftrunc<mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvr<VSs>piz %x0,%x1"
++ [(set_attr "type" "vecperm")])
++
++(define_insn "*vsx_float<VSi><mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcvsx<VSc><VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_floatuns<VSi><mode>2"
++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
++ (unsigned_float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcvux<VSc><VSs> %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fix_trunc<mode><VSi>2"
++ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
++ (fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcv<VSs>sx<VSc>s %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++(define_insn "*vsx_fixuns_trunc<mode><VSi>2"
++ [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
++ (unsigned_fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++ "VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "xvcv<VSs>ux<VSc>s %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++\f
++;; VSX scalar double precision floating point operations
++(define_insn"*vsx_adddf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (plus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsadddp %x0,%x1,%x2"
++ [(set_attr "type" "fp")
++ (set_attr "fp_type" "fp_addsub_d")])
++
++(define_insn"*vsx_subdf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (minus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xssubdp %x0,%x1,%x2"
++ [(set_attr "type" "fp")
++ (set_attr "fp_type" "fp_addsub_d")])
++
++(define_insn"*vsx_muldf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (mult:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsmuldp %x0,%x1,%x2"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_mul_d")])
++
++(define_insn"*vsx_divdf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (div:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsdivdp %x0,%x1,%x2"
++ [(set_attr "type" "ddiv")])
++
++(define_insn "*vsx_fredf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRES))]
++ "flag_finite_math_only && VECTOR_UNIT_VSX_P (DFmode)"
++ "xsredp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_sqrtdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (sqrt:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xssqrtdp %x0,%x1"
++ [(set_attr "type" "dsqrt")])
++
++(define_insn"*vsx_negdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (neg:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsnegdp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn"vsx_absdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsabsdp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn"*vsx_nabsdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (neg:DF (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsnabsdp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_smaxdf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (smax:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsmaxdp %x0,%x1,%x2"
++ [(set_attr "type" "fp")])
++
++
++(define_insn "*vsx_smindf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (smin:DF (match_operand:DF 1 "vsx_register_operand" "ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsmindp %x0,%x1,%x2"
++ [(set_attr "type" "fp")])
++
++;; Fused vector multiply/add instructions
++(define_insn "*vsx_fmadddf4"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "gpc_reg_operand" "0,ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xsmaddadp %x0,%x1,%x2
++ xsmaddmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fmsubdf4"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (minus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++ "@
++ xsmsubadp %x0,%x1,%x2
++ xsmsubmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmadddf4_1"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (neg:DF
++ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmaddadp %x0,%x1,%x2
++ xsnmaddmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmadddf4_2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (minus:DF (mult:DF (neg:DF
++ (match_operand:DF 1 "gpc_reg_operand" "%ws,ws"))
++ (match_operand:DF 2 "gpc_reg_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmaddadp %x0,%x1,%x2
++ xsnmaddmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmsubdf4_1"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (neg:DF
++ (minus:DF
++ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))
++ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmsubadp %x0,%x1,%x2
++ xsnmsubmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++(define_insn "*vsx_fnmsubdf4_2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
++ (minus:DF
++ (match_operand:DF 3 "vsx_register_operand" "0,ws")
++ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
++ (match_operand:DF 2 "vsx_register_operand" "ws,0"))))]
++ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++ && !HONOR_SIGNED_ZEROS (DFmode)"
++ "@
++ xsnmsubadp %x0,%x1,%x2
++ xsnmsubmdp %x0,%x1,%x3"
++ [(set_attr "type" "dmul")
++ (set_attr "fp_type" "fp_maddsub_d")])
++
++;; For the conversions, limit the register class for the integer value to be
++;; the fprs. 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_floatdidf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xscvsxddp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_floatunsdidf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unsigned_float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
++ "TARGET_HARD_FLOAT && TARGET_VSX"
++ "xscvuxddp %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_fix_truncdfdi2"
++ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
++ (fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xscvdpsxds %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_fixuns_truncdfdi2"
++ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
++ (unsigned_fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
++ "TARGET_HARD_FLOAT && TARGET_VSX"
++ "xscvdpuxds %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_btruncdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRIZ))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdpiz %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_floordf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRIM))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdpim %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_ceildf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
++ UNSPEC_FRIP))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdpip %x0,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "vsx_copysigndf3"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (if_then_else:DF (ge:DF (match_operand:DF 2 "vsx_register_operand" "ws")
++ (const_int 0))
++ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))
++ (neg:DF (abs:DF (match_dup 1)))))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xscpsgndp %x0,%x2,%x1"
++ [(set_attr "type" "fp")])
++
++(define_insn "*vsx_ftruncdf2"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (fix:DF (match_operand:DF 1 "register_operand" "ws")))]
++ "VECTOR_UNIT_VSX_P (DFmode)"
++ "xsrdppiz %x0,%x1"
++ [(set_attr "type" "vecfloat")])
++
++\f
++;; 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")])
++
++\f
++;; Permute operations
++
++(define_insn "vsx_concat_v2df"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
++ (unspec:V2DF
++ [(match_operand:DF 1 "vsx_register_operand" "f,wa")
++ (match_operand:DF 2 "vsx_register_operand" "f,wa")]
++ UNSPEC_VSX_CONCAT_V2DF))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++ "xxpermdi %x0,%x1,%x2,0"
++ [(set_attr "type" "vecperm")])
++
++;; Set a double into one element
++(define_insn "vsx_set_v2df"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
++ (vec_merge:V2DF
++ (match_operand:V2DF 1 "vsx_register_operand" "wd")
++ (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws"))
++ (match_operand:QI 3 "u5bit_cint_operand" "i")))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++{
++ operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
++ return \"xxpermdi %x0,%x1,%x2,%3\";
++}
++ [(set_attr "type" "vecperm")])
++
++;; Extract a DF element from V2DF
++(define_insn "vsx_extract_v2df"
++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
++ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
++ (parallel
++ [(match_operand:QI 2 "u5bit_cint_operand" "i")])))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++{
++ operands[3] = GEN_INT (INTVAL (operands[2]) & 1);
++ return \"xxpermdi %x0,%x1,%x1,%3\";
++}
++ [(set_attr "type" "vecperm")])
++
++;; General V2DF permute
++(define_insn "vsx_xxpermdi"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
++ (vec_concat:V2DF
++ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
++ (parallel
++ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
++ (vec_select:DF (match_operand:V2DF 3 "vsx_register_operand" "wd")
++ (parallel
++ [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++{
++ operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
++ | (INTVAL (operands[4]) & 1));
++ return \"xxpermdi %x0,%x1,%x3,%5\";
++}
++ [(set_attr "type" "vecperm")])
++
++;; V2DF splat
++(define_insn "vsx_splatv2df"
++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd")
++ (vec_duplicate:V2DF
++ (match_operand:DF 1 "input_operand" "ws,Z")))]
++ "VECTOR_UNIT_VSX_P (V2DFmode)"
++ "@
++ xxpermdi %x0,%x1,%x1,0
++ lxvdsx %x0,%y1"
++ [(set_attr "type" "vecperm,vecload")])
++
++;; V4SF splat
++(define_insn "*vsx_xxspltw"
++ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf")
++ (vec_duplicate:V4SF
++ (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf")
++ (parallel
++ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
++ "VECTOR_UNIT_VSX_P (V4SFmode)"
++ "xxspltw %x0,%x1,%2"
++ [(set_attr "type" "vecperm")])
++
++;; V4SF interleave
++(define_insn "*vsx_xxmrghw"
++ [(set (match_operand:V4SF 0 "register_operand" "=v")
++ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_VSX_P (V4SFmode)"
++ "xxmrghw %x0,%x1,%x2"
++ [(set_attr "type" "vecperm")])
++
++(define_insn "*vsx_xxmrglw"
++ [(set (match_operand:V4SF 0 "register_operand" "=v")
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_VSX_P (V4SFmode)"
++ "xxmrglw %x0,%x1,%x2"
++ [(set_attr "type" "vecperm")])
+--- gcc/config/rs6000/rs6000.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -1,6 +1,6 @@
+ /* Definitions of target machine for GNU compiler, for IBM RS/6000.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
++ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
+ Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+@@ -72,14 +72,16 @@
+ #define ASM_CPU_POWER6_SPEC "-mpower4 -maltivec"
+ #endif
+
+-#ifdef HAVE_AS_VSX
++#ifdef HAVE_AS_POPCNTD
+ #define ASM_CPU_POWER7_SPEC "-mpower7"
+ #else
+ #define ASM_CPU_POWER7_SPEC "-mpower4 -maltivec"
+ #endif
+
+-/* Common ASM definitions used by ASM_SPEC among the various targets
+- for handling -mcpu=xxx switches. */
++/* Common ASM definitions used by ASM_SPEC among the various targets for
++ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
++ provide the default assembler options if the user uses -mcpu=native, so if
++ you make changes here, make them also there. */
+ #define ASM_CPU_SPEC \
+ "%{!mcpu*: \
+ %{mpower: %{!mpower2: -mpwr}} \
+@@ -88,6 +90,7 @@
+ %{!mpowerpc64*: %{mpowerpc*: -mppc}} \
+ %{mno-power: %{!mpowerpc*: -mcom}} \
+ %{!mno-power: %{!mpower*: %(asm_default)}}} \
++%{mcpu=native: %(asm_cpu_native)} \
+ %{mcpu=common: -mcom} \
+ %{mcpu=cell: -mcell} \
+ %{mcpu=power: -mpwr} \
+@@ -163,6 +166,7 @@
+ #define EXTRA_SPECS \
+ { "cpp_default", CPP_DEFAULT_SPEC }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
++ { "asm_cpu_native", ASM_CPU_NATIVE_SPEC }, \
+ { "asm_default", ASM_DEFAULT_SPEC }, \
+ { "cc1_cpu", CC1_CPU_SPEC }, \
+ { "asm_cpu_power5", ASM_CPU_POWER5_SPEC }, \
+@@ -179,6 +183,10 @@ extern const char *host_detect_local_cpu
+ #define EXTRA_SPEC_FUNCTIONS \
+ { "local_cpu_detect", host_detect_local_cpu },
+ #define HAVE_LOCAL_CPU_DETECT
++#define ASM_CPU_NATIVE_SPEC "%:local_cpu_detect(asm)"
++
++#else
++#define ASM_CPU_NATIVE_SPEC "%(asm_default)"
+ #endif
+
+ #ifndef CC1_CPU_SPEC
+@@ -240,6 +248,14 @@ extern const char *host_detect_local_cpu
+ #define TARGET_DFP 0
+ #endif
+
++/* Define TARGET_POPCNTD if the target assembler does not support the
++ popcount word and double word instructions. */
++
++#ifndef HAVE_AS_POPCNTD
++#undef TARGET_POPCNTD
++#define TARGET_POPCNTD 0
++#endif
++
+ #ifndef TARGET_SECURE_PLT
+ #define TARGET_SECURE_PLT 0
+ #endif
+@@ -295,6 +311,7 @@ enum processor_type
+ PROCESSOR_POWER4,
+ PROCESSOR_POWER5,
+ PROCESSOR_POWER6,
++ PROCESSOR_POWER7,
+ PROCESSOR_CELL
+ };
+
+@@ -388,9 +405,13 @@ extern struct rs6000_cpu_select rs6000_s
+ extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
+ extern int rs6000_debug_stack; /* debug stack applications */
+ extern int rs6000_debug_arg; /* debug argument handling */
++extern int rs6000_debug_reg; /* debug register handling */
++extern int rs6000_debug_addr; /* debug memory addressing */
+
+ #define TARGET_DEBUG_STACK rs6000_debug_stack
+ #define TARGET_DEBUG_ARG rs6000_debug_arg
++#define TARGET_DEBUG_REG rs6000_debug_reg
++#define TARGET_DEBUG_ADDR rs6000_debug_addr
+
+ extern const char *rs6000_traceback_name; /* Type of traceback table. */
+
+@@ -401,13 +422,65 @@ extern int rs6000_ieeequad;
+ extern int rs6000_altivec_abi;
+ extern int rs6000_spe_abi;
+ extern int rs6000_spe;
+-extern int rs6000_isel;
+ extern int rs6000_float_gprs;
+ extern int rs6000_alignment_flags;
+ extern const char *rs6000_sched_insert_nops_str;
+ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
+ extern int rs6000_xilinx_fpu;
+
++/* Describe which vector unit to use for a given machine mode. */
++enum rs6000_vector {
++ VECTOR_NONE, /* Type is not a vector or not supported */
++ VECTOR_ALTIVEC, /* Use altivec for vector processing */
++ VECTOR_VSX, /* Use VSX for vector processing */
++ VECTOR_PAIRED, /* Use paired floating point for vectors */
++ VECTOR_SPE, /* Use SPE for vector processing */
++ VECTOR_OTHER /* Some other vector unit */
++};
++
++extern enum rs6000_vector rs6000_vector_unit[];
++
++#define VECTOR_UNIT_NONE_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_NONE)
++
++#define VECTOR_UNIT_VSX_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_VSX)
++
++#define VECTOR_UNIT_ALTIVEC_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC)
++
++#define VECTOR_UNIT_ALTIVEC_OR_VSX_P(MODE) \
++ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC \
++ || rs6000_vector_unit[(MODE)] == VECTOR_VSX)
++
++/* Describe whether to use VSX loads or Altivec loads. For now, just use the
++ same unit as the vector unit we are using, but we may want to migrate to
++ using VSX style loads even for types handled by altivec. */
++extern enum rs6000_vector rs6000_vector_mem[];
++
++#define VECTOR_MEM_NONE_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_NONE)
++
++#define VECTOR_MEM_VSX_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_VSX)
++
++#define VECTOR_MEM_ALTIVEC_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC)
++
++#define VECTOR_MEM_ALTIVEC_OR_VSX_P(MODE) \
++ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC \
++ || rs6000_vector_mem[(MODE)] == VECTOR_VSX)
++
++/* Return the alignment of a given vector type, which is set based on the
++ vector unit use. VSX for instance can load 32 or 64 bit aligned words
++ without problems, while Altivec requires 128-bit aligned vectors. */
++extern int rs6000_vector_align[];
++
++#define VECTOR_ALIGN(MODE) \
++ ((rs6000_vector_align[(MODE)] != 0) \
++ ? rs6000_vector_align[(MODE)] \
++ : (int)GET_MODE_BITSIZE ((MODE)))
++
+ /* Alignment options for fields in structures for sub-targets following
+ AIX-like ABI.
+ ALIGN_POWER word-aligns FP doubles (default AIX ABI).
+@@ -432,7 +505,7 @@ extern int rs6000_xilinx_fpu;
+ #define TARGET_SPE_ABI 0
+ #define TARGET_SPE 0
+ #define TARGET_E500 0
+-#define TARGET_ISEL rs6000_isel
++#define TARGET_ISEL64 (TARGET_ISEL && TARGET_POWERPC64)
+ #define TARGET_FPRS 1
+ #define TARGET_E500_SINGLE 0
+ #define TARGET_E500_DOUBLE 0
+@@ -530,6 +603,7 @@ extern int rs6000_xilinx_fpu;
+ #endif
+ #define UNITS_PER_FP_WORD 8
+ #define UNITS_PER_ALTIVEC_WORD 16
++#define UNITS_PER_VSX_WORD 16
+ #define UNITS_PER_SPE_WORD 8
+ #define UNITS_PER_PAIRED_WORD 8
+
+@@ -600,8 +674,9 @@ extern int rs6000_xilinx_fpu;
+ #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
+
+ /* Boundary (in *bits*) on which stack pointer should be aligned. */
+-#define STACK_BOUNDARY \
+- ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI) ? 64 : 128)
++#define STACK_BOUNDARY \
++ ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI && !TARGET_VSX) \
++ ? 64 : 128)
+
+ /* Allocation boundary (in *bits*) for the code of a function. */
+ #define FUNCTION_BOUNDARY 32
+@@ -613,10 +688,11 @@ extern int rs6000_xilinx_fpu;
+ local store. TYPE is the data type, and ALIGN is the alignment
+ that the object would ordinarily have. */
+ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+- ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
++ (((TARGET_ALTIVEC || TARGET_VSX) \
++ && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
+ (TARGET_E500_DOUBLE \
+- && TYPE_MODE (TYPE) == DFmode) ? 64 : \
+- ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
++ && TYPE_MODE (TYPE) == DFmode) ? 64 : \
++ ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
+ && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
+ && TREE_CODE (TYPE) == VECTOR_TYPE \
+ && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN)
+@@ -674,15 +750,17 @@ extern int rs6000_xilinx_fpu;
+ /* Define this macro to be the value 1 if unaligned accesses have a cost
+ many times greater than aligned accesses, for example if they are
+ emulated in a trap handler. */
+-/* Altivec vector memory instructions simply ignore the low bits; SPE
+- vector memory instructions trap on unaligned accesses. */
++/* Altivec vector memory instructions simply ignore the low bits; SPE vector
++ memory instructions trap on unaligned accesses; VSX memory instructions are
++ aligned to 4 or 8 bytes. */
+ #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \
+ (STRICT_ALIGNMENT \
+ || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \
+ || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode \
+ || (MODE) == DImode) \
+ && (ALIGN) < 32) \
+- || (VECTOR_MODE_P ((MODE)) && (ALIGN) < GET_MODE_BITSIZE ((MODE))))
++ || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))
++
+ \f
+ /* Standard register usage. */
+
+@@ -909,16 +987,60 @@ extern int rs6000_xilinx_fpu;
+ /* True if register is an AltiVec register. */
+ #define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO)
+
++/* True if register is a VSX register. */
++#define VSX_REGNO_P(N) (FP_REGNO_P (N) || ALTIVEC_REGNO_P (N))
++
++/* Alternate name for any vector register supporting floating point, no matter
++ which instruction set(s) are available. */
++#define VFLOAT_REGNO_P(N) \
++ (ALTIVEC_REGNO_P (N) || (TARGET_VSX && FP_REGNO_P (N)))
++
++/* Alternate name for any vector register supporting integer, no matter which
++ instruction set(s) are available. */
++#define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N)
++
++/* Alternate name for any vector register supporting logical operations, no
++ matter which instruction set(s) are available. */
++#define VLOGICAL_REGNO_P(N) VFLOAT_REGNO_P (N)
++
+ /* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE. */
+
+-#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs ((REGNO), (MODE))
++#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)]
+
+ #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
+ ((TARGET_32BIT && TARGET_POWERPC64 \
+ && (GET_MODE_SIZE (MODE) > 4) \
+ && INT_REGNO_P (REGNO)) ? 1 : 0)
+
++#define VSX_VECTOR_MODE(MODE) \
++ ((MODE) == V4SFmode \
++ || (MODE) == V2DFmode) \
++
++#define VSX_VECTOR_MOVE_MODE(MODE) \
++ ((MODE) == V16QImode \
++ || (MODE) == V8HImode \
++ || (MODE) == V4SImode \
++ || (MODE) == V2DImode \
++ || (MODE) == V4SFmode \
++ || (MODE) == V2DFmode) \
++
++#define VSX_SCALAR_MODE(MODE) \
++ ((MODE) == DFmode)
++
++#define VSX_MODE(MODE) \
++ (VSX_VECTOR_MODE (MODE) \
++ || VSX_SCALAR_MODE (MODE))
++
++#define VSX_MOVE_MODE(MODE) \
++ (VSX_VECTOR_MOVE_MODE (MODE) \
++ || VSX_SCALAR_MODE(MODE) \
++ || (MODE) == V16QImode \
++ || (MODE) == V8HImode \
++ || (MODE) == V4SImode \
++ || (MODE) == V2DImode \
++ || (MODE) == TImode)
++
+ #define ALTIVEC_VECTOR_MODE(MODE) \
+ ((MODE) == V16QImode \
+ || (MODE) == V8HImode \
+@@ -934,10 +1056,12 @@ extern int rs6000_xilinx_fpu;
+ #define PAIRED_VECTOR_MODE(MODE) \
+ ((MODE) == V2SFmode)
+
+-#define UNITS_PER_SIMD_WORD(MODE) \
+- (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
+- : (TARGET_SPE ? UNITS_PER_SPE_WORD : (TARGET_PAIRED_FLOAT ? \
+- UNITS_PER_PAIRED_WORD : UNITS_PER_WORD)))
++#define UNITS_PER_SIMD_WORD(MODE) \
++ (TARGET_VSX ? UNITS_PER_VSX_WORD \
++ : (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
++ : (TARGET_SPE ? UNITS_PER_SPE_WORD \
++ : (TARGET_PAIRED_FLOAT ? UNITS_PER_PAIRED_WORD \
++ : UNITS_PER_WORD))))
+
+ /* Value is TRUE if hard register REGNO can hold a value of
+ machine-mode MODE. */
+@@ -965,6 +1089,10 @@ extern int rs6000_xilinx_fpu;
+ ? ALTIVEC_VECTOR_MODE (MODE2) \
+ : ALTIVEC_VECTOR_MODE (MODE2) \
+ ? ALTIVEC_VECTOR_MODE (MODE1) \
++ : VSX_VECTOR_MODE (MODE1) \
++ ? VSX_VECTOR_MODE (MODE2) \
++ : VSX_VECTOR_MODE (MODE2) \
++ ? VSX_VECTOR_MODE (MODE1) \
+ : 1)
+
+ /* Post-reload, we can't use any new AltiVec registers, as we already
+@@ -1056,9 +1184,10 @@ extern int rs6000_xilinx_fpu;
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+-/* The RS/6000 has three types of registers, fixed-point, floating-point,
+- and condition registers, plus three special registers, MQ, CTR, and the
+- link register. AltiVec adds a vector register class.
++/* The RS/6000 has three types of registers, fixed-point, floating-point, and
++ condition registers, plus three special registers, MQ, CTR, and the link
++ register. AltiVec adds a vector register class. VSX registers overlap the
++ FPR registers and the Altivec registers.
+
+ However, r0 is special in that it cannot be used as a base register.
+ So make a class for registers valid as base registers.
+@@ -1073,6 +1202,7 @@ enum reg_class
+ GENERAL_REGS,
+ FLOAT_REGS,
+ ALTIVEC_REGS,
++ VSX_REGS,
+ VRSAVE_REGS,
+ VSCR_REGS,
+ SPE_ACC_REGS,
+@@ -1103,6 +1233,7 @@ enum reg_class
+ "GENERAL_REGS", \
+ "FLOAT_REGS", \
+ "ALTIVEC_REGS", \
++ "VSX_REGS", \
+ "VRSAVE_REGS", \
+ "VSCR_REGS", \
+ "SPE_ACC_REGS", \
+@@ -1132,6 +1263,7 @@ enum reg_class
+ { 0xffffffff, 0x00000000, 0x00000008, 0x00020000 }, /* GENERAL_REGS */ \
+ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */ \
+ { 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */ \
++ { 0x00000000, 0xffffffff, 0xffffe000, 0x00001fff }, /* VSX_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \
+@@ -1179,8 +1311,8 @@ enum reg_class
+ : (REGNO) == CR0_REGNO ? CR0_REGS \
+ : CR_REGNO_P (REGNO) ? CR_REGS \
+ : (REGNO) == MQ_REGNO ? MQ_REGS \
+- : (REGNO) == LR_REGNO ? LINK_REGS \
+- : (REGNO) == CTR_REGNO ? CTR_REGS \
++ : (REGNO) == LR_REGNO ? LINK_REGS \
++ : (REGNO) == CTR_REGNO ? CTR_REGS \
+ : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \
+ : (REGNO) == XER_REGNO ? XER_REGS \
+ : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \
+@@ -1190,10 +1322,18 @@ enum reg_class
+ : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \
+ : NO_REGS)
+
++/* VSX register classes. */
++extern enum reg_class rs6000_vector_reg_class[];
++extern enum reg_class rs6000_vsx_reg_class;
++
+ /* The class value for index registers, and the one for base regs. */
+ #define INDEX_REG_CLASS GENERAL_REGS
+ #define BASE_REG_CLASS BASE_REGS
+
++/* Return whether a given register class can hold VSX objects. */
++#define VSX_REG_CLASS_P(CLASS) \
++ ((CLASS) == VSX_REGS || (CLASS) == FLOAT_REGS || (CLASS) == ALTIVEC_REGS)
++
+ /* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+@@ -1213,13 +1353,7 @@ enum reg_class
+ */
+
+ #define PREFERRED_RELOAD_CLASS(X,CLASS) \
+- ((CONSTANT_P (X) \
+- && reg_classes_intersect_p ((CLASS), FLOAT_REGS)) \
+- ? NO_REGS \
+- : (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
+- && (CLASS) == NON_SPECIAL_REGS) \
+- ? GENERAL_REGS \
+- : (CLASS))
++ rs6000_preferred_reload_class (X, CLASS)
+
+ /* Return the register class of a scratch register needed to copy IN into
+ or out of a register in CLASS in MODE. If it can be done directly,
+@@ -1234,18 +1368,7 @@ enum reg_class
+ are available.*/
+
+ #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
+- ((CLASS1) != (CLASS2) && (((CLASS1) == FLOAT_REGS \
+- && (!TARGET_MFPGPR || !TARGET_POWERPC64 \
+- || ((MODE != DFmode) \
+- && (MODE != DDmode) \
+- && (MODE != DImode)))) \
+- || ((CLASS2) == FLOAT_REGS \
+- && (!TARGET_MFPGPR || !TARGET_POWERPC64 \
+- || ((MODE != DFmode) \
+- && (MODE != DDmode) \
+- && (MODE != DImode)))) \
+- || (CLASS1) == ALTIVEC_REGS \
+- || (CLASS2) == ALTIVEC_REGS))
++ rs6000_secondary_memory_needed (CLASS1, CLASS2, MODE)
+
+ /* For cpus that cannot load/store SDmode values from the 64-bit
+ FP registers without using a full 64-bit load/store, we need
+@@ -1257,32 +1380,15 @@ enum reg_class
+ /* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS.
+
+- On RS/6000, this is the size of MODE in words,
+- except in the FP regs, where a single reg is enough for two words. */
+-#define CLASS_MAX_NREGS(CLASS, MODE) \
+- (((CLASS) == FLOAT_REGS) \
+- ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+- : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS \
+- && (MODE) == DFmode) \
+- ? 1 \
+- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
++ On RS/6000, this is the size of MODE in words, except in the FP regs, where
++ a single reg is enough for two words, unless we have VSX, where the FP
++ registers can hold 128 bits. */
++#define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
+
+ /* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
+
+ #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+- ? ((GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8 \
+- || TARGET_IEEEQUAD) \
+- && reg_classes_intersect_p (FLOAT_REGS, CLASS)) \
+- : (((TARGET_E500_DOUBLE \
+- && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \
+- || (((TO) == TFmode) + ((FROM) == TFmode)) == 1 \
+- || (((TO) == DDmode) + ((FROM) == DDmode)) == 1 \
+- || (((TO) == TDmode) + ((FROM) == TDmode)) == 1 \
+- || (((TO) == DImode) + ((FROM) == DImode)) == 1)) \
+- || (TARGET_SPE \
+- && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \
+- && reg_classes_intersect_p (GENERAL_REGS, CLASS)))
++ rs6000_cannot_change_mode_class (FROM, TO, CLASS)
+
+ /* Stack layout; function entry, exit and calling. */
+
+@@ -1343,8 +1449,8 @@ extern enum rs6000_abi rs6000_current_ab
+ #define STARTING_FRAME_OFFSET \
+ (FRAME_GROWS_DOWNWARD \
+ ? 0 \
+- : (RS6000_ALIGN (crtl->outgoing_args_size, \
+- TARGET_ALTIVEC ? 16 : 8) \
++ : (RS6000_ALIGN (crtl->outgoing_args_size, \
++ (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \
+ + RS6000_SAVE_AREA))
+
+ /* Offset from the stack pointer register to an item dynamically
+@@ -1354,8 +1460,8 @@ extern enum rs6000_abi rs6000_current_ab
+ length of the outgoing arguments. The default is correct for most
+ machines. See `function.c' for details. */
+ #define STACK_DYNAMIC_OFFSET(FUNDECL) \
+- (RS6000_ALIGN (crtl->outgoing_args_size, \
+- TARGET_ALTIVEC ? 16 : 8) \
++ (RS6000_ALIGN (crtl->outgoing_args_size, \
++ (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \
+ + (STACK_POINTER_OFFSET))
+
+ /* If we generate an insn to push BYTES bytes,
+@@ -1605,7 +1711,7 @@ typedef struct rs6000_args
+ #define EPILOGUE_USES(REGNO) \
+ ((reload_completed && (REGNO) == LR_REGNO) \
+ || (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO) \
+- || (crtl->calls_eh_return \
++ || (crtl->calls_eh_return \
+ && TARGET_AIX \
+ && (REGNO) == 2))
+
+@@ -2316,7 +2422,24 @@ extern char rs6000_reg_names[][8]; /* re
+ /* no additional names for: mq, lr, ctr, ap */ \
+ {"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \
+ {"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \
+- {"cc", 68}, {"sp", 1}, {"toc", 2} }
++ {"cc", 68}, {"sp", 1}, {"toc", 2}, \
++ /* VSX registers overlaid on top of FR, Altivec registers */ \
++ {"vs0", 32}, {"vs1", 33}, {"vs2", 34}, {"vs3", 35}, \
++ {"vs4", 36}, {"vs5", 37}, {"vs6", 38}, {"vs7", 39}, \
++ {"vs8", 40}, {"vs9", 41}, {"vs10", 42}, {"vs11", 43}, \
++ {"vs12", 44}, {"vs13", 45}, {"vs14", 46}, {"vs15", 47}, \
++ {"vs16", 48}, {"vs17", 49}, {"vs18", 50}, {"vs19", 51}, \
++ {"vs20", 52}, {"vs21", 53}, {"vs22", 54}, {"vs23", 55}, \
++ {"vs24", 56}, {"vs25", 57}, {"vs26", 58}, {"vs27", 59}, \
++ {"vs28", 60}, {"vs29", 61}, {"vs30", 62}, {"vs31", 63}, \
++ {"vs32", 77}, {"vs33", 78}, {"vs34", 79}, {"vs35", 80}, \
++ {"vs36", 81}, {"vs37", 82}, {"vs38", 83}, {"vs39", 84}, \
++ {"vs40", 85}, {"vs41", 86}, {"vs42", 87}, {"vs43", 88}, \
++ {"vs44", 89}, {"vs45", 90}, {"vs46", 91}, {"vs47", 92}, \
++ {"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96}, \
++ {"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100}, \
++ {"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104}, \
++ {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} }
+
+ /* Text to write out after a CALL that may be replaced by glue code by
+ the loader. This depends on the AIX version. */
+@@ -2480,10 +2603,14 @@ enum rs6000_builtins
+ ALTIVEC_BUILTIN_VSEL_4SF,
+ ALTIVEC_BUILTIN_VSEL_8HI,
+ ALTIVEC_BUILTIN_VSEL_16QI,
++ ALTIVEC_BUILTIN_VSEL_2DF, /* needed for VSX */
++ ALTIVEC_BUILTIN_VSEL_2DI, /* needed for VSX */
+ ALTIVEC_BUILTIN_VPERM_4SI,
+ ALTIVEC_BUILTIN_VPERM_4SF,
+ ALTIVEC_BUILTIN_VPERM_8HI,
+ ALTIVEC_BUILTIN_VPERM_16QI,
++ ALTIVEC_BUILTIN_VPERM_2DF, /* needed for VSX */
++ ALTIVEC_BUILTIN_VPERM_2DI, /* needed for VSX */
+ ALTIVEC_BUILTIN_VPKUHUM,
+ ALTIVEC_BUILTIN_VPKUWUM,
+ ALTIVEC_BUILTIN_VPKPX,
+@@ -3110,6 +3237,163 @@ enum rs6000_builtins
+ RS6000_BUILTIN_RECIPF,
+ RS6000_BUILTIN_RSQRTF,
+
++ /* VSX builtins. */
++ VSX_BUILTIN_LXSDUX,
++ VSX_BUILTIN_LXSDX,
++ VSX_BUILTIN_LXVD2UX,
++ VSX_BUILTIN_LXVD2X,
++ VSX_BUILTIN_LXVDSX,
++ VSX_BUILTIN_LXVW4UX,
++ VSX_BUILTIN_LXVW4X,
++ VSX_BUILTIN_STXSDUX,
++ VSX_BUILTIN_STXSDX,
++ VSX_BUILTIN_STXVD2UX,
++ VSX_BUILTIN_STXVD2X,
++ VSX_BUILTIN_STXVW4UX,
++ VSX_BUILTIN_STXVW4X,
++ VSX_BUILTIN_XSABSDP,
++ VSX_BUILTIN_XSADDDP,
++ VSX_BUILTIN_XSCMPODP,
++ VSX_BUILTIN_XSCMPUDP,
++ VSX_BUILTIN_XSCPSGNDP,
++ VSX_BUILTIN_XSCVDPSP,
++ VSX_BUILTIN_XSCVDPSXDS,
++ VSX_BUILTIN_XSCVDPSXWS,
++ VSX_BUILTIN_XSCVDPUXDS,
++ VSX_BUILTIN_XSCVDPUXWS,
++ VSX_BUILTIN_XSCVSPDP,
++ VSX_BUILTIN_XSCVSXDDP,
++ VSX_BUILTIN_XSCVUXDDP,
++ VSX_BUILTIN_XSDIVDP,
++ VSX_BUILTIN_XSMADDADP,
++ VSX_BUILTIN_XSMADDMDP,
++ VSX_BUILTIN_XSMAXDP,
++ VSX_BUILTIN_XSMINDP,
++ VSX_BUILTIN_XSMOVDP,
++ VSX_BUILTIN_XSMSUBADP,
++ VSX_BUILTIN_XSMSUBMDP,
++ VSX_BUILTIN_XSMULDP,
++ VSX_BUILTIN_XSNABSDP,
++ VSX_BUILTIN_XSNEGDP,
++ VSX_BUILTIN_XSNMADDADP,
++ VSX_BUILTIN_XSNMADDMDP,
++ VSX_BUILTIN_XSNMSUBADP,
++ VSX_BUILTIN_XSNMSUBMDP,
++ VSX_BUILTIN_XSRDPI,
++ VSX_BUILTIN_XSRDPIC,
++ VSX_BUILTIN_XSRDPIM,
++ VSX_BUILTIN_XSRDPIP,
++ VSX_BUILTIN_XSRDPIZ,
++ VSX_BUILTIN_XSREDP,
++ VSX_BUILTIN_XSRSQRTEDP,
++ VSX_BUILTIN_XSSQRTDP,
++ VSX_BUILTIN_XSSUBDP,
++ VSX_BUILTIN_XSTDIVDP,
++ VSX_BUILTIN_XSTSQRTDP,
++ VSX_BUILTIN_XVABSDP,
++ VSX_BUILTIN_XVABSSP,
++ VSX_BUILTIN_XVADDDP,
++ VSX_BUILTIN_XVADDSP,
++ VSX_BUILTIN_XVCMPEQDP,
++ VSX_BUILTIN_XVCMPEQSP,
++ VSX_BUILTIN_XVCMPGEDP,
++ VSX_BUILTIN_XVCMPGESP,
++ VSX_BUILTIN_XVCMPGTDP,
++ VSX_BUILTIN_XVCMPGTSP,
++ VSX_BUILTIN_XVCPSGNDP,
++ VSX_BUILTIN_XVCPSGNSP,
++ VSX_BUILTIN_XVCVDPSP,
++ VSX_BUILTIN_XVCVDPSXDS,
++ VSX_BUILTIN_XVCVDPSXWS,
++ VSX_BUILTIN_XVCVDPUXDS,
++ VSX_BUILTIN_XVCVDPUXWS,
++ VSX_BUILTIN_XVCVSPDP,
++ VSX_BUILTIN_XVCVSPSXDS,
++ VSX_BUILTIN_XVCVSPSXWS,
++ VSX_BUILTIN_XVCVSPUXDS,
++ VSX_BUILTIN_XVCVSPUXWS,
++ VSX_BUILTIN_XVCVSXDDP,
++ VSX_BUILTIN_XVCVSXDSP,
++ VSX_BUILTIN_XVCVSXWDP,
++ VSX_BUILTIN_XVCVSXWSP,
++ VSX_BUILTIN_XVCVUXDDP,
++ VSX_BUILTIN_XVCVUXDSP,
++ VSX_BUILTIN_XVCVUXWDP,
++ VSX_BUILTIN_XVCVUXWSP,
++ VSX_BUILTIN_XVDIVDP,
++ VSX_BUILTIN_XVDIVSP,
++ VSX_BUILTIN_XVMADDADP,
++ VSX_BUILTIN_XVMADDASP,
++ VSX_BUILTIN_XVMADDMDP,
++ VSX_BUILTIN_XVMADDMSP,
++ VSX_BUILTIN_XVMAXDP,
++ VSX_BUILTIN_XVMAXSP,
++ VSX_BUILTIN_XVMINDP,
++ VSX_BUILTIN_XVMINSP,
++ VSX_BUILTIN_XVMOVDP,
++ VSX_BUILTIN_XVMOVSP,
++ VSX_BUILTIN_XVMSUBADP,
++ VSX_BUILTIN_XVMSUBASP,
++ VSX_BUILTIN_XVMSUBMDP,
++ VSX_BUILTIN_XVMSUBMSP,
++ VSX_BUILTIN_XVMULDP,
++ VSX_BUILTIN_XVMULSP,
++ VSX_BUILTIN_XVNABSDP,
++ VSX_BUILTIN_XVNABSSP,
++ VSX_BUILTIN_XVNEGDP,
++ VSX_BUILTIN_XVNEGSP,
++ VSX_BUILTIN_XVNMADDADP,
++ VSX_BUILTIN_XVNMADDASP,
++ VSX_BUILTIN_XVNMADDMDP,
++ VSX_BUILTIN_XVNMADDMSP,
++ VSX_BUILTIN_XVNMSUBADP,
++ VSX_BUILTIN_XVNMSUBASP,
++ VSX_BUILTIN_XVNMSUBMDP,
++ VSX_BUILTIN_XVNMSUBMSP,
++ VSX_BUILTIN_XVRDPI,
++ VSX_BUILTIN_XVRDPIC,
++ VSX_BUILTIN_XVRDPIM,
++ VSX_BUILTIN_XVRDPIP,
++ VSX_BUILTIN_XVRDPIZ,
++ VSX_BUILTIN_XVREDP,
++ VSX_BUILTIN_XVRESP,
++ VSX_BUILTIN_XVRSPI,
++ VSX_BUILTIN_XVRSPIC,
++ VSX_BUILTIN_XVRSPIM,
++ VSX_BUILTIN_XVRSPIP,
++ VSX_BUILTIN_XVRSPIZ,
++ VSX_BUILTIN_XVRSQRTEDP,
++ VSX_BUILTIN_XVRSQRTESP,
++ VSX_BUILTIN_XVSQRTDP,
++ VSX_BUILTIN_XVSQRTSP,
++ VSX_BUILTIN_XVSUBDP,
++ VSX_BUILTIN_XVSUBSP,
++ VSX_BUILTIN_XVTDIVDP,
++ VSX_BUILTIN_XVTDIVSP,
++ VSX_BUILTIN_XVTSQRTDP,
++ VSX_BUILTIN_XVTSQRTSP,
++ VSX_BUILTIN_XXLAND,
++ VSX_BUILTIN_XXLANDC,
++ VSX_BUILTIN_XXLNOR,
++ VSX_BUILTIN_XXLOR,
++ VSX_BUILTIN_XXLXOR,
++ VSX_BUILTIN_XXMRGHD,
++ VSX_BUILTIN_XXMRGHW,
++ VSX_BUILTIN_XXMRGLD,
++ VSX_BUILTIN_XXMRGLW,
++ VSX_BUILTIN_XXPERMDI,
++ VSX_BUILTIN_XXSEL,
++ VSX_BUILTIN_XXSLDWI,
++ VSX_BUILTIN_XXSPLTD,
++ VSX_BUILTIN_XXSPLTW,
++ VSX_BUILTIN_XXSWAPD,
++
++ /* Combine VSX/Altivec builtins. */
++ VECTOR_BUILTIN_FLOAT_V4SI_V4SF,
++ VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,
++ VECTOR_BUILTIN_FIX_V4SF_V4SI,
++ VECTOR_BUILTIN_FIXUNS_V4SF_V4SI,
++
+ RS6000_BUILTIN_COUNT
+ };
+
+@@ -3123,6 +3407,8 @@ enum rs6000_builtin_type_index
+ RS6000_BTI_V16QI,
+ RS6000_BTI_V2SI,
+ RS6000_BTI_V2SF,
++ RS6000_BTI_V2DI,
++ RS6000_BTI_V2DF,
+ RS6000_BTI_V4HI,
+ RS6000_BTI_V4SI,
+ RS6000_BTI_V4SF,
+@@ -3146,7 +3432,10 @@ enum rs6000_builtin_type_index
+ RS6000_BTI_UINTHI, /* unsigned_intHI_type_node */
+ RS6000_BTI_INTSI, /* intSI_type_node */
+ RS6000_BTI_UINTSI, /* unsigned_intSI_type_node */
++ RS6000_BTI_INTDI, /* intDI_type_node */
++ RS6000_BTI_UINTDI, /* unsigned_intDI_type_node */
+ RS6000_BTI_float, /* float_type_node */
++ RS6000_BTI_double, /* double_type_node */
+ RS6000_BTI_void, /* void_type_node */
+ RS6000_BTI_MAX
+ };
+@@ -3157,6 +3446,8 @@ enum rs6000_builtin_type_index
+ #define opaque_p_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI])
+ #define opaque_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V4SI])
+ #define V16QI_type_node (rs6000_builtin_types[RS6000_BTI_V16QI])
++#define V2DI_type_node (rs6000_builtin_types[RS6000_BTI_V2DI])
++#define V2DF_type_node (rs6000_builtin_types[RS6000_BTI_V2DF])
+ #define V2SI_type_node (rs6000_builtin_types[RS6000_BTI_V2SI])
+ #define V2SF_type_node (rs6000_builtin_types[RS6000_BTI_V2SF])
+ #define V4HI_type_node (rs6000_builtin_types[RS6000_BTI_V4HI])
+@@ -3183,7 +3474,10 @@ enum rs6000_builtin_type_index
+ #define uintHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTHI])
+ #define intSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTSI])
+ #define uintSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTSI])
++#define intDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTDI])
++#define uintDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTDI])
+ #define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
++#define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double])
+ #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
+
+ extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
+--- gcc/config/rs6000/altivec.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/altivec.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -21,18 +21,7 @@
+
+ (define_constants
+ [(UNSPEC_VCMPBFP 50)
+- (UNSPEC_VCMPEQUB 51)
+- (UNSPEC_VCMPEQUH 52)
+- (UNSPEC_VCMPEQUW 53)
+- (UNSPEC_VCMPEQFP 54)
+- (UNSPEC_VCMPGEFP 55)
+- (UNSPEC_VCMPGTUB 56)
+- (UNSPEC_VCMPGTSB 57)
+- (UNSPEC_VCMPGTUH 58)
+- (UNSPEC_VCMPGTSH 59)
+- (UNSPEC_VCMPGTUW 60)
+- (UNSPEC_VCMPGTSW 61)
+- (UNSPEC_VCMPGTFP 62)
++ ;; 51-62 deleted
+ (UNSPEC_VMSUMU 65)
+ (UNSPEC_VMSUMM 66)
+ (UNSPEC_VMSUMSHM 68)
+@@ -87,10 +76,7 @@ (define_constants
+ (UNSPEC_VEXPTEFP 156)
+ (UNSPEC_VRSQRTEFP 157)
+ (UNSPEC_VREFP 158)
+- (UNSPEC_VSEL4SI 159)
+- (UNSPEC_VSEL4SF 160)
+- (UNSPEC_VSEL8HI 161)
+- (UNSPEC_VSEL16QI 162)
++ ;; 159-162 deleted
+ (UNSPEC_VLSDOI 163)
+ (UNSPEC_VUPKHSB 167)
+ (UNSPEC_VUPKHPX 168)
+@@ -125,11 +111,11 @@ (define_constants
+ (UNSPEC_INTERHI_V4SI 228)
+ (UNSPEC_INTERHI_V8HI 229)
+ (UNSPEC_INTERHI_V16QI 230)
+- (UNSPEC_INTERHI_V4SF 231)
++ ;; delete 231
+ (UNSPEC_INTERLO_V4SI 232)
+ (UNSPEC_INTERLO_V8HI 233)
+ (UNSPEC_INTERLO_V16QI 234)
+- (UNSPEC_INTERLO_V4SF 235)
++ ;; delete 235
+ (UNSPEC_LVLX 236)
+ (UNSPEC_LVLXL 237)
+ (UNSPEC_LVRX 238)
+@@ -176,39 +162,17 @@ (define_mode_iterator VIshort [V8HI V16Q
+ (define_mode_iterator VF [V4SF])
+ ;; Vec modes, pity mode iterators are not composable
+ (define_mode_iterator V [V4SI V8HI V16QI V4SF])
++;; Vec modes for move/logical/permute ops, include vector types for move not
++;; otherwise handled by altivec (v2df, v2di, ti)
++(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI TI])
+
+ (define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
+
+-;; Generic LVX load instruction.
+-(define_insn "altivec_lvx_<mode>"
+- [(set (match_operand:V 0 "altivec_register_operand" "=v")
+- (match_operand:V 1 "memory_operand" "Z"))]
+- "TARGET_ALTIVEC"
+- "lvx %0,%y1"
+- [(set_attr "type" "vecload")])
+-
+-;; Generic STVX store instruction.
+-(define_insn "altivec_stvx_<mode>"
+- [(set (match_operand:V 0 "memory_operand" "=Z")
+- (match_operand:V 1 "altivec_register_operand" "v"))]
+- "TARGET_ALTIVEC"
+- "stvx %1,%y0"
+- [(set_attr "type" "vecstore")])
+-
+ ;; Vector move instructions.
+-(define_expand "mov<mode>"
+- [(set (match_operand:V 0 "nonimmediate_operand" "")
+- (match_operand:V 1 "any_operand" ""))]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_emit_move (operands[0], operands[1], <MODE>mode);
+- DONE;
+-})
+-
+-(define_insn "*mov<mode>_internal"
+- [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,o,r,r,v")
+- (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,W"))]
+- "TARGET_ALTIVEC
++(define_insn "*altivec_mov<mode>"
++ [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v")
++ (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,j,W"))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
+ && (register_operand (operands[0], <MODE>mode)
+ || register_operand (operands[1], <MODE>mode))"
+ {
+@@ -220,52 +184,17 @@ (define_insn "*mov<mode>_internal"
+ case 3: return "#";
+ case 4: return "#";
+ case 5: return "#";
+- case 6: return output_vec_const_move (operands);
++ case 6: return "vxor %0,%0,%0";
++ case 7: return output_vec_const_move (operands);
+ default: gcc_unreachable ();
+ }
+ }
+- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+-
+-(define_split
+- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+- (match_operand:V4SI 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{
+- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+-})
+-
+-(define_split
+- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+- (match_operand:V8HI 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
++ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
+
+ (define_split
+- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+- (match_operand:V16QI 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
+-
+-(define_split
+- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+- (match_operand:V4SF 1 "input_operand" ""))]
+- "TARGET_ALTIVEC && reload_completed
+- && gpr_or_gpr_p (operands[0], operands[1])"
+- [(pc)]
+-{
+- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+-})
+-
+-(define_split
+- [(set (match_operand:V 0 "altivec_register_operand" "")
+- (match_operand:V 1 "easy_vector_constant_add_self" ""))]
+- "TARGET_ALTIVEC && reload_completed"
++ [(set (match_operand:VM 0 "altivec_register_operand" "")
++ (match_operand:VM 1 "easy_vector_constant_add_self" ""))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && reload_completed"
+ [(set (match_dup 0) (match_dup 3))
+ (set (match_dup 0) (match_dup 4))]
+ {
+@@ -346,11 +275,11 @@ (define_insn "add<mode>3"
+ "vaddu<VI_char>m %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "addv4sf3"
++(define_insn "*altivec_addv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vaddfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+@@ -392,11 +321,11 @@ (define_insn "sub<mode>3"
+ "vsubu<VI_char>m %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "subv4sf3"
++(define_insn "*altivec_subv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vsubfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+@@ -457,131 +386,81 @@ (define_insn "altivec_vcmpbfp"
+ "vcmpbfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpequb"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")]
+- UNSPEC_VCMPEQUB))]
++(define_insn "*altivec_eq<mode>"
++ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
++ (eq:VI (match_operand:VI 1 "altivec_register_operand" "v")
++ (match_operand:VI 2 "altivec_register_operand" "v")))]
+ "TARGET_ALTIVEC"
+- "vcmpequb %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
++ "vcmpequ<VI_char> %0,%1,%2"
++ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpequh"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")]
+- UNSPEC_VCMPEQUH))]
++(define_insn "*altivec_gt<mode>"
++ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
++ (gt:VI (match_operand:VI 1 "altivec_register_operand" "v")
++ (match_operand:VI 2 "altivec_register_operand" "v")))]
+ "TARGET_ALTIVEC"
+- "vcmpequh %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
++ "vcmpgts<VI_char> %0,%1,%2"
++ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpequw"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")]
+- UNSPEC_VCMPEQUW))]
++(define_insn "*altivec_gtu<mode>"
++ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
++ (gtu:VI (match_operand:VI 1 "altivec_register_operand" "v")
++ (match_operand:VI 2 "altivec_register_operand" "v")))]
+ "TARGET_ALTIVEC"
+- "vcmpequw %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
++ "vcmpgtu<VI_char> %0,%1,%2"
++ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpeqfp"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")]
+- UNSPEC_VCMPEQFP))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_eqv4sf"
++ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
++ (eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
++ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpeqfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpgefp"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")]
+- UNSPEC_VCMPGEFP))]
+- "TARGET_ALTIVEC"
+- "vcmpgefp %0,%1,%2"
++(define_insn "*altivec_gtv4sf"
++ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
++ (gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
++ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
++ "vcmpgtfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+-(define_insn "altivec_vcmpgtub"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTUB))]
+- "TARGET_ALTIVEC"
+- "vcmpgtub %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtsb"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTSB))]
+- "TARGET_ALTIVEC"
+- "vcmpgtsb %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtuh"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTUH))]
+- "TARGET_ALTIVEC"
+- "vcmpgtuh %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtsh"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTSH))]
+- "TARGET_ALTIVEC"
+- "vcmpgtsh %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtuw"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTUW))]
+- "TARGET_ALTIVEC"
+- "vcmpgtuw %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtsw"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")]
+- UNSPEC_VCMPGTSW))]
+- "TARGET_ALTIVEC"
+- "vcmpgtsw %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "altivec_vcmpgtfp"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")]
+- UNSPEC_VCMPGTFP))]
+- "TARGET_ALTIVEC"
+- "vcmpgtfp %0,%1,%2"
++(define_insn "*altivec_gev4sf"
++ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
++ (ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
++ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
++ "vcmpgefp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
++(define_insn "altivec_vsel<mode>"
++ [(set (match_operand:VM 0 "altivec_register_operand" "=v")
++ (if_then_else:VM (ne (match_operand:VM 1 "altivec_register_operand" "v")
++ (const_int 0))
++ (match_operand:VM 2 "altivec_register_operand" "v")
++ (match_operand:VM 3 "altivec_register_operand" "v")))]
++ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
++ "vsel %0,%3,%2,%1"
++ [(set_attr "type" "vecperm")])
++
+ ;; Fused multiply add
+ (define_insn "altivec_vmaddfp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 3 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmaddfp %0,%1,%2,%3"
+ [(set_attr "type" "vecfloat")])
+
+ ;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
+
+-(define_expand "mulv4sf3"
++(define_expand "altivec_mulv4sf3"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))
+ (use (match_operand:V4SF 2 "register_operand" ""))]
+- "TARGET_ALTIVEC && TARGET_FUSED_MADD"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode) && TARGET_FUSED_MADD"
+ "
+ {
+ rtx neg0;
+@@ -684,7 +563,7 @@ (define_insn "altivec_vnmsubfp"
+ (neg:V4SF (minus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 3 "register_operand" "v"))))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vnmsubfp %0,%1,%2,%3"
+ [(set_attr "type" "vecfloat")])
+
+@@ -758,11 +637,11 @@ (define_insn "smax<mode>3"
+ "vmaxs<VI_char> %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "smaxv4sf3"
++(define_insn "*altivec_smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmaxfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+@@ -782,11 +661,11 @@ (define_insn "smin<mode>3"
+ "vmins<VI_char> %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "sminv4sf3"
++(define_insn "*altivec_sminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vminfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+@@ -905,7 +784,7 @@ (define_insn "altivec_vmrghw"
+ "vmrghw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+-(define_insn "altivec_vmrghsf"
++(define_insn "*altivec_vmrghsf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (parallel [(const_int 0)
+@@ -918,7 +797,7 @@ (define_insn "altivec_vmrghsf"
+ (const_int 3)
+ (const_int 1)]))
+ (const_int 5)))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmrghw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+@@ -990,35 +869,37 @@ (define_insn "altivec_vmrglh"
+
+ (define_insn "altivec_vmrglw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
+- (parallel [(const_int 2)
+- (const_int 0)
+- (const_int 3)
+- (const_int 1)]))
+- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
+- (parallel [(const_int 0)
+- (const_int 2)
+- (const_int 1)
+- (const_int 3)]))
+- (const_int 5)))]
++ (vec_merge:V4SI
++ (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
+ "TARGET_ALTIVEC"
+ "vmrglw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+-(define_insn "altivec_vmrglsf"
++(define_insn "*altivec_vmrglsf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
+- (parallel [(const_int 2)
+- (const_int 0)
+- (const_int 3)
+- (const_int 1)]))
+- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
+- (parallel [(const_int 0)
+- (const_int 2)
+- (const_int 1)
+- (const_int 3)]))
+- (const_int 5)))]
+- "TARGET_ALTIVEC"
++ (vec_merge:V4SF
++ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
++ (parallel [(const_int 2)
++ (const_int 0)
++ (const_int 3)
++ (const_int 1)]))
++ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++ (parallel [(const_int 0)
++ (const_int 2)
++ (const_int 1)
++ (const_int 3)]))
++ (const_int 5)))]
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vmrglw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+@@ -1095,68 +976,53 @@ (define_insn "altivec_vmulosh"
+ [(set_attr "type" "veccomplex")])
+
+
+-;; logical ops
++;; logical ops. Have the logical ops follow the memory ops in
++;; terms of whether to prefer VSX or Altivec
+
+-(define_insn "and<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (and:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_and<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (and:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vand %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "ior<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (ior:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_ior<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (ior:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "xor<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (xor:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_xor<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (xor:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "xorv4sf3"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (xor:V4SF (match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "vxor %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "one_cmpl<mode>2"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (not:VI (match_operand:VI 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_one_cmpl<mode>2"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (not:VM (match_operand:VM 1 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vnor %0,%1,%1"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "altivec_nor<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (not:VI (ior:VI (match_operand:VI 1 "register_operand" "v")
+- (match_operand:VI 2 "register_operand" "v"))))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_nor<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (not:VM (ior:VM (match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v"))))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vnor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+-(define_insn "andc<mode>3"
+- [(set (match_operand:VI 0 "register_operand" "=v")
+- (and:VI (not:VI (match_operand:VI 2 "register_operand" "v"))
+- (match_operand:VI 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "vandc %0,%1,%2"
+- [(set_attr "type" "vecsimple")])
+-
+-(define_insn "*andc3_v4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (and:V4SF (not:V4SF (match_operand:V4SF 2 "register_operand" "v"))
+- (match_operand:V4SF 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++(define_insn "*altivec_andc<mode>3"
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (and:VM (not:VM (match_operand:VM 2 "register_operand" "v"))
++ (match_operand:VM 1 "register_operand" "v")))]
++ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "vandc %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+@@ -1392,7 +1258,7 @@ (define_insn "*altivec_vspltsf"
+ (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vspltw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+@@ -1404,19 +1270,19 @@ (define_insn "altivec_vspltis<VI_char>"
+ "vspltis<VI_char> %0,%1"
+ [(set_attr "type" "vecperm")])
+
+-(define_insn "ftruncv4sf2"
++(define_insn "*altivec_ftruncv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
++ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vrfiz %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+ (define_insn "altivec_vperm_<mode>"
+- [(set (match_operand:V 0 "register_operand" "=v")
+- (unspec:V [(match_operand:V 1 "register_operand" "v")
+- (match_operand:V 2 "register_operand" "v")
+- (match_operand:V16QI 3 "register_operand" "v")]
+- UNSPEC_VPERM))]
++ [(set (match_operand:VM 0 "register_operand" "=v")
++ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
++ (match_operand:VM 2 "register_operand" "v")
++ (match_operand:V16QI 3 "register_operand" "v")]
++ UNSPEC_VPERM))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+@@ -1515,180 +1381,6 @@ (define_insn "altivec_vrefp"
+ "vrefp %0,%1"
+ [(set_attr "type" "vecfloat")])
+
+-(define_expand "vcondv4si"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (if_then_else:V4SI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V4SI 4 "register_operand" "v")
+- (match_operand:V4SI 5 "register_operand" "v")])
+- (match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vconduv4si"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (if_then_else:V4SI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V4SI 4 "register_operand" "v")
+- (match_operand:V4SI 5 "register_operand" "v")])
+- (match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vcondv4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (if_then_else:V4SF
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V4SF 4 "register_operand" "v")
+- (match_operand:V4SF 5 "register_operand" "v")])
+- (match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vcondv8hi"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (if_then_else:V8HI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V8HI 4 "register_operand" "v")
+- (match_operand:V8HI 5 "register_operand" "v")])
+- (match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vconduv8hi"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (if_then_else:V8HI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V8HI 4 "register_operand" "v")
+- (match_operand:V8HI 5 "register_operand" "v")])
+- (match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vcondv16qi"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (if_then_else:V16QI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V16QI 4 "register_operand" "v")
+- (match_operand:V16QI 5 "register_operand" "v")])
+- (match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-(define_expand "vconduv16qi"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (if_then_else:V16QI
+- (match_operator 3 "comparison_operator"
+- [(match_operand:V16QI 4 "register_operand" "v")
+- (match_operand:V16QI 5 "register_operand" "v")])
+- (match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+- operands[3], operands[4], operands[5]))
+- DONE;
+- else
+- FAIL;
+-}
+- ")
+-
+-
+-(define_insn "altivec_vsel_v4si"
+- [(set (match_operand:V4SI 0 "register_operand" "=v")
+- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+- (match_operand:V4SI 2 "register_operand" "v")
+- (match_operand:V4SI 3 "register_operand" "v")]
+- UNSPEC_VSEL4SI))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+-(define_insn "altivec_vsel_v4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "=v")
+- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+- (match_operand:V4SF 2 "register_operand" "v")
+- (match_operand:V4SI 3 "register_operand" "v")]
+- UNSPEC_VSEL4SF))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+-(define_insn "altivec_vsel_v8hi"
+- [(set (match_operand:V8HI 0 "register_operand" "=v")
+- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+- (match_operand:V8HI 2 "register_operand" "v")
+- (match_operand:V8HI 3 "register_operand" "v")]
+- UNSPEC_VSEL8HI))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+-(define_insn "altivec_vsel_v16qi"
+- [(set (match_operand:V16QI 0 "register_operand" "=v")
+- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+- (match_operand:V16QI 2 "register_operand" "v")
+- (match_operand:V16QI 3 "register_operand" "v")]
+- UNSPEC_VSEL16QI))]
+- "TARGET_ALTIVEC"
+- "vsel %0,%1,%2,%3"
+- [(set_attr "type" "vecperm")])
+-
+ (define_insn "altivec_vsldoi_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+@@ -1878,6 +1570,14 @@ (define_expand "build_vector_mask_for_lo
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+
+ addr = XEXP (operands[1], 0);
++ if (VECTOR_MEM_VSX_P (GET_MODE (operands[1])))
++ {
++ /* VSX doesn't and off the bottom address bits, and memory
++ operations are aligned to the natural data type. */
++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
++ DONE;
++ }
++
+ temp = gen_reg_rtx (GET_MODE (addr));
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_NEG (GET_MODE (addr), addr)));
+@@ -1959,95 +1659,6 @@ (define_insn "*altivec_stvesfx"
+ "stvewx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
+-(define_expand "vec_init<mode>"
+- [(match_operand:V 0 "register_operand" "")
+- (match_operand 1 "" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_init (operands[0], operands[1]);
+- DONE;
+-})
+-
+-(define_expand "vec_setv4si"
+- [(match_operand:V4SI 0 "register_operand" "")
+- (match_operand:SI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_setv8hi"
+- [(match_operand:V8HI 0 "register_operand" "")
+- (match_operand:HI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_setv16qi"
+- [(match_operand:V16QI 0 "register_operand" "")
+- (match_operand:QI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_setv4sf"
+- [(match_operand:V4SF 0 "register_operand" "")
+- (match_operand:SF 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv4si"
+- [(match_operand:SI 0 "register_operand" "")
+- (match_operand:V4SI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv8hi"
+- [(match_operand:HI 0 "register_operand" "")
+- (match_operand:V8HI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv16qi"
+- [(match_operand:QI 0 "register_operand" "")
+- (match_operand:V16QI 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+-(define_expand "vec_extractv4sf"
+- [(match_operand:SF 0 "register_operand" "")
+- (match_operand:V4SF 1 "register_operand" "")
+- (match_operand 2 "const_int_operand" "")]
+- "TARGET_ALTIVEC"
+-{
+- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+- DONE;
+-})
+-
+ ;; Generate
+ ;; vspltis? SCRATCH0,0
+ ;; vsubu?m SCRATCH2,SCRATCH1,%1
+@@ -2069,7 +1680,7 @@ (define_expand "abs<mode>2"
+ ;; vspltisw SCRATCH1,-1
+ ;; vslw SCRATCH2,SCRATCH1,SCRATCH1
+ ;; vandc %0,%1,SCRATCH2
+-(define_expand "absv4sf2"
++(define_expand "altivec_absv4sf2"
+ [(set (match_dup 2)
+ (vec_duplicate:V4SI (const_int -1)))
+ (set (match_dup 3)
+@@ -2132,7 +1743,7 @@ (define_expand "vec_shl_<mode>"
+ DONE;
+ }")
+
+-;; Vector shift left in bits. Currently supported ony for shift
++;; Vector shift right in bits. Currently supported ony for shift
+ ;; amounts that can be expressed as byte shifts (divisible by 8).
+ ;; General shift amounts can be supported using vsro + vsr. We're
+ ;; not expecting to see these yet (the vectorizer currently
+@@ -2665,7 +2276,7 @@ (define_expand "vec_pack_trunc_v4si"
+ DONE;
+ }")
+
+-(define_expand "negv4sf2"
++(define_expand "altivec_negv4sf2"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+@@ -2994,29 +2605,6 @@ (define_expand "vec_extract_oddv16qi"
+ emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2]));
+ DONE;
+ }")
+-(define_expand "vec_interleave_highv4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "")
+- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
+- (match_operand:V4SF 2 "register_operand" "")]
+- UNSPEC_INTERHI_V4SF))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- emit_insn (gen_altivec_vmrghsf (operands[0], operands[1], operands[2]));
+- DONE;
+-}")
+-
+-(define_expand "vec_interleave_lowv4sf"
+- [(set (match_operand:V4SF 0 "register_operand" "")
+- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
+- (match_operand:V4SF 2 "register_operand" "")]
+- UNSPEC_INTERLO_V4SF))]
+- "TARGET_ALTIVEC"
+- "
+-{
+- emit_insn (gen_altivec_vmrglsf (operands[0], operands[1], operands[2]));
+- DONE;
+-}")
+
+ (define_expand "vec_interleave_high<mode>"
+ [(set (match_operand:VI 0 "register_operand" "")
+--- gcc/config/rs6000/aix61.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/aix61.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -57,20 +57,24 @@ do { \
+ #undef ASM_SPEC
+ #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
+
+-/* Common ASM definitions used by ASM_SPEC amongst the various targets
+- for handling -mcpu=xxx switches. */
++/* Common ASM definitions used by ASM_SPEC amongst the various targets for
++ handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
++ provide the default assembler options if the user uses -mcpu=native, so if
++ you make changes here, make them there also. */
+ #undef ASM_CPU_SPEC
+ #define ASM_CPU_SPEC \
+ "%{!mcpu*: %{!maix64: \
+ %{mpowerpc64: -mppc64} \
+ %{maltivec: -m970} \
+ %{!maltivec: %{!mpower64: %(asm_default)}}}} \
++%{mcpu=native: %(asm_cpu_native)} \
+ %{mcpu=power3: -m620} \
+ %{mcpu=power4: -mpwr4} \
+ %{mcpu=power5: -mpwr5} \
+ %{mcpu=power5+: -mpwr5x} \
+ %{mcpu=power6: -mpwr6} \
+ %{mcpu=power6x: -mpwr6} \
++%{mcpu=power7: -mpwr7} \
+ %{mcpu=powerpc: -mppc} \
+ %{mcpu=rs64a: -mppc} \
+ %{mcpu=603: -m603} \
+--- gcc/config/rs6000/rs6000.md (.../trunk) (revision 144557)
++++ gcc/config/rs6000/rs6000.md (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -138,7 +138,7 @@ (define_attr "length" ""
+ ;; Processor type -- this attribute must exactly match the processor_type
+ ;; enumeration in rs6000.h.
+
+-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,cell"
++(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell"
+ (const (symbol_ref "rs6000_cpu_attr")))
+
+
+@@ -167,6 +167,7 @@ (define_attr "cell_micro" "not,condition
+ (include "power4.md")
+ (include "power5.md")
+ (include "power6.md")
++(include "power7.md")
+ (include "cell.md")
+ (include "xfpu.md")
+
+@@ -218,6 +219,9 @@ (define_mode_attr wd [(QI "b") (HI "h")
+ ; DImode bits
+ (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
+
++;; ISEL/ISEL64 target selection
++(define_mode_attr sel [(SI "") (DI "64")])
++
+ \f
+ ;; Start with fixed-point load and store insns. Here we put only the more
+ ;; complex forms. Basic data transfer is done later.
+@@ -520,7 +524,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %2,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -546,7 +550,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %0,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -687,7 +691,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %2,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -713,7 +717,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %0,%1,0xff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -856,7 +860,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %2,%1,0xffff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -882,7 +886,7 @@ (define_insn ""
+ "@
+ {andil.|andi.} %0,%1,0xffff
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -1670,7 +1674,7 @@ (define_insn ""
+ "@
+ nor. %2,%1,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -1696,7 +1700,7 @@ (define_insn ""
+ "@
+ nor. %0,%1,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -2221,10 +2225,22 @@ (define_insn "popcntb<mode>2"
+ "TARGET_POPCNTB"
+ "popcntb %0,%1")
+
++(define_insn "popcntwsi2"
++ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
++ (popcount:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
++ "TARGET_POPCNTD"
++ "popcntw %0,%1")
++
++(define_insn "popcntddi2"
++ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
++ (popcount:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
++ "TARGET_POPCNTD && TARGET_POWERPC64"
++ "popcntd %0,%1")
++
+ (define_expand "popcount<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
+- "TARGET_POPCNTB"
++ "TARGET_POPCNTB || TARGET_POPCNTD"
+ {
+ rs6000_emit_popcount (operands[0], operands[1]);
+ DONE;
+@@ -2852,7 +2868,7 @@ (define_insn "andsi3_mc"
+ {rlinm|rlwinm} %0,%1,0,%m2,%M2
+ {andil.|andi.} %0,%1,%b2
+ {andiu.|andis.} %0,%1,%u2"
+- [(set_attr "type" "*,*,compare,compare")])
++ [(set_attr "type" "*,*,fast_compare,fast_compare")])
+
+ (define_insn "andsi3_nomc"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+@@ -2895,7 +2911,8 @@ (define_insn "*andsi3_internal2_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
++ compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,8,8,8,8")])
+
+ (define_insn "*andsi3_internal3_mc"
+@@ -2915,7 +2932,8 @@ (define_insn "*andsi3_internal3_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
++ compare,compare,compare")
+ (set_attr "length" "8,4,4,4,8,8,8,8")])
+
+ (define_split
+@@ -2974,7 +2992,8 @@ (define_insn "*andsi3_internal4"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
++ compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,8,8,8,8")])
+
+ (define_insn "*andsi3_internal5_mc"
+@@ -2996,7 +3015,8 @@ (define_insn "*andsi3_internal5_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
++ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
++ compare,compare,compare")
+ (set_attr "length" "8,4,4,4,8,8,8,8")])
+
+ (define_insn "*andsi3_internal5_nomc"
+@@ -3141,7 +3161,7 @@ (define_insn "*boolsi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -3170,7 +3190,7 @@ (define_insn "*boolsi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -3295,7 +3315,7 @@ (define_insn "*boolccsi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -3324,7 +3344,7 @@ (define_insn "*boolccsi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -5317,7 +5337,7 @@ (define_insn "fres"
+ "fres %0,%1"
+ [(set_attr "type" "fp")])
+
+-(define_insn ""
++(define_insn "*fmaddsf4_powerpc"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5328,7 +5348,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fmaddsf4_power"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5337,7 +5357,7 @@ (define_insn ""
+ "{fma|fmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fmsubsf4_powerpc"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5348,7 +5368,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fmsubsf4_power"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5357,7 +5377,7 @@ (define_insn ""
+ "{fms|fmsub} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_powerpc_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5368,7 +5388,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_powerpc_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5379,7 +5399,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_power_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5388,7 +5408,7 @@ (define_insn ""
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmaddsf4_power_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5398,7 +5418,7 @@ (define_insn ""
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_powerpc_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5409,7 +5429,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_powerpc_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+@@ -5420,7 +5440,7 @@ (define_insn ""
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_s")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_power_1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+@@ -5429,7 +5449,7 @@ (define_insn ""
+ "{fnms|fnmsub} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+-(define_insn ""
++(define_insn "*fnmsubsf4_power_2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+@@ -5510,9 +5530,18 @@ (define_expand "copysigndf3"
+ (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]));
++ DONE;
++ }
+ operands[3] = gen_reg_rtx (DFmode);
+ operands[4] = gen_reg_rtx (DFmode);
+ operands[5] = CONST0_RTX (DFmode);
+@@ -5556,12 +5585,12 @@ (define_split
+ DONE;
+ }")
+
+-(define_expand "movsicc"
+- [(set (match_operand:SI 0 "gpc_reg_operand" "")
+- (if_then_else:SI (match_operand 1 "comparison_operator" "")
+- (match_operand:SI 2 "gpc_reg_operand" "")
+- (match_operand:SI 3 "gpc_reg_operand" "")))]
+- "TARGET_ISEL"
++(define_expand "mov<mode>cc"
++ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
++ (if_then_else:GPR (match_operand 1 "comparison_operator" "")
++ (match_operand:GPR 2 "gpc_reg_operand" "")
++ (match_operand:GPR 3 "gpc_reg_operand" "")))]
++ "TARGET_ISEL<sel>"
+ "
+ {
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+@@ -5578,28 +5607,28 @@ (define_expand "movsicc"
+ ;; leave out the mode in operand 4 and use one pattern, but reload can
+ ;; change the mode underneath our feet and then gets confused trying
+ ;; to reload the value.
+-(define_insn "isel_signed"
+- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (if_then_else:SI
++(define_insn "isel_signed_<mode>"
++ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
++ (if_then_else:GPR
+ (match_operator 1 "comparison_operator"
+ [(match_operand:CC 4 "cc_reg_operand" "y")
+ (const_int 0)])
+- (match_operand:SI 2 "gpc_reg_operand" "b")
+- (match_operand:SI 3 "gpc_reg_operand" "b")))]
+- "TARGET_ISEL"
++ (match_operand:GPR 2 "gpc_reg_operand" "b")
++ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
++ "TARGET_ISEL<sel>"
+ "*
+ { return output_isel (operands); }"
+ [(set_attr "length" "4")])
+
+-(define_insn "isel_unsigned"
+- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (if_then_else:SI
++(define_insn "isel_unsigned_<mode>"
++ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
++ (if_then_else:GPR
+ (match_operator 1 "comparison_operator"
+ [(match_operand:CCUNS 4 "cc_reg_operand" "y")
+ (const_int 0)])
+- (match_operand:SI 2 "gpc_reg_operand" "b")
+- (match_operand:SI 3 "gpc_reg_operand" "b")))]
+- "TARGET_ISEL"
++ (match_operand:GPR 2 "gpc_reg_operand" "b")
++ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
++ "TARGET_ISEL<sel>"
+ "*
+ { return output_isel (operands); }"
+ [(set_attr "length" "4")])
+@@ -5647,7 +5676,8 @@ (define_expand "negdf2"
+ (define_insn "*negdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+- "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")])
+
+@@ -5660,14 +5690,16 @@ (define_expand "absdf2"
+ (define_insn "*absdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+- "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" "=f")
+ (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
+- "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")])
+
+@@ -5682,7 +5714,8 @@ (define_insn "*adddf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+@@ -5698,7 +5731,8 @@ (define_insn "*subdf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+@@ -5714,7 +5748,8 @@ (define_insn "*muldf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+@@ -5732,7 +5767,8 @@ (define_insn "*divdf3_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
+ (match_operand:DF 2 "gpc_reg_operand" "f")))]
+- "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")])
+
+@@ -5748,73 +5784,81 @@ (define_expand "recipdf3"
+ DONE;
+ })
+
+-(define_insn "fred"
++(define_expand "fred"
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
++ "(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"
++ "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" "=f")
+ (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+- "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" "=f")
+ (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+- "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" "=f")
+ (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f"))))]
+ "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" "=f")
+ (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f"))
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+ "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" "=f")
+ (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f"))))]
+ "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" "=f")
+ (minus:DF (match_operand:DF 3 "gpc_reg_operand" "f")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))))]
+ "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")])
+@@ -5823,7 +5867,8 @@ (define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+ "(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")])
+
+@@ -5912,6 +5957,18 @@ (define_expand "fix_truncsfsi2"
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
+ "")
+
++(define_expand "fixuns_truncdfsi2"
++ [(set (match_operand:SI 0 "gpc_reg_operand" "")
++ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
++ "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,
+@@ -6153,10 +6210,17 @@ (define_insn "fctiwz"
+ "{fcirz|fctiwz} %0,%1"
+ [(set_attr "type" "fp")])
+
+-(define_insn "btruncdf2"
++(define_expand "btruncdf2"
+ [(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"
++ "")
++
++(define_insn "*btruncdf2_fprs"
++ [(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")])
+
+@@ -6167,10 +6231,17 @@ (define_insn "btruncsf2"
+ "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_fprs"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] 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")])
+
+@@ -6181,10 +6252,17 @@ (define_insn "ceilsf2"
+ "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_fprs"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] 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")])
+
+@@ -6195,6 +6273,7 @@ (define_insn "floorsf2"
+ "frim %0,%1"
+ [(set_attr "type" "fp")])
+
++;; No VSX equivalent to frin
+ (define_insn "rounddf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
+@@ -6209,6 +6288,12 @@ (define_insn "roundsf2"
+ "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")
+@@ -6224,17 +6309,40 @@ (define_expand "floatsisf2"
+ "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" "=f")
+ (float:DF (match_operand:DI 1 "gpc_reg_operand" "!f#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" "=!f#r")
+ (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))]
+- "(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")])
+
+@@ -7623,7 +7731,7 @@ (define_insn "anddi3_mc"
+ andi. %0,%1,%b2
+ andis. %0,%1,%u2
+ #"
+- [(set_attr "type" "*,*,*,compare,compare,*")
++ [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
+ (set_attr "length" "4,4,4,4,4,8")])
+
+ (define_insn "anddi3_nomc"
+@@ -7681,7 +7789,9 @@ (define_insn "*anddi3_internal2_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
++ fast_compare,compare,compare,compare,compare,compare,\
++ compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
+
+ (define_insn "*anddi3_internal2_nomc"
+@@ -7744,7 +7854,9 @@ (define_insn "*anddi3_internal3_mc"
+ #
+ #
+ #"
+- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
++ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
++ fast_compare,compare,compare,compare,compare,compare,\
++ compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
+
+ (define_insn "*anddi3_internal3_nomc"
+@@ -7896,7 +8008,7 @@ (define_insn "*booldi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -7925,7 +8037,7 @@ (define_insn "*booldi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -7996,7 +8108,7 @@ (define_insn "*boolcdi3_internal2"
+ "@
+ %q4. %3,%2,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8025,7 +8137,7 @@ (define_insn "*boolcdi3_internal3"
+ "@
+ %q4. %0,%2,%1
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8062,7 +8174,7 @@ (define_insn "*boolccdi3_internal2"
+ "@
+ %q4. %3,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8091,7 +8203,7 @@ (define_insn "*boolccdi3_internal3"
+ "@
+ %q4. %0,%1,%2
+ #"
+- [(set_attr "type" "compare")
++ [(set_attr "type" "fast_compare,compare")
+ (set_attr "length" "4,8")])
+
+ (define_split
+@@ -8108,6 +8220,51 @@ (define_split
+ (compare:CC (match_dup 0)
+ (const_int 0)))]
+ "")
++
++(define_expand "smindi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
++ DONE;
++}")
++
++(define_expand "smaxdi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
++ DONE;
++}")
++
++(define_expand "umindi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]);
++ DONE;
++}")
++
++(define_expand "umaxdi3"
++ [(match_operand:DI 0 "gpc_reg_operand" "")
++ (match_operand:DI 1 "gpc_reg_operand" "")
++ (match_operand:DI 2 "gpc_reg_operand" "")]
++ "TARGET_ISEL64"
++ "
++{
++ rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]);
++ DONE;
++}")
++
+ \f
+ ;; Now define ways of moving data around.
+
+@@ -8511,8 +8668,8 @@ (define_split
+ ;; 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,f,f,m,!r,!r,!r")
+- (match_operand:DF 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r, ??r, m, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, !r, !r, !r")
++ (match_operand:DF 1 "input_operand" "r, m, r, ws, wa, Z, Z, ws, wa, f, m, f, 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))"
+@@ -8591,19 +8748,30 @@ (define_insn "*movdf_hardfloat32"
+ return \"\";
+ }
+ case 3:
+- return \"fmr %0,%1\";
+ case 4:
+- return \"lfd%U1%X1 %0,%1\";
++ return \"xscpsgndp %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")
+@@ -8651,19 +8819,26 @@ (define_insn "*movdf_softfloat32"
+ ; 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,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
+- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y, r, !r, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, *c*l, !r, *h, !r, !r, !r, r, f")
++ (match_operand:DF 1 "input_operand" "r, Y, r, ws, ?wa, Z, Z, ws, wa, f, m, f, j, r, h, 0, G, H, F, f, 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
++ xscpsgndp %x0,%x1,%x1
++ xscpsgndp %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}
+@@ -8672,33 +8847,40 @@ (define_insn "*movdf_hardfloat64_mfpgpr"
+ #
+ 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,f,f,m,*c*l,!r,*h,!r,!r,!r")
+- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y, r, !r, ws, ?wa, ws, ?wa, Z, ?Z, f, f, m, wa, *c*l, !r, *h, !r, !r, !r")
++ (match_operand:DF 1 "input_operand" "r, Y, r, ws, wa, Z, Z, ws, wa, f, m, f, 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
++ xscpsgndp %x0,%x1,%x1
++ xscpsgndp %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")
+@@ -9275,15 +9457,16 @@ (define_insn "*movti_string"
+ (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" "*,load,store")])
+
+ (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))]
+ "
+@@ -9309,7 +9492,7 @@ (define_split
+ (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; })
+@@ -14929,6 +15112,8 @@ (define_insn "prefetch"
+ \f
+
+ (include "sync.md")
++(include "vector.md")
++(include "vsx.md")
+ (include "altivec.md")
+ (include "spe.md")
+ (include "dfp.md")
+--- gcc/config/rs6000/e500.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/e500.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -37,6 +37,8 @@
+ { \
+ if (TARGET_ALTIVEC) \
+ error ("AltiVec and E500 instructions cannot coexist"); \
++ if (TARGET_VSX) \
++ error ("VSX and E500 instructions cannot coexist"); \
+ if (TARGET_64BIT) \
+ error ("64-bit E500 not supported"); \
+ if (TARGET_HARD_FLOAT && TARGET_FPRS) \
+--- gcc/config/rs6000/driver-rs6000.c (.../trunk) (revision 144557)
++++ gcc/config/rs6000/driver-rs6000.c (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -343,11 +343,115 @@ detect_processor_aix (void)
+ #endif /* _AIX */
+
+
++/*
++ * Array to map -mcpu=native names to the switches passed to the assembler.
++ * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
++ * should be made there as well.
++ */
++
++struct asm_name {
++ const char *cpu;
++ const char *asm_sw;
++};
++
++static const
++struct asm_name asm_names[] = {
++#if defined (_AIX)
++ { "power3", "-m620" },
++ { "power4", "-mpwr4" },
++ { "power5", "-mpwr5" },
++ { "power5+", "-mpwr5x" },
++ { "power6", "-mpwr6" },
++ { "power6x", "-mpwr6" },
++ { "power7", "-mpwr7" },
++ { "powerpc", "-mppc" },
++ { "rs64a", "-mppc" },
++ { "603", "-m603" },
++ { "603e", "-m603" },
++ { "604", "-m604" },
++ { "604e", "-m604" },
++ { "620", "-m620" },
++ { "630", "-m620" },
++ { "970", "-m970" },
++ { "G5", "-m970" },
++ { NULL, "\
++%{!maix64: \
++%{mpowerpc64: -mppc64} \
++%{maltivec: -m970} \
++%{!maltivec: %{!mpower64: %(asm_default)}}}" },
++
++#else
++ { "common", "-mcom" },
++ { "cell", "-mcell" },
++ { "power", "-mpwr" },
++ { "power2", "-mpwrx" },
++ { "power3", "-mppc64" },
++ { "power4", "-mpower4" },
++ { "power5", "%(asm_cpu_power5)" },
++ { "power5+", "%(asm_cpu_power5)" },
++ { "power6", "%(asm_cpu_power6) -maltivec" },
++ { "power6x", "%(asm_cpu_power6) -maltivec" },
++ { "power7", "%(asm_cpu_power7)" },
++ { "powerpc", "-mppc" },
++ { "rios", "-mpwr" },
++ { "rios1", "-mpwr" },
++ { "rios2", "-mpwrx" },
++ { "rsc", "-mpwr" },
++ { "rsc1", "-mpwr" },
++ { "rs64a", "-mppc64" },
++ { "401", "-mppc" },
++ { "403", "-m403" },
++ { "405", "-m405" },
++ { "405fp", "-m405" },
++ { "440", "-m440" },
++ { "440fp", "-m440" },
++ { "464", "-m440" },
++ { "464fp", "-m440" },
++ { "505", "-mppc" },
++ { "601", "-m601" },
++ { "602", "-mppc" },
++ { "603", "-mppc" },
++ { "603e", "-mppc" },
++ { "ec603e", "-mppc" },
++ { "604", "-mppc" },
++ { "604e", "-mppc" },
++ { "620", "-mppc64" },
++ { "630", "-mppc64" },
++ { "740", "-mppc" },
++ { "750", "-mppc" },
++ { "G3", "-mppc" },
++ { "7400", "-mppc -maltivec" },
++ { "7450", "-mppc -maltivec" },
++ { "G4", "-mppc -maltivec" },
++ { "801", "-mppc" },
++ { "821", "-mppc" },
++ { "823", "-mppc" },
++ { "860", "-mppc" },
++ { "970", "-mpower4 -maltivec" },
++ { "G5", "-mpower4 -maltivec" },
++ { "8540", "-me500" },
++ { "8548", "-me500" },
++ { "e300c2", "-me300" },
++ { "e300c3", "-me300" },
++ { "e500mc", "-me500mc" },
++ { NULL, "\
++%{mpower: %{!mpower2: -mpwr}} \
++%{mpower2: -mpwrx} \
++%{mpowerpc64*: -mppc64} \
++%{!mpowerpc64*: %{mpowerpc*: -mppc}} \
++%{mno-power: %{!mpowerpc*: -mcom}} \
++%{!mno-power: %{!mpower*: %(asm_default)}}" },
++#endif
++};
++
+ /* This will be called by the spec parser in gcc.c when it sees
+ a %:local_cpu_detect(args) construct. Currently it will be called
+ with either "arch" or "tune" as argument depending on if -march=native
+ or -mtune=native is to be substituted.
+
++ Additionally it will be called with "asm" to select the appropriate flags
++ for the assembler.
++
+ It returns a string containing new command line parameters to be
+ put at the place of the above two options, depending on what CPU
+ this is executed.
+@@ -361,29 +465,35 @@ const char
+ const char *cache = "";
+ const char *options = "";
+ bool arch;
++ bool assembler;
++ size_t i;
+
+ if (argc < 1)
+ return NULL;
+
+ arch = strcmp (argv[0], "cpu") == 0;
+- if (!arch && strcmp (argv[0], "tune"))
++ assembler = (!arch && strcmp (argv[0], "asm") == 0);
++ if (!arch && !assembler && strcmp (argv[0], "tune"))
+ return NULL;
+
++ if (! assembler)
++ {
+ #if defined (_AIX)
+- cache = detect_caches_aix ();
++ cache = detect_caches_aix ();
+ #elif defined (__APPLE__)
+- cache = detect_caches_darwin ();
++ cache = detect_caches_darwin ();
+ #elif defined (__FreeBSD__)
+- cache = detect_caches_freebsd ();
+- /* FreeBSD PPC does not provide any cache information yet. */
+- cache = "";
++ cache = detect_caches_freebsd ();
++ /* FreeBSD PPC does not provide any cache information yet. */
++ cache = "";
+ #elif defined (__linux__)
+- cache = detect_caches_linux ();
+- /* PPC Linux does not provide any cache information yet. */
+- cache = "";
++ cache = detect_caches_linux ();
++ /* PPC Linux does not provide any cache information yet. */
++ cache = "";
+ #else
+- cache = "";
++ cache = "";
+ #endif
++ }
+
+ #if defined (_AIX)
+ cpu = detect_processor_aix ();
+@@ -397,6 +507,17 @@ const char
+ cpu = "powerpc";
+ #endif
+
++ if (assembler)
++ {
++ for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++)
++ {
++ if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu))
++ return asm_names[i].asm_sw;
++ }
++
++ return NULL;
++ }
++
+ return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
+ }
+
+--- gcc/config/rs6000/sysv4.h (.../trunk) (revision 144557)
++++ gcc/config/rs6000/sysv4.h (.../branches/ibm/power7-meissner) (revision 144692)
+@@ -119,9 +119,9 @@ do { \
+ else if (!strcmp (rs6000_abi_name, "i960-old")) \
+ { \
+ rs6000_current_abi = ABI_V4; \
+- target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI \
+- | MASK_NO_BITFIELD_WORD); \
++ target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI); \
+ target_flags &= ~MASK_STRICT_ALIGN; \
++ TARGET_NO_BITFIELD_WORD = 1; \
+ } \
+ else \
+ { \
+
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-29 12:24 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-29 12:24 [rpms/gcc] rhel-f41-base: 4.4.0-0.23 Jakub Jelinek
-- strict thread matches above, loose matches on Subject: below --
2026-06-29 12:24 Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox