gcc/power7.patch
Jakub Jelinek caa5b98426 4.4.0-0.23
2009-03-07 09:16:22 +00:00

9507 lines
318 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
+ }
}
}
--- 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;
+})
+
+
+;; 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)"
+ "")
+
+
+;; 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;
+}")
+
+
+;; 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;
+ }
+}")
+
+
+;; 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;
+
/* 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 */
+};
+
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;
+/* 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)));
+}
/* 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.
+
+
+;; 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")])
+
+
+;; 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")])
+
+
+;; Logical and permute operations
+(define_insn "*vsx_and<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (and:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxland %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_ior<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (ior:VSX_L (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlor %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_xor<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (xor:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlxor %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_one_cmpl<mode>2"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (not:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlnor %x0,%x1,%x1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_nor<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (not:VSX_L
+ (ior:VSX_L
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlnor %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*vsx_andc<mode>3"
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+ (and:VSX_L
+ (not:VSX_L
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,?wa"))
+ (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,?wa")))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxlandc %x0,%x1,%x2"
+ [(set_attr "type" "vecsimple")])
+
+
+;; Permute operations
+
+(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))))
+
/* 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")])
+
;; 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;
+}")
+
;; 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"
(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 \
{ \