]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
predicates.md (indexed_address, [...]): New predicates.
authorMichael Meissner <meissner@gcc.gnu.org>
Wed, 20 Mar 2013 15:50:27 +0000 (15:50 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Wed, 20 Mar 2013 15:50:27 +0000 (15:50 +0000)
[gcc]
2013-03-20  Pat Haugen <pthaugen@us.ibm.com>

* config/rs6000/predicates.md (indexed_address, update_address_mem
update_indexed_address_mem): New predicates.
* config/rs6000/vsx.md (vsx_extract_<mode>_zero): Set correct "type"
attribute for load/store instructions.
* config/rs6000/dfp.md (movsd_store): Likewise.
(movsd_load): Likewise.
* config/rs6000/rs6000.md (zero_extend<mode>di2_internal1): Likewise.
(unnamed HI->DI extend define_insn): Likewise.
(unnamed SI->DI extend define_insn): Likewise.
(unnamed QI->SI extend define_insn): Likewise.
(unnamed QI->HI extend define_insn): Likewise.
(unnamed HI->SI extend define_insn): Likewise.
(unnamed HI->SI extend define_insn): Likewise.
(extendsfdf2_fpr): Likewise.
(movsi_internal1): Likewise.
(movsi_internal1_single): Likewise.
(movhi_internal): Likewise.
(movqi_internal): Likewise.
(movcc_internal1): Correct mnemonic for stw insn. Set correct "type"
attribute for load/store instructions.
(mov<mode>_hardfloat): Set correct "type" attribute for load/store
instructions.
(mov<mode>_softfloat): Likewise.
(mov<mode>_hardfloat32): Likewise.
(mov<mode>_hardfloat64): Likewise.
(mov<mode>_softfloat64): Likewise.
(movdi_internal32): Likewise.
(movdi_internal64): Likewise.
(probe_stack_<mode>): Likewise.

2013-03-20  Michael Meissner  <meissner@linux.vnet.ibm.com>

* config/rs6000/vector.md (VEC_R): Add 32-bit integer, binary
floating point, and decimal floating point to reload iterator.

* config/rs6000/constraints.md (wl constraint): New constraints to
return FLOAT_REGS if certain options are used to reduce the number
of separate patterns that exist in the file.
(wx constraint): Likewise.
(wz constraint): Likewise.

* config/rs6000/rs6000.c (rs6000_debug_reg_global): If
-mdebug=reg, print wg, wl, wx, and wz constraints.
(rs6000_init_hard_regno_mode_ok): Initialize new constraints.
Initialize the reload functions for 64-bit binary/decimal floating
point types.
(reg_offset_addressing_ok_p): If we are on a power7 or later, use
LFIWZX and STFIWX to load/store 32-bit decimal types, and don't
create the buffer on the stack to overcome not having a 32-bit
load and store.
(rs6000_emit_move): Likewise.
(rs6000_secondary_memory_needed_rtx): Likewise.
(rs6000_alloc_sdmode_stack_slot): Likewise.
(rs6000_preferred_reload_class): On VSX, we can create SFmode 0.0f
via xxlxor, just like DFmode 0.0.

* config/rs6000/rs6000.h (TARGET_NO_SDMODE_STACK): New macro,
define as 1 if we are running on a power7 or newer.
(enum r6000_reg_class_enum): Add new constraints.

* config/rs6000/dfp.md (movsd): Delete, combine with binary
floating point moves in rs6000.md.  Combine power6x (mfpgpr) moves
with other moves by using conditional constraits (wg).  Use LFIWZX
and STFIWX for loading SDmode on power7.  Use xxlxor to create
0.0f.
(movsd splitter): Likewise.
(movsd_hardfloat): Likewise.
(movsd_softfloat): Likewise.

* config/rs6000/rs6000.md (FMOVE32): New iterators to combine
binary and decimal floating point moves.
(fmove_ok): New attributes to combine binary and decimal floating
point moves, and to combine power6x (mfpgpr) moves along normal
floating moves.
(real_value_to_target): Likewise.
(f32_lr): Likewise.
(f32_lm): Likewise.
(f32_li): Likewise.
(f32_sr): Likewise.
(f32_sm): Likewise.
(f32_si): Likewise.
(movsf): Combine binary and decimal floating point moves.  Combine
power6x (mfpgpr) moves with other moves by using conditional
constraits (wg).  Use LFIWZX and STFIWX for loading SDmode on
power7.
(mov<mode> for SFmode/SDmode); Likewise.
(SFmode/SDmode splitters): Likewise.
(movsf_hardfloat): Likewise.
(mov<mode>_hardfloat for SFmode/SDmode): Likewise.
(movsf_softfloat): Likewise.
(mov<mode>_softfloat for SFmode/SDmode): Likewise.

* doc/md.texi (PowerPC and IBM RS6000 constraints): Document wl,
wx and wz constraints.

* config/rs6000/constraints.md (wg constraint): New constraint to
return FLOAT_REGS if -mmfpgpr (power6x) was used.

* config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wg
constraint.

* config/rs6000/rs6000.c (rs6000_debug_reg_global): If
-mdebug=reg, print wg, wl, wx, and wz constraints.
(rs6000_init_hard_regno_mode_ok): Initialize new constraints.
Initialize the reload functions for 64-bit binary/decimal floating
point types.
(reg_offset_addressing_ok_p): If we are on a power7 or later, use
LFIWZX and STFIWX to load/store 32-bit decimal types, and don't
create the buffer on the stack to overcome not having a 32-bit
load and store.
(rs6000_emit_move): Likewise.
(rs6000_secondary_memory_needed_rtx): Likewise.
(rs6000_alloc_sdmode_stack_slot): Likewise.
(rs6000_preferred_reload_class): On VSX, we can create SFmode 0.0f
via xxlxor, just like DFmode 0.0.

* config/rs6000/dfp.md (movdd): Delete, combine with binary
floating point moves in rs6000.md.  Combine power6x (mfpgpr) moves
with other moves by using conditional constraits (wg).  Use LFIWZX
and STFIWX for loading SDmode on power7.
(movdd splitters): Likewise.
(movdd_hardfloat32): Likewise.
(movdd_softfloat32): Likewise.
(movdd_hardfloat64_mfpgpr): Likewise.
(movdd_hardfloat64): Likewise.
(movdd_softfloat64): Likewise.

* config/rs6000/rs6000.md (FMOVE64): New iterators to combine
64-bit binary and decimal floating point moves.
(FMOVE64X): Likewise.
(movdf): Combine 64-bit binary and decimal floating point moves.
Combine power6x (mfpgpr) moves with other moves by using
conditional constraits (wg).
(mov<mode> for DFmode/DDmode): Likewise.
(DFmode/DDmode splitters): Likewise.
(movdf_hardfloat32): Likewise.
(mov<mode>_hardfloat32 for DFmode/DDmode): Likewise.
(movdf_softfloat32): Likewise.
(movdf_hardfloat64_mfpgpr): Likewise.
(movdf_hardfloat64): Likewise.
(mov<mode>_hardfloat64 for DFmode/DDmode): Likewise.
(movdf_softfloat64): Likewise.
(mov<mode>_softfloat64 for DFmode/DDmode): Likewise.
(reload_<mode>_load): Move to later in the file so they aren't in
the middle of the floating point move insns.
(reload_<mode>_store): Likewise.

* doc/md.texi (PowerPC and IBM RS6000 constraints): Document wg
constraint.

* config/rs6000/rs6000.c (rs6000_debug_reg_global): Print out wg
constraint if -mdebug=reg.
(rs6000_initi_hard_regno_mode_ok): Enable wg constraint if
-mfpgpr.  Enable using dd reload support if needed.

* config/rs6000/dfp.md (movtd): Delete, combine with 128-bit
binary and decimal floating point moves in rs6000.md.
(movtd_internal): Likewise.

* config/rs6000/rs6000.md (FMOVE128): Combine 128-bit binary and
decimal floating point moves.
(movtf): Likewise.
(movtf_internal): Likewise.
(mov<mode>_internal, TDmode/TFmode): Likewise.
(movtf_softfloat): Likewise.
(mov<mode>_softfloat, TDmode/TFmode): Likewise.

* config/rs6000/rs6000.md (movdi_mfpgpr): Delete, combine with
movdi_internal64, using wg constraint for move direct operations.
(movdi_internal64): Likewise.

* config/rs6000/rs6000.c (rs6000_debug_reg_global): Print
MODES_TIEABLE_P for selected modes.  Print the numerical value of
the various virtual registers. Use GPR/FPR first/last values,
instead of hard coding the register numbers.  Print which modes
have reload functions registered.
(rs6000_option_override_internal): If -mdebug=reg, trace the
options settings before/after setting cpu, target and subtarget
settings.
(rs6000_secondary_reload_trace): Improve the RTL dump for
-mdebug=addr and for secondary reload failures in
rs6000_secondary_reload_inner.
(rs6000_secondary_reload_fail): Likewise.
(rs6000_secondary_reload_inner): Likewise.

* config/rs6000/rs6000.md (FIRST_GPR_REGNO): Add convenience
macros for first/last GPR and FPR registers.
(LAST_GPR_REGNO): Likewise.
(FIRST_FPR_REGNO): Likewise.
(LAST_FPR_REGNO): Likewise.

* config/rs6000/vector.md (mul<mode>3): Use the combined macro
VECTOR_UNIT_ALTIVEC_OR_VSX_P instead of separate calls to
VECTOR_UNIT_ALTIVEC_P and VECTOR_UNIT_VSX_P.
(vcond<mode><mode>): Likewise.
(vcondu<mode><mode>): Likewise.
(vector_gtu<mode>): Likewise.
(vector_gte<mode>): Likewise.
(xor<mode>3): Don't allow logical operations on TImode in 32-bit
to prevent the compiler from converting DImode operations to
TImode.
(ior<mode>3): Likewise.
(and<mode>3): Likewise.
(one_cmpl<mode>2): Likewise.
(nor<mode>3): Likewise.
(andc<mode>3): Likewise.

* config/rs6000/constraints.md (wt constraint): New constraint
that returns VSX_REGS if TImode is allowed in VSX registers.

* config/rs6000/predicates.md (easy_fp_constant): 0.0f is an easy
constant under VSX.

* config/rs6000/rs6000-modes.def (PTImode): Define, PTImode is
similar to TImode, but it is restricted to being in the GPRs.

* config/rs6000/rs6000.opt (-mvsx-timode): New switch to allow
TImode to occupy a single VSX register.

* config/rs6000/rs6000-cpus.def (ISA_2_6_MASKS_SERVER): Default to
-mvsx-timode for power7/power8.
(power7 cpu): Likewise.
(power8 cpu): Likewise.

* config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Make
sure that TFmode/TDmode take up two registers if they are ever
allowed in the upper VSX registers.
(rs6000_hard_regno_mode_ok): If -mvsx-timode, allow TImode in VSX
registers.
(rs6000_init_hard_regno_mode_ok): Likewise.
(rs6000_debug_reg_global): Add debugging for PTImode and wt
constraint.  Print if LRA is turned on.
(rs6000_option_override_internal): Give an error if -mvsx-timode
and VSX is not enabled.
(invalid_e500_subreg): Handle PTImode, restricting it to GPRs.  If
-mvsx-timode, restrict TImode to reg+reg addressing, and PTImode
to reg+offset addressing.  Use PTImode when checking offset
addresses for validity.
(reg_offset_addressing_ok_p): Likewise.
(rs6000_legitimate_offset_address_p): Likewise.
(rs6000_legitimize_address): Likewise.
(rs6000_legitimize_reload_address): Likewise.
(rs6000_legitimate_address_p): Likewise.
(rs6000_eliminate_indexed_memrefs): Likewise.
(rs6000_emit_move): Likewise.
(rs6000_secondary_reload): Likewise.
(rs6000_secondary_reload_inner): Handle PTImode.  Allow 64-bit
reloads to fpr registers to continue to use reg+offset addressing,
but 64-bit reloads to altivec registers need reg+reg addressing.
Drop test for PRE_MODIFY, since VSX loads/stores no longer support
it.  Treat LO_SUM like a PLUS operation.
(rs6000_secondary_reload_class): If type is 64-bit, prefer to use
FLOAT_REGS instead of VSX_RGS to allow use of reg+offset
addressing.
(rs6000_cannot_change_mode_class): Do not allow TImode in VSX
registers to share a register with a smaller sized type, since VSX
puts scalars in the upper 64-bits.
(print_operand): Add support for PTImode.
(rs6000_register_move_cost): Use VECTOR_MEM_VSX_P instead of
VECTOR_UNIT_VSX_P to catch types that can be loaded in VSX
registers, but don't have arithmetic support.
(rs6000_memory_move_cost): Add test for VSX.
(rs6000_opt_masks): Add -mvsx-timode.

* config/rs6000/vsx.md (VSm): Change to use 64-bit aligned moves
for TImode.
(VSs): Likewise.
(VSr): Use wt constraint for TImode.
(VSv): Drop TImode support.
(vsx_movti): Delete, replace with versions for 32-bit and 64-bit.
(vsx_movti_64bit): Likewise.
(vsx_movti_32bit): Likewise.
(vec_store_<mode>): Use VSX iterator instead of vector iterator.
(vsx_and<mode>3): Delete use of '?' constraint on inputs, just put
one '?' on the appropriate output constraint.  Do not allow TImode
logical operations on 32-bit systems.
(vsx_ior<mode>3): Likewise.
(vsx_xor<mode>3): Likewise.
(vsx_one_cmpl<mode>2): Likewise.
(vsx_nor<mode>3): Likewise.
(vsx_andc<mode>3): Likewise.
(vsx_concat_<mode>): Likewise.
(vsx_xxpermdi_<mode>): Fix thinko for non V2DF/V2DI modes.

* config/rs6000/rs6000.h (MASK_VSX_TIMODE): Map from
OPTION_MASK_VSX_TIMODE.
(enum rs6000_reg_class_enum): Add RS6000_CONSTRAINT_wt.
(STACK_SAVEAREA_MODE): Use PTImode instead of TImode.

* config/rs6000/rs6000.md (INT mode attribute): Add PTImode.
(TI2 iterator): New iterator for TImode, PTImode.
(wd mode attribute): Add values for vector types.
(movti_string): Replace TI move operations with operations for
TImode and PTImode.  Add support for TImode being allowed in VSX
registers.
(mov<mode>_string, TImode/PTImode): Likewise.
(movti_ppc64): Likewise.
(mov<mode>_ppc64, TImode/PTImode): Likewise.
(TI mode splitters): Likewise.

* doc/md.texi (PowerPC and IBM RS6000 constraints): Document wt
constraint.

[gcc/testsuite]
2013-03-20  Michael Meissner  <meissner@linux.vnet.ibm.com>

* gcc.target/powerpc/mmfpgpr.c: New test.
* gcc.target/powerpc/sd-vsx.c: Likewise.
* gcc.target/powerpc/sd-pwr6.c: Likewise.
* gcc.target/powerpc/vsx-float0.c: Likewise.

From-SVN: r196831

18 files changed:
gcc/ChangeLog
gcc/config/rs6000/constraints.md
gcc/config/rs6000/dfp.md
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000-cpus.def
gcc/config/rs6000/rs6000-modes.def
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/rs6000.opt
gcc/config/rs6000/vector.md
gcc/config/rs6000/vsx.md
gcc/doc/md.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/mmfpgpr.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/sd-pwr6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/sd-vsx.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/vsx-float0.c [new file with mode: 0644]

index 1f4bb6d82670365af360003e66b631112b7ced84..1cc25b054b1eaae0f41830abe96c4e2eb257baff 100644 (file)
@@ -1,3 +1,309 @@
+2013-03-20  Pat Haugen <pthaugen@us.ibm.com>
+
+       * config/rs6000/predicates.md (indexed_address, update_address_mem
+       update_indexed_address_mem): New predicates.
+       * config/rs6000/vsx.md (vsx_extract_<mode>_zero): Set correct "type"
+       attribute for load/store instructions.
+       * config/rs6000/dfp.md (movsd_store): Likewise.
+       (movsd_load): Likewise.
+       * config/rs6000/rs6000.md (zero_extend<mode>di2_internal1): Likewise.
+       (unnamed HI->DI extend define_insn): Likewise.
+       (unnamed SI->DI extend define_insn): Likewise.
+       (unnamed QI->SI extend define_insn): Likewise.
+       (unnamed QI->HI extend define_insn): Likewise.
+       (unnamed HI->SI extend define_insn): Likewise.
+       (unnamed HI->SI extend define_insn): Likewise.
+       (extendsfdf2_fpr): Likewise.
+       (movsi_internal1): Likewise.
+       (movsi_internal1_single): Likewise.
+       (movhi_internal): Likewise.
+       (movqi_internal): Likewise.
+       (movcc_internal1): Correct mnemonic for stw insn. Set correct "type"
+       attribute for load/store instructions.
+       (mov<mode>_hardfloat): Set correct "type" attribute for load/store
+       instructions.
+       (mov<mode>_softfloat): Likewise.
+       (mov<mode>_hardfloat32): Likewise.
+       (mov<mode>_hardfloat64): Likewise.
+       (mov<mode>_softfloat64): Likewise.
+       (movdi_internal32): Likewise.
+       (movdi_internal64): Likewise.
+       (probe_stack_<mode>): Likewise.
+
+2013-03-20  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * config/rs6000/vector.md (VEC_R): Add 32-bit integer, binary
+       floating point, and decimal floating point to reload iterator.
+
+       * config/rs6000/constraints.md (wl constraint): New constraints to
+       return FLOAT_REGS if certain options are used to reduce the number
+       of separate patterns that exist in the file.
+       (wx constraint): Likewise.
+       (wz constraint): Likewise.
+
+       * config/rs6000/rs6000.c (rs6000_debug_reg_global): If
+       -mdebug=reg, print wg, wl, wx, and wz constraints.
+       (rs6000_init_hard_regno_mode_ok): Initialize new constraints.
+       Initialize the reload functions for 64-bit binary/decimal floating
+       point types.
+       (reg_offset_addressing_ok_p): If we are on a power7 or later, use
+       LFIWZX and STFIWX to load/store 32-bit decimal types, and don't
+       create the buffer on the stack to overcome not having a 32-bit
+       load and store.
+       (rs6000_emit_move): Likewise.
+       (rs6000_secondary_memory_needed_rtx): Likewise.
+       (rs6000_alloc_sdmode_stack_slot): Likewise.
+       (rs6000_preferred_reload_class): On VSX, we can create SFmode 0.0f
+       via xxlxor, just like DFmode 0.0.
+
+       * config/rs6000/rs6000.h (TARGET_NO_SDMODE_STACK): New macro,
+       define as 1 if we are running on a power7 or newer.
+       (enum r6000_reg_class_enum): Add new constraints.
+
+       * config/rs6000/dfp.md (movsd): Delete, combine with binary
+       floating point moves in rs6000.md.  Combine power6x (mfpgpr) moves
+       with other moves by using conditional constraits (wg).  Use LFIWZX
+       and STFIWX for loading SDmode on power7.  Use xxlxor to create
+       0.0f.
+       (movsd splitter): Likewise.
+       (movsd_hardfloat): Likewise.
+       (movsd_softfloat): Likewise.
+
+       * config/rs6000/rs6000.md (FMOVE32): New iterators to combine
+       binary and decimal floating point moves.
+       (fmove_ok): New attributes to combine binary and decimal floating
+       point moves, and to combine power6x (mfpgpr) moves along normal
+       floating moves.
+       (real_value_to_target): Likewise.
+       (f32_lr): Likewise.
+       (f32_lm): Likewise.
+       (f32_li): Likewise.
+       (f32_sr): Likewise.
+       (f32_sm): Likewise.
+       (f32_si): Likewise.
+       (movsf): Combine binary and decimal floating point moves.  Combine
+       power6x (mfpgpr) moves with other moves by using conditional
+       constraits (wg).  Use LFIWZX and STFIWX for loading SDmode on
+       power7.
+       (mov<mode> for SFmode/SDmode); Likewise.
+       (SFmode/SDmode splitters): Likewise.
+       (movsf_hardfloat): Likewise.
+       (mov<mode>_hardfloat for SFmode/SDmode): Likewise.
+       (movsf_softfloat): Likewise.
+       (mov<mode>_softfloat for SFmode/SDmode): Likewise.
+
+       * doc/md.texi (PowerPC and IBM RS6000 constraints): Document wl,
+       wx and wz constraints.
+
+       * config/rs6000/constraints.md (wg constraint): New constraint to
+       return FLOAT_REGS if -mmfpgpr (power6x) was used.
+
+       * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wg
+       constraint.
+
+       * config/rs6000/rs6000.c (rs6000_debug_reg_global): If
+       -mdebug=reg, print wg, wl, wx, and wz constraints.
+       (rs6000_init_hard_regno_mode_ok): Initialize new constraints.
+       Initialize the reload functions for 64-bit binary/decimal floating
+       point types.
+       (reg_offset_addressing_ok_p): If we are on a power7 or later, use
+       LFIWZX and STFIWX to load/store 32-bit decimal types, and don't
+       create the buffer on the stack to overcome not having a 32-bit
+       load and store.
+       (rs6000_emit_move): Likewise.
+       (rs6000_secondary_memory_needed_rtx): Likewise.
+       (rs6000_alloc_sdmode_stack_slot): Likewise.
+       (rs6000_preferred_reload_class): On VSX, we can create SFmode 0.0f
+       via xxlxor, just like DFmode 0.0.
+
+
+       * config/rs6000/dfp.md (movdd): Delete, combine with binary
+       floating point moves in rs6000.md.  Combine power6x (mfpgpr) moves
+       with other moves by using conditional constraits (wg).  Use LFIWZX
+       and STFIWX for loading SDmode on power7.
+       (movdd splitters): Likewise.
+       (movdd_hardfloat32): Likewise.
+       (movdd_softfloat32): Likewise.
+       (movdd_hardfloat64_mfpgpr): Likewise.
+       (movdd_hardfloat64): Likewise.
+       (movdd_softfloat64): Likewise.
+
+       * config/rs6000/rs6000.md (FMOVE64): New iterators to combine
+       64-bit binary and decimal floating point moves.
+       (FMOVE64X): Likewise.
+       (movdf): Combine 64-bit binary and decimal floating point moves.
+       Combine power6x (mfpgpr) moves with other moves by using
+       conditional constraits (wg).
+       (mov<mode> for DFmode/DDmode): Likewise.
+       (DFmode/DDmode splitters): Likewise.
+       (movdf_hardfloat32): Likewise.
+       (mov<mode>_hardfloat32 for DFmode/DDmode): Likewise.
+       (movdf_softfloat32): Likewise.
+       (movdf_hardfloat64_mfpgpr): Likewise.
+       (movdf_hardfloat64): Likewise.
+       (mov<mode>_hardfloat64 for DFmode/DDmode): Likewise.
+       (movdf_softfloat64): Likewise.
+       (mov<mode>_softfloat64 for DFmode/DDmode): Likewise.
+       (reload_<mode>_load): Move to later in the file so they aren't in
+       the middle of the floating point move insns.
+       (reload_<mode>_store): Likewise.
+
+       * doc/md.texi (PowerPC and IBM RS6000 constraints): Document wg
+       constraint.
+
+       * config/rs6000/rs6000.c (rs6000_debug_reg_global): Print out wg
+       constraint if -mdebug=reg.
+       (rs6000_initi_hard_regno_mode_ok): Enable wg constraint if
+       -mfpgpr.  Enable using dd reload support if needed.
+
+       * config/rs6000/dfp.md (movtd): Delete, combine with 128-bit
+       binary and decimal floating point moves in rs6000.md.
+       (movtd_internal): Likewise.
+
+       * config/rs6000/rs6000.md (FMOVE128): Combine 128-bit binary and
+       decimal floating point moves.
+       (movtf): Likewise.
+       (movtf_internal): Likewise.
+       (mov<mode>_internal, TDmode/TFmode): Likewise.
+       (movtf_softfloat): Likewise.
+       (mov<mode>_softfloat, TDmode/TFmode): Likewise.
+
+       * config/rs6000/rs6000.md (movdi_mfpgpr): Delete, combine with
+       movdi_internal64, using wg constraint for move direct operations.
+       (movdi_internal64): Likewise.
+
+       * config/rs6000/rs6000.c (rs6000_debug_reg_global): Print
+       MODES_TIEABLE_P for selected modes.  Print the numerical value of
+       the various virtual registers. Use GPR/FPR first/last values,
+       instead of hard coding the register numbers.  Print which modes
+       have reload functions registered.
+       (rs6000_option_override_internal): If -mdebug=reg, trace the
+       options settings before/after setting cpu, target and subtarget
+       settings.
+       (rs6000_secondary_reload_trace): Improve the RTL dump for
+       -mdebug=addr and for secondary reload failures in
+       rs6000_secondary_reload_inner.
+       (rs6000_secondary_reload_fail): Likewise.
+       (rs6000_secondary_reload_inner): Likewise.
+
+       * config/rs6000/rs6000.md (FIRST_GPR_REGNO): Add convenience
+       macros for first/last GPR and FPR registers.
+       (LAST_GPR_REGNO): Likewise.
+       (FIRST_FPR_REGNO): Likewise.
+       (LAST_FPR_REGNO): Likewise.
+
+       * config/rs6000/vector.md (mul<mode>3): Use the combined macro
+       VECTOR_UNIT_ALTIVEC_OR_VSX_P instead of separate calls to
+       VECTOR_UNIT_ALTIVEC_P and VECTOR_UNIT_VSX_P.
+       (vcond<mode><mode>): Likewise.
+       (vcondu<mode><mode>): Likewise.
+       (vector_gtu<mode>): Likewise.
+       (vector_gte<mode>): Likewise.
+       (xor<mode>3): Don't allow logical operations on TImode in 32-bit
+       to prevent the compiler from converting DImode operations to
+       TImode.
+       (ior<mode>3): Likewise.
+       (and<mode>3): Likewise.
+       (one_cmpl<mode>2): Likewise.
+       (nor<mode>3): Likewise.
+       (andc<mode>3): Likewise.
+
+       * config/rs6000/constraints.md (wt constraint): New constraint
+       that returns VSX_REGS if TImode is allowed in VSX registers.
+
+       * config/rs6000/predicates.md (easy_fp_constant): 0.0f is an easy
+       constant under VSX.
+
+       * config/rs6000/rs6000-modes.def (PTImode): Define, PTImode is
+       similar to TImode, but it is restricted to being in the GPRs.
+
+       * config/rs6000/rs6000.opt (-mvsx-timode): New switch to allow
+       TImode to occupy a single VSX register.
+
+       * config/rs6000/rs6000-cpus.def (ISA_2_6_MASKS_SERVER): Default to
+       -mvsx-timode for power7/power8.
+       (power7 cpu): Likewise.
+       (power8 cpu): Likewise.
+
+       * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Make
+       sure that TFmode/TDmode take up two registers if they are ever
+       allowed in the upper VSX registers.
+       (rs6000_hard_regno_mode_ok): If -mvsx-timode, allow TImode in VSX
+       registers.
+       (rs6000_init_hard_regno_mode_ok): Likewise.
+       (rs6000_debug_reg_global): Add debugging for PTImode and wt
+       constraint.  Print if LRA is turned on.
+       (rs6000_option_override_internal): Give an error if -mvsx-timode
+       and VSX is not enabled.
+       (invalid_e500_subreg): Handle PTImode, restricting it to GPRs.  If
+       -mvsx-timode, restrict TImode to reg+reg addressing, and PTImode
+       to reg+offset addressing.  Use PTImode when checking offset
+       addresses for validity.
+       (reg_offset_addressing_ok_p): Likewise.
+       (rs6000_legitimate_offset_address_p): Likewise.
+       (rs6000_legitimize_address): Likewise.
+       (rs6000_legitimize_reload_address): Likewise.
+       (rs6000_legitimate_address_p): Likewise.
+       (rs6000_eliminate_indexed_memrefs): Likewise.
+       (rs6000_emit_move): Likewise.
+       (rs6000_secondary_reload): Likewise.
+       (rs6000_secondary_reload_inner): Handle PTImode.  Allow 64-bit
+       reloads to fpr registers to continue to use reg+offset addressing,
+       but 64-bit reloads to altivec registers need reg+reg addressing.
+       Drop test for PRE_MODIFY, since VSX loads/stores no longer support
+       it.  Treat LO_SUM like a PLUS operation.
+       (rs6000_secondary_reload_class): If type is 64-bit, prefer to use
+       FLOAT_REGS instead of VSX_RGS to allow use of reg+offset
+       addressing.
+       (rs6000_cannot_change_mode_class): Do not allow TImode in VSX
+       registers to share a register with a smaller sized type, since VSX
+       puts scalars in the upper 64-bits.
+       (print_operand): Add support for PTImode.
+       (rs6000_register_move_cost): Use VECTOR_MEM_VSX_P instead of
+       VECTOR_UNIT_VSX_P to catch types that can be loaded in VSX
+       registers, but don't have arithmetic support.
+       (rs6000_memory_move_cost): Add test for VSX.
+       (rs6000_opt_masks): Add -mvsx-timode.
+
+       * config/rs6000/vsx.md (VSm): Change to use 64-bit aligned moves
+       for TImode.
+       (VSs): Likewise.
+       (VSr): Use wt constraint for TImode.
+       (VSv): Drop TImode support.
+       (vsx_movti): Delete, replace with versions for 32-bit and 64-bit.
+       (vsx_movti_64bit): Likewise.
+       (vsx_movti_32bit): Likewise.
+       (vec_store_<mode>): Use VSX iterator instead of vector iterator.
+       (vsx_and<mode>3): Delete use of '?' constraint on inputs, just put
+       one '?' on the appropriate output constraint.  Do not allow TImode
+       logical operations on 32-bit systems.
+       (vsx_ior<mode>3): Likewise.
+       (vsx_xor<mode>3): Likewise.
+       (vsx_one_cmpl<mode>2): Likewise.
+       (vsx_nor<mode>3): Likewise.
+       (vsx_andc<mode>3): Likewise.
+       (vsx_concat_<mode>): Likewise.
+       (vsx_xxpermdi_<mode>): Fix thinko for non V2DF/V2DI modes.
+
+       * config/rs6000/rs6000.h (MASK_VSX_TIMODE): Map from
+       OPTION_MASK_VSX_TIMODE.
+       (enum rs6000_reg_class_enum): Add RS6000_CONSTRAINT_wt.
+       (STACK_SAVEAREA_MODE): Use PTImode instead of TImode.
+
+       * config/rs6000/rs6000.md (INT mode attribute): Add PTImode.
+       (TI2 iterator): New iterator for TImode, PTImode.
+       (wd mode attribute): Add values for vector types.
+       (movti_string): Replace TI move operations with operations for
+       TImode and PTImode.  Add support for TImode being allowed in VSX
+       registers.
+       (mov<mode>_string, TImode/PTImode): Likewise.
+       (movti_ppc64): Likewise.
+       (mov<mode>_ppc64, TImode/PTImode): Likewise.
+       (TI mode splitters): Likewise.
+
+       * doc/md.texi (PowerPC and IBM RS6000 constraints): Document wt
+       constraint.
+
 2013-03-20  Marc Glisse  <marc.glisse@inria.fr>
 
        PR tree-optimization/56355
index ccb61edce45b308dd5988333cfcd1aa103353d07..463d69c6ba4647ffd071e650aa0bec8d3b09456a 100644 (file)
 (define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
   "@internal")
 
+;; TImode in VSX registers
+(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
+  "@internal")
+
 ;; any VSX register
 (define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
   "@internal")
 
+;; Register constraints to simplify move patterns
+(define_register_constraint "wg" "rs6000_constraints[RS6000_CONSTRAINT_wg]"
+  "Floating point register if -mmfpgpr is used, or NO_REGS.")
+
+(define_register_constraint "wl" "rs6000_constraints[RS6000_CONSTRAINT_wl]"
+  "Floating point register if the LFIWAX instruction is enabled or NO_REGS.")
+
+(define_register_constraint "wx" "rs6000_constraints[RS6000_CONSTRAINT_wx]"
+  "Floating point register if the STFIWX instruction is enabled or NO_REGS.")
+
+(define_register_constraint "wz" "rs6000_constraints[RS6000_CONSTRAINT_wz]"
+  "Floating point register if the LFIWZX instruction is enabled or NO_REGS.")
+
 ;; Altivec style load/store that ignores the bottom bits of the address
 (define_memory_constraint "wZ"
   "Indexed or indirect memory operand, ignoring the bottom 4 bits"
index f73e115e342352a129885324205d7843e3560467..052ac482e0f487b21c0f89df430e3672cefac84a 100644 (file)
   ])
 
 
-(define_expand "movsd"
-  [(set (match_operand:SD 0 "nonimmediate_operand" "")
-       (match_operand:SD 1 "any_operand" ""))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS"
-  "{ rs6000_emit_move (operands[0], operands[1], SDmode); DONE; }")
-
-(define_split
-  [(set (match_operand:SD 0 "gpc_reg_operand" "")
-       (match_operand:SD 1 "const_double_operand" ""))]
-  "reload_completed
-   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
-       || (GET_CODE (operands[0]) == SUBREG
-          && GET_CODE (SUBREG_REG (operands[0])) == REG
-          && REGNO (SUBREG_REG (operands[0])) <= 31))"
-  [(set (match_dup 2) (match_dup 3))]
-  "
-{
-  long l;
-  REAL_VALUE_TYPE rv;
-
-  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-  REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
-
-  if (! TARGET_POWERPC64)
-    operands[2] = operand_subword (operands[0], 0, 0, SDmode);
-  else
-    operands[2] = gen_lowpart (SImode, operands[0]);
-
-  operands[3] = gen_int_mode (l, SImode);
-}")
-
-(define_insn "movsd_hardfloat"
-  [(set (match_operand:SD 0 "nonimmediate_operand" "=r,r,m,f,*c*l,!r,*h,!r,!r")
-       (match_operand:SD 1 "input_operand"        "r,m,r,f,r,h,0,G,Fn"))]
-  "(gpc_reg_operand (operands[0], SDmode)
-   || gpc_reg_operand (operands[1], SDmode))
-   && (TARGET_HARD_FLOAT && TARGET_FPRS)"
-  "@
-   mr %0,%1
-   lwz%U1%X1 %0,%1
-   stw%U0%X0 %1,%0
-   fmr %0,%1
-   mt%0 %1
-   mf%1 %0
-   nop
-   #
-   #"
-  [(set_attr "type" "*,load,store,fp,mtjmpr,mfjmpr,*,*,*")
-   (set_attr "length" "4,4,4,4,4,4,4,4,8")])
-
-(define_insn "movsd_softfloat"
-  [(set (match_operand:SD 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,r,*h")
-       (match_operand:SD 1 "input_operand" "r,r,h,m,r,I,L,R,G,Fn,0"))]
-  "(gpc_reg_operand (operands[0], SDmode)
-   || gpc_reg_operand (operands[1], SDmode))
-   && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
-  "@
-   mr %0,%1
-   mt%0 %1
-   mf%1 %0
-   lwz%U1%X1 %0,%1
-   stw%U0%X0 %1,%0
-   li %0,%1
-   lis %0,%v1
-   la %0,%a1
-   #
-   #
-   nop"
-  [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*,*")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,4")])
-
 (define_insn "movsd_store"
   [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
        (unspec:DD [(match_operand:SD 1 "input_operand" "d")]
    || gpc_reg_operand (operands[1], SDmode))
    && TARGET_HARD_FLOAT && TARGET_FPRS"
   "stfd%U0%X0 %1,%0"
-  [(set_attr "type" "fpstore")
+  [(set (attr "type")
+      (if_then_else
+       (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+       (const_string "fpstore_ux")
+       (if_then_else
+         (match_test "update_address_mem (operands[0], VOIDmode)")
+         (const_string "fpstore_u")
+         (const_string "fpstore"))))
    (set_attr "length" "4")])
 
 (define_insn "movsd_load"
    || gpc_reg_operand (operands[1], DDmode))
    && TARGET_HARD_FLOAT && TARGET_FPRS"
   "lfd%U1%X1 %0,%1"
-  [(set_attr "type" "fpload")
+  [(set (attr "type")
+      (if_then_else
+       (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+       (const_string "fpload_ux")
+       (if_then_else
+         (match_test "update_address_mem (operands[1], VOIDmode)")
+         (const_string "fpload_u")
+         (const_string "fpload"))))
    (set_attr "length" "4")])
 
 ;; Hardware support for decimal floating point operations.
   "fnabs %0,%1"
   [(set_attr "type" "fp")])
 
-(define_expand "movdd"
-  [(set (match_operand:DD 0 "nonimmediate_operand" "")
-       (match_operand:DD 1 "any_operand" ""))]
-  ""
-  "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }")
-
-(define_split
-  [(set (match_operand:DD 0 "gpc_reg_operand" "")
-       (match_operand:DD 1 "const_int_operand" ""))]
-  "! TARGET_POWERPC64 && reload_completed
-   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
-       || (GET_CODE (operands[0]) == SUBREG
-          && GET_CODE (SUBREG_REG (operands[0])) == REG
-          && REGNO (SUBREG_REG (operands[0])) <= 31))"
-  [(set (match_dup 2) (match_dup 4))
-   (set (match_dup 3) (match_dup 1))]
-  "
-{
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  HOST_WIDE_INT value = INTVAL (operands[1]);
-
-  operands[2] = operand_subword (operands[0], endian, 0, DDmode);
-  operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
-#if HOST_BITS_PER_WIDE_INT == 32
-  operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
-#else
-  operands[4] = GEN_INT (value >> 32);
-  operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
-#endif
-}")
-
-(define_split
-  [(set (match_operand:DD 0 "gpc_reg_operand" "")
-       (match_operand:DD 1 "const_double_operand" ""))]
-  "! TARGET_POWERPC64 && reload_completed
-   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
-       || (GET_CODE (operands[0]) == SUBREG
-          && GET_CODE (SUBREG_REG (operands[0])) == REG
-          && REGNO (SUBREG_REG (operands[0])) <= 31))"
-  [(set (match_dup 2) (match_dup 4))
-   (set (match_dup 3) (match_dup 5))]
-  "
-{
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  long l[2];
-  REAL_VALUE_TYPE rv;
-
-  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-  REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
-
-  operands[2] = operand_subword (operands[0], endian, 0, DDmode);
-  operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode);
-  operands[4] = gen_int_mode (l[endian], SImode);
-  operands[5] = gen_int_mode (l[1 - endian], SImode);
-}")
-
-(define_split
-  [(set (match_operand:DD 0 "gpc_reg_operand" "")
-       (match_operand:DD 1 "const_double_operand" ""))]
-  "TARGET_POWERPC64 && reload_completed
-   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
-       || (GET_CODE (operands[0]) == SUBREG
-          && GET_CODE (SUBREG_REG (operands[0])) == REG
-          && REGNO (SUBREG_REG (operands[0])) <= 31))"
-  [(set (match_dup 2) (match_dup 3))]
-  "
-{
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  long l[2];
-  REAL_VALUE_TYPE rv;
-#if HOST_BITS_PER_WIDE_INT >= 64
-  HOST_WIDE_INT val;
-#endif
-
-  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-  REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l);
-
-  operands[2] = gen_lowpart (DImode, operands[0]);
-  /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN.  */
-#if HOST_BITS_PER_WIDE_INT >= 64
-  val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32
-        | ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
-
-  operands[3] = gen_int_mode (val, DImode);
-#else
-  operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
-#endif
-}")
-
-;; Don't have reload use general registers to load a constant.  First,
-;; it might not work if the output operand is the equivalent of
-;; a non-offsettable memref, but also it is less efficient than loading
-;; the constant into an FP register, since it will probably be used there.
-;; The "??" is a kludge until we can figure out a more reasonable way
-;; of handling these non-offsettable values.
-(define_insn "*movdd_hardfloat32"
-  [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r")
-       (match_operand:DD 1 "input_operand" "r,m,r,d,m,d,G,H,F"))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
-   && (gpc_reg_operand (operands[0], DDmode)
-       || gpc_reg_operand (operands[1], DDmode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      gcc_unreachable ();
-    case 0:
-    case 1:
-    case 2:
-      return \"#\";
-    case 3:
-      return \"fmr %0,%1\";
-    case 4:
-      return \"lfd%U1%X1 %0,%1\";
-    case 5:
-      return \"stfd%U0%X0 %1,%0\";
-    case 6:
-    case 7:
-    case 8:
-      return \"#\";
-    }
-}"
-  [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
-   (set_attr "length" "8,16,16,4,4,4,8,12,16")])
-
-(define_insn "*movdd_softfloat32"
-  [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r")
-       (match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))]
-  "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
-   && (gpc_reg_operand (operands[0], DDmode)
-       || gpc_reg_operand (operands[1], DDmode))"
-  "#"
-  [(set_attr "type" "two,load,store,*,*,*")
-   (set_attr "length" "8,8,8,8,12,16")])
-
-; ld/std require word-aligned displacements -> 'Y' constraint.
-; List Y->r and r->Y before r->r for reload.
-(define_insn "*movdd_hardfloat64_mfpgpr"
-  [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d")
-       (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))]
-  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
-   && (gpc_reg_operand (operands[0], DDmode)
-       || gpc_reg_operand (operands[1], DDmode))"
-  "@
-   std%U0%X0 %1,%0
-   ld%U1%X1 %0,%1
-   mr %0,%1
-   fmr %0,%1
-   lfd%U1%X1 %0,%1
-   stfd%U0%X0 %1,%0
-   mt%0 %1
-   mf%1 %0
-   nop
-   #
-   #
-   #
-   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")])
-
-; ld/std require word-aligned displacements -> 'Y' constraint.
-; List Y->r and r->Y before r->r for reload.
-(define_insn "*movdd_hardfloat64"
-  [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r")
-       (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))]
-  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
-   && (gpc_reg_operand (operands[0], DDmode)
-       || gpc_reg_operand (operands[1], DDmode))"
-  "@
-   std%U0%X0 %1,%0
-   ld%U1%X1 %0,%1
-   mr %0,%1
-   fmr %0,%1
-   lfd%U1%X1 %0,%1
-   stfd%U0%X0 %1,%0
-   mt%0 %1
-   mf%1 %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")])
-
-(define_insn "*movdd_softfloat64"
-  [(set (match_operand:DD 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
-       (match_operand:DD 1 "input_operand" "Y,r,r,r,h,G,H,F,0"))]
-  "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
-   && (gpc_reg_operand (operands[0], DDmode)
-       || gpc_reg_operand (operands[1], DDmode))"
-  "@
-   ld%U1%X1 %0,%1
-   std%U0%X0 %1,%0
-   mr %0,%1
-   mt%0 %1
-   mf%1 %0
-   #
-   #
-   #
-   nop"
-  [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*")
-   (set_attr "length" "4,4,4,4,4,8,12,16,4")])
-
 (define_expand "negtd2"
   [(set (match_operand:TD 0 "gpc_reg_operand" "")
        (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
   "fnabs %0,%1"
   [(set_attr "type" "fp")])
 
-(define_expand "movtd"
-  [(set (match_operand:TD 0 "general_operand" "")
-       (match_operand:TD 1 "any_operand" ""))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS"
-  "{ rs6000_emit_move (operands[0], operands[1], TDmode); DONE; }")
-
-; It's important to list the Y->r and r->Y moves before r->r because
-; otherwise reload, given m->r, will try to pick r->r and reload it,
-; which doesn't make progress.
-(define_insn_and_split "*movtd_internal"
-  [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
-       (match_operand:TD 1 "input_operand"         "d,m,d,r,YGHF,r"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS
-   && (gpc_reg_operand (operands[0], TDmode)
-       || gpc_reg_operand (operands[1], TDmode))"
-  "#"
-  "&& reload_completed"
-  [(pc)]
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
-  [(set_attr "length" "8,8,8,20,20,16")])
-
 ;; Hardware support for decimal floating point operations.
 
 (define_insn "extendddtd2"
index 868ba567976a6353d4f4450a6acf14c3447a02df..8112f26fe19883903da2c9303350650fab82ec8d 100644 (file)
       && mode != DImode)
     return 1;
 
+  /* The constant 0.0 is easy under VSX.  */
+  if ((mode == SFmode || mode == DFmode || mode == SDmode || mode == DDmode)
+      && VECTOR_UNIT_VSX_P (DFmode) && op == CONST0_RTX (mode))
+    return 1;
+
   if (DECIMAL_FLOAT_MODE_P (mode))
     return 0;
 
                        && REG_P (XEXP (op, 1)))")
        (match_operand 0 "address_operand")))
 
+;; Return 1 if the operand is an index-form address.
+(define_special_predicate "indexed_address"
+  (match_test "(GET_CODE (op) == PLUS
+               && REG_P (XEXP (op, 0))
+               && REG_P (XEXP (op, 1)))"))
+
+;; Return 1 if the operand is a MEM with an update-form address. This may
+;; also include update-indexed form.
+(define_special_predicate "update_address_mem"
+  (match_test "(MEM_P (op)
+               && (GET_CODE (XEXP (op, 0)) == PRE_INC
+                   || GET_CODE (XEXP (op, 0)) == PRE_DEC
+                   || GET_CODE (XEXP (op, 0)) == PRE_MODIFY))"))
+
+;; Return 1 if the operand is a MEM with an update-indexed-form address. Note
+;; that PRE_INC/PRE_DEC will always be non-indexed (i.e. non X-form) since the
+;; increment is based on the mode size and will therefor always be a const.
+(define_special_predicate "update_indexed_address_mem"
+  (match_test "(MEM_P (op)
+               && GET_CODE (XEXP (op, 0)) == PRE_MODIFY
+               && indexed_address (XEXP (XEXP (op, 0), 1), mode))"))
+
 ;; Used for the destination of the fix_truncdfsi2 expander.
 ;; If stfiwx will be used, the result goes to memory; otherwise,
 ;; we're going to emit a store and a load of a subreg, so the dest is a
index 3f17c6f2395f3e6acde547bb75d4a7922eb4bc22..0564018b3f01ed85df818a8eb5eb3834c4c96503 100644 (file)
@@ -42,7 +42,8 @@
 #define ISA_2_6_MASKS_SERVER   (ISA_2_5_MASKS_SERVER                   \
                                 | OPTION_MASK_POPCNTD                  \
                                 | OPTION_MASK_ALTIVEC                  \
-                                | OPTION_MASK_VSX)
+                                | OPTION_MASK_VSX                      \
+                                | OPTION_MASK_VSX_TIMODE)
 
 #define POWERPC_7400_MASK      (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC)
 
@@ -76,7 +77,8 @@
                                 | OPTION_MASK_RECIP_PRECISION          \
                                 | OPTION_MASK_SOFT_FLOAT               \
                                 | OPTION_MASK_STRICT_ALIGN_OPTIONAL    \
-                                | OPTION_MASK_VSX)
+                                | OPTION_MASK_VSX                      \
+                                | OPTION_MASK_VSX_TIMODE)
 
 #endif
 
@@ -165,11 +167,11 @@ RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
 RS6000_CPU ("power7", PROCESSOR_POWER7,   /* Don't add MASK_ISEL by default */
            POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
            | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
-           | MASK_VSX | MASK_RECIP_PRECISION)
+           | MASK_VSX | MASK_RECIP_PRECISION | MASK_VSX_TIMODE)
 RS6000_CPU ("power8", PROCESSOR_POWER7,   /* Don't add MASK_ISEL by default */
            POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
            | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
-           | MASK_VSX | MASK_RECIP_PRECISION)
+           | MASK_VSX | MASK_RECIP_PRECISION | MASK_VSX_TIMODE)
 RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
 RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
 RS6000_CPU ("rs64", PROCESSOR_RS64A, MASK_PPC_GFXOPT | MASK_POWERPC64)
index bc18f8a168c245b2f54b3130d3f0879e6f597204..54548be703858dd326febba1ac764127aea11e1c 100644 (file)
@@ -41,3 +41,6 @@ VECTOR_MODE (INT, DI, 1);
 VECTOR_MODES (FLOAT, 8);      /*             V4HF V2SF */
 VECTOR_MODES (FLOAT, 16);     /*       V8HF  V4SF V2DF */
 VECTOR_MODES (FLOAT, 32);     /*       V16HF V8SF V4DF */
+
+/* Replacement for TImode that only is allowed in GPRs.  */
+PARTIAL_INT_MODE (TI);
index fbf57be44a3474f683ed14505202068c8773d3d1..921ff4b04161d5d6b6021d1801436eaa4a9b78ed 100644 (file)
@@ -1516,8 +1516,9 @@ rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
 {
   unsigned HOST_WIDE_INT reg_size;
 
+  /* TF/TD modes are special in that they always take 2 registers.  */
   if (FP_REGNO_P (regno))
-    reg_size = (VECTOR_MEM_VSX_P (mode)
+    reg_size = ((VECTOR_MEM_VSX_P (mode) && mode != TDmode && mode != TFmode)
                ? UNITS_PER_VSX_WORD
                : UNITS_PER_FP_WORD);
 
@@ -1561,14 +1562,18 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
        return ALTIVEC_REGNO_P (last_regno);
     }
 
+  /* Allow TImode in all VSX registers if the user asked for it.  Note, PTImode
+     can only go in GPRs.  */
+  if (mode == TImode && TARGET_VSX_TIMODE && VSX_REGNO_P (regno))
+    return 1;
+
   /* 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 (last_regno);
 
   /* 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.  */
+     modes and DImode.  */
   if (FP_REGNO_P (regno))
     {
       if (SCALAR_FLOAT_MODE_P (mode)
@@ -1602,9 +1607,8 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
   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.  In the future, allow TImode in the
-     Altivec or VSX registers.  */
+  /* We cannot put non-VSX TImode or PTImode anywhere except general register
+     and it must be able to fit within the register set.  */
 
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
@@ -1693,6 +1697,7 @@ rs6000_debug_reg_global (void)
   static const char *const tf[2] = { "false", "true" };
   const char *nl = (const char *)0;
   int m;
+  size_t m1, m2, v;
   char costly_num[20];
   char nop_num[20];
   char flags_buffer[40];
@@ -1713,10 +1718,67 @@ rs6000_debug_reg_global (void)
     "other"
   };
 
-  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");
+  /* Modes we want tieable information on.  */
+  static const enum machine_mode print_tieable_modes[] = {
+    QImode,
+    HImode,
+    SImode,
+    DImode,
+    TImode,
+    PTImode,
+    SFmode,
+    DFmode,
+    TFmode,
+    SDmode,
+    DDmode,
+    TDmode,
+    V8QImode,
+    V4HImode,
+    V2SImode,
+    V16QImode,
+    V8HImode,
+    V4SImode,
+    V2DImode,
+    V32QImode,
+    V16HImode,
+    V8SImode,
+    V4DImode,
+    V2SFmode,
+    V4SFmode,
+    V2DFmode,
+    V8SFmode,
+    V4DFmode,
+    CCmode,
+    CCUNSmode,
+    CCEQmode,
+  };
+
+  /* Virtual regs we are interested in.  */
+  const static struct {
+    int regno;                 /* register number.  */
+    const char *name;          /* register name.  */
+  } virtual_regs[] = {
+    { STACK_POINTER_REGNUM,                    "stack pointer:" },
+    { TOC_REGNUM,                              "toc:          " },
+    { STATIC_CHAIN_REGNUM,                     "static chain: " },
+    { RS6000_PIC_OFFSET_TABLE_REGNUM,          "pic offset:   " },
+    { HARD_FRAME_POINTER_REGNUM,               "hard frame:   " },
+    { ARG_POINTER_REGNUM,                      "arg pointer:  " },
+    { FRAME_POINTER_REGNUM,                    "frame pointer:" },
+    { FIRST_PSEUDO_REGISTER,                   "first pseudo: " },
+    { FIRST_VIRTUAL_REGISTER,                  "first virtual:" },
+    { VIRTUAL_INCOMING_ARGS_REGNUM,            "incoming_args:" },
+    { VIRTUAL_STACK_VARS_REGNUM,               "stack_vars:   " },
+    { VIRTUAL_STACK_DYNAMIC_REGNUM,            "stack_dynamic:" },
+    { VIRTUAL_OUTGOING_ARGS_REGNUM,            "outgoing_args:" },
+    { VIRTUAL_CFA_REGNUM,                      "cfa (frame):  " },
+    { VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM, "stack boundry:" },
+    { LAST_VIRTUAL_REGISTER,                   "last virtual: " },
+  };
+
+  fputs ("\nHard register information:\n", stderr);
+  rs6000_debug_reg_print (FIRST_GPR_REGNO, LAST_GPR_REGNO, "gr");
+  rs6000_debug_reg_print (FIRST_FPR_REGNO, LAST_FPR_REGNO, "fp");
   rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
                          LAST_ALTIVEC_REGNO,
                          "vs");
@@ -1729,6 +1791,10 @@ rs6000_debug_reg_global (void)
   rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a");
   rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f");
 
+  fputs ("\nVirtual/stack/frame registers:\n", stderr);
+  for (v = 0; v < ARRAY_SIZE (virtual_regs); v++)
+    fprintf (stderr, "%s regno = %3d\n", virtual_regs[v].name, virtual_regs[v].regno);
+
   fprintf (stderr,
           "\n"
           "d  reg_class = %s\n"
@@ -1737,28 +1803,74 @@ rs6000_debug_reg_global (void)
           "wa reg_class = %s\n"
           "wd reg_class = %s\n"
           "wf reg_class = %s\n"
-          "ws reg_class = %s\n\n",
+          "wg reg_class = %s\n"
+          "wl reg_class = %s\n"
+          "ws reg_class = %s\n"
+          "wt reg_class = %s\n"
+          "wx reg_class = %s\n"
+          "wz reg_class = %s\n"
+          "\n",
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_f]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_v]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wa]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]]);
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]],
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]],
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]],
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]]);
 
   for (m = 0; m < NUM_MACHINE_MODES; ++m)
-    if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
+    if (rs6000_vector_unit[m] || rs6000_vector_mem[m]
+       || (rs6000_vector_reload[m][0] != CODE_FOR_nothing)
+       || (rs6000_vector_reload[m][1] != CODE_FOR_nothing))
       {
        nl = "\n";
-       fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n",
+       fprintf (stderr,
+                "Vector mode: %-5s arithmetic: %-10s move: %-10s "
+                "reload-out: %c reload-in: %c\n",
                 GET_MODE_NAME (m),
                 rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
-                rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]);
+                rs6000_debug_vector_unit[ rs6000_vector_mem[m] ],
+                (rs6000_vector_reload[m][0] != CODE_FOR_nothing) ? 'y' : 'n',
+                (rs6000_vector_reload[m][1] != CODE_FOR_nothing) ? 'y' : 'n');
       }
 
   if (nl)
     fputs (nl, stderr);
 
+  for (m1 = 0; m1 < ARRAY_SIZE (print_tieable_modes); m1++)
+    {
+      enum machine_mode mode1 = print_tieable_modes[m1];
+      bool first_time = true;
+
+      nl = (const char *)0;
+      for (m2 = 0; m2 < ARRAY_SIZE (print_tieable_modes); m2++)
+       {
+         enum machine_mode mode2 = print_tieable_modes[m2];
+         if (mode1 != mode2 && MODES_TIEABLE_P (mode1, mode2))
+           {
+             if (first_time)
+               {
+                 fprintf (stderr, "Tieable modes %s:", GET_MODE_NAME (mode1));
+                 nl = "\n";
+                 first_time = false;
+               }
+
+             fprintf (stderr, " %s", GET_MODE_NAME (mode2));
+           }
+       }
+
+      if (!first_time)
+       fputs ("\n", stderr);
+    }
+
+  if (nl)
+    fputs (nl, stderr);
+
   if (rs6000_recip_control)
     {
       fprintf (stderr, "\nReciprocal mask = 0x%x\n", rs6000_recip_control);
@@ -1938,6 +2050,9 @@ rs6000_debug_reg_global (void)
   if (TARGET_LINK_STACK)
     fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
 
+  if (targetm.lra_p ())
+    fprintf (stderr, DEBUG_FMT_S, "lra", "true");
+
   fprintf (stderr, DEBUG_FMT_S, "plt-format",
           TARGET_SECURE_PLT ? "secure" : "bss");
   fprintf (stderr, DEBUG_FMT_S, "struct-return",
@@ -2083,6 +2198,13 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
       rs6000_vector_align[DFmode] = align64;
     }
 
+  /* Allow TImode in VSX register and set the VSX memory macros.  */
+  if (TARGET_VSX && TARGET_VSX_TIMODE)
+    {
+      rs6000_vector_mem[TImode] = VECTOR_VSX;
+      rs6000_vector_align[TImode] = align64;
+    }
+
   /* TODO add SPE and paired floating point vector support.  */
 
   /* Register class constraints for the constraints that depend on compile
@@ -2106,11 +2228,27 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
       rs6000_constraints[RS6000_CONSTRAINT_ws] = (TARGET_VSX_SCALAR_MEMORY
                                                  ? VSX_REGS
                                                  : FLOAT_REGS);
+      if (TARGET_VSX_TIMODE)
+       rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS;
     }
 
+  /* Add conditional constraints based on various options, to allow us to
+     collapse multiple insn patterns.  */
   if (TARGET_ALTIVEC)
     rs6000_constraints[RS6000_CONSTRAINT_v] = ALTIVEC_REGS;
 
+  if (TARGET_MFPGPR)
+    rs6000_constraints[RS6000_CONSTRAINT_wg] = FLOAT_REGS;
+
+  if (TARGET_LFIWAX)
+    rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS;
+
+  if (TARGET_STFIWX)
+    rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS;
+
+  if (TARGET_LFIWZX)
+    rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;
+
   /* Set up the reload helper functions.  */
   if (TARGET_VSX || TARGET_ALTIVEC)
     {
@@ -2132,6 +2270,13 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
            {
              rs6000_vector_reload[DFmode][0]  = CODE_FOR_reload_df_di_store;
              rs6000_vector_reload[DFmode][1]  = CODE_FOR_reload_df_di_load;
+             rs6000_vector_reload[DDmode][0]  = CODE_FOR_reload_dd_di_store;
+             rs6000_vector_reload[DDmode][1]  = CODE_FOR_reload_dd_di_load;
+           }
+         if (TARGET_VSX_TIMODE)
+           {
+             rs6000_vector_reload[TImode][0]  = CODE_FOR_reload_ti_di_store;
+             rs6000_vector_reload[TImode][1]  = CODE_FOR_reload_ti_di_load;
            }
        }
       else
@@ -2152,6 +2297,13 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
            {
              rs6000_vector_reload[DFmode][0]  = CODE_FOR_reload_df_si_store;
              rs6000_vector_reload[DFmode][1]  = CODE_FOR_reload_df_si_load;
+             rs6000_vector_reload[DDmode][0]  = CODE_FOR_reload_dd_si_store;
+             rs6000_vector_reload[DDmode][1]  = CODE_FOR_reload_dd_si_load;
+           }
+         if (TARGET_VSX_TIMODE)
+           {
+             rs6000_vector_reload[TImode][0]  = CODE_FOR_reload_ti_si_store;
+             rs6000_vector_reload[TImode][1]  = CODE_FOR_reload_ti_si_load;
            }
        }
     }
@@ -2641,6 +2793,9 @@ rs6000_option_override_internal (bool global_init_p)
        }
     }
 
+  if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
+    rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags);
+
   /* For the newer switches (vsx, dfp, etc.) set some of the older options,
      unless the user explicitly used the -mno-<option> to disable the code.  */
   if (TARGET_VSX)
@@ -2658,6 +2813,16 @@ rs6000_option_override_internal (bool global_init_p)
   else if (TARGET_ALTIVEC)
     rs6000_isa_flags |= (OPTION_MASK_PPC_GFXOPT & ~rs6000_isa_flags_explicit);
 
+  if (TARGET_VSX_TIMODE && !TARGET_VSX)
+    {
+      if (rs6000_isa_flags_explicit & OPTION_MASK_VSX_TIMODE)
+       error ("-mvsx-timode requires -mvsx");
+      rs6000_isa_flags &= ~OPTION_MASK_VSX_TIMODE;
+    }
+
+  if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
+    rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
+
   /* E500mc does "better" if we inline more aggressively.  Respect the
      user's opinion, though.  */
   if (rs6000_block_move_inline_limit == 0
@@ -2784,6 +2949,9 @@ rs6000_option_override_internal (bool global_init_p)
   if (flag_section_anchors)
     TARGET_NO_FP_IN_TOC = 1;
 
+  if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
+    rs6000_print_isa_options (stderr, 0, "before subtarget", rs6000_isa_flags);
+
 #ifdef SUBTARGET_OVERRIDE_OPTIONS
   SUBTARGET_OVERRIDE_OPTIONS;
 #endif
@@ -2794,6 +2962,9 @@ rs6000_option_override_internal (bool global_init_p)
   SUB3TARGET_OVERRIDE_OPTIONS;
 #endif
 
+  if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
+    rs6000_print_isa_options (stderr, 0, "after subtarget", rs6000_isa_flags);
+
   /* For the E500 family of cores, reset the single/double FP flags to let us
      check that they remain constant across attributes or pragmas.  Also,
      clear a possible request for string instructions, not supported and which
@@ -4932,7 +5103,7 @@ invalid_e500_subreg (rtx op, enum machine_mode mode)
         purpose.  */
       if (GET_CODE (op) == SUBREG
          && (mode == SImode || mode == DImode || mode == TImode
-             || mode == DDmode || mode == TDmode)
+             || mode == DDmode || mode == TDmode || mode == PTImode)
          && REG_P (SUBREG_REG (op))
          && (GET_MODE (SUBREG_REG (op)) == DFmode
              || GET_MODE (SUBREG_REG (op)) == TFmode))
@@ -4945,6 +5116,7 @@ invalid_e500_subreg (rtx op, enum machine_mode mode)
          && REG_P (SUBREG_REG (op))
          && (GET_MODE (SUBREG_REG (op)) == DImode
              || GET_MODE (SUBREG_REG (op)) == TImode
+             || GET_MODE (SUBREG_REG (op)) == PTImode
              || GET_MODE (SUBREG_REG (op)) == DDmode
              || GET_MODE (SUBREG_REG (op)) == TDmode))
        return true;
@@ -5164,7 +5336,11 @@ reg_offset_addressing_ok_p (enum machine_mode mode)
     case V4SImode:
     case V2DFmode:
     case V2DImode:
-      /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid.  */
+    case TImode:
+      /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid.  While
+        TImode is not a vector mode, if we want to use the VSX registers to
+        move it around, we need to restrict ourselves to reg+reg
+        addressing.  */
       if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
        return false;
       break;
@@ -5178,6 +5354,13 @@ reg_offset_addressing_ok_p (enum machine_mode mode)
         return false;
       break;
 
+    case SDmode:
+      /* If we can do direct load/stores of SDmode, restrict it to reg+reg
+        addressing for the LFIWZX and STFIWX instructions.  */
+      if (TARGET_NO_SDMODE_STACK)
+       return false;
+      break;
+
     default:
       break;
     }
@@ -5410,7 +5593,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
 
       /* If we are using VSX scalar loads, restrict ourselves to reg+reg
         addressing.  */
-      if (mode == DFmode && VECTOR_MEM_VSX_P (DFmode))
+      if (VECTOR_MEM_VSX_P (mode))
        return false;
 
       if (!worst_case)
@@ -5424,6 +5607,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
     case TFmode:
     case TDmode:
     case TImode:
+    case PTImode:
       if (TARGET_E500_DOUBLE)
        return (SPE_CONST_OFFSET_OK (offset)
                && SPE_CONST_OFFSET_OK (offset + 8));
@@ -5597,11 +5781,12 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
     case TFmode:
     case TDmode:
     case TImode:
+    case PTImode:
       /* As in legitimate_offset_address_p we do not assume
         worst-case.  The mode here is just a hint as to the registers
         used.  A TImode is usually in gprs, but may actually be in
         fprs.  Leave worst-case scenario for reload to handle via
-        insn constraints.  */
+        insn constraints.  PTImode is only GPRs.  */
       extra = 8;
       break;
     default:
@@ -6332,7 +6517,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
       && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
                                  || mode == DDmode || mode == TDmode
                                  || mode == DImode))
-      && VECTOR_MEM_NONE_P (mode))
+      && (!VECTOR_MODE_P (mode) || VECTOR_MEM_NONE_P (mode)))
     {
       HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
       HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
@@ -6363,7 +6548,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
 
   if (GET_CODE (x) == SYMBOL_REF
       && reg_offset_p
-      && VECTOR_MEM_NONE_P (mode)
+      && (!VECTOR_MODE_P (mode) || VECTOR_MEM_NONE_P (mode))
       && !SPE_VECTOR_MODE (mode)
 #if TARGET_MACHO
       && DEFAULT_ABI == ABI_DARWIN
@@ -6389,6 +6574,8 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
         mem is sufficiently aligned.  */
       && mode != TFmode
       && mode != TDmode
+      && (mode != TImode || !TARGET_VSX_TIMODE)
+      && mode != PTImode
       && (mode != DImode || TARGET_POWERPC64)
       && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
          || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
@@ -6510,10 +6697,12 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
   if (legitimate_indirect_address_p (x, reg_ok_strict))
     return 1;
   if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
-      && !VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
+      && !ALTIVEC_OR_VSX_VECTOR_MODE (mode)
       && !SPE_VECTOR_MODE (mode)
       && mode != TFmode
       && mode != TDmode
+      && mode != TImode
+      && mode != PTImode
       /* Restrict addressing for DI because of our SUBREG hackery.  */
       && !(TARGET_E500_DOUBLE
           && (mode == DFmode || mode == DDmode || mode == DImode))
@@ -6538,26 +6727,28 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
     return 1;
   if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict, false))
     return 1;
-  if (mode != TImode
-      && mode != TFmode
+  if (mode != TFmode
       && mode != TDmode
       && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
          || TARGET_POWERPC64
          || (mode != DFmode && mode != DDmode)
          || (TARGET_E500_DOUBLE && mode != DDmode))
       && (TARGET_POWERPC64 || mode != DImode)
+      && (mode != TImode || VECTOR_MEM_VSX_P (TImode))
+      && mode != PTImode
       && !avoiding_indexed_address_p (mode)
       && legitimate_indexed_address_p (x, reg_ok_strict))
     return 1;
   if (GET_CODE (x) == PRE_MODIFY
       && mode != TImode
+      && mode != PTImode
       && 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_OR_VSX_P (mode)
+      && !ALTIVEC_OR_VSX_VECTOR_MODE (mode)
       && !SPE_VECTOR_MODE (mode)
       /* Restrict addressing for DI because of our SUBREG hackery.  */
       && !(TARGET_E500_DOUBLE
@@ -7000,7 +7191,7 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
 }
 
 /* Helper for the following.  Get rid of [r+r] memory refs
-   in cases where it won't work (TImode, TFmode, TDmode).  */
+   in cases where it won't work (TImode, TFmode, TDmode, PTImode).  */
 
 static void
 rs6000_eliminate_indexed_memrefs (rtx operands[2])
@@ -7145,6 +7336,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
 
   if (reload_in_progress
       && mode == SDmode
+      && cfun->machine->sdmode_stack_slot != NULL_RTX
       && MEM_P (operands[0])
       && rtx_equal_p (operands[0], cfun->machine->sdmode_stack_slot)
       && REG_P (operands[1]))
@@ -7169,6 +7361,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
       && mode == SDmode
       && REG_P (operands[0])
       && MEM_P (operands[1])
+      && cfun->machine->sdmode_stack_slot != NULL_RTX
       && rtx_equal_p (operands[1], cfun->machine->sdmode_stack_slot))
     {
       if (FP_REGNO_P (REGNO (operands[0])))
@@ -7382,6 +7575,11 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
       break;
 
     case TImode:
+      if (!VECTOR_MEM_VSX_P (TImode))
+       rs6000_eliminate_indexed_memrefs (operands);
+      break;
+
+    case PTImode:
       rs6000_eliminate_indexed_memrefs (operands);
       break;
 
@@ -13624,7 +13822,7 @@ rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
   static bool eliminated = false;
   rtx ret;
 
-  if (mode != SDmode)
+  if (mode != SDmode || TARGET_NO_SDMODE_STACK)
     ret = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
   else
     {
@@ -13751,7 +13949,7 @@ rs6000_secondary_reload (bool in_p,
          if (rclass == GENERAL_REGS || rclass == BASE_REGS)
            {
              if (!legitimate_indirect_address_p (addr, false)
-                 && !rs6000_legitimate_offset_address_p (TImode, addr,
+                 && !rs6000_legitimate_offset_address_p (PTImode, addr,
                                                          false, true))
                {
                  sri->icode = icode;
@@ -13761,8 +13959,20 @@ rs6000_secondary_reload (bool in_p,
                                     + ((GET_CODE (addr) == AND) ? 1 : 0));
                }
            }
-         /* Loads to and stores from vector registers can only do reg+reg
-            addressing.  Altivec registers can also do (reg+reg)&(-16).  */
+         /* Allow scalar loads to/from the traditional floating point
+            registers, even if VSX memory is set.  */
+         else if ((rclass == FLOAT_REGS || rclass == NO_REGS)
+                  && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
+                  && (legitimate_indirect_address_p (addr, false)
+                      || legitimate_indirect_address_p (XEXP (addr, 0), false)
+                      || rs6000_legitimate_offset_address_p (mode, addr,
+                                                             false, true)))
+
+           ;
+         /* Loads to and stores from vector registers can only do reg+reg
+            addressing.  Altivec registers can also do (reg+reg)&(-16).  Allow
+            scalar modes loading up the traditional floating point registers
+            to use offset addresses.  */
          else if (rclass == VSX_REGS || rclass == ALTIVEC_REGS
                   || rclass == FLOAT_REGS || rclass == NO_REGS)
            {
@@ -13938,6 +14148,36 @@ rs6000_secondary_reload (bool in_p,
   return ret;
 }
 
+/* Better tracing for rs6000_secondary_reload_inner.  */
+
+static void
+rs6000_secondary_reload_trace (int line, rtx reg, rtx mem, rtx scratch,
+                              bool store_p)
+{
+  rtx set, clobber;
+
+  gcc_assert (reg != NULL_RTX && mem != NULL_RTX && scratch != NULL_RTX);
+
+  fprintf (stderr, "rs6000_secondary_reload_inner:%d, type = %s\n", line,
+          store_p ? "store" : "load");
+
+  if (store_p)
+    set = gen_rtx_SET (VOIDmode, mem, reg);
+  else
+    set = gen_rtx_SET (VOIDmode, reg, mem);
+
+  clobber = gen_rtx_CLOBBER (VOIDmode, scratch);
+  debug_rtx (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));
+}
+
+static void
+rs6000_secondary_reload_fail (int line, rtx reg, rtx mem, rtx scratch,
+                             bool store_p)
+{
+  rs6000_secondary_reload_trace (line, reg, mem, scratch, store_p);
+  gcc_unreachable ();
+}
+
 /* Fixup reload addresses for Altivec or VSX loads/stores to change SP+offset
    to SP+reg addressing.  */
 
@@ -13956,19 +14196,14 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
   rtx cc_clobber;
 
   if (TARGET_DEBUG_ADDR)
-    {
-      fprintf (stderr, "\nrs6000_secondary_reload_inner, type = %s\n",
-              store_p ? "store" : "load");
-      fprintf (stderr, "reg:\n");
-      debug_rtx (reg);
-      fprintf (stderr, "mem:\n");
-      debug_rtx (mem);
-      fprintf (stderr, "scratch:\n");
-      debug_rtx (scratch);
-    }
+    rs6000_secondary_reload_trace (__LINE__, reg, mem, scratch, store_p);
+
+  if (regno < 0 || regno >= FIRST_PSEUDO_REGISTER)
+    rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
+
+  if (GET_CODE (mem) != MEM)
+    rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
 
-  gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
-  gcc_assert (GET_CODE (mem) == MEM);
   rclass = REGNO_REG_CLASS (regno);
   addr = XEXP (mem, 0);
 
@@ -13987,19 +14222,24 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
       if (GET_CODE (addr) == PRE_MODIFY)
        {
          scratch_or_premodify = XEXP (addr, 0);
-         gcc_assert (REG_P (scratch_or_premodify));
-         gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+         if (!REG_P (scratch_or_premodify))
+           rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
+
+         if (GET_CODE (XEXP (addr, 1)) != PLUS)
+           rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
+
          addr = XEXP (addr, 1);
        }
 
       if (GET_CODE (addr) == PLUS
          && (and_op2 != NULL_RTX
-             || !rs6000_legitimate_offset_address_p (TImode, addr,
+             || !rs6000_legitimate_offset_address_p (PTImode, addr,
                                                      false, true)))
        {
          addr_op1 = XEXP (addr, 0);
          addr_op2 = XEXP (addr, 1);
-         gcc_assert (legitimate_indirect_address_p (addr_op1, false));
+         if (!legitimate_indirect_address_p (addr_op1, false))
+           rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
 
          if (!REG_P (addr_op2)
              && (GET_CODE (addr_op2) != CONST_INT
@@ -14027,7 +14267,7 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
          scratch_or_premodify = scratch;
        }
       else if (!legitimate_indirect_address_p (addr, false)
-              && !rs6000_legitimate_offset_address_p (TImode, addr,
+              && !rs6000_legitimate_offset_address_p (PTImode, addr,
                                                       false, true))
        {
          if (TARGET_DEBUG_ADDR)
@@ -14043,9 +14283,21 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
        }
       break;
 
-      /* Float/Altivec registers can only handle reg+reg addressing.  Move
-        other addresses into a scratch register.  */
+      /* Float registers can do offset+reg addressing for scalar types.  */
     case FLOAT_REGS:
+      if (legitimate_indirect_address_p (addr, false)  /* reg */
+         || legitimate_indexed_address_p (addr, false) /* reg+reg */
+         || ((GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
+             && and_op2 == NULL_RTX
+             && scratch_or_premodify == scratch
+             && rs6000_legitimate_offset_address_p (mode, addr, false, false)))
+       break;
+
+      /* If this isn't a legacy floating point load/store, fall through to the
+        VSX defaults.  */
+
+      /* VSX/Altivec registers can only handle reg+reg addressing.  Move other
+        addresses into a scratch register.  */
     case VSX_REGS:
     case ALTIVEC_REGS:
 
@@ -14065,36 +14317,38 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
       /* If we aren't using a VSX load, save the PRE_MODIFY register and use it
         as the address later.  */
       if (GET_CODE (addr) == PRE_MODIFY
-         && (!VECTOR_MEM_VSX_P (mode)
+         && ((ALTIVEC_OR_VSX_VECTOR_MODE (mode)
+              && (rclass != FLOAT_REGS
+                  || (GET_MODE_SIZE (mode) != 4 && GET_MODE_SIZE (mode) != 8)))
              || and_op2 != NULL_RTX
              || !legitimate_indexed_address_p (XEXP (addr, 1), false)))
        {
          scratch_or_premodify = XEXP (addr, 0);
-         gcc_assert (legitimate_indirect_address_p (scratch_or_premodify,
-                                                    false));
-         gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+         if (!legitimate_indirect_address_p (scratch_or_premodify, false))
+           rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
+
+         if (GET_CODE (XEXP (addr, 1)) != PLUS)
+           rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
+
          addr = XEXP (addr, 1);
        }
 
       if (legitimate_indirect_address_p (addr, false)  /* reg */
          || legitimate_indexed_address_p (addr, false) /* reg+reg */
-         || GET_CODE (addr) == PRE_MODIFY              /* VSX pre-modify */
          || (GET_CODE (addr) == AND                    /* Altivec memory */
+             && rclass == ALTIVEC_REGS
              && GET_CODE (XEXP (addr, 1)) == CONST_INT
              && INTVAL (XEXP (addr, 1)) == -16
-             && VECTOR_MEM_ALTIVEC_P (mode))
-         || (rclass == FLOAT_REGS                      /* legacy float mem */
-             && GET_MODE_SIZE (mode) == 8
-             && and_op2 == NULL_RTX
-             && scratch_or_premodify == scratch
-             && rs6000_legitimate_offset_address_p (mode, addr, false, false)))
+             && (legitimate_indirect_address_p (XEXP (addr, 0), false)
+                 || legitimate_indexed_address_p (XEXP (addr, 0), false))))
        ;
 
       else if (GET_CODE (addr) == PLUS)
        {
          addr_op1 = XEXP (addr, 0);
          addr_op2 = XEXP (addr, 1);
-         gcc_assert (REG_P (addr_op1));
+         if (!REG_P (addr_op1))
+           rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
 
          if (TARGET_DEBUG_ADDR)
            {
@@ -14113,7 +14367,8 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
        }
 
       else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
-              || GET_CODE (addr) == CONST_INT || REG_P (addr))
+              || GET_CODE (addr) == CONST_INT || GET_CODE (addr) == LO_SUM
+              || REG_P (addr))
        {
          if (TARGET_DEBUG_ADDR)
            {
@@ -14129,12 +14384,12 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
        }
 
       else
-       gcc_unreachable ();
+       rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
 
       break;
 
     default:
-      gcc_unreachable ();
+      rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
     }
 
   /* If the original address involved a pre-modify that we couldn't use the VSX
@@ -14246,8 +14501,10 @@ rs6000_secondary_reload_gpr (rtx reg, rtx mem, rtx scratch, bool store_p)
   return;
 }
 
-/* Allocate a 64-bit stack slot to be used for copying SDmode
-   values through if this function has any SDmode references.  */
+/* Allocate a 64-bit stack slot to be used for copying SDmode values through if
+   this function has any SDmode references.  If we are on a power7 or later, we
+   don't need the 64-bit stack slot since the LFIWZX and STIFWX instructions
+   can load/store the value.  */
 
 static void
 rs6000_alloc_sdmode_stack_slot (void)
@@ -14258,6 +14515,9 @@ rs6000_alloc_sdmode_stack_slot (void)
 
   gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
 
+  if (TARGET_NO_SDMODE_STACK)
+    return;
+
   FOR_EACH_BB (bb)
     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
       {
@@ -14318,8 +14578,7 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
 {
   enum machine_mode mode = GET_MODE (x);
 
-  if (VECTOR_UNIT_VSX_P (mode)
-      && x == CONST0_RTX (mode) && VSX_REG_CLASS_P (rclass))
+  if (TARGET_VSX && x == CONST0_RTX (mode) && VSX_REG_CLASS_P (rclass))
     return rclass;
 
   if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)
@@ -14494,11 +14753,17 @@ rs6000_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
     return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
 
   /* Memory, and FP/altivec registers can go into fp/altivec registers under
-     VSX.  */
+     VSX.  However, for scalar variables, use the traditional floating point
+     registers so that we can use offset+register addressing.  */
   if (TARGET_VSX
       && (regno == -1 || VSX_REGNO_P (regno))
       && VSX_REG_CLASS_P (rclass))
-    return NO_REGS;
+    {
+      if (GET_MODE_SIZE (mode) < 16)
+       return FLOAT_REGS;
+
+      return NO_REGS;
+    }
 
   /* Memory, and AltiVec registers can go into AltiVec registers.  */
   if ((regno == -1 || ALTIVEC_REGNO_P (regno))
@@ -14543,8 +14808,35 @@ rs6000_cannot_change_mode_class (enum machine_mode from,
   if (from_size != to_size)
     {
       enum reg_class xclass = (TARGET_VSX) ? VSX_REGS : FLOAT_REGS;
-      return ((from_size < 8 || to_size < 8 || TARGET_IEEEQUAD)
-             && reg_classes_intersect_p (xclass, rclass));
+
+      if (reg_classes_intersect_p (xclass, rclass))
+       {
+         unsigned to_nregs = hard_regno_nregs[FIRST_FPR_REGNO][to];
+         unsigned from_nregs = hard_regno_nregs[FIRST_FPR_REGNO][from];
+
+         /* Don't allow 64-bit types to overlap with 128-bit types that take a
+            single register under VSX because the scalar part of the register
+            is in the upper 64-bits, and not the lower 64-bits.  Types like
+            TFmode/TDmode that take 2 scalar register can overlap.  128-bit
+            IEEE floating point can't overlap, and neither can small
+            values.  */
+
+         if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode))
+           return true;
+
+         if (from_size < 8 || to_size < 8)
+           return true;
+
+         if (from_size == 8 && (8 * to_nregs) != to_size)
+           return true;
+
+         if (to_size == 8 && (8 * from_nregs) != from_size)
+           return true;
+
+         return false;
+       }
+      else
+       return false;
     }
 
   if (TARGET_E500_DOUBLE
@@ -14558,9 +14850,18 @@ rs6000_cannot_change_mode_class (enum machine_mode from,
   /* Since the VSX register set includes traditional floating point registers
      and altivec registers, just check for the size being different instead of
      trying to check whether the modes are vector modes.  Otherwise it won't
-     allow say DF and DI to change classes.  */
+     allow say DF and DI to change classes.  For types like TFmode and TDmode
+     that take 2 64-bit registers, rather than a single 128-bit register, don't
+     allow subregs of those types to other 128 bit types.  */
   if (TARGET_VSX && VSX_REG_CLASS_P (rclass))
-    return (from_size != 8 && from_size != 16);
+    {
+      unsigned num_regs = (from_size + 15) / 16;
+      if (hard_regno_nregs[FIRST_FPR_REGNO][to] > num_regs
+         || hard_regno_nregs[FIRST_FPR_REGNO][from] > num_regs)
+       return true;
+
+      return (from_size != 8 && from_size != 16);
+    }
 
   if (TARGET_ALTIVEC && rclass == ALTIVEC_REGS
       && (ALTIVEC_VECTOR_MODE (from) + ALTIVEC_VECTOR_MODE (to)) == 1)
@@ -15295,7 +15596,7 @@ print_operand (FILE *file, rtx x, int code)
       return;
 
     case 'Y':
-      /* Like 'L', for third word of TImode  */
+      /* Like 'L', for third word of TImode/PTImode  */
       if (REG_P (x))
        fputs (reg_names[REGNO (x) + 2], file);
       else if (MEM_P (x))
@@ -15345,7 +15646,7 @@ print_operand (FILE *file, rtx x, int code)
       return;
 
     case 'Z':
-      /* Like 'L', for last word of TImode.  */
+      /* Like 'L', for last word of TImode/PTImode.  */
       if (REG_P (x))
        fputs (reg_names[REGNO (x) + 3], file);
       else if (MEM_P (x))
@@ -15376,7 +15677,8 @@ print_operand (FILE *file, rtx x, int code)
        if ((TARGET_SPE || TARGET_E500_DOUBLE)
            && (GET_MODE_SIZE (GET_MODE (x)) == 8
                || GET_MODE (x) == TFmode
-               || GET_MODE (x) == TImode))
+               || GET_MODE (x) == TImode
+               || GET_MODE (x) == PTImode))
          {
            /* Handle [reg].  */
            if (REG_P (tmp))
@@ -26429,7 +26731,7 @@ rs6000_register_move_cost (enum machine_mode mode,
     }
 
   /* If we have VSX, we can easily move between FPR or Altivec registers.  */
-  else if (VECTOR_UNIT_VSX_P (mode)
+  else if (VECTOR_MEM_VSX_P (mode)
           && reg_classes_intersect_p (to, VSX_REGS)
           && reg_classes_intersect_p (from, VSX_REGS))
     ret = 2 * hard_regno_nregs[32][mode];
@@ -26470,7 +26772,8 @@ rs6000_memory_move_cost (enum machine_mode mode, reg_class_t rclass,
 
   if (reg_classes_intersect_p (rclass, GENERAL_REGS))
     ret = 4 * hard_regno_nregs[0][mode];
-  else if (reg_classes_intersect_p (rclass, FLOAT_REGS))
+  else if ((reg_classes_intersect_p (rclass, FLOAT_REGS)
+           || reg_classes_intersect_p (rclass, VSX_REGS)))
     ret = 4 * hard_regno_nregs[32][mode];
   else if (reg_classes_intersect_p (rclass, ALTIVEC_REGS))
     ret = 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
@@ -27684,6 +27987,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
   { "recip-precision",         OPTION_MASK_RECIP_PRECISION,    false, true  },
   { "string",                  OPTION_MASK_STRING,             false, true  },
   { "vsx",                     OPTION_MASK_VSX,                false, true  },
+  { "vsx-timode",              OPTION_MASK_VSX_TIMODE,         false, true  },
 #ifdef OPTION_MASK_64BIT
 #if TARGET_AIX_OS
   { "aix64",                   OPTION_MASK_64BIT,              false, false },
index b5c79ea6e958f1f108167bfaa2a64c3b05ffd1db..b7b415d69c050590f07413b5cf37d1162a58d052 100644 (file)
@@ -479,6 +479,11 @@ extern int rs6000_vector_align[];
 #define TARGET_FCTIDUZ TARGET_POPCNTD
 #define TARGET_FCTIWUZ TARGET_POPCNTD
 
+/* Power7 has both 32-bit load and store integer for the FPRs, so we don't need
+   to allocate the SDmode stack slot to get the value into the proper location
+   in the register.  */
+#define TARGET_NO_SDMODE_STACK (TARGET_LFIWZX && TARGET_STFIWX && TARGET_DFP)
+
 /* In switching from using target_flags to using rs6000_isa_flags, the options
    machinery creates OPTION_MASK_<xxx> instead of MASK_<xxx>.  For now map
    OPTION_MASK_<xxx> back into MASK_<xxx>.  */
@@ -505,6 +510,7 @@ extern int rs6000_vector_align[];
 #define MASK_STRING                    OPTION_MASK_STRING
 #define MASK_UPDATE                    OPTION_MASK_UPDATE
 #define MASK_VSX                       OPTION_MASK_VSX
+#define MASK_VSX_TIMODE                        OPTION_MASK_VSX_TIMODE
 
 #ifndef IN_LIBGCC2
 #define MASK_POWERPC64                 OPTION_MASK_POWERPC64
@@ -1325,8 +1331,13 @@ enum r6000_reg_class_enum {
   RS6000_CONSTRAINT_v,         /* Altivec registers */
   RS6000_CONSTRAINT_wa,                /* Any VSX register */
   RS6000_CONSTRAINT_wd,                /* VSX register for V2DF */
+  RS6000_CONSTRAINT_wg,                /* FPR register for -mmfpgpr */
   RS6000_CONSTRAINT_wf,                /* VSX register for V4SF */
+  RS6000_CONSTRAINT_wl,                /* FPR register for LFIWAX */
   RS6000_CONSTRAINT_ws,                /* VSX register for DF */
+  RS6000_CONSTRAINT_wt,                /* VSX register for TImode */
+  RS6000_CONSTRAINT_wx,                /* FPR register for STFIWX */
+  RS6000_CONSTRAINT_wz,                /* FPR register for LFIWZX */
   RS6000_CONSTRAINT_MAX
 };
 
@@ -1511,7 +1522,7 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
    NONLOCAL needs twice Pmode to maintain both backchain and SP.  */
 #define STACK_SAVEAREA_MODE(LEVEL)     \
   (LEVEL == SAVE_FUNCTION ? VOIDmode   \
-  : LEVEL == SAVE_NONLOCAL ? (TARGET_32BIT ? DImode : TImode) : Pmode)
+  : LEVEL == SAVE_NONLOCAL ? (TARGET_32BIT ? DImode : PTImode) : Pmode)
 
 /* Minimum and maximum general purpose registers used to hold arguments.  */
 #define GP_ARG_MIN_REG 3
index a665fa50abfd159a40f80a510136ac66645a1641..0a5d32728a1a171f182d6616eb81b55e5c2070ad 100644 (file)
 ;;
 
 (define_constants
-  [(STACK_POINTER_REGNUM       1)
+  [(FIRST_GPR_REGNO            0)
+   (STACK_POINTER_REGNUM       1)
    (TOC_REGNUM                 2)
    (STATIC_CHAIN_REGNUM                11)
    (HARD_FRAME_POINTER_REGNUM  31)
+   (LAST_GPR_REGNO             31)
+   (FIRST_FPR_REGNO            32)
+   (LAST_FPR_REGNO             63)
    (LR_REGNO                   65)
    (CTR_REGNO                  66)
    (ARG_POINTER_REGNUM         67)
 (define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")])
 
 ; Any supported integer mode.
-(define_mode_iterator INT [QI HI SI DI TI])
+(define_mode_iterator INT [QI HI SI DI TI PTI])
 
 ; Any supported integer mode that fits in one register.
 (define_mode_iterator INT1 [QI HI SI (DI "TARGET_POWERPC64")])
 ; (one with a '.') will compare; and the size used for arithmetic carries.
 (define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
 
+; Iterator to add PTImode along with TImode (TImode can go in VSX registers,
+; PTImode is GPR only)
+(define_mode_iterator TI2 [TI PTI])
+
 ; Any hardware-supported floating-point mode
 (define_mode_iterator FP [
   (SF "TARGET_HARD_FLOAT 
   (V2DF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)")
   ])
 
+; Floating point move iterators to combine binary and decimal moves
+(define_mode_iterator FMOVE32 [SF SD])
+(define_mode_iterator FMOVE64 [DF DD])
+(define_mode_iterator FMOVE64X [DI DF DD])
+(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128")
+                               (TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
+
+; Whether a floating point move is ok, don't allow SD without hardware FP
+(define_mode_attr fmove_ok [(SF "")
+                           (DF "")
+                           (SD "TARGET_HARD_FLOAT && TARGET_FPRS")
+                           (DD "")])
+
+; Convert REAL_VALUE to the appropriate bits
+(define_mode_attr real_value_to_target [(SF "REAL_VALUE_TO_TARGET_SINGLE")
+                                       (DF "REAL_VALUE_TO_TARGET_DOUBLE")
+                                       (SD "REAL_VALUE_TO_TARGET_DECIMAL32")
+                                       (DD "REAL_VALUE_TO_TARGET_DECIMAL64")])
+
+; Definitions for load to 32-bit fpr register
+(define_mode_attr f32_lr [(SF "f")              (SD "wz")])
+(define_mode_attr f32_lm [(SF "m")              (SD "Z")])
+(define_mode_attr f32_li [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")])
+
+; Definitions for store from 32-bit fpr register
+(define_mode_attr f32_sr [(SF "f")               (SD "wx")])
+(define_mode_attr f32_sm [(SF "m")               (SD "Z")])
+(define_mode_attr f32_si [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")])
+
 ; These modes do not fit in integer registers in 32-bit mode.
 ; but on e500v2, the gpr are 64 bit registers
 (define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD])
 
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
-(define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
+(define_mode_attr wd [(QI    "b")
+                     (HI    "h")
+                     (SI    "w")
+                     (DI    "d")
+                     (V16QI "b")
+                     (V8HI  "h")
+                     (V4SI  "w")
+                     (V2DI  "d")])
 
 ; DImode bits
 (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
   "@
    l<wd>z%U1%X1 %0,%1
    rldicl %0,%1,0,<dbits>"
-  [(set_attr "type" "load,*")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")])])
 
 (define_insn "*zero_extend<mode>di2_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lha%U1%X1 %0,%1
    extsh %0,%1"
-  [(set_attr "type" "load_ext,exts")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ext_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_ext_u")
+          (const_string "load_ext")))
+       (const_string "exts")])])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
   "@
    lwa%U1%X1 %0,%1
    extsw %0,%1"
-  [(set_attr "type" "load_ext,exts")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ext_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_ext_u")
+          (const_string "load_ext")))
+       (const_string "exts")])])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
   "@
    lbz%U1%X1 %0,%1
    rlwinm %0,%1,0,0xff"
-  [(set_attr "type" "load,*")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")])])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lbz%U1%X1 %0,%1
    rlwinm %0,%1,0,0xff"
-  [(set_attr "type" "load,*")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")])])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lhz%U1%X1 %0,%1
    rlwinm %0,%1,0,0xffff"
-  [(set_attr "type" "load,*")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")])])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
   "@
    lha%U1%X1 %0,%1
    extsh %0,%1"
-  [(set_attr "type" "load_ext,exts")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ext_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_ext_u")
+          (const_string "load_ext")))
+       (const_string "exts")])])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
   emit_note (NOTE_INSN_DELETED);
   DONE;
 }
-  [(set_attr "type" "fp,fp,fpload")])
+  [(set_attr_alternative "type"
+      [(const_string "fp")
+       (const_string "fp")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))])])
 
 (define_expand "truncdfsf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
    mt%0 %1
    mt%0 %1
    nop"
-  [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*")
+  [(set_attr_alternative "type"
+      [(const_string "*")
+       (const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "mfjmpr")
+       (const_string "mtjmpr")
+       (const_string "*")
+       (const_string "*")])
+
    (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4")])
 
 (define_insn "*movsi_internal1_single"
    nop
    stfs%U0%X0 %1,%0
    lfs%U1%X1 %0,%1"
-  [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*,*,*")
+  [(set_attr_alternative "type"
+      [(const_string "*")
+       (const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "mfjmpr")
+       (const_string "mtjmpr")
+       (const_string "*")
+       (const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "fpstore_u")
+          (const_string "fpstore")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))])
    (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
 
 ;; Split a load of a large constant into the appropriate two-insn
    mf%1 %0
    mt%0 %1
    nop"
-  [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")])
+  [(set_attr_alternative "type"
+      [(const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (const_string "*")
+       (const_string "mfjmpr")
+       (const_string "mtjmpr")
+       (const_string "*")])])
 
 (define_expand "mov<mode>"
   [(set (match_operand:INT 0 "general_operand" "")
    mf%1 %0
    mt%0 %1
    nop"
-  [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")])
+  [(set_attr_alternative "type"
+      [(const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (const_string "*")
+       (const_string "mfjmpr")
+       (const_string "mtjmpr")
+       (const_string "*")])])
 \f
 ;; Here is how to move condition codes around.  When we store CC data in
 ;; an integer register or memory, we store just the high-order 4 bits.
    mf%1 %0
    mt%0 %1
    lwz%U1%X1 %0,%1
-   stw%U0%U1 %1,%0"
+   stw%U0%X0 %1,%0"
   [(set (attr "type")
      (cond [(eq_attr "alternative" "0,3")
                (const_string "cr_logical")
            (eq_attr "alternative" "9")
                (const_string "mtjmpr")
            (eq_attr "alternative" "10")
-               (const_string "load")
+               (if_then_else
+                 (match_test "update_indexed_address_mem (operands[1],
+                                                          VOIDmode)")
+                 (const_string "load_ux")
+                 (if_then_else
+                   (match_test "update_address_mem (operands[1], VOIDmode)")
+                   (const_string "load_u")
+                   (const_string "load")))
            (eq_attr "alternative" "11")
-               (const_string "store")
+               (if_then_else
+                 (match_test "update_indexed_address_mem (operands[0],
+                                                          VOIDmode)")
+                 (const_string "store_ux")
+                 (if_then_else
+                   (match_test "update_address_mem (operands[0], VOIDmode)")
+                   (const_string "store_u")
+                   (const_string "store")))
            (match_test "TARGET_MFCRF")
                (const_string "mfcrf")
           ]
 ;; can produce floating-point values in fixed-point registers.  Unless the
 ;; value is a simple constant or already in memory, we deal with this by
 ;; allocating memory and copying the value explicitly via that memory location.
-(define_expand "movsf"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "")
-       (match_operand:SF 1 "any_operand" ""))]
-  ""
-  "{ rs6000_emit_move (operands[0], operands[1], SFmode); DONE; }")
+
+;; Move 32-bit binary/decimal floating point
+(define_expand "mov<mode>"
+  [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "")
+       (match_operand:FMOVE32 1 "any_operand" ""))]
+  "<fmove_ok>"
+  "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
 
 (define_split
-  [(set (match_operand:SF 0 "gpc_reg_operand" "")
-       (match_operand:SF 1 "const_double_operand" ""))]
+  [(set (match_operand:FMOVE32 0 "gpc_reg_operand" "")
+       (match_operand:FMOVE32 1 "const_double_operand" ""))]
   "reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
   REAL_VALUE_TYPE rv;
 
   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-  REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+  <real_value_to_target> (rv, l);
 
   if (! TARGET_POWERPC64)
-    operands[2] = operand_subword (operands[0], 0, 0, SFmode);
+    operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
   else
     operands[2] = gen_lowpart (SImode, operands[0]);
 
   operands[3] = gen_int_mode (l, SImode);
 }")
 
-(define_insn "*movsf_hardfloat"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,*c*l,!r,*h,!r,!r")
-       (match_operand:SF 1 "input_operand" "r,m,r,f,m,f,r,h,0,G,Fn"))]
-  "(gpc_reg_operand (operands[0], SFmode)
-   || gpc_reg_operand (operands[1], SFmode))
+(define_insn "mov<mode>_hardfloat"
+  [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,*c*l,!r,*h,!r,!r")
+       (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,r,h,0,G,Fn"))]
+  "(gpc_reg_operand (operands[0], <MODE>mode)
+   || gpc_reg_operand (operands[1], <MODE>mode))
    && (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)"
   "@
    mr %0,%1
    lwz%U1%X1 %0,%1
    stw%U0%X0 %1,%0
    fmr %0,%1
-   lfs%U1%X1 %0,%1
-   stfs%U0%X0 %1,%0
+   xxlor %x0,%x1,%x1
+   xxlxor %x0,%x0,%x0
+   <f32_li>
+   <f32_si>
    mt%0 %1
    mf%1 %0
    nop
    #
    #"
-  [(set_attr "type" "*,load,store,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8")])
-
-(define_insn "*movsf_softfloat"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,*h")
-       (match_operand:SF 1 "input_operand" "r,r,h,m,r,I,L,G,Fn,0"))]
-  "(gpc_reg_operand (operands[0], SFmode)
-   || gpc_reg_operand (operands[1], SFmode))
+  [(set_attr_alternative "type"
+      [(const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (const_string "fp")
+       (const_string "vecsimple")
+       (const_string "vecsimple")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "fpstore_u")
+          (const_string "fpstore")))
+       (const_string "mtjmpr")
+       (const_string "mfjmpr")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")])
+   (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,8")])
+
+(define_insn "*mov<mode>_softfloat"
+  [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,*h")
+       (match_operand:FMOVE32 1 "input_operand" "r, r,h,m,r,I,L,G,Fn,0"))]
+  "(gpc_reg_operand (operands[0], <MODE>mode)
+   || gpc_reg_operand (operands[1], <MODE>mode))
    && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
   "@
    mr %0,%1
    #
    #
    nop"
-  [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*")
+  [(set_attr_alternative "type"
+      [(const_string "*")
+       (const_string "mtjmpr")
+       (const_string "mfjmpr")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")])
    (set_attr "length" "4,4,4,4,4,4,4,4,8,4")])
 
 \f
-(define_expand "movdf"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
-       (match_operand:DF 1 "any_operand" ""))]
+;; Move 64-bit binary/decimal floating point
+(define_expand "mov<mode>"
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "")
+       (match_operand:FMOVE64 1 "any_operand" ""))]
   ""
-  "{ rs6000_emit_move (operands[0], operands[1], DFmode); DONE; }")
+  "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
 
 (define_split
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (match_operand:DF 1 "const_int_operand" ""))]
+  [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "")
+       (match_operand:FMOVE64 1 "const_int_operand" ""))]
   "! TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
   int endian = (WORDS_BIG_ENDIAN == 0);
   HOST_WIDE_INT value = INTVAL (operands[1]);
 
-  operands[2] = operand_subword (operands[0], endian, 0, DFmode);
-  operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode);
+  operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode);
+  operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode);
 #if HOST_BITS_PER_WIDE_INT == 32
   operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
 #else
 }")
 
 (define_split
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (match_operand:DF 1 "const_double_operand" ""))]
+  [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "")
+       (match_operand:FMOVE64 1 "const_double_operand" ""))]
   "! TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
   REAL_VALUE_TYPE rv;
 
   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-  REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
+  <real_value_to_target> (rv, l);
 
-  operands[2] = operand_subword (operands[0], endian, 0, DFmode);
-  operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode);
+  operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode);
+  operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode);
   operands[4] = gen_int_mode (l[endian], SImode);
   operands[5] = gen_int_mode (l[1 - endian], SImode);
 }")
 
 (define_split
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (match_operand:DF 1 "const_double_operand" ""))]
+  [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "")
+       (match_operand:FMOVE64 1 "const_double_operand" ""))]
   "TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
 #endif
 
   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-  REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
+  <real_value_to_target> (rv, l);
 
   operands[2] = gen_lowpart (DImode, operands[0]);
   /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN.  */
 ;; since the D-form version of the memory instructions does not need a GPR for
 ;; reloading.
 
-(define_insn "*movdf_hardfloat32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r")
-       (match_operand:DF 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))]
+(define_insn "*mov<mode>_hardfloat32"
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r")
+       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,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))"
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "@
    stfd%U0%X0 %1,%0
    lfd%U1%X1 %0,%1
    #
    #
    #"
-  [(set_attr "type" "fpstore,fpload,fp,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,vecsimple,store,load,two,fp,fp,*")
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "fpstore_u")
+          (const_string "fpstore")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))
+       (const_string "fp")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (const_string "fpload"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (const_string "fpload"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (const_string "fpstore"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (const_string "fpstore"))
+       (const_string "vecsimple")
+       (const_string "vecsimple")
+       (const_string "vecsimple")
+       (const_string "store")
+       (const_string "load")
+       (const_string "two")
+       (const_string "fp")
+       (const_string "fp")
+       (const_string "*")])
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,8,8,8,12,16")])
 
-(define_insn "*movdf_softfloat32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
-       (match_operand:DF 1 "input_operand" "r,Y,r,G,H,F"))]
+(define_insn "*mov<mode>_softfloat32"
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
+       (match_operand:FMOVE64 1 "input_operand" "r,Y,r,G,H,F"))]
   "! TARGET_POWERPC64 
    && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) 
        || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
-   && (gpc_reg_operand (operands[0], DFmode)
-       || gpc_reg_operand (operands[1], DFmode))"
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "#"
   [(set_attr "type" "store,load,two,*,*,*")
    (set_attr "length" "8,8,8,8,12,16")])
 
-;; Reload patterns to support gpr load/store with misaligned mem.
-;; and multiple gpr load/store at offset >= 0xfffc
-(define_expand "reload_<mode>_store"
-  [(parallel [(match_operand 0 "memory_operand" "=m")
-              (match_operand 1 "gpc_reg_operand" "r")
-              (match_operand:GPR 2 "register_operand" "=&b")])]
-  ""
-{
-  rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true);
-  DONE;
-})
-
-(define_expand "reload_<mode>_load"
-  [(parallel [(match_operand 0 "gpc_reg_operand" "=r")
-              (match_operand 1 "memory_operand" "m")
-              (match_operand:GPR 2 "register_operand" "=b")])]
-  ""
-{
-  rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false);
-  DONE;
-})
-
 ; 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,ws,?wa,ws,?wa,Z,?Z,m,d,d,wa,*c*l,!r,*h,!r,!r,!r,r,d")
-       (match_operand:DF 1 "input_operand" "r,Y,r,ws,?wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F,d,r"))]
-  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS 
-   && TARGET_DOUBLE_FLOAT
-   && (gpc_reg_operand (operands[0], DFmode)
-       || gpc_reg_operand (operands[1], DFmode))"
+(define_insn "*mov<mode>_hardfloat64"
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg")
+       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,r,h,0,G,H,F,wg,r"))]
+  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "@
-   std%U0%X0 %1,%0
-   ld%U1%X1 %0,%1
-   mr %0,%1
-   xxlor %x0,%x1,%x1
-   xxlor %x0,%x1,%x1
-   lxsd%U1x %x0,%y1
-   lxsd%U1x %x0,%y1
-   stxsd%U0x %x1,%y0
-   stxsd%U0x %x1,%y0
    stfd%U0%X0 %1,%0
    lfd%U1%X1 %0,%1
    fmr %0,%1
-   xxlxor %x0,%x0,%x0
-   mt%0 %1
-   mf%1 %0
-   nop
-   #
-   #
-   #
-   mftgpr %0,%1
-   mffgpr %0,%1"
-  [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fpstore,fpload,fp,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" "=m,d,d,Y,r,!r,ws,?wa,Z,?Z,ws,?wa,wa,*c*l,!r,*h,!r,!r,!r")
-       (match_operand:DF 1 "input_operand" "d,m,d,r,Y,r,Z,Z,ws,wa,ws,wa,j,r,h,0,G,H,F"))]
-  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS 
-   && TARGET_DOUBLE_FLOAT
-   && (gpc_reg_operand (operands[0], DFmode)
-       || gpc_reg_operand (operands[1], DFmode))"
-  "@
-   stfd%U0%X0 %1,%0
-   lfd%U1%X1 %0,%1
-   fmr %0,%1
-   std%U0%X0 %1,%0
-   ld%U1%X1 %0,%1
-   mr %0,%1
    lxsd%U1x %x0,%y1
    lxsd%U1x %x0,%y1
    stxsd%U0x %x1,%y0
    xxlor %x0,%x1,%x1
    xxlor %x0,%x1,%x1
    xxlxor %x0,%x0,%x0
+   std%U0%X0 %1,%0
+   ld%U1%X1 %0,%1
+   mr %0,%1
    mt%0 %1
    mf%1 %0
    nop
    #
    #
-   #"
-  [(set_attr "type" "fpstore,fpload,fp,store,load,*,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,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")])
+   #
+   mftgpr %0,%1
+   mffgpr %0,%1"
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "fpstore_u")
+          (const_string "fpstore")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))
+       (const_string "fp")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (const_string "fpload"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (const_string "fpload"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (const_string "fpstore"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (const_string "fpstore"))
+       (const_string "vecsimple")
+       (const_string "vecsimple")
+       (const_string "vecsimple")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")
+       (const_string "mtjmpr")
+       (const_string "mfjmpr")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "mftgpr")
+       (const_string "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")])
 
-(define_insn "*movdf_softfloat64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h")
-       (match_operand:DF 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))]
+(define_insn "*mov<mode>_softfloat64"
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h")
+       (match_operand:FMOVE64 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))]
   "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
-   && (gpc_reg_operand (operands[0], DFmode)
-       || gpc_reg_operand (operands[1], DFmode))"
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "@
    std%U0%X0 %1,%0
    ld%U1%X1 %0,%1
    #
    #
    nop"
-  [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*")
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")
+       (const_string "mtjmpr")
+       (const_string "mfjmpr")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")])
    (set_attr "length" "4,4,4,4,4,8,12,16,4")])
 \f
-(define_expand "movtf"
-  [(set (match_operand:TF 0 "general_operand" "")
-       (match_operand:TF 1 "any_operand" ""))]
-  "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
-  "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
+(define_expand "mov<mode>"
+  [(set (match_operand:FMOVE128 0 "general_operand" "")
+       (match_operand:FMOVE128 1 "any_operand" ""))]
+  ""
+  "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
 
 ;; It's important to list Y->r and r->Y before r->r because otherwise
 ;; reload, given m->r, will try to pick r->r and reload it, which
 ;; doesn't make progress.
-(define_insn_and_split "*movtf_internal"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
-       (match_operand:TF 1 "input_operand" "d,m,d,r,YGHF,r"))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
-   && (gpc_reg_operand (operands[0], TFmode)
-       || gpc_reg_operand (operands[1], TFmode))"
+(define_insn_and_split "*mov<mode>_internal"
+  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
+       (match_operand:FMOVE128 1 "input_operand" "d,m,d,r,YGHF,r"))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "#"
   "&& reload_completed"
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
   [(set_attr "length" "8,8,8,20,20,16")])
 
-(define_insn_and_split "*movtf_softfloat"
-  [(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=Y,r,r")
-       (match_operand:TF 1 "input_operand"         "r,YGHF,r"))]
-  "!TARGET_IEEEQUAD
-   && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128
-   && (gpc_reg_operand (operands[0], TFmode)
-       || gpc_reg_operand (operands[1], TFmode))"
+(define_insn_and_split "*mov<mode>_softfloat"
+  [(set (match_operand:FMOVE128 0 "rs6000_nonimmediate_operand" "=Y,r,r")
+       (match_operand:FMOVE128 1 "input_operand" "r,YGHF,r"))]
+  "(TARGET_SOFT_FLOAT || !TARGET_FPRS)
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "#"
   "&& reload_completed"
   [(pc)]
   operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
   operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
 }")
+\f
+;; Reload helper functions used by rs6000_secondary_reload.  The patterns all
+;; must have 3 arguments, and scratch register constraint must be a single
+;; constraint.
+
+;; Reload patterns to support gpr load/store with misaligned mem.
+;; and multiple gpr load/store at offset >= 0xfffc
+(define_expand "reload_<mode>_store"
+  [(parallel [(match_operand 0 "memory_operand" "=m")
+              (match_operand 1 "gpc_reg_operand" "r")
+              (match_operand:GPR 2 "register_operand" "=&b")])]
+  ""
+{
+  rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true);
+  DONE;
+})
+
+(define_expand "reload_<mode>_load"
+  [(parallel [(match_operand 0 "gpc_reg_operand" "=r")
+              (match_operand 1 "memory_operand" "m")
+              (match_operand:GPR 2 "register_operand" "=b")])]
+  ""
+{
+  rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false);
+  DONE;
+})
+
 \f
 ;; Next come the multi-word integer load and store and the load and store
 ;; multiple insns.
    fmr %0,%1
    #
    xxlxor %x0,%x0,%x0"
-  [(set_attr "type" "store,load,*,fpstore,fpload,fp,*,vecsimple")])
+  [(set_attr_alternative "type"
+      [(const_string "store")
+       (const_string "load")
+       (const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "fpstore_u")
+          (const_string "fpstore")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))
+       (const_string "fp")
+       (const_string "*")
+       (const_string "vecsimple")])])
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
-(define_insn "*movdi_mfpgpr"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,r,?*d")
-       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,*d,r"))]
-  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+(define_insn "*movdi_internal64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,?Z,?wa,?wa,r,*h,*h,?wa,r,?*wg")
+       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,wa,Z,wa,*h,r,0,O,*wg,r"))]
+  "TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
   "@
    stfd%U0%X0 %1,%0
    lfd%U1%X1 %0,%1
    fmr %0,%1
+   stxsd%U0x %x1,%y0
+   lxsd%U1x %x0,%y1
+   xxlor %x0,%x1,%x1
    mf%1 %0
    mt%0 %1
    nop
+   xxlxor %x0,%x0,%x0
    mftgpr %0,%1
    mffgpr %0,%1"
-  [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,fp,mfjmpr,mtjmpr,*,mftgpr,mffgpr")
-   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")])
-
-(define_insn "*movdi_internal64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,?wa")
-       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,O"))]
-  "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS)
-   && (gpc_reg_operand (operands[0], DImode)
-       || gpc_reg_operand (operands[1], DImode))"
-  "@
-   std%U0%X0 %1,%0
-   ld%U1%X1 %0,%1
-   mr %0,%1
-   li %0,%1
-   lis %0,%v1
-   #
-   stfd%U0%X0 %1,%0
-   lfd%U1%X1 %0,%1
-   fmr %0,%1
-   mf%1 %0
-   mt%0 %1
-   nop
-   xxlxor %x0,%x0,%x0"
-  [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,fp,mfjmpr,mtjmpr,*,vecsimple")
-   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
+  [(set_attr_alternative "type"
+      [(if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "store_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "store_u")
+          (const_string "store")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "load_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "load_u")
+          (const_string "load")))
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (const_string "*")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[0], VOIDmode)")
+          (const_string "fpstore_u")
+          (const_string "fpstore")))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (if_then_else
+          (match_test "update_address_mem (operands[1], VOIDmode)")
+          (const_string "fpload_u")
+          (const_string "fpload")))
+       (const_string "fp")
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+        (const_string "fpstore_ux")
+        (const_string "fpstore"))
+       (if_then_else
+        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_ux")
+        (const_string "fpload"))
+       (const_string "vecsimple")
+       (const_string "mfjmpr")
+       (const_string "mtjmpr")
+       (const_string "*")
+       (const_string "vecsimple")
+       (const_string "mftgpr")
+       (const_string "mffgpr")])
+   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4,4,4")])
 
 ;; immediate value valid for a single instruction hiding in a const_double
 (define_insn ""
     FAIL;
 }")
 \f
-;; TImode is similar, except that we usually want to compute the address into
-;; a register and use lsi/stsi (the exception is during reload).
+;; TImode/PTImode is similar, except that we usually want to compute the
+;; address into a register and use lsi/stsi (the exception is during reload).
 
-(define_insn "*movti_string"
-  [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,Y,????r,????r,????r,r")
-       (match_operand:TI 1 "input_operand" "r,r,Q,Y,r,n"))]
+(define_insn "*mov<mode>_string"
+  [(set (match_operand:TI2 0 "reg_or_mem_operand" "=Q,Y,????r,????r,????r,r")
+       (match_operand:TI2 1 "input_operand" "r,r,Q,Y,r,n"))]
   "! TARGET_POWERPC64
-   && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
+   && (<MODE>mode != TImode || VECTOR_MEM_NONE_P (TImode))
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode))"
   "*
 {
   switch (which_alternative)
                                          (const_string "always")
                                          (const_string "conditional")))])
 
-(define_insn "*movti_ppc64"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=Y,r,r")
-       (match_operand:TI 1 "input_operand" "r,Y,r"))]
-  "(TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
-    || gpc_reg_operand (operands[1], TImode)))
-   && VECTOR_MEM_NONE_P (TImode)"
+(define_insn "*mov<mode>_ppc64"
+  [(set (match_operand:TI2 0 "nonimmediate_operand" "=Y,r,r")
+       (match_operand:TI2 1 "input_operand" "r,Y,r"))]
+  "(TARGET_POWERPC64
+   && (<MODE>mode != TImode || VECTOR_MEM_NONE_P (TImode))
+   && (gpc_reg_operand (operands[0], <MODE>mode)
+       || gpc_reg_operand (operands[1], <MODE>mode)))"
   "#"
   [(set_attr "type" "store,load,*")])
 
 (define_split
-  [(set (match_operand:TI 0 "gpc_reg_operand" "")
-       (match_operand:TI 1 "const_double_operand" ""))]
-  "TARGET_POWERPC64 && VECTOR_MEM_NONE_P (TImode)"
+  [(set (match_operand:TI2 0 "gpc_reg_operand" "")
+       (match_operand:TI2 1 "const_double_operand" ""))]
+  "TARGET_POWERPC64"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
   "
 {
   operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
-                                      TImode);
+                                      <MODE>mode);
   operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
-                                      TImode);
+                                      <MODE>mode);
   if (GET_CODE (operands[1]) == CONST_DOUBLE)
     {
       operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
 }")
 
 (define_split
-  [(set (match_operand:TI 0 "nonimmediate_operand" "")
-        (match_operand:TI 1 "input_operand" ""))]
-  "reload_completed && VECTOR_MEM_NONE_P (TImode)
+  [(set (match_operand:TI2 0 "nonimmediate_operand" "")
+        (match_operand:TI2 1 "input_operand" ""))]
+  "reload_completed
    && gpr_or_gpr_p (operands[0], operands[1])"
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
   operands[1] = gen_rtx_REG (Pmode, 0);
   return "st<wd>%U0%X0 %1,%0";
 }
-  [(set_attr "type" "store")
+  [(set (attr "type")
+      (if_then_else
+       (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
+       (const_string "store_ux")
+       (if_then_else
+         (match_test "update_address_mem (operands[0], VOIDmode)")
+         (const_string "store_u")
+         (const_string "store"))))
    (set_attr "length" "4")])
 
 (define_insn "probe_stack_range<P:mode>"
index 8e3cea12185a365d868a32534191a5424f63af89..17b77629fa1761ef201618b3afa6e393df6de72e 100644 (file)
@@ -514,3 +514,7 @@ Use/do not use r11 to hold the static link in calls to functions via pointers.
 msave-toc-indirect
 Target Report Var(TARGET_SAVE_TOC_INDIRECT) Save
 Control whether we save the TOC in the prologue for indirect calls or generate the save inline
+
+mvsx-timode
+Target Undocumented Mask(VSX_TIMODE) Var(rs6000_isa_flags)
+; Allow/disallow TImode in VSX registers
index 5a6e1fb302652fa3ad1ecdc46f2a800a6104187f..c1d00ca2a9be5fb13c38a272b2ea4f55e32c6019 100644 (file)
@@ -54,7 +54,7 @@
 (define_mode_iterator VEC_64 [V2DI V2DF])
 
 ;; Vector reload iterator
-(define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI])
+(define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF SF SD SI DF DD DI TI])
 
 ;; Base type from vector mode
 (define_mode_attr VEC_base [(V16QI "QI")
   [(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)"
+  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
 {
   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
     {
                          (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)"
+  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   "
 {
   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
                          (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)"
+  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   "
 {
   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
   [(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)"
+  "VECTOR_UNIT_ALTIVEC_OR_VSX_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)"
+  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   "")
 
 (define_insn_and_split "*vector_uneq<mode>"
 
 \f
 ;; Vector logical instructions
+;; Do not support TImode logical instructions on 32-bit at present, because the
+;; compiler will see that we have a TImode and when it wanted DImode, and
+;; convert the DImode to TImode, store it on the stack, and load it in a VSX
+;; register.
 (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)"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "")
 
 (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)"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "")
 
 (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)"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "")
 
 (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)"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "")
 
 (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)"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "")
 
 (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)"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "")
 
 ;; Same size conversions
index dcb1f64d4ee8c3dd23ce492ac7ad4b163c47b945..042bb5c73d64f90e9a37f0c782add7c663bdf9b0 100644 (file)
@@ -48,7 +48,7 @@
                        (V2DF  "vd2")
                        (V2DI  "vd2")
                        (DF    "d")
-                       (TI    "vw4")])
+                       (TI    "vd2")])
 
 ;; Map into the appropriate suffix based on the type
 (define_mode_attr VSs  [(V16QI "sp")
@@ -59,7 +59,7 @@
                         (V2DI  "dp")
                         (DF    "dp")
                         (SF    "sp")
-                        (TI    "sp")])
+                        (TI    "dp")])
 
 ;; Map the register class used
 (define_mode_attr VSr  [(V16QI "v")
@@ -70,7 +70,7 @@
                         (V2DF  "wd")
                         (DF    "ws")
                         (SF    "d")
-                        (TI    "wd")])
+                        (TI    "wt")])
 
 ;; Map the register class used for float<->int conversions
 (define_mode_attr VSr2 [(V2DF  "wd")
                         (V4SF  "v")
                         (V2DI  "v")
                         (V2DF  "v")
-                        (TI    "v")
                         (DF    "s")])
 
 ;; Appropriate type for add ops (and other simple FP ops)
 }
   [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
 
-;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
-;; unions.  However for plain data movement, slightly favor the vector loads
-(define_insn "*vsx_movti"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?Y,?r,?r,wa,v,v,wZ")
-       (match_operand:TI 1 "input_operand" "wa,Z,wa,r,Y,r,j,W,wZ,v"))]
-  "VECTOR_MEM_VSX_P (TImode)
+;; Unlike other VSX moves, allow the GPRs even for reloading, since a normal
+;; use of TImode is for unions.  However for plain data movement, slightly
+;; favor the vector loads
+(define_insn "*vsx_movti_64bit"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,?Y,?r,?r")
+       (match_operand:TI 1 "input_operand"        "wa, Z,wa, j,W,wZ, v, r, Y, r"))]
+  "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
    && (register_operand (operands[0], TImode) 
        || register_operand (operands[1], TImode))"
 {
       return "xxlor %x0,%x1,%x1";
 
     case 3:
+      return "xxlxor %x0,%x0,%x0";
+
     case 4:
+      return output_vec_const_move (operands);
+
     case 5:
-      return "#";
+      return "stvx %1,%y0";
 
     case 6:
-      return "xxlxor %x0,%x0,%x0";
+      return "lvx %0,%y1";
 
     case 7:
+    case 8:
+    case 9:
+      return "#";
+
+    default:
+      gcc_unreachable ();
+    }
+}
+  [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,*,*,*")
+   (set_attr "length" "     4,      4,        4,       4,         8,       4,      4,8,8,8")])
+
+(define_insn "*vsx_movti_32bit"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,Q,Y,????r,????r,????r,r")
+       (match_operand:TI 1 "input_operand"        "wa, Z,wa, j,W,wZ, v,r,r,    Q,    Y,    r,n"))]
+  "! TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
+   && (register_operand (operands[0], TImode)
+       || register_operand (operands[1], TImode))"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "stxvd2x %x1,%y0";
+
+    case 1:
+      return "lxvd2x %x0,%y1";
+
+    case 2:
+      return "xxlor %x0,%x1,%x1";
+
+    case 3:
+      return "xxlxor %x0,%x0,%x0";
+
+    case 4:
       return output_vec_const_move (operands);
 
-    case 8:
+    case 5:
       return "stvx %1,%y0";
 
-    case 9:
+    case 6:
       return "lvx %0,%y1";
 
+    case 7:
+      if (TARGET_STRING)
+        return \"stswi %1,%P0,16\";
+
+    case 8:
+      return \"#\";
+
+    case 9:
+      /* If the address is not used in the output, we can use lsi.  Otherwise,
+        fall through to generating four loads.  */
+      if (TARGET_STRING
+          && ! reg_overlap_mentioned_p (operands[0], operands[1]))
+       return \"lswi %0,%P1,16\";
+      /* ... fall through ...  */
+
+    case 10:
+    case 11:
+    case 12:
+      return \"#\";
     default:
       gcc_unreachable ();
     }
 }
-  [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
+  [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store_ux,store_ux,load_ux,load_ux, *, *")
+   (set_attr "length" "     4,      4,        4,       4,         8,       4,      4,      16,      16,     16,     16,16,16")
+   (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
+                                         (const_string "always")
+                                         (const_string "conditional")))])
 
 ;; Explicit  load/store expanders for the builtin functions
 (define_expand "vsx_load_<mode>"
   "")
 
 (define_expand "vsx_store_<mode>"
-  [(set (match_operand:VEC_M 0 "memory_operand" "")
-       (match_operand:VEC_M 1 "vsx_register_operand" ""))]
+  [(set (match_operand:VSX_M 0 "memory_operand" "")
+       (match_operand:VSX_M 1 "vsx_register_operand" ""))]
   "VECTOR_MEM_VSX_P (<MODE>mode)"
   "")
 
    (set_attr "fp_type" "<VSfptype_simple>")])
 
 \f
-;; Logical and permute operations
+;; Logical operations
+;; Do not support TImode logical instructions on 32-bit at present, because the
+;; compiler will see that we have a TImode and when it wanted DImode, and
+;; convert the DImode to TImode, store it on the stack, and load it in a VSX
+;; register.
 (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)"
+        (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)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "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)"
+        (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)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "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)"
+        (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)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "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)"
+        (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")))]
+  "VECTOR_MEM_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "xxlnor %x0,%x1,%x1"
   [(set_attr "type" "vecsimple")])
   
         (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)"
+  "VECTOR_MEM_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "xxlnor %x0,%x1,%x2"
   [(set_attr "type" "vecsimple")])
 
         (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)"
+  "VECTOR_MEM_VSX_P (<MODE>mode)
+   && (<MODE>mode != TImode || TARGET_POWERPC64)"
   "xxlandc %x0,%x1,%x2"
   [(set_attr "type" "vecsimple")])
 
 
 ;; Build a V2DF/V2DI vector from two scalars
 (define_insn "vsx_concat_<mode>"
-  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
-       (unspec:VSX_D
-        [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
-         (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
-        UNSPEC_VSX_CONCAT))]
+  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?wa")
+       (vec_concat:VSX_D
+        (match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
+        (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")))]
   "VECTOR_MEM_VSX_P (<MODE>mode)"
   "xxpermdi %x0,%x1,%x2,0"
   [(set_attr "type" "vecperm")])
         (parallel [(const_int 0)])))]
   "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN"
   "lxsd%U1x %x0,%y1"
-  [(set_attr "type" "fpload")
+  [(set (attr "type")
+      (if_then_else
+       (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+       (const_string "fpload_ux")
+       (const_string "fpload")))
    (set_attr "length" "4")])  
 
 ;; Extract a SF element from V4SF
       if (<MODE>mode != V2DImode)
        {
          target = gen_lowpart (V2DImode, target);
-         op0 = gen_lowpart (V2DImode, target);
-         op1 = gen_lowpart (V2DImode, target);
+         op0 = gen_lowpart (V2DImode, op0);
+         op1 = gen_lowpart (V2DImode, op1);
        }
     }
   emit_insn (gen (target, op0, op1, perm0, perm1));
index b84a2028d645ade6fe5857e4e1f8ed18b709f820..6729eb691fd60d88ca26cc44bd657540c46def39 100644 (file)
@@ -2075,9 +2075,24 @@ VSX vector register to hold vector double data
 @item wf
 VSX vector register to hold vector float data
 
+@item wg
+If @option{-mmfpgpr} was used, a floating point register
+
+@item wl
+If the LFIWAX instruction is enabled, a floating point register
+
 @item ws
 VSX vector register to hold scalar float data
 
+@item wt
+VSX vector register to hold 128 bit integer
+
+@item wx
+If the STFIWX instruction is enabled, a floating point register
+
+@item wz
+If the LFIWZX instruction is enabled, a floating point register
+
 @item wa
 Any VSX register
 
index ef7bdd61a87c73e40608962fa81e7e790c431fdf..93d02bbd166f884652c8016e4e90946ac81a2f00 100644 (file)
@@ -1,3 +1,10 @@
+2013-03-20  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/mmfpgpr.c: New test.
+       * gcc.target/powerpc/sd-vsx.c: Likewise.
+       * gcc.target/powerpc/sd-pwr6.c: Likewise.
+       * gcc.target/powerpc/vsx-float0.c: Likewise.
+
 2013-03-20  Marc Glisse  <marc.glisse@inria.fr>
 
        PR tree-optimization/56355
diff --git a/gcc/testsuite/gcc.target/powerpc/mmfpgpr.c b/gcc/testsuite/gcc.target/powerpc/mmfpgpr.c
new file mode 100644 (file)
index 0000000..7f2d3d3
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power6x -mmfpgpr" } */
+/* { dg-final { scan-assembler "mffgpr" } } */
+/* { dg-final { scan-assembler "mftgpr" } } */
+
+/* Test that we generate the instructions to move between the GPR and FPR
+   registers under power6x.  */
+
+extern long return_long (void);
+extern double return_double (void);
+
+double return_double2 (void)
+{
+  return (double) return_long ();
+}
+
+long return_long2 (void)
+{
+  return (long) return_double ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sd-pwr6.c b/gcc/testsuite/gcc.target/powerpc/sd-pwr6.c
new file mode 100644 (file)
index 0000000..947382b
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power6 -mhard-dfp" } */
+/* { dg-final { scan-assembler-not   "lfiwzx"   } } */
+/* { dg-final { scan-assembler-times "lfd"    2 } } */
+/* { dg-final { scan-assembler-times "dctdp"  2 } } */
+/* { dg-final { scan-assembler-times "dadd"   1 } } */
+/* { dg-final { scan-assembler-times "drsp"   1 } } */
+
+/* Test that for power6 we need to use a bounce buffer on the stack to load
+   SDmode variables because the power6 does not have a way to directly load
+   32-bit values from memory.  */
+_Decimal32 a;
+
+void inc_dec32 (void)
+{
+  a += (_Decimal32) 1.0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sd-vsx.c b/gcc/testsuite/gcc.target/powerpc/sd-vsx.c
new file mode 100644 (file)
index 0000000..7e41e1e
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7 -mhard-dfp" } */
+/* { dg-final { scan-assembler-times "lfiwzx" 2 } } */
+/* { dg-final { scan-assembler-times "stfiwx" 1 } } */
+/* { dg-final { scan-assembler-not   "lfd"      } } */
+/* { dg-final { scan-assembler-not   "stfd"     } } */
+/* { dg-final { scan-assembler-times "dctdp"  2 } } */
+/* { dg-final { scan-assembler-times "dadd"   1 } } */
+/* { dg-final { scan-assembler-times "drsp"   1 } } */
+
+/* Test that power7 can directly load/store SDmode variables without using a
+   bounce buffer.  */
+_Decimal32 a;
+
+void inc_dec32 (void)
+{
+  a += (_Decimal32) 1.0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-float0.c b/gcc/testsuite/gcc.target/powerpc/vsx-float0.c
new file mode 100644 (file)
index 0000000..7e4fea6
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xxlxor" } } */
+
+/* Test that we generate xxlor to clear a SFmode register.  */
+
+float sum (float *p, unsigned long n)
+{
+  float sum = 0.0f;    /* generate xxlxor instead of load */
+  while (n-- > 0)
+    sum += *p++;
+
+  return sum;
+}