3524 lines
134 KiB
Diff
3524 lines
134 KiB
Diff
2009-04-26 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||
|
||
* config/rs6000/vector.md (vector_vsel<mode>): Generate the insns
|
||
directly instead of calling VSX/Altivec expanders.
|
||
|
||
* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Map VSX
|
||
builtins that are identical to Altivec, to the Altivec vesion.
|
||
(altivec_overloaded_builtins): Add V2DF/V2DI sel, perm support.
|
||
(altivec_resolve_overloaded_builtin): Add V2DF/V2DI support.
|
||
|
||
* config/rs6000/rs6000.c (rs6000_expand_vector_init): Rename VSX
|
||
splat functions.
|
||
(expand_vector_set): Merge V2DF/V2DI code.
|
||
(expand_vector_extract): Ditto.
|
||
(bdesc_3arg): Add more VSX builtins.
|
||
(bdesc_2arg): Ditto.
|
||
(bdesc_1arg): Ditto.
|
||
(rs6000_expand_ternop_builtin): Require xxpermdi 3rd argument to
|
||
be 2 bit-constant, and V2DF/V2DI set to be a 1 bit-constant.
|
||
(altivec_expand_builtin): Add support for VSX overloaded builtins.
|
||
(altivec_init_builtins): Ditto.
|
||
(rs6000_common_init_builtins): Ditto.
|
||
(rs6000_init_builtins): Add V2DI types and vector long support.
|
||
(rs6000_handle_altivec_attribute): Ditto.
|
||
(rs6000_mange_type): Ditto.
|
||
|
||
* config/rs6000/vsx.md (UNSPEC_*): Add new UNSPEC constants.
|
||
(vsx_vsel<mode>): Add support for all vector types, including
|
||
Altivec types.
|
||
(vsx_ftrunc<mode>2): Emit the correct instruction.
|
||
(vsx_x<VSv>r<VSs>i): New builtin rounding mode insns.
|
||
(vsx_x<VSv>r<VSs>ic): Ditto.
|
||
(vsx_concat_<mode>): Key off of VSX memory instructions being
|
||
generated instead of the vector arithmetic unit to enable V2DI
|
||
mode.
|
||
(vsx_extract_<mode>): Ditto.
|
||
(vsx_set_<mode>): Rewrite as an unspec.
|
||
(vsx_xxpermdi2_<mode>): Rename old vsx_xxpermdi_<mode> here. Key
|
||
off of VSX memory instructions instead of arithmetic unit.
|
||
(vsx_xxpermdi_<mode>): New insn for __builtin_vsx_xxpermdi.
|
||
(vsx_splat_<mode>): Rename from vsx_splat<mode>.
|
||
(vsx_xxspltw_<mode>): Change from V4SF only to V4SF/V4SI modes.
|
||
Fix up constraints. Key off of memory instructions instead of
|
||
arithmetic instructions to allow use with V4SI.
|
||
(vsx_xxmrghw_<mode>): Ditto.
|
||
(vsx_xxmrglw_<mode>): Ditto.
|
||
(vsx_xxsldwi_<mode>): Implement vector shift double by word
|
||
immediate.
|
||
|
||
* config/rs6000/rs6000.h (VSX_BUILTIN_*): Update for current
|
||
builtins being generated.
|
||
(RS6000_BTI_unsigned_V2DI): Add vector long support.
|
||
(RS6000_BTI_bool_long): Ditto.
|
||
(RS6000_BTI_bool_V2DI): Ditto.
|
||
(unsigned_V2DI_type_node): Ditto.
|
||
(bool_long_type_node): Ditto.
|
||
(bool_V2DI_type_node): Ditto.
|
||
|
||
* config/rs6000/altivec.md (altivec_vsel<mode>): Add '*' since we
|
||
don't need the generator function now. Use VSX instruction if
|
||
-mvsx.
|
||
(altivec_vmrghw): Use VSX instruction if -mvsx.
|
||
(altivec_vmrghsf): Ditto.
|
||
(altivec_vmrglw): Ditto.
|
||
(altivec_vmrglsf): Ditto.
|
||
|
||
* doc/extend.texi (PowerPC AltiVec/VSX Built-in Functions):
|
||
Document that under VSX, vector double/long are available.
|
||
|
||
testsuite/
|
||
* gcc.target/powerpc/vsx-builtin-3.c: New test for VSX builtins.
|
||
|
||
2009-04-23 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||
|
||
* config/rs6000/vector.md (VEC_E): New iterator to add V2DImode.
|
||
(vec_init<mode>): Use VEC_E instead of VEC_C iterator, to add
|
||
V2DImode support.
|
||
(vec_set<mode>): Ditto.
|
||
(vec_extract<mode>): Ditto.
|
||
|
||
* config/rs6000/predicates.md (easy_vector_constant): Add support
|
||
for setting TImode to 0.
|
||
|
||
* config/rs6000/rs6000.opt (-mvsx-vector-memory): Delete old debug
|
||
switch that is no longer used.
|
||
(-mvsx-vector-float): Ditto.
|
||
(-mvsx-vector-double): Ditto.
|
||
(-mvsx-v4sf-altivec-regs): Ditto.
|
||
(-mreload-functions): Ditto.
|
||
(-mallow-timode): New debug switch.
|
||
|
||
* config/rs6000/rs6000.c (rs6000_ira_cover_classes): New target
|
||
hook for IRA cover classes, to know that under VSX the float and
|
||
altivec registers are part of the same register class, but before
|
||
they weren't.
|
||
(TARGET_IRA_COVER_CLASSES): Set ira cover classes target hookd.
|
||
(rs6000_hard_regno_nregs): Key off of whether VSX/Altivec memory
|
||
instructions are supported, and not whether the vector unit has
|
||
arithmetic support to enable V2DI/TI mode.
|
||
(rs6000_hard_regno_mode_ok): Ditto.
|
||
(rs6000_init_hard_regno_mode_ok): Add V2DImode, TImode support.
|
||
Drop several of the debug switches.
|
||
(rs6000_emit_move): Force TImode constants to memory if we have
|
||
either Altivec or VSX.
|
||
(rs6000_builtin_conversion): Use correct insns for V2DI<->V2DF
|
||
conversions.
|
||
(rs6000_expand_vector_init): Add V2DI support.
|
||
(rs6000_expand_vector_set): Ditto.
|
||
(avoiding_indexed_address_p): Simplify tests to say if the mode
|
||
uses VSX/Altivec memory instructions we can't eliminate reg+reg
|
||
addressing.
|
||
(rs6000_legitimize_address): Move VSX/Altivec REG+REG support
|
||
before the large integer support.
|
||
(rs6000_legitimate_address): Add support for TImode in VSX/Altivec
|
||
registers.
|
||
(rs6000_emit_move): Ditto.
|
||
(def_builtin): Change internal error message to provide more
|
||
information.
|
||
(bdesc_2arg): Add conversion builtins.
|
||
(builtin_hash_function): New function for hashing all of the types
|
||
for builtin functions.
|
||
(builtin_hash_eq): Ditto.
|
||
(builtin_function_type): Ditto.
|
||
(builtin_mode_to_type): New static for builtin argument hashing.
|
||
(builtin_hash_table): Ditto.
|
||
(rs6000_common_init_builtins): Rewrite so that types for builtin
|
||
functions are only created when we need them, and use a hash table
|
||
to store all of the different argument combinations that are
|
||
created. Add support for VSX conversion builtins.
|
||
(rs6000_preferred_reload_class): Add TImode support.
|
||
(reg_classes_cannot_change_mode_class): Be stricter about VSX and
|
||
Altivec vector types.
|
||
(rs6000_emit_vector_cond_expr): Use VSX_MOVE_MODE, not
|
||
VSX_VECTOR_MOVE_MODE.
|
||
(rs6000_handle_altivec_attribute): Allow __vector long on VSX.
|
||
|
||
* config/rs6000/vsx.md (VSX_D): New iterator for vectors with
|
||
64-bit elements.
|
||
(VSX_M): New iterator for 128 bit types for moves, except for
|
||
TImode.
|
||
(VSm, VSs, VSr): Add TImode.
|
||
(VSr4, VSr5): New mode attributes for float<->double conversion.
|
||
(VSX_SPDP): New iterator for float<->double conversion.
|
||
(VS_spdp_*): New mode attributes for float<->double conversion.
|
||
(UNSPEC_VSX_*): Rename unspec constants to remove XV from the
|
||
names. Change all users.
|
||
(vsx_mov<mode>): Drop TImode support here.
|
||
(vsx_movti): New TImode support, allow GPRs, but favor VSX
|
||
registers.
|
||
(vsx_<VS_spdp_insn>): New support for float<->double conversions.
|
||
(vsx_xvcvdpsp): Delete, move into vsx_<VS_spdp_insn>.
|
||
(vsx_xvcvspdp): Ditto.
|
||
(vsx_xvcvuxdsp): New conversion insn.
|
||
(vsx_xvcvspsxds): Ditto.
|
||
(vsx_xvcvspuxds): Ditto.
|
||
(vsx_concat_<mode>): Generalize V2DF permute/splat operations to
|
||
include V2DI.
|
||
(vsx_set_<mode>): Ditto.
|
||
(vsx_extract_<mode>): Ditto.
|
||
(vsx_xxpermdi_<mode>): Ditto.
|
||
(vsx_splat<mode>): Ditto.
|
||
|
||
* config/rs6000/rs6000.h (VSX_VECTOR_MOVE_MODE): Delete.
|
||
(VSX_MOVE_MODE): Add TImode.
|
||
(IRA_COVER_CLASSES): Delete.
|
||
(IRA_COVER_CLASSES_PRE_VSX): New cover classes for machines
|
||
without VSX where float and altivec are different registers.
|
||
(IRA_COVER_CLASS_VSX): New cover classes for machines with VSX
|
||
where float and altivec are part of the same register class.
|
||
|
||
* config/rs6000/altivec.md (VM2): New iterator for 128-bit types,
|
||
except TImode.
|
||
(altivec_mov<mode>): Drop movti mode here.
|
||
(altivec_movti): Add movti insn, and allow GPRs, but favor altivec
|
||
registers.
|
||
|
||
2009-04-16 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||
|
||
* config/rs6000/rs6000-protos.h (rs6000_has_indirect_jump_p): New
|
||
declaration.
|
||
(rs6000_set_indirect_jump): Ditto.
|
||
|
||
* config/rs6000/rs6000.c (struct machine_function): Add
|
||
indirect_jump_p field.
|
||
(rs6000_override_options): Wrap warning messages in N_(). If
|
||
-mvsx was implicitly set, don't give a warning for -msoft-float,
|
||
just silently turn off vsx.
|
||
(rs6000_secondary_reload_inner): Don't use strict register
|
||
checking, since pseudos may still be present.
|
||
(register_move_cost): If -mdebug=cost, print out cost information.
|
||
(rs6000_memory_move_cost): Ditto.
|
||
(rs6000_has_indirect_jump_p): New function, return true if
|
||
current function has an indirect jump.
|
||
(rs6000_set_indirect_jump): New function, note that an indirect
|
||
jump has been generated.
|
||
|
||
* config/rs6000/rs6000.md (indirect_jump): Note that we've
|
||
generated an indirect jump.
|
||
(tablejump): Ditto.
|
||
(doloop_end): Do not generate decrement ctr and branch
|
||
instructions if an indirect jump has been generated.
|
||
|
||
--- gcc/doc/extend.texi (revision 146119)
|
||
+++ gcc/doc/extend.texi (revision 146798)
|
||
@@ -7094,7 +7094,7 @@ instructions, but allow the compiler to
|
||
* MIPS Loongson Built-in Functions::
|
||
* Other MIPS Built-in Functions::
|
||
* picoChip Built-in Functions::
|
||
-* PowerPC AltiVec Built-in Functions::
|
||
+* PowerPC AltiVec/VSX Built-in Functions::
|
||
* SPARC VIS Built-in Functions::
|
||
* SPU Built-in Functions::
|
||
@end menu
|
||
@@ -9571,7 +9571,7 @@ GCC defines the preprocessor macro @code
|
||
when this function is available.
|
||
@end table
|
||
|
||
-@node PowerPC AltiVec Built-in Functions
|
||
+@node PowerPC AltiVec/VSX Built-in Functions
|
||
@subsection PowerPC AltiVec Built-in Functions
|
||
|
||
GCC provides an interface for the PowerPC family of processors to access
|
||
@@ -9597,6 +9597,19 @@ vector bool int
|
||
vector float
|
||
@end smallexample
|
||
|
||
+If @option{-mvsx} is used the following additional vector types are
|
||
+implemented.
|
||
+
|
||
+@smallexample
|
||
+vector unsigned long
|
||
+vector signed long
|
||
+vector double
|
||
+@end smallexample
|
||
+
|
||
+The long types are only implemented for 64-bit code generation, and
|
||
+the long type is only used in the floating point/integer conversion
|
||
+instructions.
|
||
+
|
||
GCC's implementation of the high-level language interface available from
|
||
C and C++ code differs from Motorola's documentation in several ways.
|
||
|
||
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c (revision 0)
|
||
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c (revision 146798)
|
||
@@ -0,0 +1,212 @@
|
||
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
|
||
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
|
||
+/* { dg-require-effective-target powerpc_vsx_ok } */
|
||
+/* { dg-options "-O2 -mcpu=power7" } */
|
||
+/* { dg-final { scan-assembler "xxsel" } } */
|
||
+/* { dg-final { scan-assembler "vperm" } } */
|
||
+/* { dg-final { scan-assembler "xvrdpi" } } */
|
||
+/* { dg-final { scan-assembler "xvrdpic" } } */
|
||
+/* { dg-final { scan-assembler "xvrdpim" } } */
|
||
+/* { dg-final { scan-assembler "xvrdpip" } } */
|
||
+/* { dg-final { scan-assembler "xvrdpiz" } } */
|
||
+/* { dg-final { scan-assembler "xvrspi" } } */
|
||
+/* { dg-final { scan-assembler "xvrspic" } } */
|
||
+/* { dg-final { scan-assembler "xvrspim" } } */
|
||
+/* { dg-final { scan-assembler "xvrspip" } } */
|
||
+/* { dg-final { scan-assembler "xvrspiz" } } */
|
||
+/* { dg-final { scan-assembler "xsrdpi" } } */
|
||
+/* { dg-final { scan-assembler "xsrdpic" } } */
|
||
+/* { dg-final { scan-assembler "xsrdpim" } } */
|
||
+/* { dg-final { scan-assembler "xsrdpip" } } */
|
||
+/* { dg-final { scan-assembler "xsrdpiz" } } */
|
||
+/* { dg-final { scan-assembler "xsmaxdp" } } */
|
||
+/* { dg-final { scan-assembler "xsmindp" } } */
|
||
+/* { dg-final { scan-assembler "xxland" } } */
|
||
+/* { dg-final { scan-assembler "xxlandc" } } */
|
||
+/* { dg-final { scan-assembler "xxlnor" } } */
|
||
+/* { dg-final { scan-assembler "xxlor" } } */
|
||
+/* { dg-final { scan-assembler "xxlxor" } } */
|
||
+/* { dg-final { scan-assembler "xvcmpeqdp" } } */
|
||
+/* { dg-final { scan-assembler "xvcmpgtdp" } } */
|
||
+/* { dg-final { scan-assembler "xvcmpgedp" } } */
|
||
+/* { dg-final { scan-assembler "xvcmpeqsp" } } */
|
||
+/* { dg-final { scan-assembler "xvcmpgtsp" } } */
|
||
+/* { dg-final { scan-assembler "xvcmpgesp" } } */
|
||
+/* { dg-final { scan-assembler "xxsldwi" } } */
|
||
+/* { dg-final { scan-assembler-not "call" } } */
|
||
+
|
||
+extern __vector int si[][4];
|
||
+extern __vector short ss[][4];
|
||
+extern __vector signed char sc[][4];
|
||
+extern __vector float f[][4];
|
||
+extern __vector unsigned int ui[][4];
|
||
+extern __vector unsigned short us[][4];
|
||
+extern __vector unsigned char uc[][4];
|
||
+extern __vector __bool int bi[][4];
|
||
+extern __vector __bool short bs[][4];
|
||
+extern __vector __bool char bc[][4];
|
||
+extern __vector __pixel p[][4];
|
||
+#ifdef __VSX__
|
||
+extern __vector double d[][4];
|
||
+extern __vector long sl[][4];
|
||
+extern __vector unsigned long ul[][4];
|
||
+extern __vector __bool long bl[][4];
|
||
+#endif
|
||
+
|
||
+int do_sel(void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_xxsel_4si (si[i][1], si[i][2], si[i][3]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxsel_8hi (ss[i][1], ss[i][2], ss[i][3]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxsel_16qi (sc[i][1], sc[i][2], sc[i][3]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxsel_4sf (f[i][1], f[i][2], f[i][3]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxsel_2df (d[i][1], d[i][2], d[i][3]); i++;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], bi[i][3]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], bs[i][3]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], bc[i][3]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], bi[i][3]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], bl[i][3]); i++;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], ui[i][3]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], us[i][3]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], uc[i][3]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], ui[i][3]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], ul[i][3]); i++;
|
||
+
|
||
+ return i;
|
||
+}
|
||
+
|
||
+int do_perm(void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_vperm_4si (si[i][1], si[i][2], sc[i][3]); i++;
|
||
+ ss[i][0] = __builtin_vsx_vperm_8hi (ss[i][1], ss[i][2], sc[i][3]); i++;
|
||
+ sc[i][0] = __builtin_vsx_vperm_16qi (sc[i][1], sc[i][2], sc[i][3]); i++;
|
||
+ f[i][0] = __builtin_vsx_vperm_4sf (f[i][1], f[i][2], sc[i][3]); i++;
|
||
+ d[i][0] = __builtin_vsx_vperm_2df (d[i][1], d[i][2], sc[i][3]); i++;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_vperm (si[i][1], si[i][2], uc[i][3]); i++;
|
||
+ ss[i][0] = __builtin_vsx_vperm (ss[i][1], ss[i][2], uc[i][3]); i++;
|
||
+ sc[i][0] = __builtin_vsx_vperm (sc[i][1], sc[i][2], uc[i][3]); i++;
|
||
+ f[i][0] = __builtin_vsx_vperm (f[i][1], f[i][2], uc[i][3]); i++;
|
||
+ d[i][0] = __builtin_vsx_vperm (d[i][1], d[i][2], uc[i][3]); i++;
|
||
+
|
||
+ return i;
|
||
+}
|
||
+
|
||
+int do_xxperm (void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ d[i][0] = __builtin_vsx_xxpermdi_2df (d[i][1], d[i][2], 0); i++;
|
||
+ d[i][0] = __builtin_vsx_xxpermdi (d[i][1], d[i][2], 1); i++;
|
||
+ return i;
|
||
+}
|
||
+
|
||
+double x, y;
|
||
+void do_concat (void)
|
||
+{
|
||
+ d[0][0] = __builtin_vsx_concat_2df (x, y);
|
||
+}
|
||
+
|
||
+void do_set (void)
|
||
+{
|
||
+ d[0][0] = __builtin_vsx_set_2df (d[0][1], x, 0);
|
||
+ d[1][0] = __builtin_vsx_set_2df (d[1][1], y, 1);
|
||
+}
|
||
+
|
||
+extern double z[][4];
|
||
+
|
||
+int do_math (void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ d[i][0] = __builtin_vsx_xvrdpi (d[i][1]); i++;
|
||
+ d[i][0] = __builtin_vsx_xvrdpic (d[i][1]); i++;
|
||
+ d[i][0] = __builtin_vsx_xvrdpim (d[i][1]); i++;
|
||
+ d[i][0] = __builtin_vsx_xvrdpip (d[i][1]); i++;
|
||
+ d[i][0] = __builtin_vsx_xvrdpiz (d[i][1]); i++;
|
||
+
|
||
+ f[i][0] = __builtin_vsx_xvrspi (f[i][1]); i++;
|
||
+ f[i][0] = __builtin_vsx_xvrspic (f[i][1]); i++;
|
||
+ f[i][0] = __builtin_vsx_xvrspim (f[i][1]); i++;
|
||
+ f[i][0] = __builtin_vsx_xvrspip (f[i][1]); i++;
|
||
+ f[i][0] = __builtin_vsx_xvrspiz (f[i][1]); i++;
|
||
+
|
||
+ z[i][0] = __builtin_vsx_xsrdpi (z[i][1]); i++;
|
||
+ z[i][0] = __builtin_vsx_xsrdpic (z[i][1]); i++;
|
||
+ z[i][0] = __builtin_vsx_xsrdpim (z[i][1]); i++;
|
||
+ z[i][0] = __builtin_vsx_xsrdpip (z[i][1]); i++;
|
||
+ z[i][0] = __builtin_vsx_xsrdpiz (z[i][1]); i++;
|
||
+ z[i][0] = __builtin_vsx_xsmaxdp (z[i][1], z[i][0]); i++;
|
||
+ z[i][0] = __builtin_vsx_xsmindp (z[i][1], z[i][0]); i++;
|
||
+ return i;
|
||
+}
|
||
+
|
||
+int do_cmp (void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ d[i][0] = __builtin_vsx_xvcmpeqdp (d[i][1], d[i][2]); i++;
|
||
+ d[i][0] = __builtin_vsx_xvcmpgtdp (d[i][1], d[i][2]); i++;
|
||
+ d[i][0] = __builtin_vsx_xvcmpgedp (d[i][1], d[i][2]); i++;
|
||
+
|
||
+ f[i][0] = __builtin_vsx_xvcmpeqsp (f[i][1], f[i][2]); i++;
|
||
+ f[i][0] = __builtin_vsx_xvcmpgtsp (f[i][1], f[i][2]); i++;
|
||
+ f[i][0] = __builtin_vsx_xvcmpgesp (f[i][1], f[i][2]); i++;
|
||
+ return i;
|
||
+}
|
||
+
|
||
+int do_logical (void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_xxland (si[i][1], si[i][2]); i++;
|
||
+ si[i][0] = __builtin_vsx_xxlandc (si[i][1], si[i][2]); i++;
|
||
+ si[i][0] = __builtin_vsx_xxlnor (si[i][1], si[i][2]); i++;
|
||
+ si[i][0] = __builtin_vsx_xxlor (si[i][1], si[i][2]); i++;
|
||
+ si[i][0] = __builtin_vsx_xxlxor (si[i][1], si[i][2]); i++;
|
||
+
|
||
+ ss[i][0] = __builtin_vsx_xxland (ss[i][1], ss[i][2]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxlandc (ss[i][1], ss[i][2]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxlnor (ss[i][1], ss[i][2]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxlor (ss[i][1], ss[i][2]); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxlxor (ss[i][1], ss[i][2]); i++;
|
||
+
|
||
+ sc[i][0] = __builtin_vsx_xxland (sc[i][1], sc[i][2]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxlandc (sc[i][1], sc[i][2]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxlnor (sc[i][1], sc[i][2]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxlor (sc[i][1], sc[i][2]); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxlxor (sc[i][1], sc[i][2]); i++;
|
||
+
|
||
+ d[i][0] = __builtin_vsx_xxland (d[i][1], d[i][2]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxlandc (d[i][1], d[i][2]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxlnor (d[i][1], d[i][2]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxlor (d[i][1], d[i][2]); i++;
|
||
+ d[i][0] = __builtin_vsx_xxlxor (d[i][1], d[i][2]); i++;
|
||
+
|
||
+ f[i][0] = __builtin_vsx_xxland (f[i][1], f[i][2]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxlandc (f[i][1], f[i][2]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxlnor (f[i][1], f[i][2]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxlor (f[i][1], f[i][2]); i++;
|
||
+ f[i][0] = __builtin_vsx_xxlxor (f[i][1], f[i][2]); i++;
|
||
+ return i;
|
||
+}
|
||
+
|
||
+int do_xxsldwi (void)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ si[i][0] = __builtin_vsx_xxsldwi (si[i][1], si[i][2], 0); i++;
|
||
+ ss[i][0] = __builtin_vsx_xxsldwi (ss[i][1], ss[i][2], 1); i++;
|
||
+ sc[i][0] = __builtin_vsx_xxsldwi (sc[i][1], sc[i][2], 2); i++;
|
||
+ ui[i][0] = __builtin_vsx_xxsldwi (ui[i][1], ui[i][2], 3); i++;
|
||
+ us[i][0] = __builtin_vsx_xxsldwi (us[i][1], us[i][2], 0); i++;
|
||
+ uc[i][0] = __builtin_vsx_xxsldwi (uc[i][1], uc[i][2], 1); i++;
|
||
+ f[i][0] = __builtin_vsx_xxsldwi (f[i][1], f[i][2], 2); i++;
|
||
+ d[i][0] = __builtin_vsx_xxsldwi (d[i][1], d[i][2], 3); i++;
|
||
+ return i;
|
||
+}
|
||
--- gcc/config/rs6000/vector.md (revision 146119)
|
||
+++ gcc/config/rs6000/vector.md (revision 146798)
|
||
@@ -39,6 +39,9 @@ (define_mode_iterator VEC_M [V16QI V8HI
|
||
;; Vector comparison modes
|
||
(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
|
||
|
||
+;; Vector init/extract modes
|
||
+(define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
|
||
+
|
||
;; Vector reload iterator
|
||
(define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI])
|
||
|
||
@@ -347,34 +350,13 @@ (define_expand "vector_geu<mode>"
|
||
;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
|
||
;; which is in the reverse order that we want
|
||
(define_expand "vector_vsel<mode>"
|
||
- [(match_operand:VEC_F 0 "vlogical_operand" "")
|
||
- (match_operand:VEC_F 1 "vlogical_operand" "")
|
||
- (match_operand:VEC_F 2 "vlogical_operand" "")
|
||
- (match_operand:VEC_F 3 "vlogical_operand" "")]
|
||
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
|
||
+ (if_then_else:VEC_L (ne (match_operand:VEC_L 3 "vlogical_operand" "")
|
||
+ (const_int 0))
|
||
+ (match_operand:VEC_L 2 "vlogical_operand" "")
|
||
+ (match_operand:VEC_L 1 "vlogical_operand" "")))]
|
||
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||
- "
|
||
-{
|
||
- if (VECTOR_UNIT_VSX_P (<MODE>mode))
|
||
- emit_insn (gen_vsx_vsel<mode> (operands[0], operands[3],
|
||
- operands[2], operands[1]));
|
||
- else
|
||
- emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
|
||
- operands[2], operands[1]));
|
||
- DONE;
|
||
-}")
|
||
-
|
||
-(define_expand "vector_vsel<mode>"
|
||
- [(match_operand:VEC_I 0 "vlogical_operand" "")
|
||
- (match_operand:VEC_I 1 "vlogical_operand" "")
|
||
- (match_operand:VEC_I 2 "vlogical_operand" "")
|
||
- (match_operand:VEC_I 3 "vlogical_operand" "")]
|
||
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
|
||
- "
|
||
-{
|
||
- emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
|
||
- operands[2], operands[1]));
|
||
- DONE;
|
||
-}")
|
||
+ "")
|
||
|
||
|
||
;; Vector logical instructions
|
||
@@ -475,19 +457,23 @@ (define_expand "fixuns_trunc<mode><VEC_i
|
||
|
||
;; Vector initialization, set, extract
|
||
(define_expand "vec_init<mode>"
|
||
- [(match_operand:VEC_C 0 "vlogical_operand" "")
|
||
- (match_operand:VEC_C 1 "vec_init_operand" "")]
|
||
- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||
+ [(match_operand:VEC_E 0 "vlogical_operand" "")
|
||
+ (match_operand:VEC_E 1 "vec_init_operand" "")]
|
||
+ "(<MODE>mode == V2DImode
|
||
+ ? VECTOR_MEM_VSX_P (V2DImode)
|
||
+ : VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode))"
|
||
{
|
||
rs6000_expand_vector_init (operands[0], operands[1]);
|
||
DONE;
|
||
})
|
||
|
||
(define_expand "vec_set<mode>"
|
||
- [(match_operand:VEC_C 0 "vlogical_operand" "")
|
||
+ [(match_operand:VEC_E 0 "vlogical_operand" "")
|
||
(match_operand:<VEC_base> 1 "register_operand" "")
|
||
(match_operand 2 "const_int_operand" "")]
|
||
- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||
+ "(<MODE>mode == V2DImode
|
||
+ ? VECTOR_MEM_VSX_P (V2DImode)
|
||
+ : VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode))"
|
||
{
|
||
rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
|
||
DONE;
|
||
@@ -495,9 +481,11 @@ (define_expand "vec_set<mode>"
|
||
|
||
(define_expand "vec_extract<mode>"
|
||
[(match_operand:<VEC_base> 0 "register_operand" "")
|
||
- (match_operand:VEC_C 1 "vlogical_operand" "")
|
||
+ (match_operand:VEC_E 1 "vlogical_operand" "")
|
||
(match_operand 2 "const_int_operand" "")]
|
||
- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||
+ "(<MODE>mode == V2DImode
|
||
+ ? VECTOR_MEM_VSX_P (V2DImode)
|
||
+ : VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode))"
|
||
{
|
||
rs6000_expand_vector_extract (operands[0], operands[1],
|
||
INTVAL (operands[2]));
|
||
--- gcc/config/rs6000/predicates.md (revision 146119)
|
||
+++ gcc/config/rs6000/predicates.md (revision 146798)
|
||
@@ -327,6 +327,9 @@ (define_predicate "easy_vector_constant"
|
||
if (TARGET_PAIRED_FLOAT)
|
||
return false;
|
||
|
||
+ if ((VSX_VECTOR_MODE (mode) || mode == TImode) && zero_constant (op, mode))
|
||
+ return true;
|
||
+
|
||
if (ALTIVEC_VECTOR_MODE (mode))
|
||
{
|
||
if (zero_constant (op, mode))
|
||
--- gcc/config/rs6000/rs6000-protos.h (revision 146119)
|
||
+++ gcc/config/rs6000/rs6000-protos.h (revision 146798)
|
||
@@ -176,6 +176,8 @@ extern int rs6000_register_move_cost (en
|
||
enum reg_class, enum reg_class);
|
||
extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
|
||
extern bool rs6000_tls_referenced_p (rtx);
|
||
+extern bool rs6000_has_indirect_jump_p (void);
|
||
+extern void rs6000_set_indirect_jump (void);
|
||
extern void rs6000_conditional_register_usage (void);
|
||
|
||
/* Declare functions in rs6000-c.c */
|
||
--- gcc/config/rs6000/rs6000-c.c (revision 146119)
|
||
+++ gcc/config/rs6000/rs6000-c.c (revision 146798)
|
||
@@ -336,7 +336,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
|
||
if (TARGET_NO_LWSYNC)
|
||
builtin_define ("__NO_LWSYNC__");
|
||
if (TARGET_VSX)
|
||
- builtin_define ("__VSX__");
|
||
+ {
|
||
+ builtin_define ("__VSX__");
|
||
+
|
||
+ /* For the VSX builtin functions identical to Altivec functions, just map
|
||
+ the altivec builtin into the vsx version (the altivec functions
|
||
+ generate VSX code if -mvsx). */
|
||
+ builtin_define ("__builtin_vsx_xxland=__builtin_vec_and");
|
||
+ builtin_define ("__builtin_vsx_xxlandc=__builtin_vec_andc");
|
||
+ builtin_define ("__builtin_vsx_xxlnor=__builtin_vec_nor");
|
||
+ builtin_define ("__builtin_vsx_xxlor=__builtin_vec_or");
|
||
+ builtin_define ("__builtin_vsx_xxlxor=__builtin_vec_xor");
|
||
+ builtin_define ("__builtin_vsx_xxsel=__builtin_vec_sel");
|
||
+ builtin_define ("__builtin_vsx_vperm=__builtin_vec_perm");
|
||
+ }
|
||
|
||
/* May be overridden by target configuration. */
|
||
RS6000_CPU_CPP_ENDIAN_BUILTINS();
|
||
@@ -400,7 +413,7 @@ struct altivec_builtin_types
|
||
};
|
||
|
||
const struct altivec_builtin_types altivec_overloaded_builtins[] = {
|
||
- /* Unary AltiVec builtins. */
|
||
+ /* Unary AltiVec/VSX builtins. */
|
||
{ ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V16QI,
|
||
RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
|
||
{ ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V8HI,
|
||
@@ -496,7 +509,7 @@ const struct altivec_builtin_types altiv
|
||
{ ALTIVEC_BUILTIN_VEC_VUPKLSB, ALTIVEC_BUILTIN_VUPKLSB,
|
||
RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
|
||
|
||
- /* Binary AltiVec builtins. */
|
||
+ /* Binary AltiVec/VSX builtins. */
|
||
{ ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
|
||
RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
|
||
{ ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
|
||
@@ -2206,7 +2219,7 @@ const struct altivec_builtin_types altiv
|
||
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
|
||
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
|
||
|
||
- /* Ternary AltiVec builtins. */
|
||
+ /* Ternary AltiVec/VSX builtins. */
|
||
{ ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
|
||
RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
|
||
{ ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
|
||
@@ -2407,6 +2420,10 @@ const struct altivec_builtin_types altiv
|
||
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
|
||
{ ALTIVEC_BUILTIN_VEC_NMSUB, ALTIVEC_BUILTIN_VNMSUBFP,
|
||
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
|
||
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V16QI },
|
||
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DI,
|
||
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V16QI },
|
||
{ ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SF,
|
||
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI },
|
||
{ ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI,
|
||
@@ -2433,11 +2450,29 @@ const struct altivec_builtin_types altiv
|
||
RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
|
||
{ ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
|
||
RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V2DI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI,
|
||
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI,
|
||
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V2DI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI,
|
||
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI },
|
||
{ ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF,
|
||
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI },
|
||
{ ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF,
|
||
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI },
|
||
{ ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
|
||
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
|
||
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SI },
|
||
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
|
||
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI },
|
||
{ ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
|
||
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI },
|
||
@@ -2805,6 +2840,37 @@ const struct altivec_builtin_types altiv
|
||
RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
|
||
{ ALTIVEC_BUILTIN_VEC_STVRXL, ALTIVEC_BUILTIN_STVRXL,
|
||
RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
|
||
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
|
||
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
|
||
+ RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI,
|
||
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI,
|
||
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI,
|
||
+ RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI,
|
||
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI,
|
||
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI,
|
||
+ RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI,
|
||
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI,
|
||
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
|
||
+ RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SF,
|
||
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DF,
|
||
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI,
|
||
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE },
|
||
+ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI,
|
||
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
|
||
+ RS6000_BTI_NOT_OPAQUE },
|
||
|
||
/* Predicates. */
|
||
{ ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
|
||
@@ -3108,6 +3174,10 @@ altivec_resolve_overloaded_builtin (tree
|
||
goto bad;
|
||
switch (TYPE_MODE (type))
|
||
{
|
||
+ case DImode:
|
||
+ type = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
|
||
+ size = 2;
|
||
+ break;
|
||
case SImode:
|
||
type = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
|
||
size = 4;
|
||
@@ -3121,6 +3191,7 @@ altivec_resolve_overloaded_builtin (tree
|
||
size = 16;
|
||
break;
|
||
case SFmode: type = V4SF_type_node; size = 4; break;
|
||
+ case DFmode: type = V2DF_type_node; size = 2; break;
|
||
default:
|
||
goto bad;
|
||
}
|
||
--- gcc/config/rs6000/rs6000.opt (revision 146119)
|
||
+++ gcc/config/rs6000/rs6000.opt (revision 146798)
|
||
@@ -119,18 +119,6 @@ mvsx
|
||
Target Report Mask(VSX)
|
||
Use vector/scalar (VSX) instructions
|
||
|
||
-mvsx-vector-memory
|
||
-Target Undocumented Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
|
||
-; If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
|
||
-
|
||
-mvsx-vector-float
|
||
-Target Undocumented Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
|
||
-; If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
|
||
-
|
||
-mvsx-vector-double
|
||
-Target Undocumented Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
|
||
-; If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
|
||
-
|
||
mvsx-scalar-double
|
||
Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
|
||
; If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
|
||
@@ -139,18 +127,14 @@ mvsx-scalar-memory
|
||
Target Undocumented Report Var(TARGET_VSX_SCALAR_MEMORY)
|
||
; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
|
||
|
||
-mvsx-v4sf-altivec-regs
|
||
-Target Undocumented Report Var(TARGET_V4SF_ALTIVEC_REGS) Init(-1)
|
||
-; If -mvsx, prefer V4SF types to use Altivec regs and not the floating registers
|
||
-
|
||
-mreload-functions
|
||
-Target Undocumented Report Var(TARGET_RELOAD_FUNCTIONS) Init(-1)
|
||
-; If -mvsx or -maltivec, enable reload functions
|
||
-
|
||
mpower7-adjust-cost
|
||
Target Undocumented Var(TARGET_POWER7_ADJUST_COST)
|
||
; Add extra cost for setting CR registers before a branch like is done for Power5
|
||
|
||
+mallow-timode
|
||
+Target Undocumented Var(TARGET_ALLOW_TIMODE)
|
||
+; Allow VSX/Altivec to target loading TImode variables.
|
||
+
|
||
mdisallow-float-in-lr-ctr
|
||
Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1)
|
||
; Disallow floating point in LR or CTR, causes some reload bugs
|
||
--- gcc/config/rs6000/rs6000.c (revision 146119)
|
||
+++ gcc/config/rs6000/rs6000.c (revision 146798)
|
||
@@ -130,6 +130,8 @@ typedef struct machine_function GTY(())
|
||
64-bits wide and is allocated early enough so that the offset
|
||
does not overflow the 16-bit load/store offset field. */
|
||
rtx sdmode_stack_slot;
|
||
+ /* Whether an indirect jump or table jump was generated. */
|
||
+ bool indirect_jump_p;
|
||
} machine_function;
|
||
|
||
/* Target cpu type */
|
||
@@ -917,6 +919,11 @@ static rtx rs6000_expand_binop_builtin (
|
||
static rtx rs6000_expand_ternop_builtin (enum insn_code, tree, rtx);
|
||
static rtx rs6000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
|
||
static void altivec_init_builtins (void);
|
||
+static unsigned builtin_hash_function (const void *);
|
||
+static int builtin_hash_eq (const void *, const void *);
|
||
+static tree builtin_function_type (enum machine_mode, enum machine_mode,
|
||
+ enum machine_mode, enum machine_mode,
|
||
+ const char *name);
|
||
static void rs6000_common_init_builtins (void);
|
||
static void rs6000_init_libfuncs (void);
|
||
|
||
@@ -1018,6 +1025,8 @@ static enum reg_class rs6000_secondary_r
|
||
enum machine_mode,
|
||
struct secondary_reload_info *);
|
||
|
||
+static const enum reg_class *rs6000_ira_cover_classes (void);
|
||
+
|
||
const int INSN_NOT_AVAILABLE = -1;
|
||
static enum machine_mode rs6000_eh_return_filter_mode (void);
|
||
|
||
@@ -1033,6 +1042,16 @@ struct toc_hash_struct GTY(())
|
||
};
|
||
|
||
static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
|
||
+
|
||
+/* Hash table to keep track of the argument types for builtin functions. */
|
||
+
|
||
+struct builtin_hash_struct GTY(())
|
||
+{
|
||
+ tree type;
|
||
+ enum machine_mode mode[4]; /* return value + 3 arguments */
|
||
+};
|
||
+
|
||
+static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table;
|
||
|
||
/* Default register names. */
|
||
char rs6000_reg_names[][8] =
|
||
@@ -1350,6 +1369,9 @@ static const char alt_reg_names[][8] =
|
||
#undef TARGET_SECONDARY_RELOAD
|
||
#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
|
||
|
||
+#undef TARGET_IRA_COVER_CLASSES
|
||
+#define TARGET_IRA_COVER_CLASSES rs6000_ira_cover_classes
|
||
+
|
||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||
|
||
/* Return number of consecutive hard regs needed starting at reg REGNO
|
||
@@ -1370,7 +1392,7 @@ rs6000_hard_regno_nregs_internal (int re
|
||
unsigned HOST_WIDE_INT reg_size;
|
||
|
||
if (FP_REGNO_P (regno))
|
||
- reg_size = (VECTOR_UNIT_VSX_P (mode)
|
||
+ reg_size = (VECTOR_MEM_VSX_P (mode)
|
||
? UNITS_PER_VSX_WORD
|
||
: UNITS_PER_FP_WORD);
|
||
|
||
@@ -1452,7 +1474,7 @@ rs6000_hard_regno_mode_ok (int regno, en
|
||
|
||
/* AltiVec only in AldyVec registers. */
|
||
if (ALTIVEC_REGNO_P (regno))
|
||
- return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode);
|
||
+ return VECTOR_MEM_ALTIVEC_OR_VSX_P (mode);
|
||
|
||
/* ...but GPRs can hold SIMD data on the SPE in one register. */
|
||
if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
|
||
@@ -1613,10 +1635,8 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
rs6000_vector_reload[m][1] = CODE_FOR_nothing;
|
||
}
|
||
|
||
- /* TODO, add TI/V2DI mode for moving data if Altivec or VSX. */
|
||
-
|
||
/* V2DF mode, VSX only. */
|
||
- if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE)
|
||
+ if (float_p && TARGET_VSX)
|
||
{
|
||
rs6000_vector_unit[V2DFmode] = VECTOR_VSX;
|
||
rs6000_vector_mem[V2DFmode] = VECTOR_VSX;
|
||
@@ -1624,17 +1644,11 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
}
|
||
|
||
/* V4SF mode, either VSX or Altivec. */
|
||
- if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_FLOAT)
|
||
+ if (float_p && TARGET_VSX)
|
||
{
|
||
rs6000_vector_unit[V4SFmode] = VECTOR_VSX;
|
||
- if (TARGET_VSX_VECTOR_MEMORY || !TARGET_ALTIVEC)
|
||
- {
|
||
- rs6000_vector_align[V4SFmode] = 32;
|
||
- rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
|
||
- } else {
|
||
- rs6000_vector_align[V4SFmode] = 128;
|
||
- rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
|
||
- }
|
||
+ rs6000_vector_align[V4SFmode] = 32;
|
||
+ rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
|
||
}
|
||
else if (float_p && TARGET_ALTIVEC)
|
||
{
|
||
@@ -1655,7 +1669,7 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
|
||
rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
|
||
|
||
- if (TARGET_VSX && TARGET_VSX_VECTOR_MEMORY)
|
||
+ if (TARGET_VSX)
|
||
{
|
||
rs6000_vector_mem[V4SImode] = VECTOR_VSX;
|
||
rs6000_vector_mem[V8HImode] = VECTOR_VSX;
|
||
@@ -1675,6 +1689,23 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
}
|
||
}
|
||
|
||
+ /* V2DImode, prefer vsx over altivec, since the main use will be for
|
||
+ vectorized floating point conversions. */
|
||
+ if (float_p && TARGET_VSX)
|
||
+ {
|
||
+ rs6000_vector_mem[V2DImode] = VECTOR_VSX;
|
||
+ rs6000_vector_unit[V2DImode] = VECTOR_NONE;
|
||
+ rs6000_vector_reg_class[V2DImode] = vsx_rc;
|
||
+ rs6000_vector_align[V2DImode] = 64;
|
||
+ }
|
||
+ else if (TARGET_ALTIVEC)
|
||
+ {
|
||
+ rs6000_vector_mem[V2DImode] = VECTOR_ALTIVEC;
|
||
+ rs6000_vector_unit[V2DImode] = VECTOR_NONE;
|
||
+ rs6000_vector_reg_class[V2DImode] = ALTIVEC_REGS;
|
||
+ rs6000_vector_align[V2DImode] = 128;
|
||
+ }
|
||
+
|
||
/* DFmode, see if we want to use the VSX unit. */
|
||
if (float_p && TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
|
||
{
|
||
@@ -1684,16 +1715,30 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
= (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
|
||
}
|
||
|
||
- /* TODO, add SPE and paired floating point vector support. */
|
||
+ /* TImode. Until this is debugged, only add it under switch control. */
|
||
+ if (TARGET_ALLOW_TIMODE)
|
||
+ {
|
||
+ if (float_p && TARGET_VSX)
|
||
+ {
|
||
+ rs6000_vector_mem[TImode] = VECTOR_VSX;
|
||
+ rs6000_vector_unit[TImode] = VECTOR_NONE;
|
||
+ rs6000_vector_reg_class[TImode] = vsx_rc;
|
||
+ rs6000_vector_align[TImode] = 64;
|
||
+ }
|
||
+ else if (TARGET_ALTIVEC)
|
||
+ {
|
||
+ rs6000_vector_mem[TImode] = VECTOR_ALTIVEC;
|
||
+ rs6000_vector_unit[TImode] = VECTOR_NONE;
|
||
+ rs6000_vector_reg_class[TImode] = ALTIVEC_REGS;
|
||
+ rs6000_vector_align[TImode] = 128;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* TODO add SPE and paired floating point vector support. */
|
||
|
||
/* Set the VSX register classes. */
|
||
-
|
||
- /* For V4SF, prefer the Altivec registers, because there are a few operations
|
||
- that want to use Altivec operations instead of VSX. */
|
||
rs6000_vector_reg_class[V4SFmode]
|
||
- = ((VECTOR_UNIT_VSX_P (V4SFmode)
|
||
- && VECTOR_MEM_VSX_P (V4SFmode)
|
||
- && !TARGET_V4SF_ALTIVEC_REGS)
|
||
+ = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
|
||
? vsx_rc
|
||
: (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
|
||
? ALTIVEC_REGS
|
||
@@ -1712,7 +1757,7 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
|
||
|
||
/* Set up the reload helper functions. */
|
||
- if (TARGET_RELOAD_FUNCTIONS && (TARGET_VSX || TARGET_ALTIVEC))
|
||
+ if (TARGET_VSX || TARGET_ALTIVEC)
|
||
{
|
||
if (TARGET_64BIT)
|
||
{
|
||
@@ -1728,6 +1773,11 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_di_load;
|
||
rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_di_store;
|
||
rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_di_load;
|
||
+ if (TARGET_ALLOW_TIMODE)
|
||
+ {
|
||
+ rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_di_store;
|
||
+ rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_di_load;
|
||
+ }
|
||
}
|
||
else
|
||
{
|
||
@@ -1743,6 +1793,11 @@ rs6000_init_hard_regno_mode_ok (void)
|
||
rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_si_load;
|
||
rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_si_store;
|
||
rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_si_load;
|
||
+ if (TARGET_ALLOW_TIMODE)
|
||
+ {
|
||
+ rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_si_store;
|
||
+ rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_si_load;
|
||
+ }
|
||
}
|
||
}
|
||
|
||
@@ -2132,23 +2187,29 @@ rs6000_override_options (const char *def
|
||
const char *msg = NULL;
|
||
if (!TARGET_HARD_FLOAT || !TARGET_FPRS
|
||
|| !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT)
|
||
- msg = "-mvsx requires hardware floating point";
|
||
+ {
|
||
+ if (target_flags_explicit & MASK_VSX)
|
||
+ msg = N_("-mvsx requires hardware floating point");
|
||
+ else
|
||
+ target_flags &= ~ MASK_VSX;
|
||
+ }
|
||
else if (TARGET_PAIRED_FLOAT)
|
||
- msg = "-mvsx and -mpaired are incompatible";
|
||
+ msg = N_("-mvsx and -mpaired are incompatible");
|
||
/* The hardware will allow VSX and little endian, but until we make sure
|
||
things like vector select, etc. work don't allow VSX on little endian
|
||
systems at this point. */
|
||
else if (!BYTES_BIG_ENDIAN)
|
||
- msg = "-mvsx used with little endian code";
|
||
+ msg = N_("-mvsx used with little endian code");
|
||
else if (TARGET_AVOID_XFORM > 0)
|
||
- msg = "-mvsx needs indexed addressing";
|
||
+ msg = N_("-mvsx needs indexed addressing");
|
||
|
||
if (msg)
|
||
{
|
||
warning (0, msg);
|
||
- target_flags &= MASK_VSX;
|
||
+ target_flags &= ~ MASK_VSX;
|
||
}
|
||
- else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC) == 0)
|
||
+ else if (TARGET_VSX && !TARGET_ALTIVEC
|
||
+ && (target_flags_explicit & MASK_ALTIVEC) == 0)
|
||
target_flags |= MASK_ALTIVEC;
|
||
}
|
||
|
||
@@ -2581,8 +2642,8 @@ rs6000_builtin_conversion (enum tree_cod
|
||
return NULL_TREE;
|
||
|
||
return TYPE_UNSIGNED (type)
|
||
- ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP]
|
||
- : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP];
|
||
+ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP]
|
||
+ : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP];
|
||
|
||
case V4SImode:
|
||
if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
|
||
@@ -3780,15 +3841,28 @@ rs6000_expand_vector_init (rtx target, r
|
||
}
|
||
}
|
||
|
||
- if (mode == V2DFmode)
|
||
+ if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
|
||
{
|
||
- gcc_assert (TARGET_VSX);
|
||
+ rtx (*splat) (rtx, rtx);
|
||
+ rtx (*concat) (rtx, rtx, rtx);
|
||
+
|
||
+ if (mode == V2DFmode)
|
||
+ {
|
||
+ splat = gen_vsx_splat_v2df;
|
||
+ concat = gen_vsx_concat_v2df;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ splat = gen_vsx_splat_v2di;
|
||
+ concat = gen_vsx_concat_v2di;
|
||
+ }
|
||
+
|
||
if (all_same)
|
||
- emit_insn (gen_vsx_splatv2df (target, XVECEXP (vals, 0, 0)));
|
||
+ emit_insn (splat (target, XVECEXP (vals, 0, 0)));
|
||
else
|
||
- emit_insn (gen_vsx_concat_v2df (target,
|
||
- copy_to_reg (XVECEXP (vals, 0, 0)),
|
||
- copy_to_reg (XVECEXP (vals, 0, 1))));
|
||
+ emit_insn (concat (target,
|
||
+ copy_to_reg (XVECEXP (vals, 0, 0)),
|
||
+ copy_to_reg (XVECEXP (vals, 0, 1))));
|
||
return;
|
||
}
|
||
|
||
@@ -3851,10 +3925,12 @@ rs6000_expand_vector_set (rtx target, rt
|
||
int width = GET_MODE_SIZE (inner_mode);
|
||
int i;
|
||
|
||
- if (mode == V2DFmode)
|
||
+ if (mode == V2DFmode || mode == V2DImode)
|
||
{
|
||
+ rtx (*set_func) (rtx, rtx, rtx, rtx)
|
||
+ = ((mode == V2DFmode) ? gen_vsx_set_v2df : gen_vsx_set_v2di);
|
||
gcc_assert (TARGET_VSX);
|
||
- emit_insn (gen_vsx_set_v2df (target, val, target, GEN_INT (elt)));
|
||
+ emit_insn (set_func (target, val, target, GEN_INT (elt)));
|
||
return;
|
||
}
|
||
|
||
@@ -3895,10 +3971,12 @@ rs6000_expand_vector_extract (rtx target
|
||
enum machine_mode inner_mode = GET_MODE_INNER (mode);
|
||
rtx mem, x;
|
||
|
||
- if (mode == V2DFmode)
|
||
+ if (mode == V2DFmode || mode == V2DImode)
|
||
{
|
||
+ rtx (*extract_func) (rtx, rtx, rtx)
|
||
+ = ((mode == V2DFmode) ? gen_vsx_extract_v2df : gen_vsx_extract_v2di);
|
||
gcc_assert (TARGET_VSX);
|
||
- emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt)));
|
||
+ emit_insn (extract_func (target, vec, GEN_INT (elt)));
|
||
return;
|
||
}
|
||
|
||
@@ -4318,9 +4396,7 @@ avoiding_indexed_address_p (enum machine
|
||
{
|
||
/* Avoid indexed addressing for modes that have non-indexed
|
||
load/store instruction forms. */
|
||
- return (TARGET_AVOID_XFORM
|
||
- && (!TARGET_ALTIVEC || !ALTIVEC_VECTOR_MODE (mode))
|
||
- && (!TARGET_VSX || !VSX_VECTOR_MODE (mode)));
|
||
+ return (TARGET_AVOID_XFORM && VECTOR_MEM_NONE_P (mode));
|
||
}
|
||
|
||
inline bool
|
||
@@ -4443,6 +4519,16 @@ rs6000_legitimize_address (rtx x, rtx ol
|
||
ret = rs6000_legitimize_tls_address (x, model);
|
||
}
|
||
|
||
+ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
|
||
+ {
|
||
+ /* Make sure both operands are registers. */
|
||
+ if (GET_CODE (x) == PLUS)
|
||
+ ret = gen_rtx_PLUS (Pmode,
|
||
+ force_reg (Pmode, XEXP (x, 0)),
|
||
+ force_reg (Pmode, XEXP (x, 1)));
|
||
+ else
|
||
+ ret = force_reg (Pmode, x);
|
||
+ }
|
||
else if (GET_CODE (x) == PLUS
|
||
&& GET_CODE (XEXP (x, 0)) == REG
|
||
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
||
@@ -4452,8 +4538,6 @@ rs6000_legitimize_address (rtx x, rtx ol
|
||
&& (mode == DImode || mode == TImode)
|
||
&& (INTVAL (XEXP (x, 1)) & 3) != 0)
|
||
|| (TARGET_SPE && SPE_VECTOR_MODE (mode))
|
||
- || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
|
||
- || (TARGET_VSX && VSX_VECTOR_MODE (mode))
|
||
|| (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
|
||
|| mode == DImode || mode == DDmode
|
||
|| mode == TDmode))))
|
||
@@ -4485,15 +4569,6 @@ rs6000_legitimize_address (rtx x, rtx ol
|
||
ret = gen_rtx_PLUS (Pmode, XEXP (x, 0),
|
||
force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
|
||
}
|
||
- else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
|
||
- {
|
||
- /* Make sure both operands are registers. */
|
||
- if (GET_CODE (x) == PLUS)
|
||
- ret = gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
|
||
- force_reg (Pmode, XEXP (x, 1)));
|
||
- else
|
||
- ret = force_reg (Pmode, x);
|
||
- }
|
||
else if ((TARGET_SPE && SPE_VECTOR_MODE (mode))
|
||
|| (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
|
||
|| mode == DDmode || mode == TDmode
|
||
@@ -5131,7 +5206,7 @@ rs6000_legitimate_address (enum machine_
|
||
ret = 1;
|
||
else if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
|
||
ret = 1;
|
||
- else if (mode != TImode
|
||
+ else if ((mode != TImode || !VECTOR_MEM_NONE_P (TImode))
|
||
&& mode != TFmode
|
||
&& mode != TDmode
|
||
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|
||
@@ -5971,7 +6046,13 @@ rs6000_emit_move (rtx dest, rtx source,
|
||
|
||
case TImode:
|
||
if (VECTOR_MEM_ALTIVEC_OR_VSX_P (TImode))
|
||
- break;
|
||
+ {
|
||
+ if (CONSTANT_P (operands[1])
|
||
+ && !easy_vector_constant (operands[1], mode))
|
||
+ operands[1] = force_const_mem (mode, operands[1]);
|
||
+
|
||
+ break;
|
||
+ }
|
||
|
||
rs6000_eliminate_indexed_memrefs (operands);
|
||
|
||
@@ -7888,7 +7969,8 @@ def_builtin (int mask, const char *name,
|
||
if ((mask & target_flags) || TARGET_PAIRED_FLOAT)
|
||
{
|
||
if (rs6000_builtin_decls[code])
|
||
- abort ();
|
||
+ fatal_error ("internal error: builtin function to %s already processed.",
|
||
+ name);
|
||
|
||
rs6000_builtin_decls[code] =
|
||
add_builtin_function (name, type, code, BUILT_IN_MD,
|
||
@@ -7953,6 +8035,34 @@ static const struct builtin_description
|
||
{ MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP },
|
||
{ MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP },
|
||
|
||
+ { MASK_VSX, CODE_FOR_vector_vselv2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI },
|
||
+ { MASK_VSX, CODE_FOR_vector_vselv2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF },
|
||
+ { MASK_VSX, CODE_FOR_vector_vselv4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF },
|
||
+ { MASK_VSX, CODE_FOR_vector_vselv4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI },
|
||
+ { MASK_VSX, CODE_FOR_vector_vselv8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI },
|
||
+ { MASK_VSX, CODE_FOR_vector_vselv16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_altivec_vperm_v2di, "__builtin_vsx_vperm_2di", VSX_BUILTIN_VPERM_2DI },
|
||
+ { MASK_VSX, CODE_FOR_altivec_vperm_v2df, "__builtin_vsx_vperm_2df", VSX_BUILTIN_VPERM_2DF },
|
||
+ { MASK_VSX, CODE_FOR_altivec_vperm_v4sf, "__builtin_vsx_vperm_4sf", VSX_BUILTIN_VPERM_4SF },
|
||
+ { MASK_VSX, CODE_FOR_altivec_vperm_v4si, "__builtin_vsx_vperm_4si", VSX_BUILTIN_VPERM_4SI },
|
||
+ { MASK_VSX, CODE_FOR_altivec_vperm_v8hi, "__builtin_vsx_vperm_8hi", VSX_BUILTIN_VPERM_8HI },
|
||
+ { MASK_VSX, CODE_FOR_altivec_vperm_v16qi, "__builtin_vsx_vperm_16qi", VSX_BUILTIN_VPERM_16QI },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2df, "__builtin_vsx_xxpermdi_2df", VSX_BUILTIN_XXPERMDI_2DF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2di, "__builtin_vsx_xxpermdi_2di", VSX_BUILTIN_XXPERMDI_2DI },
|
||
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxpermdi", VSX_BUILTIN_VEC_XXPERMDI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_set_v2df, "__builtin_vsx_set_2df", VSX_BUILTIN_SET_2DF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_set_v2di, "__builtin_vsx_set_2di", VSX_BUILTIN_SET_2DI },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2di, "__builtin_vsx_xxsldwi_2di", VSX_BUILTIN_XXSLDWI_2DI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2df, "__builtin_vsx_xxsldwi_2df", VSX_BUILTIN_XXSLDWI_2DF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4sf, "__builtin_vsx_xxsldwi_4sf", VSX_BUILTIN_XXSLDWI_4SF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4si, "__builtin_vsx_xxsldwi_4si", VSX_BUILTIN_XXSLDWI_4SI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v8hi, "__builtin_vsx_xxsldwi_8hi", VSX_BUILTIN_XXSLDWI_8HI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v16qi, "__builtin_vsx_xxsldwi_16qi", VSX_BUILTIN_XXSLDWI_16QI },
|
||
+ { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxsldwi", VSX_BUILTIN_VEC_XXSLDWI },
|
||
+
|
||
{ 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB },
|
||
{ 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD },
|
||
{ 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 },
|
||
@@ -8102,6 +8212,9 @@ static struct builtin_description bdesc_
|
||
{ MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP },
|
||
{ MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP },
|
||
{ MASK_VSX, CODE_FOR_vsx_tdivv2df3, "__builtin_vsx_xvtdivdp", VSX_BUILTIN_XVTDIVDP },
|
||
+ { MASK_VSX, CODE_FOR_vector_eqv2df, "__builtin_vsx_xvcmpeqdp", VSX_BUILTIN_XVCMPEQDP },
|
||
+ { MASK_VSX, CODE_FOR_vector_gtv2df, "__builtin_vsx_xvcmpgtdp", VSX_BUILTIN_XVCMPGTDP },
|
||
+ { MASK_VSX, CODE_FOR_vector_gev2df, "__builtin_vsx_xvcmpgedp", VSX_BUILTIN_XVCMPGEDP },
|
||
|
||
{ MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP },
|
||
{ MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP },
|
||
@@ -8110,6 +8223,21 @@ static struct builtin_description bdesc_
|
||
{ MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP },
|
||
{ MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP },
|
||
{ MASK_VSX, CODE_FOR_vsx_tdivv4sf3, "__builtin_vsx_xvtdivsp", VSX_BUILTIN_XVTDIVSP },
|
||
+ { MASK_VSX, CODE_FOR_vector_eqv4sf, "__builtin_vsx_xvcmpeqsp", VSX_BUILTIN_XVCMPEQSP },
|
||
+ { MASK_VSX, CODE_FOR_vector_gtv4sf, "__builtin_vsx_xvcmpgtsp", VSX_BUILTIN_XVCMPGTSP },
|
||
+ { MASK_VSX, CODE_FOR_vector_gev4sf, "__builtin_vsx_xvcmpgesp", VSX_BUILTIN_XVCMPGESP },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_smindf3, "__builtin_vsx_xsmindp", VSX_BUILTIN_XSMINDP },
|
||
+ { MASK_VSX, CODE_FOR_smaxdf3, "__builtin_vsx_xsmaxdp", VSX_BUILTIN_XSMAXDP },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_concat_v2df, "__builtin_vsx_concat_2df", VSX_BUILTIN_CONCAT_2DF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_concat_v2di, "__builtin_vsx_concat_2di", VSX_BUILTIN_CONCAT_2DI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_splat_v2df, "__builtin_vsx_splat_2df", VSX_BUILTIN_SPLAT_2DF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_splat_v2di, "__builtin_vsx_splat_2di", VSX_BUILTIN_SPLAT_2DI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4sf, "__builtin_vsx_xxmrghw", VSX_BUILTIN_XXMRGHW_4SF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4si, "__builtin_vsx_xxmrghw_4si", VSX_BUILTIN_XXMRGHW_4SI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4sf, "__builtin_vsx_xxmrglw", VSX_BUILTIN_XXMRGLW_4SF },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4si, "__builtin_vsx_xxmrglw_4si", VSX_BUILTIN_XXMRGLW_4SI },
|
||
|
||
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
|
||
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
|
||
@@ -8527,6 +8655,47 @@ static struct builtin_description bdesc_
|
||
{ MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2, "__builtin_vsx_xvtsqrtsp", VSX_BUILTIN_XVTSQRTSP },
|
||
{ MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP },
|
||
|
||
+ { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvdpsp", VSX_BUILTIN_XSCVDPSP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvspdp", VSX_BUILTIN_XSCVSPDP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvdpsp, "__builtin_vsx_xvcvdpsp", VSX_BUILTIN_XVCVDPSP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvspdp, "__builtin_vsx_xvcvspdp", VSX_BUILTIN_XVCVSPDP },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_fix_truncv2dfv2di2, "__builtin_vsx_xvcvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_fix_truncv4sfv4si2, "__builtin_vsx_xvcvspsxws", VSX_BUILTIN_XVCVSPSXWS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv4sfv4si2, "__builtin_vsx_xvcvspuxws", VSX_BUILTIN_XVCVSPUXWS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXWSP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floatunsv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvdpsxws, "__builtin_vsx_xvcvdpsxws", VSX_BUILTIN_XVCVDPSXWS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvdpuxws, "__builtin_vsx_xvcvdpuxws", VSX_BUILTIN_XVCVDPUXWS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvsxwdp, "__builtin_vsx_xvcvsxwdp", VSX_BUILTIN_XVCVSXWDP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvuxwdp, "__builtin_vsx_xvcvuxwdp", VSX_BUILTIN_XVCVUXWDP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvrdpi, "__builtin_vsx_xvrdpi", VSX_BUILTIN_XVRDPI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvrdpic, "__builtin_vsx_xvrdpic", VSX_BUILTIN_XVRDPIC },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floorv2df2, "__builtin_vsx_xvrdpim", VSX_BUILTIN_XVRDPIM },
|
||
+ { MASK_VSX, CODE_FOR_vsx_ceilv2df2, "__builtin_vsx_xvrdpip", VSX_BUILTIN_XVRDPIP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_btruncv2df2, "__builtin_vsx_xvrdpiz", VSX_BUILTIN_XVRDPIZ },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvspsxds, "__builtin_vsx_xvcvspsxds", VSX_BUILTIN_XVCVSPSXDS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvspuxds, "__builtin_vsx_xvcvspuxds", VSX_BUILTIN_XVCVSPUXDS },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvsxdsp, "__builtin_vsx_xvcvsxdsp", VSX_BUILTIN_XVCVSXDSP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvcvuxdsp, "__builtin_vsx_xvcvuxdsp", VSX_BUILTIN_XVCVUXDSP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvrspi, "__builtin_vsx_xvrspi", VSX_BUILTIN_XVRSPI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xvrspic, "__builtin_vsx_xvrspic", VSX_BUILTIN_XVRSPIC },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floorv4sf2, "__builtin_vsx_xvrspim", VSX_BUILTIN_XVRSPIM },
|
||
+ { MASK_VSX, CODE_FOR_vsx_ceilv4sf2, "__builtin_vsx_xvrspip", VSX_BUILTIN_XVRSPIP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_btruncv4sf2, "__builtin_vsx_xvrspiz", VSX_BUILTIN_XVRSPIZ },
|
||
+
|
||
+ { MASK_VSX, CODE_FOR_vsx_xsrdpi, "__builtin_vsx_xsrdpi", VSX_BUILTIN_XSRDPI },
|
||
+ { MASK_VSX, CODE_FOR_vsx_xsrdpic, "__builtin_vsx_xsrdpic", VSX_BUILTIN_XSRDPIC },
|
||
+ { MASK_VSX, CODE_FOR_vsx_floordf2, "__builtin_vsx_xsrdpim", VSX_BUILTIN_XSRDPIM },
|
||
+ { MASK_VSX, CODE_FOR_vsx_ceildf2, "__builtin_vsx_xsrdpip", VSX_BUILTIN_XSRDPIP },
|
||
+ { MASK_VSX, CODE_FOR_vsx_btruncdf2, "__builtin_vsx_xsrdpiz", VSX_BUILTIN_XSRDPIZ },
|
||
+
|
||
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
|
||
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
|
||
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
|
||
@@ -8552,15 +8721,6 @@ static struct builtin_description bdesc_
|
||
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
|
||
{ MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
|
||
|
||
- { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
|
||
- { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
|
||
- { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
|
||
- { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
|
||
- { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP },
|
||
- { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
|
||
- { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS },
|
||
- { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS },
|
||
-
|
||
/* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
|
||
end with SPE_BUILTIN_EVSUBFUSIAAW. */
|
||
{ 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
|
||
@@ -9065,11 +9225,12 @@ rs6000_expand_ternop_builtin (enum insn_
|
||
|| arg2 == error_mark_node)
|
||
return const0_rtx;
|
||
|
||
- if (icode == CODE_FOR_altivec_vsldoi_v4sf
|
||
- || icode == CODE_FOR_altivec_vsldoi_v4si
|
||
- || icode == CODE_FOR_altivec_vsldoi_v8hi
|
||
- || icode == CODE_FOR_altivec_vsldoi_v16qi)
|
||
+ switch (icode)
|
||
{
|
||
+ case CODE_FOR_altivec_vsldoi_v4sf:
|
||
+ case CODE_FOR_altivec_vsldoi_v4si:
|
||
+ case CODE_FOR_altivec_vsldoi_v8hi:
|
||
+ case CODE_FOR_altivec_vsldoi_v16qi:
|
||
/* Only allow 4-bit unsigned literals. */
|
||
STRIP_NOPS (arg2);
|
||
if (TREE_CODE (arg2) != INTEGER_CST
|
||
@@ -9078,6 +9239,40 @@ rs6000_expand_ternop_builtin (enum insn_
|
||
error ("argument 3 must be a 4-bit unsigned literal");
|
||
return const0_rtx;
|
||
}
|
||
+ break;
|
||
+
|
||
+ case CODE_FOR_vsx_xxpermdi_v2df:
|
||
+ case CODE_FOR_vsx_xxpermdi_v2di:
|
||
+ case CODE_FOR_vsx_xxsldwi_v16qi:
|
||
+ case CODE_FOR_vsx_xxsldwi_v8hi:
|
||
+ case CODE_FOR_vsx_xxsldwi_v4si:
|
||
+ case CODE_FOR_vsx_xxsldwi_v4sf:
|
||
+ case CODE_FOR_vsx_xxsldwi_v2di:
|
||
+ case CODE_FOR_vsx_xxsldwi_v2df:
|
||
+ /* Only allow 2-bit unsigned literals. */
|
||
+ STRIP_NOPS (arg2);
|
||
+ if (TREE_CODE (arg2) != INTEGER_CST
|
||
+ || TREE_INT_CST_LOW (arg2) & ~0x3)
|
||
+ {
|
||
+ error ("argument 3 must be a 2-bit unsigned literal");
|
||
+ return const0_rtx;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case CODE_FOR_vsx_set_v2df:
|
||
+ case CODE_FOR_vsx_set_v2di:
|
||
+ /* Only allow 1-bit unsigned literals. */
|
||
+ STRIP_NOPS (arg2);
|
||
+ if (TREE_CODE (arg2) != INTEGER_CST
|
||
+ || TREE_INT_CST_LOW (arg2) & ~0x1)
|
||
+ {
|
||
+ error ("argument 3 must be a 1-bit unsigned literal");
|
||
+ return const0_rtx;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
}
|
||
|
||
if (target == 0
|
||
@@ -9385,8 +9580,10 @@ altivec_expand_builtin (tree exp, rtx ta
|
||
enum machine_mode tmode, mode0;
|
||
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
|
||
|
||
- if (fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
- && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
|
||
+ if ((fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
+ && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
|
||
+ || (fcode >= VSX_BUILTIN_OVERLOADED_FIRST
|
||
+ && fcode <= VSX_BUILTIN_OVERLOADED_LAST))
|
||
{
|
||
*expandedp = true;
|
||
error ("unresolved overload for Altivec builtin %qF", fndecl);
|
||
@@ -10175,6 +10372,7 @@ rs6000_init_builtins (void)
|
||
unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
|
||
unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
|
||
unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
|
||
+ unsigned_V2DI_type_node = build_vector_type (unsigned_intDI_type_node, 2);
|
||
|
||
opaque_V2SF_type_node = build_opaque_vector_type (float_type_node, 2);
|
||
opaque_V2SI_type_node = build_opaque_vector_type (intSI_type_node, 2);
|
||
@@ -10188,6 +10386,7 @@ rs6000_init_builtins (void)
|
||
bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node);
|
||
bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
|
||
bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node);
|
||
+ bool_long_type_node = build_distinct_type_copy (unsigned_intDI_type_node);
|
||
pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
|
||
|
||
long_integer_type_internal_node = long_integer_type_node;
|
||
@@ -10220,6 +10419,7 @@ rs6000_init_builtins (void)
|
||
bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16);
|
||
bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8);
|
||
bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4);
|
||
+ bool_V2DI_type_node = build_vector_type (bool_long_type_node, 2);
|
||
pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8);
|
||
|
||
(*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
|
||
@@ -10260,9 +10460,17 @@ rs6000_init_builtins (void)
|
||
pixel_V8HI_type_node));
|
||
|
||
if (TARGET_VSX)
|
||
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
|
||
- get_identifier ("__vector double"),
|
||
- V2DF_type_node));
|
||
+ {
|
||
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
|
||
+ get_identifier ("__vector double"),
|
||
+ V2DF_type_node));
|
||
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
|
||
+ get_identifier ("__vector long"),
|
||
+ V2DI_type_node));
|
||
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
|
||
+ get_identifier ("__vector __bool long"),
|
||
+ bool_V2DI_type_node));
|
||
+ }
|
||
|
||
if (TARGET_PAIRED_FLOAT)
|
||
paired_init_builtins ();
|
||
@@ -10837,8 +11045,10 @@ altivec_init_builtins (void)
|
||
{
|
||
enum machine_mode mode1;
|
||
tree type;
|
||
- bool is_overloaded = dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
- && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
|
||
+ bool is_overloaded = ((dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
+ && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
|
||
+ || (dp->code >= VSX_BUILTIN_OVERLOADED_FIRST
|
||
+ && dp->code <= VSX_BUILTIN_OVERLOADED_LAST));
|
||
|
||
if (is_overloaded)
|
||
mode1 = VOIDmode;
|
||
@@ -11001,592 +11211,302 @@ altivec_init_builtins (void)
|
||
ALTIVEC_BUILTIN_VEC_EXT_V4SF);
|
||
}
|
||
|
||
-static void
|
||
-rs6000_common_init_builtins (void)
|
||
+/* Hash function for builtin functions with up to 3 arguments and a return
|
||
+ type. */
|
||
+static unsigned
|
||
+builtin_hash_function (const void *hash_entry)
|
||
{
|
||
- const struct builtin_description *d;
|
||
- size_t i;
|
||
+ unsigned ret = 0;
|
||
+ int i;
|
||
+ const struct builtin_hash_struct *bh =
|
||
+ (const struct builtin_hash_struct *) hash_entry;
|
||
|
||
- tree v2sf_ftype_v2sf_v2sf_v2sf
|
||
- = build_function_type_list (V2SF_type_node,
|
||
- V2SF_type_node, V2SF_type_node,
|
||
- V2SF_type_node, NULL_TREE);
|
||
-
|
||
- tree v4sf_ftype_v4sf_v4sf_v16qi
|
||
- = build_function_type_list (V4SF_type_node,
|
||
- V4SF_type_node, V4SF_type_node,
|
||
- V16QI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4si_v4si_v16qi
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SI_type_node, V4SI_type_node,
|
||
- V16QI_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v8hi_v8hi_v16qi
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V8HI_type_node, V8HI_type_node,
|
||
- V16QI_type_node, NULL_TREE);
|
||
- tree v16qi_ftype_v16qi_v16qi_v16qi
|
||
- = build_function_type_list (V16QI_type_node,
|
||
- V16QI_type_node, V16QI_type_node,
|
||
- V16QI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_int
|
||
- = build_function_type_list (V4SI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_int
|
||
- = build_function_type_list (V8HI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v16qi_ftype_int
|
||
- = build_function_type_list (V16QI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v16qi
|
||
- = build_function_type_list (V8HI_type_node, V16QI_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4sf
|
||
- = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
|
||
+ for (i = 0; i < 4; i++)
|
||
+ ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]);
|
||
|
||
- tree v2si_ftype_v2si_v2si
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- opaque_V2SI_type_node,
|
||
- opaque_V2SI_type_node, NULL_TREE);
|
||
-
|
||
- tree v2sf_ftype_v2sf_v2sf_spe
|
||
- = build_function_type_list (opaque_V2SF_type_node,
|
||
- opaque_V2SF_type_node,
|
||
- opaque_V2SF_type_node, NULL_TREE);
|
||
-
|
||
- tree v2sf_ftype_v2sf_v2sf
|
||
- = build_function_type_list (V2SF_type_node,
|
||
- V2SF_type_node,
|
||
- V2SF_type_node, NULL_TREE);
|
||
-
|
||
-
|
||
- tree v2si_ftype_int_int
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- integer_type_node, integer_type_node,
|
||
- NULL_TREE);
|
||
+ return ret;
|
||
+}
|
||
|
||
- tree opaque_ftype_opaque
|
||
- = build_function_type_list (opaque_V4SI_type_node,
|
||
- opaque_V4SI_type_node, NULL_TREE);
|
||
+/* Compare builtin hash entries H1 and H2 for equivalence. */
|
||
+static int
|
||
+builtin_hash_eq (const void *h1, const void *h2)
|
||
+{
|
||
+ const struct builtin_hash_struct *p1 = (const struct builtin_hash_struct *) h1;
|
||
+ const struct builtin_hash_struct *p2 = (const struct builtin_hash_struct *) h2;
|
||
|
||
- tree v2si_ftype_v2si
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- opaque_V2SI_type_node, NULL_TREE);
|
||
-
|
||
- tree v2sf_ftype_v2sf_spe
|
||
- = build_function_type_list (opaque_V2SF_type_node,
|
||
- opaque_V2SF_type_node, NULL_TREE);
|
||
-
|
||
- tree v2sf_ftype_v2sf
|
||
- = build_function_type_list (V2SF_type_node,
|
||
- V2SF_type_node, NULL_TREE);
|
||
-
|
||
- tree v2sf_ftype_v2si
|
||
- = build_function_type_list (opaque_V2SF_type_node,
|
||
- opaque_V2SI_type_node, NULL_TREE);
|
||
-
|
||
- tree v2si_ftype_v2sf
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- opaque_V2SF_type_node, NULL_TREE);
|
||
-
|
||
- tree v2si_ftype_v2si_char
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- opaque_V2SI_type_node,
|
||
- char_type_node, NULL_TREE);
|
||
-
|
||
- tree v2si_ftype_int_char
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- integer_type_node, char_type_node, NULL_TREE);
|
||
-
|
||
- tree v2si_ftype_char
|
||
- = build_function_type_list (opaque_V2SI_type_node,
|
||
- char_type_node, NULL_TREE);
|
||
+ return ((p1->mode[0] == p2->mode[0])
|
||
+ && (p1->mode[1] == p2->mode[1])
|
||
+ && (p1->mode[2] == p2->mode[2])
|
||
+ && (p1->mode[3] == p2->mode[3]));
|
||
+}
|
||
|
||
- tree int_ftype_int_int
|
||
- = build_function_type_list (integer_type_node,
|
||
- integer_type_node, integer_type_node,
|
||
- NULL_TREE);
|
||
+/* Map selected modes to types for builtins. */
|
||
+static tree builtin_mode_to_type[MAX_MACHINE_MODE];
|
||
|
||
- tree opaque_ftype_opaque_opaque
|
||
- = build_function_type_list (opaque_V4SI_type_node,
|
||
- opaque_V4SI_type_node, opaque_V4SI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4si_v4si
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SI_type_node, V4SI_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4si_int
|
||
- = build_function_type_list (V4SF_type_node,
|
||
- V4SI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4sf_int
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SF_type_node, integer_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4si_int
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v8hi_int
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V8HI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v16qi_ftype_v16qi_int
|
||
- = build_function_type_list (V16QI_type_node,
|
||
- V16QI_type_node, integer_type_node, NULL_TREE);
|
||
- tree v16qi_ftype_v16qi_v16qi_int
|
||
- = build_function_type_list (V16QI_type_node,
|
||
- V16QI_type_node, V16QI_type_node,
|
||
- integer_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v8hi_v8hi_int
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V8HI_type_node, V8HI_type_node,
|
||
- integer_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4si_v4si_int
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SI_type_node, V4SI_type_node,
|
||
- integer_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4sf_v4sf_int
|
||
- = build_function_type_list (V4SF_type_node,
|
||
- V4SF_type_node, V4SF_type_node,
|
||
- integer_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4sf_v4sf
|
||
- = build_function_type_list (V4SF_type_node,
|
||
- V4SF_type_node, V4SF_type_node, NULL_TREE);
|
||
- tree opaque_ftype_opaque_opaque_opaque
|
||
- = build_function_type_list (opaque_V4SI_type_node,
|
||
- opaque_V4SI_type_node, opaque_V4SI_type_node,
|
||
- opaque_V4SI_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4sf_v4sf_v4si
|
||
- = build_function_type_list (V4SF_type_node,
|
||
- V4SF_type_node, V4SF_type_node,
|
||
- V4SI_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4sf_v4sf_v4sf
|
||
- = build_function_type_list (V4SF_type_node,
|
||
- V4SF_type_node, V4SF_type_node,
|
||
- V4SF_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4si_v4si_v4si
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SI_type_node, V4SI_type_node,
|
||
- V4SI_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v8hi_v8hi
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V8HI_type_node, V8HI_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v8hi_v8hi_v8hi
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V8HI_type_node, V8HI_type_node,
|
||
- V8HI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v8hi_v8hi_v4si
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V8HI_type_node, V8HI_type_node,
|
||
- V4SI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v16qi_v16qi_v4si
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V16QI_type_node, V16QI_type_node,
|
||
- V4SI_type_node, NULL_TREE);
|
||
- tree v16qi_ftype_v16qi_v16qi
|
||
- = build_function_type_list (V16QI_type_node,
|
||
- V16QI_type_node, V16QI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4sf_v4sf
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V4SF_type_node, V4SF_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v16qi_v16qi
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V16QI_type_node, V16QI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v8hi_v8hi
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V8HI_type_node, V8HI_type_node, NULL_TREE);
|
||
- tree v8hi_ftype_v4si_v4si
|
||
- = build_function_type_list (V8HI_type_node,
|
||
- V4SI_type_node, V4SI_type_node, NULL_TREE);
|
||
- tree v16qi_ftype_v8hi_v8hi
|
||
- = build_function_type_list (V16QI_type_node,
|
||
- V8HI_type_node, V8HI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v16qi_v4si
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V16QI_type_node, V4SI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v16qi_v16qi
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V16QI_type_node, V16QI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v8hi_v4si
|
||
- = build_function_type_list (V4SI_type_node,
|
||
- V8HI_type_node, V4SI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v8hi
|
||
- = build_function_type_list (V4SI_type_node, V8HI_type_node, NULL_TREE);
|
||
- tree int_ftype_v4si_v4si
|
||
- = build_function_type_list (integer_type_node,
|
||
- V4SI_type_node, V4SI_type_node, NULL_TREE);
|
||
- tree int_ftype_v4sf_v4sf
|
||
- = build_function_type_list (integer_type_node,
|
||
- V4SF_type_node, V4SF_type_node, NULL_TREE);
|
||
- tree int_ftype_v16qi_v16qi
|
||
- = build_function_type_list (integer_type_node,
|
||
- V16QI_type_node, V16QI_type_node, NULL_TREE);
|
||
- tree int_ftype_v8hi_v8hi
|
||
- = build_function_type_list (integer_type_node,
|
||
- V8HI_type_node, V8HI_type_node, NULL_TREE);
|
||
- tree v2di_ftype_v2df
|
||
- = build_function_type_list (V2DI_type_node,
|
||
- V2DF_type_node, NULL_TREE);
|
||
- tree v2df_ftype_v2df
|
||
- = build_function_type_list (V2DF_type_node,
|
||
- V2DF_type_node, NULL_TREE);
|
||
- tree v2df_ftype_v2di
|
||
- = build_function_type_list (V2DF_type_node,
|
||
- V2DI_type_node, NULL_TREE);
|
||
- tree v2df_ftype_v2df_v2df
|
||
- = build_function_type_list (V2DF_type_node,
|
||
- V2DF_type_node, V2DF_type_node, NULL_TREE);
|
||
- tree v2df_ftype_v2df_v2df_v2df
|
||
- = build_function_type_list (V2DF_type_node,
|
||
- V2DF_type_node, V2DF_type_node,
|
||
- V2DF_type_node, NULL_TREE);
|
||
- tree v2di_ftype_v2di_v2di_v2di
|
||
- = build_function_type_list (V2DI_type_node,
|
||
- V2DI_type_node, V2DI_type_node,
|
||
- V2DI_type_node, NULL_TREE);
|
||
- tree v2df_ftype_v2df_v2df_v16qi
|
||
- = build_function_type_list (V2DF_type_node,
|
||
- V2DF_type_node, V2DF_type_node,
|
||
- V16QI_type_node, NULL_TREE);
|
||
- tree v2di_ftype_v2di_v2di_v16qi
|
||
- = build_function_type_list (V2DI_type_node,
|
||
- V2DI_type_node, V2DI_type_node,
|
||
- V16QI_type_node, NULL_TREE);
|
||
- tree v4sf_ftype_v4si
|
||
- = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
|
||
- tree v4si_ftype_v4sf
|
||
- = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
|
||
+/* Map types for builtin functions with an explicit return type and up to 3
|
||
+ arguments. Functions with fewer than 3 arguments use VOIDmode as the type
|
||
+ of the argument. */
|
||
+static tree
|
||
+builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
|
||
+ enum machine_mode mode_arg1, enum machine_mode mode_arg2,
|
||
+ const char *name)
|
||
+{
|
||
+ struct builtin_hash_struct h;
|
||
+ struct builtin_hash_struct *h2;
|
||
+ void **found;
|
||
+ int num_args = 3;
|
||
+ int i;
|
||
|
||
- /* Add the simple ternary operators. */
|
||
+ /* Create builtin_hash_table. */
|
||
+ if (builtin_hash_table == NULL)
|
||
+ builtin_hash_table = htab_create_ggc (1500, builtin_hash_function,
|
||
+ builtin_hash_eq, NULL);
|
||
+
|
||
+ h.type = NULL_TREE;
|
||
+ h.mode[0] = mode_ret;
|
||
+ h.mode[1] = mode_arg0;
|
||
+ h.mode[2] = mode_arg1;
|
||
+ h.mode[3] = mode_arg2;
|
||
+
|
||
+ /* Figure out how many args are present. */
|
||
+ while (num_args > 0 && h.mode[num_args] == VOIDmode)
|
||
+ num_args--;
|
||
+
|
||
+ if (num_args == 0)
|
||
+ fatal_error ("internal error: builtin function %s had no type", name);
|
||
+
|
||
+ if (!builtin_mode_to_type[h.mode[0]])
|
||
+ fatal_error ("internal error: builtin function %s had an unexpected "
|
||
+ "return type %s", name, GET_MODE_NAME (h.mode[0]));
|
||
+
|
||
+ for (i = 0; i < num_args; i++)
|
||
+ if (!builtin_mode_to_type[h.mode[i+1]])
|
||
+ fatal_error ("internal error: builtin function %s, argument %d "
|
||
+ "had unexpected argument type %s", name, i,
|
||
+ GET_MODE_NAME (h.mode[i+1]));
|
||
+
|
||
+ found = htab_find_slot (builtin_hash_table, &h, 1);
|
||
+ if (*found == NULL)
|
||
+ {
|
||
+ h2 = GGC_NEW (struct builtin_hash_struct);
|
||
+ *h2 = h;
|
||
+ *found = (void *)h2;
|
||
+
|
||
+ switch (num_args)
|
||
+ {
|
||
+ case 1:
|
||
+ h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
|
||
+ builtin_mode_to_type[mode_arg0],
|
||
+ NULL_TREE);
|
||
+ break;
|
||
+
|
||
+ case 2:
|
||
+ h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
|
||
+ builtin_mode_to_type[mode_arg0],
|
||
+ builtin_mode_to_type[mode_arg1],
|
||
+ NULL_TREE);
|
||
+ break;
|
||
+
|
||
+ case 3:
|
||
+ h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
|
||
+ builtin_mode_to_type[mode_arg0],
|
||
+ builtin_mode_to_type[mode_arg1],
|
||
+ builtin_mode_to_type[mode_arg2],
|
||
+ NULL_TREE);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ gcc_unreachable ();
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return ((struct builtin_hash_struct *)(*found))->type;
|
||
+}
|
||
+
|
||
+static void
|
||
+rs6000_common_init_builtins (void)
|
||
+{
|
||
+ const struct builtin_description *d;
|
||
+ size_t i;
|
||
+
|
||
+ tree opaque_ftype_opaque = NULL_TREE;
|
||
+ tree opaque_ftype_opaque_opaque = NULL_TREE;
|
||
+ tree opaque_ftype_opaque_opaque_opaque = NULL_TREE;
|
||
+ tree v2si_ftype_qi = NULL_TREE;
|
||
+ tree v2si_ftype_v2si_qi = NULL_TREE;
|
||
+ tree v2si_ftype_int_qi = NULL_TREE;
|
||
+
|
||
+ /* Initialize the tables for the unary, binary, and ternary ops. */
|
||
+ builtin_mode_to_type[QImode] = integer_type_node;
|
||
+ builtin_mode_to_type[HImode] = integer_type_node;
|
||
+ builtin_mode_to_type[SImode] = intSI_type_node;
|
||
+ builtin_mode_to_type[DImode] = intDI_type_node;
|
||
+ builtin_mode_to_type[SFmode] = float_type_node;
|
||
+ builtin_mode_to_type[DFmode] = double_type_node;
|
||
+ builtin_mode_to_type[V2SImode] = V2SI_type_node;
|
||
+ builtin_mode_to_type[V2SFmode] = V2SF_type_node;
|
||
+ builtin_mode_to_type[V2DImode] = V2DI_type_node;
|
||
+ builtin_mode_to_type[V2DFmode] = V2DF_type_node;
|
||
+ builtin_mode_to_type[V4HImode] = V4HI_type_node;
|
||
+ builtin_mode_to_type[V4SImode] = V4SI_type_node;
|
||
+ builtin_mode_to_type[V4SFmode] = V4SF_type_node;
|
||
+ builtin_mode_to_type[V8HImode] = V8HI_type_node;
|
||
+ builtin_mode_to_type[V16QImode] = V16QI_type_node;
|
||
+
|
||
+ if (!TARGET_PAIRED_FLOAT)
|
||
+ {
|
||
+ builtin_mode_to_type[V2SImode] = opaque_V2SI_type_node;
|
||
+ builtin_mode_to_type[V2SFmode] = opaque_V2SF_type_node;
|
||
+ }
|
||
+
|
||
+ /* Add the ternary operators. */
|
||
d = bdesc_3arg;
|
||
for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
|
||
{
|
||
- enum machine_mode mode0, mode1, mode2, mode3;
|
||
tree type;
|
||
- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
|
||
+ int mask = d->mask;
|
||
|
||
- if (is_overloaded)
|
||
- {
|
||
- mode0 = VOIDmode;
|
||
- mode1 = VOIDmode;
|
||
- mode2 = VOIDmode;
|
||
- mode3 = VOIDmode;
|
||
+ if ((mask != 0 && (mask & target_flags) == 0)
|
||
+ || (mask == 0 && !TARGET_PAIRED_FLOAT))
|
||
+ continue;
|
||
+
|
||
+ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
|
||
+ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
|
||
+ && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
|
||
+ {
|
||
+ if (! (type = opaque_ftype_opaque_opaque_opaque))
|
||
+ type = opaque_ftype_opaque_opaque_opaque
|
||
+ = build_function_type_list (opaque_V4SI_type_node,
|
||
+ opaque_V4SI_type_node,
|
||
+ opaque_V4SI_type_node,
|
||
+ opaque_V4SI_type_node,
|
||
+ NULL_TREE);
|
||
}
|
||
else
|
||
{
|
||
- if (d->name == 0 || d->icode == CODE_FOR_nothing)
|
||
+ enum insn_code icode = d->icode;
|
||
+ if (d->name == 0 || icode == CODE_FOR_nothing)
|
||
continue;
|
||
|
||
- mode0 = insn_data[d->icode].operand[0].mode;
|
||
- mode1 = insn_data[d->icode].operand[1].mode;
|
||
- mode2 = insn_data[d->icode].operand[2].mode;
|
||
- mode3 = insn_data[d->icode].operand[3].mode;
|
||
+ type = builtin_function_type (insn_data[icode].operand[0].mode,
|
||
+ insn_data[icode].operand[1].mode,
|
||
+ insn_data[icode].operand[2].mode,
|
||
+ insn_data[icode].operand[3].mode,
|
||
+ d->name);
|
||
}
|
||
|
||
- /* When all four are of the same mode. */
|
||
- if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3)
|
||
- {
|
||
- switch (mode0)
|
||
- {
|
||
- case VOIDmode:
|
||
- type = opaque_ftype_opaque_opaque_opaque;
|
||
- break;
|
||
- case V2DImode:
|
||
- type = v2di_ftype_v2di_v2di_v2di;
|
||
- break;
|
||
- case V2DFmode:
|
||
- type = v2df_ftype_v2df_v2df_v2df;
|
||
- break;
|
||
- case V4SImode:
|
||
- type = v4si_ftype_v4si_v4si_v4si;
|
||
- break;
|
||
- case V4SFmode:
|
||
- type = v4sf_ftype_v4sf_v4sf_v4sf;
|
||
- break;
|
||
- case V8HImode:
|
||
- type = v8hi_ftype_v8hi_v8hi_v8hi;
|
||
- break;
|
||
- case V16QImode:
|
||
- type = v16qi_ftype_v16qi_v16qi_v16qi;
|
||
- break;
|
||
- case V2SFmode:
|
||
- type = v2sf_ftype_v2sf_v2sf_v2sf;
|
||
- break;
|
||
- default:
|
||
- gcc_unreachable ();
|
||
- }
|
||
- }
|
||
- else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode)
|
||
- {
|
||
- switch (mode0)
|
||
- {
|
||
- case V2DImode:
|
||
- type = v2di_ftype_v2di_v2di_v16qi;
|
||
- break;
|
||
- case V2DFmode:
|
||
- type = v2df_ftype_v2df_v2df_v16qi;
|
||
- break;
|
||
- case V4SImode:
|
||
- type = v4si_ftype_v4si_v4si_v16qi;
|
||
- break;
|
||
- case V4SFmode:
|
||
- type = v4sf_ftype_v4sf_v4sf_v16qi;
|
||
- break;
|
||
- case V8HImode:
|
||
- type = v8hi_ftype_v8hi_v8hi_v16qi;
|
||
- break;
|
||
- case V16QImode:
|
||
- type = v16qi_ftype_v16qi_v16qi_v16qi;
|
||
- break;
|
||
- default:
|
||
- gcc_unreachable ();
|
||
- }
|
||
- }
|
||
- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
|
||
- && mode3 == V4SImode)
|
||
- type = v4si_ftype_v16qi_v16qi_v4si;
|
||
- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
|
||
- && mode3 == V4SImode)
|
||
- type = v4si_ftype_v8hi_v8hi_v4si;
|
||
- else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
|
||
- && mode3 == V4SImode)
|
||
- type = v4sf_ftype_v4sf_v4sf_v4si;
|
||
-
|
||
- /* vchar, vchar, vchar, 4-bit literal. */
|
||
- else if (mode0 == V16QImode && mode1 == mode0 && mode2 == mode0
|
||
- && mode3 == QImode)
|
||
- type = v16qi_ftype_v16qi_v16qi_int;
|
||
-
|
||
- /* vshort, vshort, vshort, 4-bit literal. */
|
||
- else if (mode0 == V8HImode && mode1 == mode0 && mode2 == mode0
|
||
- && mode3 == QImode)
|
||
- type = v8hi_ftype_v8hi_v8hi_int;
|
||
-
|
||
- /* vint, vint, vint, 4-bit literal. */
|
||
- else if (mode0 == V4SImode && mode1 == mode0 && mode2 == mode0
|
||
- && mode3 == QImode)
|
||
- type = v4si_ftype_v4si_v4si_int;
|
||
-
|
||
- /* vfloat, vfloat, vfloat, 4-bit literal. */
|
||
- else if (mode0 == V4SFmode && mode1 == mode0 && mode2 == mode0
|
||
- && mode3 == QImode)
|
||
- type = v4sf_ftype_v4sf_v4sf_int;
|
||
-
|
||
- else
|
||
- gcc_unreachable ();
|
||
-
|
||
def_builtin (d->mask, d->name, type, d->code);
|
||
}
|
||
|
||
- /* Add the simple binary operators. */
|
||
+ /* Add the binary operators. */
|
||
d = (struct builtin_description *) bdesc_2arg;
|
||
for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
|
||
{
|
||
enum machine_mode mode0, mode1, mode2;
|
||
tree type;
|
||
- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
|
||
+ int mask = d->mask;
|
||
|
||
- if (is_overloaded)
|
||
- {
|
||
- mode0 = VOIDmode;
|
||
- mode1 = VOIDmode;
|
||
- mode2 = VOIDmode;
|
||
+ if ((mask != 0 && (mask & target_flags) == 0)
|
||
+ || (mask == 0 && !TARGET_PAIRED_FLOAT))
|
||
+ continue;
|
||
+
|
||
+ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
|
||
+ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
|
||
+ && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
|
||
+ {
|
||
+ if (! (type = opaque_ftype_opaque_opaque))
|
||
+ type = opaque_ftype_opaque_opaque
|
||
+ = build_function_type_list (opaque_V4SI_type_node,
|
||
+ opaque_V4SI_type_node,
|
||
+ opaque_V4SI_type_node,
|
||
+ NULL_TREE);
|
||
}
|
||
else
|
||
{
|
||
- if (d->name == 0 || d->icode == CODE_FOR_nothing)
|
||
+ enum insn_code icode = d->icode;
|
||
+ if (d->name == 0 || icode == CODE_FOR_nothing)
|
||
continue;
|
||
|
||
- mode0 = insn_data[d->icode].operand[0].mode;
|
||
- mode1 = insn_data[d->icode].operand[1].mode;
|
||
- mode2 = insn_data[d->icode].operand[2].mode;
|
||
- }
|
||
+ mode0 = insn_data[icode].operand[0].mode;
|
||
+ mode1 = insn_data[icode].operand[1].mode;
|
||
+ mode2 = insn_data[icode].operand[2].mode;
|
||
|
||
- /* When all three operands are of the same mode. */
|
||
- if (mode0 == mode1 && mode1 == mode2)
|
||
- {
|
||
- switch (mode0)
|
||
+ if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
|
||
{
|
||
- case VOIDmode:
|
||
- type = opaque_ftype_opaque_opaque;
|
||
- break;
|
||
- case V2DFmode:
|
||
- type = v2df_ftype_v2df_v2df;
|
||
- break;
|
||
- case V4SFmode:
|
||
- type = v4sf_ftype_v4sf_v4sf;
|
||
- break;
|
||
- case V4SImode:
|
||
- type = v4si_ftype_v4si_v4si;
|
||
- break;
|
||
- case V16QImode:
|
||
- type = v16qi_ftype_v16qi_v16qi;
|
||
- break;
|
||
- case V8HImode:
|
||
- type = v8hi_ftype_v8hi_v8hi;
|
||
- break;
|
||
- case V2SImode:
|
||
- type = v2si_ftype_v2si_v2si;
|
||
- break;
|
||
- case V2SFmode:
|
||
- if (TARGET_PAIRED_FLOAT)
|
||
- type = v2sf_ftype_v2sf_v2sf;
|
||
- else
|
||
- type = v2sf_ftype_v2sf_v2sf_spe;
|
||
- break;
|
||
- case SImode:
|
||
- type = int_ftype_int_int;
|
||
- break;
|
||
- default:
|
||
- gcc_unreachable ();
|
||
+ if (! (type = v2si_ftype_v2si_qi))
|
||
+ type = v2si_ftype_v2si_qi
|
||
+ = build_function_type_list (opaque_V2SI_type_node,
|
||
+ opaque_V2SI_type_node,
|
||
+ char_type_node,
|
||
+ NULL_TREE);
|
||
}
|
||
- }
|
||
-
|
||
- /* A few other combos we really don't want to do manually. */
|
||
-
|
||
- /* vint, vfloat, vfloat. */
|
||
- else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
|
||
- type = v4si_ftype_v4sf_v4sf;
|
||
-
|
||
- /* vshort, vchar, vchar. */
|
||
- else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
|
||
- type = v8hi_ftype_v16qi_v16qi;
|
||
-
|
||
- /* vint, vshort, vshort. */
|
||
- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
|
||
- type = v4si_ftype_v8hi_v8hi;
|
||
-
|
||
- /* vshort, vint, vint. */
|
||
- else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
|
||
- type = v8hi_ftype_v4si_v4si;
|
||
-
|
||
- /* vchar, vshort, vshort. */
|
||
- else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
|
||
- type = v16qi_ftype_v8hi_v8hi;
|
||
-
|
||
- /* vint, vchar, vint. */
|
||
- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
|
||
- type = v4si_ftype_v16qi_v4si;
|
||
-
|
||
- /* vint, vchar, vchar. */
|
||
- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode)
|
||
- type = v4si_ftype_v16qi_v16qi;
|
||
-
|
||
- /* vint, vshort, vint. */
|
||
- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
|
||
- type = v4si_ftype_v8hi_v4si;
|
||
|
||
- /* vint, vint, 5-bit literal. */
|
||
- else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode)
|
||
- type = v4si_ftype_v4si_int;
|
||
-
|
||
- /* vshort, vshort, 5-bit literal. */
|
||
- else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode)
|
||
- type = v8hi_ftype_v8hi_int;
|
||
-
|
||
- /* vchar, vchar, 5-bit literal. */
|
||
- else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode)
|
||
- type = v16qi_ftype_v16qi_int;
|
||
-
|
||
- /* vfloat, vint, 5-bit literal. */
|
||
- else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode)
|
||
- type = v4sf_ftype_v4si_int;
|
||
-
|
||
- /* vint, vfloat, 5-bit literal. */
|
||
- else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
|
||
- type = v4si_ftype_v4sf_int;
|
||
-
|
||
- else if (mode0 == V2SImode && mode1 == SImode && mode2 == SImode)
|
||
- type = v2si_ftype_int_int;
|
||
-
|
||
- else if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
|
||
- type = v2si_ftype_v2si_char;
|
||
-
|
||
- else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode)
|
||
- type = v2si_ftype_int_char;
|
||
-
|
||
- else
|
||
- {
|
||
- /* int, x, x. */
|
||
- gcc_assert (mode0 == SImode);
|
||
- switch (mode1)
|
||
+ else if (mode0 == V2SImode && GET_MODE_CLASS (mode1) == MODE_INT
|
||
+ && mode2 == QImode)
|
||
{
|
||
- case V4SImode:
|
||
- type = int_ftype_v4si_v4si;
|
||
- break;
|
||
- case V4SFmode:
|
||
- type = int_ftype_v4sf_v4sf;
|
||
- break;
|
||
- case V16QImode:
|
||
- type = int_ftype_v16qi_v16qi;
|
||
- break;
|
||
- case V8HImode:
|
||
- type = int_ftype_v8hi_v8hi;
|
||
- break;
|
||
- default:
|
||
- gcc_unreachable ();
|
||
+ if (! (type = v2si_ftype_int_qi))
|
||
+ type = v2si_ftype_int_qi
|
||
+ = build_function_type_list (opaque_V2SI_type_node,
|
||
+ integer_type_node,
|
||
+ char_type_node,
|
||
+ NULL_TREE);
|
||
}
|
||
+
|
||
+ else
|
||
+ type = builtin_function_type (mode0, mode1, mode2, VOIDmode,
|
||
+ d->name);
|
||
}
|
||
|
||
def_builtin (d->mask, d->name, type, d->code);
|
||
}
|
||
|
||
- /* Add the simple unary operators. */
|
||
+ /* Add the unary operators. */
|
||
d = (struct builtin_description *) bdesc_1arg;
|
||
for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
|
||
{
|
||
enum machine_mode mode0, mode1;
|
||
tree type;
|
||
- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
|
||
+ int mask = d->mask;
|
||
|
||
- if (is_overloaded)
|
||
- {
|
||
- mode0 = VOIDmode;
|
||
- mode1 = VOIDmode;
|
||
- }
|
||
+ if ((mask != 0 && (mask & target_flags) == 0)
|
||
+ || (mask == 0 && !TARGET_PAIRED_FLOAT))
|
||
+ continue;
|
||
+
|
||
+ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
|
||
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
|
||
+ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
|
||
+ && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
|
||
+ {
|
||
+ if (! (type = opaque_ftype_opaque))
|
||
+ type = opaque_ftype_opaque
|
||
+ = build_function_type_list (opaque_V4SI_type_node,
|
||
+ opaque_V4SI_type_node,
|
||
+ NULL_TREE);
|
||
+ }
|
||
else
|
||
{
|
||
- if (d->name == 0 || d->icode == CODE_FOR_nothing)
|
||
+ enum insn_code icode = d->icode;
|
||
+ if (d->name == 0 || icode == CODE_FOR_nothing)
|
||
continue;
|
||
|
||
- mode0 = insn_data[d->icode].operand[0].mode;
|
||
- mode1 = insn_data[d->icode].operand[1].mode;
|
||
- }
|
||
+ mode0 = insn_data[icode].operand[0].mode;
|
||
+ mode1 = insn_data[icode].operand[1].mode;
|
||
|
||
- if (mode0 == V4SImode && mode1 == QImode)
|
||
- type = v4si_ftype_int;
|
||
- else if (mode0 == V8HImode && mode1 == QImode)
|
||
- type = v8hi_ftype_int;
|
||
- else if (mode0 == V16QImode && mode1 == QImode)
|
||
- type = v16qi_ftype_int;
|
||
- else if (mode0 == VOIDmode && mode1 == VOIDmode)
|
||
- type = opaque_ftype_opaque;
|
||
- else if (mode0 == V2DFmode && mode1 == V2DFmode)
|
||
- type = v2df_ftype_v2df;
|
||
- else if (mode0 == V4SFmode && mode1 == V4SFmode)
|
||
- type = v4sf_ftype_v4sf;
|
||
- else if (mode0 == V8HImode && mode1 == V16QImode)
|
||
- type = v8hi_ftype_v16qi;
|
||
- else if (mode0 == V4SImode && mode1 == V8HImode)
|
||
- type = v4si_ftype_v8hi;
|
||
- else if (mode0 == V2SImode && mode1 == V2SImode)
|
||
- type = v2si_ftype_v2si;
|
||
- else if (mode0 == V2SFmode && mode1 == V2SFmode)
|
||
- {
|
||
- if (TARGET_PAIRED_FLOAT)
|
||
- type = v2sf_ftype_v2sf;
|
||
- else
|
||
- type = v2sf_ftype_v2sf_spe;
|
||
- }
|
||
- else if (mode0 == V2SFmode && mode1 == V2SImode)
|
||
- type = v2sf_ftype_v2si;
|
||
- else if (mode0 == V2SImode && mode1 == V2SFmode)
|
||
- type = v2si_ftype_v2sf;
|
||
- else if (mode0 == V2SImode && mode1 == QImode)
|
||
- type = v2si_ftype_char;
|
||
- else if (mode0 == V4SImode && mode1 == V4SFmode)
|
||
- type = v4si_ftype_v4sf;
|
||
- else if (mode0 == V4SFmode && mode1 == V4SImode)
|
||
- type = v4sf_ftype_v4si;
|
||
- else if (mode0 == V2DImode && mode1 == V2DFmode)
|
||
- type = v2di_ftype_v2df;
|
||
- else if (mode0 == V2DFmode && mode1 == V2DImode)
|
||
- type = v2df_ftype_v2di;
|
||
- else
|
||
- gcc_unreachable ();
|
||
+ if (mode0 == V2SImode && mode1 == QImode)
|
||
+ {
|
||
+ if (! (type = v2si_ftype_qi))
|
||
+ type = v2si_ftype_qi
|
||
+ = build_function_type_list (opaque_V2SI_type_node,
|
||
+ char_type_node,
|
||
+ NULL_TREE);
|
||
+ }
|
||
+
|
||
+ else
|
||
+ type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode,
|
||
+ d->name);
|
||
+ }
|
||
|
||
def_builtin (d->mask, d->name, type, d->code);
|
||
}
|
||
@@ -12637,12 +12557,12 @@ rs6000_secondary_reload_inner (rtx reg,
|
||
}
|
||
|
||
if (GET_CODE (addr) == PLUS
|
||
- && (!rs6000_legitimate_offset_address_p (TImode, addr, true)
|
||
+ && (!rs6000_legitimate_offset_address_p (TImode, addr, false)
|
||
|| and_op2 != NULL_RTX))
|
||
{
|
||
addr_op1 = XEXP (addr, 0);
|
||
addr_op2 = XEXP (addr, 1);
|
||
- gcc_assert (legitimate_indirect_address_p (addr_op1, true));
|
||
+ gcc_assert (legitimate_indirect_address_p (addr_op1, false));
|
||
|
||
if (!REG_P (addr_op2)
|
||
&& (GET_CODE (addr_op2) != CONST_INT
|
||
@@ -12661,8 +12581,8 @@ rs6000_secondary_reload_inner (rtx reg,
|
||
addr = scratch_or_premodify;
|
||
scratch_or_premodify = scratch;
|
||
}
|
||
- else if (!legitimate_indirect_address_p (addr, true)
|
||
- && !rs6000_legitimate_offset_address_p (TImode, addr, true))
|
||
+ else if (!legitimate_indirect_address_p (addr, false)
|
||
+ && !rs6000_legitimate_offset_address_p (TImode, addr, false))
|
||
{
|
||
rs6000_emit_move (scratch_or_premodify, addr, Pmode);
|
||
addr = scratch_or_premodify;
|
||
@@ -12691,24 +12611,24 @@ rs6000_secondary_reload_inner (rtx reg,
|
||
if (GET_CODE (addr) == PRE_MODIFY
|
||
&& (!VECTOR_MEM_VSX_P (mode)
|
||
|| and_op2 != NULL_RTX
|
||
- || !legitimate_indexed_address_p (XEXP (addr, 1), true)))
|
||
+ || !legitimate_indexed_address_p (XEXP (addr, 1), false)))
|
||
{
|
||
scratch_or_premodify = XEXP (addr, 0);
|
||
gcc_assert (legitimate_indirect_address_p (scratch_or_premodify,
|
||
- true));
|
||
+ false));
|
||
gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
|
||
addr = XEXP (addr, 1);
|
||
}
|
||
|
||
- if (legitimate_indirect_address_p (addr, true) /* reg */
|
||
- || legitimate_indexed_address_p (addr, true) /* reg+reg */
|
||
+ 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 == 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, true)))
|
||
+ && rs6000_legitimate_offset_address_p (mode, addr, false)))
|
||
;
|
||
|
||
else if (GET_CODE (addr) == PLUS)
|
||
@@ -12728,7 +12648,7 @@ rs6000_secondary_reload_inner (rtx reg,
|
||
}
|
||
|
||
else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
|
||
- || GET_CODE (addr) == CONST_INT)
|
||
+ || GET_CODE (addr) == CONST_INT || REG_P (addr))
|
||
{
|
||
rs6000_emit_move (scratch_or_premodify, addr, Pmode);
|
||
addr = scratch_or_premodify;
|
||
@@ -12760,7 +12680,7 @@ rs6000_secondary_reload_inner (rtx reg,
|
||
andi. instruction. */
|
||
if (and_op2 != NULL_RTX)
|
||
{
|
||
- if (! legitimate_indirect_address_p (addr, true))
|
||
+ if (! legitimate_indirect_address_p (addr, false))
|
||
{
|
||
emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
|
||
addr = scratch;
|
||
@@ -12795,6 +12715,26 @@ rs6000_secondary_reload_inner (rtx reg,
|
||
return;
|
||
}
|
||
|
||
+/* Target hook to return the cover classes for Integrated Register Allocator.
|
||
+ Cover classes is a set of non-intersected register classes covering all hard
|
||
+ registers used for register allocation purpose. Any move between two
|
||
+ registers of a cover class should be cheaper than load or store of the
|
||
+ registers. The value is array of register classes with LIM_REG_CLASSES used
|
||
+ as the end marker.
|
||
+
|
||
+ We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to
|
||
+ account for the Altivec and Floating registers being subsets of the VSX
|
||
+ register set under VSX, but distinct register sets on pre-VSX machines. */
|
||
+
|
||
+static const enum reg_class *
|
||
+rs6000_ira_cover_classes (void)
|
||
+{
|
||
+ static const enum reg_class cover_pre_vsx[] = IRA_COVER_CLASSES_PRE_VSX;
|
||
+ static const enum reg_class cover_vsx[] = IRA_COVER_CLASSES_VSX;
|
||
+
|
||
+ return (TARGET_VSX) ? cover_vsx : cover_pre_vsx;
|
||
+}
|
||
+
|
||
/* Allocate a 64-bit stack slot to be used for copying SDmode
|
||
values through if this function has any SDmode references. */
|
||
|
||
@@ -12868,13 +12808,15 @@ rs6000_preferred_reload_class (rtx x, en
|
||
enum machine_mode mode = GET_MODE (x);
|
||
enum reg_class ret;
|
||
|
||
- if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
|
||
- && VSX_REG_CLASS_P (rclass))
|
||
+ if (TARGET_VSX
|
||
+ && (VSX_VECTOR_MODE (mode) || mode == TImode)
|
||
+ && x == CONST0_RTX (mode) && VSX_REG_CLASS_P (rclass))
|
||
ret = rclass;
|
||
|
||
- else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode)
|
||
- && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode))
|
||
- ret = rclass;
|
||
+ else if (TARGET_ALTIVEC && (ALTIVEC_VECTOR_MODE (mode) || mode == TImode)
|
||
+ && (rclass == ALTIVEC_REGS || rclass == VSX_REGS)
|
||
+ && easy_vector_constant (x, mode))
|
||
+ ret = ALTIVEC_REGS;
|
||
|
||
else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
|
||
ret = NO_REGS;
|
||
@@ -13093,8 +13035,10 @@ rs6000_cannot_change_mode_class (enum ma
|
||
|| (((to) == TDmode) + ((from) == TDmode)) == 1
|
||
|| (((to) == DImode) + ((from) == DImode)) == 1))
|
||
|| (TARGET_VSX
|
||
- && (VSX_VECTOR_MODE (from) + VSX_VECTOR_MODE (to)) == 1)
|
||
+ && (VSX_MOVE_MODE (from) + VSX_MOVE_MODE (to)) == 1
|
||
+ && VSX_REG_CLASS_P (rclass))
|
||
|| (TARGET_ALTIVEC
|
||
+ && rclass == ALTIVEC_REGS
|
||
&& (ALTIVEC_VECTOR_MODE (from)
|
||
+ ALTIVEC_VECTOR_MODE (to)) == 1)
|
||
|| (TARGET_SPE
|
||
@@ -14972,7 +14916,7 @@ rs6000_emit_vector_cond_expr (rtx dest,
|
||
if (!mask)
|
||
return 0;
|
||
|
||
- if ((TARGET_VSX && VSX_VECTOR_MOVE_MODE (dest_mode))
|
||
+ if ((TARGET_VSX && VSX_MOVE_MODE (dest_mode))
|
||
|| (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dest_mode)))
|
||
{
|
||
rtx cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx);
|
||
@@ -22161,7 +22105,8 @@ rs6000_handle_altivec_attribute (tree *n
|
||
mode = TYPE_MODE (type);
|
||
|
||
/* Check for invalid AltiVec type qualifiers. */
|
||
- if (type == long_unsigned_type_node || type == long_integer_type_node)
|
||
+ if ((type == long_unsigned_type_node || type == long_integer_type_node)
|
||
+ && !TARGET_VSX)
|
||
{
|
||
if (TARGET_64BIT)
|
||
error ("use of %<long%> in AltiVec types is invalid for 64-bit code");
|
||
@@ -22199,6 +22144,7 @@ rs6000_handle_altivec_attribute (tree *n
|
||
break;
|
||
case SFmode: result = V4SF_type_node; break;
|
||
case DFmode: result = V2DF_type_node; break;
|
||
+ case DImode: result = V2DI_type_node; break;
|
||
/* If the user says 'vector int bool', we may be handed the 'bool'
|
||
attribute _before_ the 'vector' attribute, and so select the
|
||
proper type in the 'b' case below. */
|
||
@@ -22210,6 +22156,7 @@ rs6000_handle_altivec_attribute (tree *n
|
||
case 'b':
|
||
switch (mode)
|
||
{
|
||
+ case DImode: case V2DImode: result = bool_V2DI_type_node; break;
|
||
case SImode: case V4SImode: result = bool_V4SI_type_node; break;
|
||
case HImode: case V8HImode: result = bool_V8HI_type_node; break;
|
||
case QImode: case V16QImode: result = bool_V16QI_type_node;
|
||
@@ -22254,6 +22201,7 @@ rs6000_mangle_type (const_tree type)
|
||
if (type == bool_short_type_node) return "U6__bools";
|
||
if (type == pixel_type_node) return "u7__pixel";
|
||
if (type == bool_int_type_node) return "U6__booli";
|
||
+ if (type == bool_long_type_node) return "U6__booll";
|
||
|
||
/* Mangle IBM extended float long double as `g' (__float128) on
|
||
powerpc*-linux where long-double-64 previously was the default. */
|
||
@@ -23781,6 +23729,8 @@ int
|
||
rs6000_register_move_cost (enum machine_mode mode,
|
||
enum reg_class from, enum reg_class to)
|
||
{
|
||
+ int ret;
|
||
+
|
||
/* Moves from/to GENERAL_REGS. */
|
||
if (reg_classes_intersect_p (to, GENERAL_REGS)
|
||
|| reg_classes_intersect_p (from, GENERAL_REGS))
|
||
@@ -23789,39 +23739,47 @@ rs6000_register_move_cost (enum machine_
|
||
from = to;
|
||
|
||
if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS)
|
||
- return (rs6000_memory_move_cost (mode, from, 0)
|
||
- + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
|
||
+ ret = (rs6000_memory_move_cost (mode, from, 0)
|
||
+ + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
|
||
|
||
/* It's more expensive to move CR_REGS than CR0_REGS because of the
|
||
shift. */
|
||
else if (from == CR_REGS)
|
||
- return 4;
|
||
+ ret = 4;
|
||
|
||
/* Power6 has slower LR/CTR moves so make them more expensive than
|
||
memory in order to bias spills to memory .*/
|
||
else if (rs6000_cpu == PROCESSOR_POWER6
|
||
&& reg_classes_intersect_p (from, LINK_OR_CTR_REGS))
|
||
- return 6 * hard_regno_nregs[0][mode];
|
||
+ ret = 6 * hard_regno_nregs[0][mode];
|
||
|
||
else
|
||
/* A move will cost one instruction per GPR moved. */
|
||
- return 2 * hard_regno_nregs[0][mode];
|
||
+ ret = 2 * hard_regno_nregs[0][mode];
|
||
}
|
||
|
||
/* If we have VSX, we can easily move between FPR or Altivec registers. */
|
||
- else if (TARGET_VSX
|
||
- && ((from == VSX_REGS || from == FLOAT_REGS || from == ALTIVEC_REGS)
|
||
- || (to == VSX_REGS || to == FLOAT_REGS || to == ALTIVEC_REGS)))
|
||
- return 2;
|
||
+ else if (VECTOR_UNIT_VSX_P (mode)
|
||
+ && reg_classes_intersect_p (to, VSX_REGS)
|
||
+ && reg_classes_intersect_p (from, VSX_REGS))
|
||
+ ret = 2 * hard_regno_nregs[32][mode];
|
||
|
||
/* Moving between two similar registers is just one instruction. */
|
||
else if (reg_classes_intersect_p (to, from))
|
||
- return (mode == TFmode || mode == TDmode) ? 4 : 2;
|
||
+ ret = (mode == TFmode || mode == TDmode) ? 4 : 2;
|
||
|
||
/* Everything else has to go through GENERAL_REGS. */
|
||
else
|
||
- return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
|
||
- + rs6000_register_move_cost (mode, from, GENERAL_REGS));
|
||
+ ret = (rs6000_register_move_cost (mode, GENERAL_REGS, to)
|
||
+ + rs6000_register_move_cost (mode, from, GENERAL_REGS));
|
||
+
|
||
+ if (TARGET_DEBUG_COST)
|
||
+ fprintf (stderr,
|
||
+ "rs6000_register_move_cost:, ret=%d, mode=%s, from=%s, to=%s\n",
|
||
+ ret, GET_MODE_NAME (mode), reg_class_names[from],
|
||
+ reg_class_names[to]);
|
||
+
|
||
+ return ret;
|
||
}
|
||
|
||
/* A C expressions returning the cost of moving data of MODE from a register to
|
||
@@ -23831,14 +23789,23 @@ int
|
||
rs6000_memory_move_cost (enum machine_mode mode, enum reg_class rclass,
|
||
int in ATTRIBUTE_UNUSED)
|
||
{
|
||
+ int ret;
|
||
+
|
||
if (reg_classes_intersect_p (rclass, GENERAL_REGS))
|
||
- return 4 * hard_regno_nregs[0][mode];
|
||
+ ret = 4 * hard_regno_nregs[0][mode];
|
||
else if (reg_classes_intersect_p (rclass, FLOAT_REGS))
|
||
- return 4 * hard_regno_nregs[32][mode];
|
||
+ ret = 4 * hard_regno_nregs[32][mode];
|
||
else if (reg_classes_intersect_p (rclass, ALTIVEC_REGS))
|
||
- return 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
|
||
+ ret = 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
|
||
else
|
||
- return 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS);
|
||
+ ret = 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS);
|
||
+
|
||
+ if (TARGET_DEBUG_COST)
|
||
+ fprintf (stderr,
|
||
+ "rs6000_memory_move_cost: ret=%d, mode=%s, rclass=%s, in=%d\n",
|
||
+ ret, GET_MODE_NAME (mode), reg_class_names[rclass], in);
|
||
+
|
||
+ return ret;
|
||
}
|
||
|
||
/* Returns a code for a target-specific builtin that implements
|
||
@@ -24546,4 +24513,24 @@ rs6000_final_prescan_insn (rtx insn, rtx
|
||
}
|
||
}
|
||
|
||
+/* Return true if the function has an indirect jump or a table jump. The compiler
|
||
+ prefers the ctr register for such jumps, which interferes with using the decrement
|
||
+ ctr register and branch. */
|
||
+
|
||
+bool
|
||
+rs6000_has_indirect_jump_p (void)
|
||
+{
|
||
+ gcc_assert (cfun && cfun->machine);
|
||
+ return cfun->machine->indirect_jump_p;
|
||
+}
|
||
+
|
||
+/* Remember when we've generated an indirect jump. */
|
||
+
|
||
+void
|
||
+rs6000_set_indirect_jump (void)
|
||
+{
|
||
+ gcc_assert (cfun && cfun->machine);
|
||
+ cfun->machine->indirect_jump_p = true;
|
||
+}
|
||
+
|
||
#include "gt-rs6000.h"
|
||
--- gcc/config/rs6000/vsx.md (revision 146119)
|
||
+++ gcc/config/rs6000/vsx.md (revision 146798)
|
||
@@ -22,12 +22,22 @@
|
||
;; Iterator for both scalar and vector floating point types supported by VSX
|
||
(define_mode_iterator VSX_B [DF V4SF V2DF])
|
||
|
||
+;; Iterator for the 2 64-bit vector types
|
||
+(define_mode_iterator VSX_D [V2DF V2DI])
|
||
+
|
||
+;; Iterator for the 2 32-bit vector types
|
||
+(define_mode_iterator VSX_W [V4SF V4SI])
|
||
+
|
||
;; Iterator for vector floating point types supported by VSX
|
||
(define_mode_iterator VSX_F [V4SF V2DF])
|
||
|
||
;; Iterator for logical types supported by VSX
|
||
(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
|
||
|
||
+;; Iterator for memory move. Handle TImode specially to allow
|
||
+;; it to use gprs as well as vsx registers.
|
||
+(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
|
||
+
|
||
;; Iterator for types for load/store with update
|
||
(define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF])
|
||
|
||
@@ -49,9 +59,10 @@ (define_mode_attr VSs [(V16QI "sp")
|
||
(V2DF "dp")
|
||
(V2DI "dp")
|
||
(DF "dp")
|
||
+ (SF "sp")
|
||
(TI "sp")])
|
||
|
||
-;; Map into the register class used
|
||
+;; Map the register class used
|
||
(define_mode_attr VSr [(V16QI "v")
|
||
(V8HI "v")
|
||
(V4SI "v")
|
||
@@ -59,9 +70,10 @@ (define_mode_attr VSr [(V16QI "v")
|
||
(V2DI "wd")
|
||
(V2DF "wd")
|
||
(DF "ws")
|
||
+ (SF "f")
|
||
(TI "wd")])
|
||
|
||
-;; Map into the register class used for float<->int conversions
|
||
+;; Map the register class used for float<->int conversions
|
||
(define_mode_attr VSr2 [(V2DF "wd")
|
||
(V4SF "wf")
|
||
(DF "!f#r")])
|
||
@@ -70,6 +82,18 @@ (define_mode_attr VSr3 [(V2DF "wa")
|
||
(V4SF "wa")
|
||
(DF "!f#r")])
|
||
|
||
+;; Map the register class for sp<->dp float conversions, destination
|
||
+(define_mode_attr VSr4 [(SF "ws")
|
||
+ (DF "f")
|
||
+ (V2DF "wd")
|
||
+ (V4SF "v")])
|
||
+
|
||
+;; Map the register class for sp<->dp float conversions, destination
|
||
+(define_mode_attr VSr5 [(SF "ws")
|
||
+ (DF "f")
|
||
+ (V2DF "v")
|
||
+ (V4SF "wd")])
|
||
+
|
||
;; Same size integer type for floating point data
|
||
(define_mode_attr VSi [(V4SF "v4si")
|
||
(V2DF "v2di")
|
||
@@ -137,6 +161,32 @@ (define_mode_attr VSfptype_sqrt [(V2DF "
|
||
(V4SF "fp_sqrt_s")
|
||
(DF "fp_sqrt_d")])
|
||
|
||
+;; Iterator and modes for sp<->dp conversions
|
||
+(define_mode_iterator VSX_SPDP [SF DF V4SF V2DF])
|
||
+
|
||
+(define_mode_attr VS_spdp_res [(SF "DF")
|
||
+ (DF "SF")
|
||
+ (V4SF "V2DF")
|
||
+ (V2DF "V4SF")])
|
||
+
|
||
+(define_mode_attr VS_spdp_insn [(SF "xscvspdp")
|
||
+ (DF "xscvdpsp")
|
||
+ (V4SF "xvcvspdp")
|
||
+ (V2DF "xvcvdpsp")])
|
||
+
|
||
+(define_mode_attr VS_spdp_type [(SF "fp")
|
||
+ (DF "fp")
|
||
+ (V4SF "vecfloat")
|
||
+ (V2DF "vecfloat")])
|
||
+
|
||
+;; Map the scalar mode for a vector type
|
||
+(define_mode_attr VS_scalar [(V2DF "DF")
|
||
+ (V2DI "DI")
|
||
+ (V4SF "SF")
|
||
+ (V4SI "SI")
|
||
+ (V8HI "HI")
|
||
+ (V16QI "QI")])
|
||
+
|
||
;; Appropriate type for load + update
|
||
(define_mode_attr VStype_load_update [(V16QI "vecload")
|
||
(V8HI "vecload")
|
||
@@ -159,25 +209,33 @@ (define_mode_attr VStype_store_update [(
|
||
|
||
;; Constants for creating unspecs
|
||
(define_constants
|
||
- [(UNSPEC_VSX_CONCAT_V2DF 500)
|
||
- (UNSPEC_VSX_XVCVDPSP 501)
|
||
- (UNSPEC_VSX_XVCVDPSXWS 502)
|
||
- (UNSPEC_VSX_XVCVDPUXWS 503)
|
||
- (UNSPEC_VSX_XVCVSPDP 504)
|
||
- (UNSPEC_VSX_XVCVSXWDP 505)
|
||
- (UNSPEC_VSX_XVCVUXWDP 506)
|
||
- (UNSPEC_VSX_XVMADD 507)
|
||
- (UNSPEC_VSX_XVMSUB 508)
|
||
- (UNSPEC_VSX_XVNMADD 509)
|
||
- (UNSPEC_VSX_XVNMSUB 510)
|
||
- (UNSPEC_VSX_XVRSQRTE 511)
|
||
- (UNSPEC_VSX_XVTDIV 512)
|
||
- (UNSPEC_VSX_XVTSQRT 513)])
|
||
+ [(UNSPEC_VSX_CONCAT 500)
|
||
+ (UNSPEC_VSX_CVDPSXWS 501)
|
||
+ (UNSPEC_VSX_CVDPUXWS 502)
|
||
+ (UNSPEC_VSX_CVSPDP 503)
|
||
+ (UNSPEC_VSX_CVSXWDP 504)
|
||
+ (UNSPEC_VSX_CVUXWDP 505)
|
||
+ (UNSPEC_VSX_CVSXDSP 506)
|
||
+ (UNSPEC_VSX_CVUXDSP 507)
|
||
+ (UNSPEC_VSX_CVSPSXDS 508)
|
||
+ (UNSPEC_VSX_CVSPUXDS 509)
|
||
+ (UNSPEC_VSX_MADD 510)
|
||
+ (UNSPEC_VSX_MSUB 511)
|
||
+ (UNSPEC_VSX_NMADD 512)
|
||
+ (UNSPEC_VSX_NMSUB 513)
|
||
+ (UNSPEC_VSX_RSQRTE 514)
|
||
+ (UNSPEC_VSX_TDIV 515)
|
||
+ (UNSPEC_VSX_TSQRT 516)
|
||
+ (UNSPEC_VSX_XXPERMDI 517)
|
||
+ (UNSPEC_VSX_SET 518)
|
||
+ (UNSPEC_VSX_ROUND_I 519)
|
||
+ (UNSPEC_VSX_ROUND_IC 520)
|
||
+ (UNSPEC_VSX_SLDWI 521)])
|
||
|
||
;; VSX moves
|
||
(define_insn "*vsx_mov<mode>"
|
||
- [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
|
||
- (match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
|
||
+ [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
|
||
+ (match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
|
||
"VECTOR_MEM_VSX_P (<MODE>mode)
|
||
&& (register_operand (operands[0], <MODE>mode)
|
||
|| register_operand (operands[1], <MODE>mode))"
|
||
@@ -220,6 +278,49 @@ (define_insn "*vsx_mov<mode>"
|
||
}
|
||
[(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
|
||
|
||
+;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for
|
||
+;; unions. However for plain data movement, slightly favor the vector loads
|
||
+(define_insn "*vsx_movti"
|
||
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ")
|
||
+ (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))]
|
||
+ "VECTOR_MEM_VSX_P (TImode)
|
||
+ && (register_operand (operands[0], TImode)
|
||
+ || register_operand (operands[1], TImode))"
|
||
+{
|
||
+ switch (which_alternative)
|
||
+ {
|
||
+ case 0:
|
||
+ return "stxvd2%U0x %x1,%y0";
|
||
+
|
||
+ case 1:
|
||
+ return "lxvd2%U0x %x0,%y1";
|
||
+
|
||
+ case 2:
|
||
+ return "xxlor %x0,%x1,%x1";
|
||
+
|
||
+ case 3:
|
||
+ case 4:
|
||
+ case 5:
|
||
+ return "#";
|
||
+
|
||
+ case 6:
|
||
+ return "xxlxor %x0,%x0,%x0";
|
||
+
|
||
+ case 7:
|
||
+ return output_vec_const_move (operands);
|
||
+
|
||
+ case 8:
|
||
+ return "stvx %1,%y0";
|
||
+
|
||
+ case 9:
|
||
+ return "lvx %0,%y1";
|
||
+
|
||
+ default:
|
||
+ gcc_unreachable ();
|
||
+ }
|
||
+}
|
||
+ [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")])
|
||
+
|
||
;; Load/store with update
|
||
;; Define insns that do load or store with update. Because VSX only has
|
||
;; reg+reg addressing, pre-decrement or pre-inrement is unlikely to be
|
||
@@ -297,7 +398,7 @@ (define_insn "vsx_tdiv<mode>3"
|
||
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
|
||
(match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
|
||
- UNSPEC_VSX_XVTDIV))]
|
||
+ UNSPEC_VSX_TDIV))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"x<VSv>tdiv<VSs> %x0,%x1,%x2"
|
||
[(set_attr "type" "<VStype_simple>")
|
||
@@ -367,7 +468,7 @@ (define_insn "*vsx_sqrt<mode>2"
|
||
(define_insn "vsx_rsqrte<mode>2"
|
||
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
|
||
- UNSPEC_VSX_XVRSQRTE))]
|
||
+ UNSPEC_VSX_RSQRTE))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"x<VSv>rsqrte<VSs> %x0,%x1"
|
||
[(set_attr "type" "<VStype_simple>")
|
||
@@ -376,7 +477,7 @@ (define_insn "vsx_rsqrte<mode>2"
|
||
(define_insn "vsx_tsqrt<mode>2"
|
||
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
|
||
- UNSPEC_VSX_XVTSQRT))]
|
||
+ UNSPEC_VSX_TSQRT))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"x<VSv>tsqrt<VSs> %x0,%x1"
|
||
[(set_attr "type" "<VStype_simple>")
|
||
@@ -426,7 +527,7 @@ (define_insn "vsx_fmadd<mode>4_2"
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
|
||
(match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
|
||
(match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
|
||
- UNSPEC_VSX_XVMADD))]
|
||
+ UNSPEC_VSX_MADD))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"@
|
||
x<VSv>madda<VSs> %x0,%x1,%x2
|
||
@@ -474,7 +575,7 @@ (define_insn "vsx_fmsub<mode>4_2"
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
|
||
(match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
|
||
(match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
|
||
- UNSPEC_VSX_XVMSUB))]
|
||
+ UNSPEC_VSX_MSUB))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"@
|
||
x<VSv>msuba<VSs> %x0,%x1,%x2
|
||
@@ -552,7 +653,7 @@ (define_insn "vsx_fnmadd<mode>4_3"
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
|
||
(match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
|
||
(match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
|
||
- UNSPEC_VSX_XVNMADD))]
|
||
+ UNSPEC_VSX_NMADD))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"@
|
||
x<VSv>nmadda<VSs> %x0,%x1,%x2
|
||
@@ -629,7 +730,7 @@ (define_insn "vsx_fnmsub<mode>4_3"
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
|
||
(match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
|
||
(match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
|
||
- UNSPEC_VSX_XVNMSUB))]
|
||
+ UNSPEC_VSX_NMSUB))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"@
|
||
x<VSv>nmsuba<VSs> %x0,%x1,%x2
|
||
@@ -667,13 +768,13 @@ (define_insn "*vsx_ge<mode>"
|
||
[(set_attr "type" "<VStype_simple>")
|
||
(set_attr "fp_type" "<VSfptype_simple>")])
|
||
|
||
-(define_insn "vsx_vsel<mode>"
|
||
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
- (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
|
||
+(define_insn "*vsx_vsel<mode>"
|
||
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
+ (if_then_else:VSX_L (ne (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
|
||
(const_int 0))
|
||
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")
|
||
- (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>,wa")))]
|
||
- "VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
|
||
+ (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
"xxsel %x0,%x3,%x2,%x1"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
@@ -698,7 +799,7 @@ (define_insn "vsx_ftrunc<mode>2"
|
||
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
(fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
|
||
"VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
- "x<VSv>r<VSs>piz %x0,%x1"
|
||
+ "x<VSv>r<VSs>iz %x0,%x1"
|
||
[(set_attr "type" "<VStype_simple>")
|
||
(set_attr "fp_type" "<VSfptype_simple>")])
|
||
|
||
@@ -735,6 +836,24 @@ (define_insn "vsx_fixuns_trunc<mode><VSi
|
||
(set_attr "fp_type" "<VSfptype_simple>")])
|
||
|
||
;; Math rounding functions
|
||
+(define_insn "vsx_x<VSv>r<VSs>i"
|
||
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
|
||
+ UNSPEC_VSX_ROUND_I))]
|
||
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
+ "x<VSv>r<VSs>i %x0,%x1"
|
||
+ [(set_attr "type" "<VStype_simple>")
|
||
+ (set_attr "fp_type" "<VSfptype_simple>")])
|
||
+
|
||
+(define_insn "vsx_x<VSv>r<VSs>ic"
|
||
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
|
||
+ UNSPEC_VSX_ROUND_IC))]
|
||
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
+ "x<VSv>r<VSs>ic %x0,%x1"
|
||
+ [(set_attr "type" "<VStype_simple>")
|
||
+ (set_attr "fp_type" "<VSfptype_simple>")])
|
||
+
|
||
(define_insn "vsx_btrunc<mode>2"
|
||
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
|
||
(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
|
||
@@ -765,22 +884,26 @@ (define_insn "vsx_ceil<mode>2"
|
||
|
||
;; VSX convert to/from double vector
|
||
|
||
+;; Convert between single and double precision
|
||
+;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
|
||
+;; scalar single precision instructions internally use the double format.
|
||
+;; Prefer the altivec registers, since we likely will need to do a vperm
|
||
+(define_insn "vsx_<VS_spdp_insn>"
|
||
+ [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
|
||
+ (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
|
||
+ UNSPEC_VSX_CVSPDP))]
|
||
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
+ "<VS_spdp_insn> %x0,%x1"
|
||
+ [(set_attr "type" "<VS_spdp_type>")])
|
||
+
|
||
;; Convert from 64-bit to 32-bit types
|
||
;; Note, favor the Altivec registers since the usual use of these instructions
|
||
;; is in vector converts and we need to use the Altivec vperm instruction.
|
||
|
||
-(define_insn "vsx_xvcvdpsp"
|
||
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=v,?wa")
|
||
- (unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
|
||
- UNSPEC_VSX_XVCVDPSP))]
|
||
- "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
- "xvcvdpsp %x0,%x1"
|
||
- [(set_attr "type" "vecfloat")])
|
||
-
|
||
(define_insn "vsx_xvcvdpsxws"
|
||
[(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
|
||
(unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
|
||
- UNSPEC_VSX_XVCVDPSXWS))]
|
||
+ UNSPEC_VSX_CVDPSXWS))]
|
||
"VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
"xvcvdpsxws %x0,%x1"
|
||
[(set_attr "type" "vecfloat")])
|
||
@@ -788,24 +911,32 @@ (define_insn "vsx_xvcvdpsxws"
|
||
(define_insn "vsx_xvcvdpuxws"
|
||
[(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
|
||
(unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
|
||
- UNSPEC_VSX_XVCVDPUXWS))]
|
||
+ UNSPEC_VSX_CVDPUXWS))]
|
||
"VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
"xvcvdpuxws %x0,%x1"
|
||
[(set_attr "type" "vecfloat")])
|
||
|
||
-;; Convert from 32-bit to 64-bit types
|
||
-(define_insn "vsx_xvcvspdp"
|
||
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
|
||
- (unspec:V2DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
|
||
- UNSPEC_VSX_XVCVSPDP))]
|
||
+(define_insn "vsx_xvcvsxdsp"
|
||
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
|
||
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
|
||
+ UNSPEC_VSX_CVSXDSP))]
|
||
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+ "xvcvsxdsp %x0,%x1"
|
||
+ [(set_attr "type" "vecfloat")])
|
||
+
|
||
+(define_insn "vsx_xvcvuxdsp"
|
||
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
|
||
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
|
||
+ UNSPEC_VSX_CVUXDSP))]
|
||
"VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
- "xvcvspdp %x0,%x1"
|
||
+ "xvcvuxwdp %x0,%x1"
|
||
[(set_attr "type" "vecfloat")])
|
||
|
||
+;; Convert from 32-bit to 64-bit types
|
||
(define_insn "vsx_xvcvsxwdp"
|
||
[(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
|
||
(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
|
||
- UNSPEC_VSX_XVCVSXWDP))]
|
||
+ UNSPEC_VSX_CVSXWDP))]
|
||
"VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
"xvcvsxwdp %x0,%x1"
|
||
[(set_attr "type" "vecfloat")])
|
||
@@ -813,11 +944,26 @@ (define_insn "vsx_xvcvsxwdp"
|
||
(define_insn "vsx_xvcvuxwdp"
|
||
[(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
|
||
(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
|
||
- UNSPEC_VSX_XVCVUXWDP))]
|
||
+ UNSPEC_VSX_CVUXWDP))]
|
||
"VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
"xvcvuxwdp %x0,%x1"
|
||
[(set_attr "type" "vecfloat")])
|
||
|
||
+(define_insn "vsx_xvcvspsxds"
|
||
+ [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
|
||
+ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
|
||
+ UNSPEC_VSX_CVSPSXDS))]
|
||
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+ "xvcvspsxds %x0,%x1"
|
||
+ [(set_attr "type" "vecfloat")])
|
||
+
|
||
+(define_insn "vsx_xvcvspuxds"
|
||
+ [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
|
||
+ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
|
||
+ UNSPEC_VSX_CVSPUXDS))]
|
||
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+ "xvcvspuxds %x0,%x1"
|
||
+ [(set_attr "type" "vecfloat")])
|
||
|
||
;; Logical and permute operations
|
||
(define_insn "*vsx_and<mode>3"
|
||
@@ -877,24 +1023,25 @@ (define_insn "*vsx_andc<mode>3"
|
||
|
||
;; Permute operations
|
||
|
||
-(define_insn "vsx_concat_v2df"
|
||
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
|
||
- (unspec:V2DF
|
||
- [(match_operand:DF 1 "vsx_register_operand" "ws,wa")
|
||
- (match_operand:DF 2 "vsx_register_operand" "ws,wa")]
|
||
- UNSPEC_VSX_CONCAT_V2DF))]
|
||
- "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+;; Build a V2DF/V2DI vector from two scalars
|
||
+(define_insn "vsx_concat_<mode>"
|
||
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
|
||
+ (unspec:VSX_D
|
||
+ [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
|
||
+ (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
|
||
+ UNSPEC_VSX_CONCAT))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
"xxpermdi %x0,%x1,%x2,0"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
-;; Set a double into one element
|
||
-(define_insn "vsx_set_v2df"
|
||
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
|
||
- (vec_merge:V2DF
|
||
- (match_operand:V2DF 1 "vsx_register_operand" "wd,wa")
|
||
- (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws,f"))
|
||
- (match_operand:QI 3 "u5bit_cint_operand" "i,i")))]
|
||
- "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+;; Set the element of a V2DI/VD2F mode
|
||
+(define_insn "vsx_set_<mode>"
|
||
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
|
||
+ (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
|
||
+ (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
|
||
+ (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
|
||
+ UNSPEC_VSX_SET))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
{
|
||
if (INTVAL (operands[3]) == 0)
|
||
return \"xxpermdi %x0,%x1,%x2,1\";
|
||
@@ -906,12 +1053,12 @@ (define_insn "vsx_set_v2df"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
;; Extract a DF element from V2DF
|
||
-(define_insn "vsx_extract_v2df"
|
||
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,f,?wa")
|
||
- (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd,wd,wa")
|
||
+(define_insn "vsx_extract_<mode>"
|
||
+ [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,f,?wa")
|
||
+ (vec_select:<VS_scalar> (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa")
|
||
(parallel
|
||
[(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
|
||
- "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
{
|
||
gcc_assert (UINTVAL (operands[2]) <= 1);
|
||
operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
|
||
@@ -919,17 +1066,30 @@ (define_insn "vsx_extract_v2df"
|
||
}
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
-;; General V2DF permute, extract_{high,low,even,odd}
|
||
-(define_insn "vsx_xxpermdi"
|
||
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
|
||
- (vec_concat:V2DF
|
||
- (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
|
||
- (parallel
|
||
- [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
|
||
- (vec_select:DF (match_operand:V2DF 3 "vsx_register_operand" "wd")
|
||
- (parallel
|
||
- [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
|
||
- "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+;; General V2DF/V2DI permute
|
||
+(define_insn "vsx_xxpermdi_<mode>"
|
||
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
|
||
+ (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa")
|
||
+ (match_operand:VSX_D 2 "vsx_register_operand" "wd,wa")
|
||
+ (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
|
||
+ UNSPEC_VSX_XXPERMDI))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
+ "xxpermdi %x0,%x1,%x2,%3"
|
||
+ [(set_attr "type" "vecperm")])
|
||
+
|
||
+;; Varient of xxpermdi that is emitted by the vec_interleave functions
|
||
+(define_insn "*vsx_xxpermdi2_<mode>"
|
||
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
|
||
+ (vec_concat:VSX_D
|
||
+ (vec_select:<VS_scalar>
|
||
+ (match_operand:VSX_D 1 "vsx_register_operand" "wd")
|
||
+ (parallel
|
||
+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
|
||
+ (vec_select:<VS_scalar>
|
||
+ (match_operand:VSX_D 3 "vsx_register_operand" "wd")
|
||
+ (parallel
|
||
+ [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
{
|
||
gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
|
||
operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
|
||
@@ -939,11 +1099,11 @@ (define_insn "vsx_xxpermdi"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
;; V2DF splat
|
||
-(define_insn "vsx_splatv2df"
|
||
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
|
||
- (vec_duplicate:V2DF
|
||
- (match_operand:DF 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
|
||
- "VECTOR_UNIT_VSX_P (V2DFmode)"
|
||
+(define_insn "vsx_splat_<mode>"
|
||
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
|
||
+ (vec_duplicate:VSX_D
|
||
+ (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
|
||
+ "VECTOR_UNIT_VSX_P (<MODE>mode)"
|
||
"@
|
||
xxpermdi %x0,%x1,%x1,0
|
||
xxpermdi %x0,%x1,%x1,0
|
||
@@ -953,52 +1113,66 @@ (define_insn "vsx_splatv2df"
|
||
lxvdsx %x0,%y1"
|
||
[(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
|
||
|
||
-;; V4SF splat
|
||
-(define_insn "*vsx_xxspltw"
|
||
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa")
|
||
- (vec_duplicate:V4SF
|
||
- (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa")
|
||
- (parallel
|
||
- [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
|
||
- "VECTOR_UNIT_VSX_P (V4SFmode)"
|
||
+;; V4SF/V4SI splat
|
||
+(define_insn "vsx_xxspltw_<mode>"
|
||
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
|
||
+ (vec_duplicate:VSX_W
|
||
+ (vec_select:<VS_scalar>
|
||
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
|
||
+ (parallel
|
||
+ [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
"xxspltw %x0,%x1,%2"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
-;; V4SF interleave
|
||
-(define_insn "vsx_xxmrghw"
|
||
- [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa")
|
||
- (vec_merge:V4SF
|
||
- (vec_select:V4SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa")
|
||
- (parallel [(const_int 0)
|
||
- (const_int 2)
|
||
- (const_int 1)
|
||
- (const_int 3)]))
|
||
- (vec_select:V4SF (match_operand:V4SF 2 "vsx_register_operand" "wf,wa")
|
||
- (parallel [(const_int 2)
|
||
- (const_int 0)
|
||
- (const_int 3)
|
||
- (const_int 1)]))
|
||
+;; V4SF/V4SI interleave
|
||
+(define_insn "vsx_xxmrghw_<mode>"
|
||
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
|
||
+ (vec_merge:VSX_W
|
||
+ (vec_select:VSX_W
|
||
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
|
||
+ (parallel [(const_int 0)
|
||
+ (const_int 2)
|
||
+ (const_int 1)
|
||
+ (const_int 3)]))
|
||
+ (vec_select:VSX_W
|
||
+ (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
|
||
+ (parallel [(const_int 2)
|
||
+ (const_int 0)
|
||
+ (const_int 3)
|
||
+ (const_int 1)]))
|
||
(const_int 5)))]
|
||
- "VECTOR_UNIT_VSX_P (V4SFmode)"
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
"xxmrghw %x0,%x1,%x2"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
-(define_insn "vsx_xxmrglw"
|
||
- [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa")
|
||
- (vec_merge:V4SF
|
||
- (vec_select:V4SF
|
||
- (match_operand:V4SF 1 "register_operand" "wf,wa")
|
||
+(define_insn "vsx_xxmrglw_<mode>"
|
||
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
|
||
+ (vec_merge:VSX_W
|
||
+ (vec_select:VSX_W
|
||
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
|
||
(parallel [(const_int 2)
|
||
(const_int 0)
|
||
(const_int 3)
|
||
(const_int 1)]))
|
||
- (vec_select:V4SF
|
||
- (match_operand:V4SF 2 "register_operand" "wf,?wa")
|
||
+ (vec_select:VSX_W
|
||
+ (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
|
||
(parallel [(const_int 0)
|
||
(const_int 2)
|
||
(const_int 1)
|
||
(const_int 3)]))
|
||
(const_int 5)))]
|
||
- "VECTOR_UNIT_VSX_P (V4SFmode)"
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
"xxmrglw %x0,%x1,%x2"
|
||
[(set_attr "type" "vecperm")])
|
||
+
|
||
+;; Shift left double by word immediate
|
||
+(define_insn "vsx_xxsldwi_<mode>"
|
||
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
|
||
+ (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
|
||
+ (match_operand:VSX_L 2 "vsx_register_operand" "wa")
|
||
+ (match_operand:QI 3 "u5bit_cint_operand" "i")]
|
||
+ UNSPEC_VSX_SLDWI))]
|
||
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
|
||
+ "xxsldwi %x0,%x1,%x2,%3"
|
||
+ [(set_attr "type" "vecperm")])
|
||
--- gcc/config/rs6000/rs6000.h (revision 146119)
|
||
+++ gcc/config/rs6000/rs6000.h (revision 146798)
|
||
@@ -1033,14 +1033,6 @@ extern int rs6000_vector_align[];
|
||
((MODE) == V4SFmode \
|
||
|| (MODE) == V2DFmode) \
|
||
|
||
-#define VSX_VECTOR_MOVE_MODE(MODE) \
|
||
- ((MODE) == V16QImode \
|
||
- || (MODE) == V8HImode \
|
||
- || (MODE) == V4SImode \
|
||
- || (MODE) == V2DImode \
|
||
- || (MODE) == V4SFmode \
|
||
- || (MODE) == V2DFmode) \
|
||
-
|
||
#define VSX_SCALAR_MODE(MODE) \
|
||
((MODE) == DFmode)
|
||
|
||
@@ -1049,12 +1041,9 @@ extern int rs6000_vector_align[];
|
||
|| VSX_SCALAR_MODE (MODE))
|
||
|
||
#define VSX_MOVE_MODE(MODE) \
|
||
- (VSX_VECTOR_MOVE_MODE (MODE) \
|
||
- || VSX_SCALAR_MODE(MODE) \
|
||
- || (MODE) == V16QImode \
|
||
- || (MODE) == V8HImode \
|
||
- || (MODE) == V4SImode \
|
||
- || (MODE) == V2DImode \
|
||
+ (VSX_VECTOR_MODE (MODE) \
|
||
+ || VSX_SCALAR_MODE (MODE) \
|
||
+ || ALTIVEC_VECTOR_MODE (MODE) \
|
||
|| (MODE) == TImode)
|
||
|
||
#define ALTIVEC_VECTOR_MODE(MODE) \
|
||
@@ -1304,12 +1293,24 @@ enum reg_class
|
||
purpose. Any move between two registers of a cover class should be
|
||
cheaper than load or store of the registers. The macro value is
|
||
array of register classes with LIM_REG_CLASSES used as the end
|
||
- marker. */
|
||
+ marker.
|
||
+
|
||
+ We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to
|
||
+ account for the Altivec and Floating registers being subsets of the VSX
|
||
+ register set. */
|
||
+
|
||
+#define IRA_COVER_CLASSES_PRE_VSX \
|
||
+{ \
|
||
+ GENERAL_REGS, SPECIAL_REGS, FLOAT_REGS, ALTIVEC_REGS, /* VSX_REGS, */ \
|
||
+ /* VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \
|
||
+ /* MQ_REGS, LINK_REGS, CTR_REGS, */ \
|
||
+ CR_REGS, XER_REGS, LIM_REG_CLASSES \
|
||
+}
|
||
|
||
-#define IRA_COVER_CLASSES \
|
||
+#define IRA_COVER_CLASSES_VSX \
|
||
{ \
|
||
- GENERAL_REGS, SPECIAL_REGS, FLOAT_REGS, ALTIVEC_REGS, \
|
||
- /*VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \
|
||
+ GENERAL_REGS, SPECIAL_REGS, /* FLOAT_REGS, ALTIVEC_REGS, */ VSX_REGS, \
|
||
+ /* VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \
|
||
/* MQ_REGS, LINK_REGS, CTR_REGS, */ \
|
||
CR_REGS, XER_REGS, LIM_REG_CLASSES \
|
||
}
|
||
@@ -3371,21 +3372,36 @@ enum rs6000_builtins
|
||
VSX_BUILTIN_XVTDIVSP,
|
||
VSX_BUILTIN_XVTSQRTDP,
|
||
VSX_BUILTIN_XVTSQRTSP,
|
||
- VSX_BUILTIN_XXLAND,
|
||
- VSX_BUILTIN_XXLANDC,
|
||
- VSX_BUILTIN_XXLNOR,
|
||
- VSX_BUILTIN_XXLOR,
|
||
- VSX_BUILTIN_XXLXOR,
|
||
- VSX_BUILTIN_XXMRGHD,
|
||
- VSX_BUILTIN_XXMRGHW,
|
||
- VSX_BUILTIN_XXMRGLD,
|
||
- VSX_BUILTIN_XXMRGLW,
|
||
- VSX_BUILTIN_XXPERMDI,
|
||
- VSX_BUILTIN_XXSEL,
|
||
- VSX_BUILTIN_XXSLDWI,
|
||
- VSX_BUILTIN_XXSPLTD,
|
||
- VSX_BUILTIN_XXSPLTW,
|
||
- VSX_BUILTIN_XXSWAPD,
|
||
+ VSX_BUILTIN_XXSEL_2DI,
|
||
+ VSX_BUILTIN_XXSEL_2DF,
|
||
+ VSX_BUILTIN_XXSEL_4SI,
|
||
+ VSX_BUILTIN_XXSEL_4SF,
|
||
+ VSX_BUILTIN_XXSEL_8HI,
|
||
+ VSX_BUILTIN_XXSEL_16QI,
|
||
+ VSX_BUILTIN_VPERM_2DI,
|
||
+ VSX_BUILTIN_VPERM_2DF,
|
||
+ VSX_BUILTIN_VPERM_4SI,
|
||
+ VSX_BUILTIN_VPERM_4SF,
|
||
+ VSX_BUILTIN_VPERM_8HI,
|
||
+ VSX_BUILTIN_VPERM_16QI,
|
||
+ VSX_BUILTIN_XXPERMDI_2DF,
|
||
+ VSX_BUILTIN_XXPERMDI_2DI,
|
||
+ VSX_BUILTIN_CONCAT_2DF,
|
||
+ VSX_BUILTIN_CONCAT_2DI,
|
||
+ VSX_BUILTIN_SET_2DF,
|
||
+ VSX_BUILTIN_SET_2DI,
|
||
+ VSX_BUILTIN_SPLAT_2DF,
|
||
+ VSX_BUILTIN_SPLAT_2DI,
|
||
+ VSX_BUILTIN_XXMRGHW_4SF,
|
||
+ VSX_BUILTIN_XXMRGHW_4SI,
|
||
+ VSX_BUILTIN_XXMRGLW_4SF,
|
||
+ VSX_BUILTIN_XXMRGLW_4SI,
|
||
+ VSX_BUILTIN_XXSLDWI_16QI,
|
||
+ VSX_BUILTIN_XXSLDWI_8HI,
|
||
+ VSX_BUILTIN_XXSLDWI_4SI,
|
||
+ VSX_BUILTIN_XXSLDWI_4SF,
|
||
+ VSX_BUILTIN_XXSLDWI_2DI,
|
||
+ VSX_BUILTIN_XXSLDWI_2DF,
|
||
|
||
/* VSX overloaded builtins, add the overloaded functions not present in
|
||
Altivec. */
|
||
@@ -3395,7 +3411,13 @@ enum rs6000_builtins
|
||
VSX_BUILTIN_VEC_NMADD,
|
||
VSX_BUITLIN_VEC_NMSUB,
|
||
VSX_BUILTIN_VEC_DIV,
|
||
- VSX_BUILTIN_OVERLOADED_LAST = VSX_BUILTIN_VEC_DIV,
|
||
+ VSX_BUILTIN_VEC_XXMRGHW,
|
||
+ VSX_BUILTIN_VEC_XXMRGLW,
|
||
+ VSX_BUILTIN_VEC_XXPERMDI,
|
||
+ VSX_BUILTIN_VEC_XXSLDWI,
|
||
+ VSX_BUILTIN_VEC_XXSPLTD,
|
||
+ VSX_BUILTIN_VEC_XXSPLTW,
|
||
+ VSX_BUILTIN_OVERLOADED_LAST = VSX_BUILTIN_VEC_XXSPLTW,
|
||
|
||
/* Combined VSX/Altivec builtins. */
|
||
VECTOR_BUILTIN_FLOAT_V4SI_V4SF,
|
||
@@ -3425,13 +3447,16 @@ enum rs6000_builtin_type_index
|
||
RS6000_BTI_unsigned_V16QI,
|
||
RS6000_BTI_unsigned_V8HI,
|
||
RS6000_BTI_unsigned_V4SI,
|
||
+ RS6000_BTI_unsigned_V2DI,
|
||
RS6000_BTI_bool_char, /* __bool char */
|
||
RS6000_BTI_bool_short, /* __bool short */
|
||
RS6000_BTI_bool_int, /* __bool int */
|
||
+ RS6000_BTI_bool_long, /* __bool long */
|
||
RS6000_BTI_pixel, /* __pixel */
|
||
RS6000_BTI_bool_V16QI, /* __vector __bool char */
|
||
RS6000_BTI_bool_V8HI, /* __vector __bool short */
|
||
RS6000_BTI_bool_V4SI, /* __vector __bool int */
|
||
+ RS6000_BTI_bool_V2DI, /* __vector __bool long */
|
||
RS6000_BTI_pixel_V8HI, /* __vector __pixel */
|
||
RS6000_BTI_long, /* long_integer_type_node */
|
||
RS6000_BTI_unsigned_long, /* long_unsigned_type_node */
|
||
@@ -3466,13 +3491,16 @@ enum rs6000_builtin_type_index
|
||
#define unsigned_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V16QI])
|
||
#define unsigned_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V8HI])
|
||
#define unsigned_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V4SI])
|
||
+#define unsigned_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V2DI])
|
||
#define bool_char_type_node (rs6000_builtin_types[RS6000_BTI_bool_char])
|
||
#define bool_short_type_node (rs6000_builtin_types[RS6000_BTI_bool_short])
|
||
#define bool_int_type_node (rs6000_builtin_types[RS6000_BTI_bool_int])
|
||
+#define bool_long_type_node (rs6000_builtin_types[RS6000_BTI_bool_long])
|
||
#define pixel_type_node (rs6000_builtin_types[RS6000_BTI_pixel])
|
||
#define bool_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V16QI])
|
||
#define bool_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V8HI])
|
||
#define bool_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V4SI])
|
||
+#define bool_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V2DI])
|
||
#define pixel_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_pixel_V8HI])
|
||
|
||
#define long_integer_type_internal_node (rs6000_builtin_types[RS6000_BTI_long])
|
||
--- gcc/config/rs6000/altivec.md (revision 146119)
|
||
+++ gcc/config/rs6000/altivec.md (revision 146798)
|
||
@@ -166,12 +166,15 @@ (define_mode_iterator V [V4SI V8HI V16QI
|
||
;; otherwise handled by altivec (v2df, v2di, ti)
|
||
(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI TI])
|
||
|
||
+;; Like VM, except don't do TImode
|
||
+(define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI])
|
||
+
|
||
(define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
|
||
|
||
;; Vector move instructions.
|
||
(define_insn "*altivec_mov<mode>"
|
||
- [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v")
|
||
- (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,j,W"))]
|
||
+ [(set (match_operand:VM2 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v")
|
||
+ (match_operand:VM2 1 "input_operand" "v,Z,v,r,o,r,j,W"))]
|
||
"VECTOR_MEM_ALTIVEC_P (<MODE>mode)
|
||
&& (register_operand (operands[0], <MODE>mode)
|
||
|| register_operand (operands[1], <MODE>mode))"
|
||
@@ -191,6 +194,31 @@ (define_insn "*altivec_mov<mode>"
|
||
}
|
||
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
|
||
|
||
+;; Unlike other altivec 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 "*altivec_movti"
|
||
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,v,v,?o,?r,?r,v,v")
|
||
+ (match_operand:TI 1 "input_operand" "v,Z,v,r,o,r,j,W"))]
|
||
+ "VECTOR_MEM_ALTIVEC_P (TImode)
|
||
+ && (register_operand (operands[0], TImode)
|
||
+ || register_operand (operands[1], TImode))"
|
||
+{
|
||
+ switch (which_alternative)
|
||
+ {
|
||
+ case 0: return "stvx %1,%y0";
|
||
+ case 1: return "lvx %0,%y1";
|
||
+ case 2: return "vor %0,%1,%1";
|
||
+ case 3: return "#";
|
||
+ case 4: return "#";
|
||
+ case 5: return "#";
|
||
+ case 6: return "vxor %0,%0,%0";
|
||
+ case 7: return output_vec_const_move (operands);
|
||
+ default: gcc_unreachable ();
|
||
+ }
|
||
+}
|
||
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
|
||
+
|
||
(define_split
|
||
[(set (match_operand:VM 0 "altivec_register_operand" "")
|
||
(match_operand:VM 1 "easy_vector_constant_add_self" ""))]
|
||
@@ -434,13 +462,13 @@ (define_insn "*altivec_gev4sf"
|
||
"vcmpgefp %0,%1,%2"
|
||
[(set_attr "type" "veccmp")])
|
||
|
||
-(define_insn "altivec_vsel<mode>"
|
||
+(define_insn "*altivec_vsel<mode>"
|
||
[(set (match_operand:VM 0 "altivec_register_operand" "=v")
|
||
(if_then_else:VM (ne (match_operand:VM 1 "altivec_register_operand" "v")
|
||
(const_int 0))
|
||
(match_operand:VM 2 "altivec_register_operand" "v")
|
||
(match_operand:VM 3 "altivec_register_operand" "v")))]
|
||
- "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
|
||
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
|
||
"vsel %0,%3,%2,%1"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
@@ -780,7 +808,7 @@ (define_insn "altivec_vmrghw"
|
||
(const_int 3)
|
||
(const_int 1)]))
|
||
(const_int 5)))]
|
||
- "TARGET_ALTIVEC"
|
||
+ "VECTOR_MEM_ALTIVEC_P (V4SImode)"
|
||
"vmrghw %0,%1,%2"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
@@ -797,7 +825,7 @@ (define_insn "*altivec_vmrghsf"
|
||
(const_int 3)
|
||
(const_int 1)]))
|
||
(const_int 5)))]
|
||
- "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
|
||
+ "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
|
||
"vmrghw %0,%1,%2"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
@@ -881,7 +909,7 @@ (define_insn "altivec_vmrglw"
|
||
(const_int 1)
|
||
(const_int 3)]))
|
||
(const_int 5)))]
|
||
- "TARGET_ALTIVEC"
|
||
+ "VECTOR_MEM_ALTIVEC_P (V4SImode)"
|
||
"vmrglw %0,%1,%2"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
@@ -899,7 +927,7 @@ (define_insn "*altivec_vmrglsf"
|
||
(const_int 1)
|
||
(const_int 3)]))
|
||
(const_int 5)))]
|
||
- "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
|
||
+ "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
|
||
"vmrglw %0,%1,%2"
|
||
[(set_attr "type" "vecperm")])
|
||
|
||
--- gcc/config/rs6000/rs6000.md (revision 146119)
|
||
+++ gcc/config/rs6000/rs6000.md (revision 146798)
|
||
@@ -14667,7 +14667,11 @@ (define_insn "return"
|
||
[(set_attr "type" "jmpreg")])
|
||
|
||
(define_expand "indirect_jump"
|
||
- [(set (pc) (match_operand 0 "register_operand" ""))])
|
||
+ [(set (pc) (match_operand 0 "register_operand" ""))]
|
||
+ ""
|
||
+{
|
||
+ rs6000_set_indirect_jump ();
|
||
+})
|
||
|
||
(define_insn "*indirect_jump<mode>"
|
||
[(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
|
||
@@ -14682,14 +14686,14 @@ (define_expand "tablejump"
|
||
[(use (match_operand 0 "" ""))
|
||
(use (label_ref (match_operand 1 "" "")))]
|
||
""
|
||
- "
|
||
{
|
||
+ rs6000_set_indirect_jump ();
|
||
if (TARGET_32BIT)
|
||
emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
|
||
else
|
||
emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
|
||
DONE;
|
||
-}")
|
||
+})
|
||
|
||
(define_expand "tablejumpsi"
|
||
[(set (match_dup 3)
|
||
@@ -14749,6 +14753,11 @@ (define_expand "doloop_end"
|
||
/* Only use this on innermost loops. */
|
||
if (INTVAL (operands[3]) > 1)
|
||
FAIL;
|
||
+ /* Do not try to use decrement and count on code that has an indirect
|
||
+ jump or a table jump, because the ctr register is preferred over the
|
||
+ lr register. */
|
||
+ if (rs6000_has_indirect_jump_p ())
|
||
+ FAIL;
|
||
if (TARGET_64BIT)
|
||
{
|
||
if (GET_MODE (operands[0]) != DImode)
|