summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boehm-gc/ChangeLog9
-rw-r--r--boehm-gc/include/private/gc_locks.h36
-rw-r--r--gcc/ChangeLog185
-rw-r--r--gcc/config/rs6000/altivec.md980
-rw-r--r--gcc/config/rs6000/constraints.md34
-rw-r--r--gcc/config/rs6000/predicates.md62
-rw-r--r--gcc/config/rs6000/rs6000-c.c48
-rw-r--r--gcc/config/rs6000/rs6000.c2339
-rw-r--r--gcc/config/rs6000/rs6000.h282
-rw-r--r--gcc/config/rs6000/rs6000.md1
-rw-r--r--gcc/config/rs6000/rs6000.opt32
-rw-r--r--gcc/config/rs6000/t-rs60001
-rw-r--r--gcc/config/rs6000/vector.md700
13 files changed, 3106 insertions, 1603 deletions
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 14ba80a9a7a..fa53669ca2a 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,12 @@
+2009-07-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR boehm-gc/40785
+ * include/private/gc_locks.h (GC_test_and_set): If GCC 4.4, use
+ the __sync_lock_test_and _set and __sync_lock_release builtins on
+ the powerpc. If not GCC 4.4, fix up the constraints so that it
+ builds without error.
+ (GC_clear): Ditto.
+
2009-07-17 Kai Tietz <kai.tietz@onevision.com>
* configure.ac: Add rule for mingw targets to add -DGC_BUILD=1 to
diff --git a/boehm-gc/include/private/gc_locks.h b/boehm-gc/include/private/gc_locks.h
index 4e2b641b78b..d1bb2e4521a 100644
--- a/boehm-gc/include/private/gc_locks.h
+++ b/boehm-gc/include/private/gc_locks.h
@@ -139,49 +139,35 @@
# define GC_TEST_AND_SET_DEFINED
# endif
# if defined(POWERPC)
-# if 0 /* CPP_WORDSZ == 64 totally broken to use int locks with ldarx */
- inline static int GC_test_and_set(volatile unsigned int *addr) {
- unsigned long oldval;
- unsigned long temp = 1; /* locked value */
-
- __asm__ __volatile__(
- "1:\tldarx %0,0,%3\n" /* load and reserve */
- "\tcmpdi %0, 0\n" /* if load is */
- "\tbne 2f\n" /* non-zero, return already set */
- "\tstdcx. %2,0,%1\n" /* else store conditional */
- "\tbne- 1b\n" /* retry if lost reservation */
- "\tsync\n" /* import barrier */
- "2:\t\n" /* oldval is zero if we set */
- : "=&r"(oldval), "=p"(addr)
- : "r"(temp), "1"(addr)
- : "cr0","memory");
- return (int)oldval;
- }
+# define GC_TEST_AND_SET_DEFINED
+# define GC_CLEAR_DEFINED
+# if (__GNUC__>4)||((__GNUC__==4)&&(__GNUC_MINOR__>=4))
+# define GC_test_and_set(addr) __sync_lock_test_and_set (addr, 1)
+# define GC_clear(addr) __sync_lock_release (addr)
# else
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
int temp = 1; /* locked value */
__asm__ __volatile__(
- "1:\tlwarx %0,0,%3\n" /* load and reserve */
+ "\n1:\n"
+ "\tlwarx %0,%y3\n" /* load and reserve, 32-bits */
"\tcmpwi %0, 0\n" /* if load is */
"\tbne 2f\n" /* non-zero, return already set */
- "\tstwcx. %2,0,%1\n" /* else store conditional */
+ "\tstwcx. %2,%y3\n" /* else store conditional */
"\tbne- 1b\n" /* retry if lost reservation */
"\tsync\n" /* import barrier */
"2:\t\n" /* oldval is zero if we set */
- : "=&r"(oldval), "=p"(addr)
- : "r"(temp), "1"(addr)
+ : "=&r"(oldval), "=m"(addr)
+ : "r"(temp), "Z"(addr)
: "cr0","memory");
return oldval;
}
-# endif
-# define GC_TEST_AND_SET_DEFINED
inline static void GC_clear(volatile unsigned int *addr) {
__asm__ __volatile__("lwsync" : : : "memory");
*(addr) = 0;
}
-# define GC_CLEAR_DEFINED
+# endif
# endif
# if defined(ALPHA)
inline static int GC_test_and_set(volatile unsigned int * addr)
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9c56aae0d30..e12299f95ce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,188 @@
+2009-07-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+ Pat Haugen <pthaugen@us.ibm.com>
+ Revital Eres <ERES@il.ibm.com>
+
+ * config/rs6000/vector.md: New file. Move most of the vector
+ expander support here from altivec.md to allow for the VSX vector
+ unit in the future. Add support for secondary_reload patterns.
+ Rewrite the patterns for vector comparison, and vector comparison
+ predicate instructions so that the RTL expresses the desired
+ behavior, instead of using unspec.
+
+ * config/rs6000/constraints.md ("f" constraint): Use
+ rs6000_constraints to hold the precalculated register class.
+ ("d" constraint): Ditto.
+ ("wd" constraint): New constraint for VSX.
+ ("wf" constraint): Ditto.
+ ("ws" constraint): Ditto.
+ ("wa" constraint): Ditto.
+ ("wZ" constraint): Ditto.
+ ("j" constraint): Ditto.
+
+ * config/rs6000/predicates.md (vsx_register_operand): New
+ predicate for VSX.
+ (vfloat_operand): New predicate for vector.md.
+ (vint_operand): Ditto.
+ (vlogical_operand): Ditto.
+ (easy_fp_constant): If VSX, 0.0 is an easy constant.
+ (easy_vector_constant): Add VSX support.
+ (altivec_indexed_or_indirect_operand): New predicate for
+ recognizing Altivec style memory references with AND -16.
+
+ * config/rs6000/rs6000.c (rs6000_vector_reload): New static global
+ for vector secondary reload support.
+ (rs6000_vector_reg_class): Delete, replacing it with rs6000_constraints.
+ (rs6000_vsx_reg_class): Ditto.
+ (rs6000_constraints): New array to hold the register classes of
+ each of the register constraints that can vary at runtime.
+ (builtin_mode_to_type): New static array for builtin function type
+ creation.
+ (builtin_hash_table): New static hash table for builtin function
+ type creation.
+ (TARGET_SECONDARY_RELOAD): Define target hook.
+ (TARGET_IRA_COVER_CLASSES): Ditto.
+ (rs6000_hard_regno_nregs_internal): If -mvsx, floating point
+ registers are 128 bits if VSX memory reference instructions are
+ used.
+ (rs6000_hard_regno_mode_ok): For VSX, only check if the VSX memory
+ unit is being used.
+ (rs6000_debug_vector_unit): Move into rs6000_debug_reg_global.
+ (rs6000_debug_reg_global): Move -mdebug=reg statements here.
+ Print several of the scheduling related parameters.
+ (rs6000_init_hard_regno_mode_ok): Switch to putting constraints in
+ rs6000_constraints instead of rs6000_vector_reg_class. Move
+ -mdebug=reg code to rs6000_debug_reg_global. Add support for
+ -mvsx-align-128 debug switch. Drop testing float_p if VSX or
+ Altivec. Add VSX support. Setup for secondary reload support on
+ Altivec/VSX registers.
+ (rs6000_override_options): Make power7 set the scheduling groups
+ like the power5. Add support for new debug switches to override
+ the scheduling defaults. Temporarily disable -mcpu=power7 from
+ setting -mvsx. Add support for debug switches -malways-hint,
+ -msched-groups, and -malign-branch-targets.
+ (rs6000_buitlin_conversion): Add support for returning unsigned
+ vector conversion functions to fix regressions due to stricter
+ type checking.
+ (rs6000_builtin_mul_widen_even): Ditto.
+ (rs6000_builtin_mul_widen_odd): Ditto.
+ (rs6000_builtin_vec_perm): Ditto.
+ (rs6000_vec_const_move): On VSX, use xxlxor to clear register.
+ (rs6000_expand_vector_init): Initial VSX support for using xxlxor
+ to zero a register.
+ (rs6000_emit_move): Fixup invalid const symbol_ref+reg that is
+ generated upstream.
+ (bdesc_3arg): Add builtins for unsigned types. Add builtins for
+ VSX types for bit operations. Changes to accomidate vector.md.
+ (bdesc_2arg): Ditto.
+ (bdesc_1arg): Ditto.
+ (struct builtin_description_predicates): Rewrite predicate
+ handling so that RTL describes the operation, instead of passing
+ the instruction to be used as a string argument.
+ (bdesc_altivec_preds): Ditto.
+ (altivec_expand_predicate_builtin): Ditto.
+ (altivec_expand_builtin): Ditto.
+ (rs6000_expand_ternop_builtin): Use a switch instead of an if
+ statement for vsldoi support.
+ (altivec_expand_ld_builtin): Change to use new names from
+ vector.md.
+ (altivec_expand_st_builtin): Ditto.
+ (paired_expand_builtin): Whitespace changes.
+ (rs6000_init_builtins): Add V2DF/V2DI types. Initialize the
+ builtin_mode_to_type table for secondary reload. Call
+ builtin_function_type to build random builtin functions.
+ (altivec_init_builtins): Change to use builtin_function_type to
+ create builtin function types dynamically as we need them.
+ (builtin_hash_function): New support for hashing the tree types
+ for builtin function as we need it, rather than trying to build
+ all of the trees that we need. Add initial preliminary VSX
+ support.
+ (builtin_function_type): Ditto.
+ (builtin_function_eq): Ditto.
+ (builtin_hash_struct): Ditto.
+ (rs6000_init_builtins): Ditto.
+ (rs6000_common_init_builtins): Ditto.
+ (altivec_init_builtins): Ditto.
+ (rs6000_common_init_builtins): Ditto.
+ (enum reload_reg_type): New enum for simplifing reg classes.
+ (rs6000_reload_register_type): Simplify register classes into GPR,
+ Vector, and other registers.
+ Altivec and VSX addresses in reload.
+ (rs6000_secondary_reload_inner): Ditto.
+ (rs6000_ira_cover_classes): New target hook, that returns the
+ appropriate cover classes, based on -mvsx being used or not.
+ (rs6000_secondary_reload_class): Add VSX support.
+ (get_vec_cmp_insn): Delete, rewrite vector conditionals.
+ (get_vsel_insn): Ditto.
+ (rs6000_emit_vector_compare): Rewrite vector conditional support
+ so that where we can, we use RTL operators, instead of blindly use
+ UNSPEC.
+ (rs6000_emit_vector_select): Ditto.
+ (rs6000_emit_vector_cond_expr): Ditto.
+ (rs6000_emit_minmax): Directly generate min/max under altivec,
+ vsx.
+ (create_TOC_reference): Add -mdebug=addr support.
+ (emit_frame_save): VSX loads/stores need register indexed
+ addressing.
+
+ * config/rs6000/rs6000.md: Include vector.md.
+
+ * config/rs6000/t-rs6000 (MD_INCLUDES): Add vector.md.
+
+ * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add
+ support for V2DI, V2DF in logical, permute, select operations.
+
+ * config/rs6000/rs6000.opt (-mvsx-scalar-double): Add new debug
+ switch for vsx/power7.
+ (-mvsx-scalar-memory): Ditto.
+ (-mvsx-align-128): Ditto.
+ (-mallow-movmisalign): Ditto.
+ (-mallow-df-permute): Ditto.
+ (-msched-groups): Ditto.
+ (-malways-hint): Ditto.
+ (-malign-branch-targets): Ditto.
+
+ * config/rs6000/rs6000.h (IRA_COVER_CLASSES): Delete, use target
+ hook instead.
+ (IRA_COVER_CLASSES_PRE_VSX): Cover classes if not -mvsx.
+ (IRA_COVER_CLASSES_VSX): Cover classes if -mvsx.
+ (rs6000_vector_reg_class): Delete.
+ (rs6000_vsx_reg_class): Ditto.
+ (enum rs6000_reg_class_enum): New enum for the constraints that
+ vary based on target switches.
+ (rs6000_constraints): New array to hold the register class for all
+ of the register constraints that vary based on the switches used.
+ (ALTIVEC_BUILTIN_*_UNS): Add unsigned builtin functions.
+ (enum rs6000_builtins): Add unsigned varients for the builtin
+ declarations returned by target hooks for expanding multiplies,
+ select, and permute operations. Add VSX builtins.
+ (enum rs6000_builtin_type_index): Add entries for VSX.
+ (V2DI_type_node): Ditto.
+ (V2DF_type_node): Ditto.
+ (unsigned_V2DI_type_node): Ditto.
+ (bool_long_type_node): Ditto.
+ (intDI_type_internal_node): Ditto.
+ (uintDI_type_internal_node): Ditto.
+ (double_type_internal_node): Ditto.
+
+ * config/rs6000/altivec.md (whole file): Move all expanders to
+ vector.md from altivec.md. Rename insn matching functions to be
+ altivec_foo.
+ (UNSPEC_VCMP*): Delete, rewrite vector comparisons.
+ (altivec_vcmp*): Ditto.
+ (UNSPEC_VPERM_UNS): New, add for unsigned types using vperm.
+ (VM): New iterator for moves that includes the VSX types.
+ (altivec_vperm_<mode>): Add VSX types. Add unsigned types.
+ (altivec_vperm_<mode>_uns): New, for unsigned types.
+ (altivec_vsel_*): Rewrite vector comparisons and predicate
+ builtins.
+ (altivec_eq<mode>): Ditto.
+ (altivec_gt<mode>): Ditto.
+ (altivec_gtu<mode>): Ditto.
+ (altivec_eqv4sf): Ditto.
+ (altivec_gev4sf): Ditto.
+ (altivec_gtv4sf): Ditto.
+ (altivec_vcmpbfp_p): Ditto.
+
2009-07-23 Richard Earnshaw <rearnsha@arm.com>
(split for ior/xor with shift and zero-extend): Cast op3 to
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 9c6245ae8ac..58af47c15ce 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -21,18 +21,7 @@
(define_constants
[(UNSPEC_VCMPBFP 50)
- (UNSPEC_VCMPEQUB 51)
- (UNSPEC_VCMPEQUH 52)
- (UNSPEC_VCMPEQUW 53)
- (UNSPEC_VCMPEQFP 54)
- (UNSPEC_VCMPGEFP 55)
- (UNSPEC_VCMPGTUB 56)
- (UNSPEC_VCMPGTSB 57)
- (UNSPEC_VCMPGTUH 58)
- (UNSPEC_VCMPGTSH 59)
- (UNSPEC_VCMPGTUW 60)
- (UNSPEC_VCMPGTSW 61)
- (UNSPEC_VCMPGTFP 62)
+ ;; 51-62 deleted
(UNSPEC_VMSUMU 65)
(UNSPEC_VMSUMM 66)
(UNSPEC_VMSUMSHM 68)
@@ -63,7 +52,7 @@
(UNSPEC_VPKSHUS 101)
(UNSPEC_VPKUWUS 102)
(UNSPEC_VPKSWUS 103)
- (UNSPEC_VRL 104)
+ ;; 104 deleted
(UNSPEC_VSLV4SI 110)
(UNSPEC_VSLO 111)
(UNSPEC_VSR 118)
@@ -76,6 +65,7 @@
(UNSPEC_VSUM2SWS 134)
(UNSPEC_VSUMSWS 135)
(UNSPEC_VPERM 144)
+ (UNSPEC_VPERM_UNS 145)
(UNSPEC_VRFIP 148)
(UNSPEC_VRFIN 149)
(UNSPEC_VRFIM 150)
@@ -87,10 +77,7 @@
(UNSPEC_VEXPTEFP 156)
(UNSPEC_VRSQRTEFP 157)
(UNSPEC_VREFP 158)
- (UNSPEC_VSEL4SI 159)
- (UNSPEC_VSEL4SF 160)
- (UNSPEC_VSEL8HI 161)
- (UNSPEC_VSEL16QI 162)
+ ;; 159-162 deleted
(UNSPEC_VLSDOI 163)
(UNSPEC_VUPKHSB 167)
(UNSPEC_VUPKHPX 168)
@@ -98,7 +85,7 @@
(UNSPEC_VUPKLSB 170)
(UNSPEC_VUPKLPX 171)
(UNSPEC_VUPKLSH 172)
- (UNSPEC_PREDICATE 173)
+ ;; 173 deleted
(UNSPEC_DST 190)
(UNSPEC_DSTT 191)
(UNSPEC_DSTST 192)
@@ -111,7 +98,7 @@
(UNSPEC_STVE 203)
(UNSPEC_SET_VSCR 213)
(UNSPEC_GET_VRSAVE 214)
- (UNSPEC_REALIGN_LOAD 215)
+ ;; 215 deleted
(UNSPEC_REDUC_PLUS 217)
(UNSPEC_VECSH 219)
(UNSPEC_EXTEVEN_V4SI 220)
@@ -125,11 +112,11 @@
(UNSPEC_INTERHI_V4SI 228)
(UNSPEC_INTERHI_V8HI 229)
(UNSPEC_INTERHI_V16QI 230)
- (UNSPEC_INTERHI_V4SF 231)
+ ;; delete 231
(UNSPEC_INTERLO_V4SI 232)
(UNSPEC_INTERLO_V8HI 233)
(UNSPEC_INTERLO_V16QI 234)
- (UNSPEC_INTERLO_V4SF 235)
+ ;; delete 235
(UNSPEC_LVLX 236)
(UNSPEC_LVLXL 237)
(UNSPEC_LVRX 238)
@@ -176,39 +163,20 @@
(define_mode_iterator VF [V4SF])
;; Vec modes, pity mode iterators are not composable
(define_mode_iterator V [V4SI V8HI V16QI V4SF])
+;; Vec modes for move/logical/permute ops, include vector types for move not
+;; otherwise handled by altivec (v2df, v2di, ti)
+(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI TI])
-(define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
-
-;; Generic LVX load instruction.
-(define_insn "altivec_lvx_<mode>"
- [(set (match_operand:V 0 "altivec_register_operand" "=v")
- (match_operand:V 1 "memory_operand" "Z"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
+;; Like VM, except don't do TImode
+(define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI])
-;; Generic STVX store instruction.
-(define_insn "altivec_stvx_<mode>"
- [(set (match_operand:V 0 "memory_operand" "=Z")
- (match_operand:V 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
+(define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
;; Vector move instructions.
-(define_expand "mov<mode>"
- [(set (match_operand:V 0 "nonimmediate_operand" "")
- (match_operand:V 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
-{
- rs6000_emit_move (operands[0], operands[1], <MODE>mode);
- DONE;
-})
-
-(define_insn "*mov<mode>_internal"
- [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,o,r,r,v")
- (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,W"))]
- "TARGET_ALTIVEC
+(define_insn "*altivec_mov<mode>"
+ [(set (match_operand: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))"
{
@@ -220,52 +188,42 @@
case 3: return "#";
case 4: return "#";
case 5: return "#";
- case 6: return output_vec_const_move (operands);
+ case 6: return "vxor %0,%0,%0";
+ case 7: return output_vec_const_move (operands);
default: gcc_unreachable ();
}
}
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
-
-(define_split
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
- (match_operand:V4SI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(pc)]
-{
- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
-})
-
-(define_split
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
- (match_operand:V8HI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(pc)]
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-
-(define_split
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
- (match_operand:V16QI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(pc)]
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-
-(define_split
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (match_operand:V4SF 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(pc)]
+ [(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))"
{
- rs6000_split_multireg_move (operands[0], operands[1]); DONE;
-})
+ 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:V 0 "altivec_register_operand" "")
- (match_operand:V 1 "easy_vector_constant_add_self" ""))]
- "TARGET_ALTIVEC && reload_completed"
+ [(set (match_operand:VM 0 "altivec_register_operand" "")
+ (match_operand:VM 1 "easy_vector_constant_add_self" ""))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && reload_completed"
[(set (match_dup 0) (match_dup 3))
(set (match_dup 0) (match_dup 4))]
{
@@ -346,11 +304,11 @@
"vaddu<VI_char>m %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "addv4sf3"
+(define_insn "*altivec_addv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vaddfp %0,%1,%2"
[(set_attr "type" "vecfloat")])
@@ -392,11 +350,11 @@
"vsubu<VI_char>m %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "subv4sf3"
+(define_insn "*altivec_subv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vsubfp %0,%1,%2"
[(set_attr "type" "vecfloat")])
@@ -457,113 +415,75 @@
"vcmpbfp %0,%1,%2"
[(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpequb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VCMPEQUB))]
+(define_insn "*altivec_eq<mode>"
+ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
+ (eq:VI (match_operand:VI 1 "altivec_register_operand" "v")
+ (match_operand:VI 2 "altivec_register_operand" "v")))]
"TARGET_ALTIVEC"
- "vcmpequb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+ "vcmpequ<VI_char> %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpequh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VCMPEQUH))]
+(define_insn "*altivec_gt<mode>"
+ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
+ (gt:VI (match_operand:VI 1 "altivec_register_operand" "v")
+ (match_operand:VI 2 "altivec_register_operand" "v")))]
"TARGET_ALTIVEC"
- "vcmpequh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+ "vcmpgts<VI_char> %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpequw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VCMPEQUW))]
+(define_insn "*altivec_gtu<mode>"
+ [(set (match_operand:VI 0 "altivec_register_operand" "=v")
+ (gtu:VI (match_operand:VI 1 "altivec_register_operand" "v")
+ (match_operand:VI 2 "altivec_register_operand" "v")))]
"TARGET_ALTIVEC"
- "vcmpequw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+ "vcmpgtu<VI_char> %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpeqfp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")]
- UNSPEC_VCMPEQFP))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_eqv4sf"
+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
+ (eq:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
+ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vcmpeqfp %0,%1,%2"
[(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpgefp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")]
- UNSPEC_VCMPGEFP))]
- "TARGET_ALTIVEC"
- "vcmpgefp %0,%1,%2"
+(define_insn "*altivec_gtv4sf"
+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
+ (gt:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
+ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpgtfp %0,%1,%2"
[(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpgtub"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VCMPGTUB))]
- "TARGET_ALTIVEC"
- "vcmpgtub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtsb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VCMPGTSB))]
- "TARGET_ALTIVEC"
- "vcmpgtsb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtuh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VCMPGTUH))]
- "TARGET_ALTIVEC"
- "vcmpgtuh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtsh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VCMPGTSH))]
- "TARGET_ALTIVEC"
- "vcmpgtsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtuw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VCMPGTUW))]
- "TARGET_ALTIVEC"
- "vcmpgtuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+(define_insn "*altivec_gev4sf"
+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
+ (ge:V4SF (match_operand:V4SF 1 "altivec_register_operand" "v")
+ (match_operand:V4SF 2 "altivec_register_operand" "v")))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpgefp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_insn "altivec_vcmpgtsw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VCMPGTSW))]
- "TARGET_ALTIVEC"
- "vcmpgtsw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+(define_insn "*altivec_vsel<mode>"
+ [(set (match_operand:VM 0 "altivec_register_operand" "=v")
+ (if_then_else:VM
+ (ne:CC (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_MEM_ALTIVEC_P (<MODE>mode)"
+ "vsel %0,%3,%2,%1"
+ [(set_attr "type" "vecperm")])
-(define_insn "altivec_vcmpgtfp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")]
- UNSPEC_VCMPGTFP))]
- "TARGET_ALTIVEC"
- "vcmpgtfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
+(define_insn "*altivec_vsel<mode>_uns"
+ [(set (match_operand:VM 0 "altivec_register_operand" "=v")
+ (if_then_else:VM
+ (ne:CCUNS (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_MEM_ALTIVEC_P (<MODE>mode)"
+ "vsel %0,%3,%2,%1"
+ [(set_attr "type" "vecperm")])
;; Fused multiply add
(define_insn "altivec_vmaddfp"
@@ -571,17 +491,17 @@
(plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))
(match_operand:V4SF 3 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vmaddfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
-(define_expand "mulv4sf3"
+(define_expand "altivec_mulv4sf3"
[(use (match_operand:V4SF 0 "register_operand" ""))
(use (match_operand:V4SF 1 "register_operand" ""))
(use (match_operand:V4SF 2 "register_operand" ""))]
- "TARGET_ALTIVEC && TARGET_FUSED_MADD"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode) && TARGET_FUSED_MADD"
"
{
rtx neg0;
@@ -631,7 +551,7 @@
emit_insn (gen_altivec_vspltisw (sixteen, gen_rtx_CONST_INT (V4SImode, -16)));
swap = gen_reg_rtx (V4SImode);
- emit_insn (gen_altivec_vrlw (swap, operands[2], sixteen));
+ emit_insn (gen_vrotlv4si3 (swap, operands[2], sixteen));
one = gen_reg_rtx (V8HImode);
convert_move (one, operands[1], 0);
@@ -684,7 +604,7 @@
(neg:V4SF (minus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v"))
(match_operand:V4SF 3 "register_operand" "v"))))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vnmsubfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
@@ -758,11 +678,11 @@
"vmaxs<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "smaxv4sf3"
+(define_insn "*altivec_smaxv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vmaxfp %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -782,11 +702,11 @@
"vmins<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "sminv4sf3"
+(define_insn "*altivec_sminv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vminfp %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -901,11 +821,11 @@
(const_int 3)
(const_int 1)]))
(const_int 5)))]
- "TARGET_ALTIVEC"
+ "VECTOR_MEM_ALTIVEC_P (V4SImode)"
"vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrghsf"
+(define_insn "*altivec_vmrghsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
(parallel [(const_int 0)
@@ -918,7 +838,7 @@
(const_int 3)
(const_int 1)]))
(const_int 5)))]
- "TARGET_ALTIVEC"
+ "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
"vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -990,35 +910,37 @@
(define_insn "altivec_vmrglw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
- "TARGET_ALTIVEC"
+ (vec_merge:V4SI
+ (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (const_int 5)))]
+ "VECTOR_MEM_ALTIVEC_P (V4SImode)"
"vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrglsf"
+(define_insn "*altivec_vmrglsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
- "TARGET_ALTIVEC"
+ (vec_merge:V4SF
+ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (const_int 5)))]
+ "VECTOR_MEM_ALTIVEC_P (V4SFmode)"
"vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1095,68 +1017,53 @@
[(set_attr "type" "veccomplex")])
-;; logical ops
+;; logical ops. Have the logical ops follow the memory ops in
+;; terms of whether to prefer VSX or Altivec
-(define_insn "and<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (and:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_and<mode>3"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (and:VM (match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
"vand %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "ior<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (ior:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_ior<mode>3"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (ior:VM (match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
"vor %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "xor<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (xor:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_xor<mode>3"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (xor:VM (match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
"vxor %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "xorv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (xor:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vxor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "one_cmpl<mode>2"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (not:VI (match_operand:VI 1 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_one_cmpl<mode>2"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (not:VM (match_operand:VM 1 "register_operand" "v")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
"vnor %0,%1,%1"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_nor<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (not:VI (ior:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v"))))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_nor<mode>3"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (not:VM (ior:VM (match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v"))))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
"vnor %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "andc<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (and:VI (not:VI (match_operand:VI 2 "register_operand" "v"))
- (match_operand:VI 1 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vandc %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*andc3_v4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (and:V4SF (not:V4SF (match_operand:V4SF 2 "register_operand" "v"))
- (match_operand:V4SF 1 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+(define_insn "*altivec_andc<mode>3"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (and:VM (not:VM (match_operand:VM 2 "register_operand" "v"))
+ (match_operand:VM 1 "register_operand" "v")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
"vandc %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -1247,11 +1154,10 @@
"vpkswus %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vrl<VI_char>"
+(define_insn "*altivec_vrl<VI_char>"
[(set (match_operand:VI 0 "register_operand" "=v")
- (unspec:VI [(match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v")]
- UNSPEC_VRL))]
+ (rotate:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
"vrl<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -1274,26 +1180,26 @@
"vslo %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "vashl<mode>3"
+(define_insn "*altivec_vsl<VI_char>"
[(set (match_operand:VI 0 "register_operand" "=v")
(ashift:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v") ))]
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
"vsl<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "vlshr<mode>3"
+(define_insn "*altivec_vsr<VI_char>"
[(set (match_operand:VI 0 "register_operand" "=v")
(lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v") ))]
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
"vsr<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "vashr<mode>3"
+(define_insn "*altivec_vsra<VI_char>"
[(set (match_operand:VI 0 "register_operand" "=v")
(ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:VI 2 "register_operand" "v") ))]
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
"vsra<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -1386,13 +1292,13 @@
"vspltw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "*altivec_vspltsf"
+(define_insn "altivec_vspltsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_duplicate:V4SF
(vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vspltw %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1404,19 +1310,29 @@
"vspltis<VI_char> %0,%1"
[(set_attr "type" "vecperm")])
-(define_insn "ftruncv4sf2"
+(define_insn "*altivec_ftruncv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
- "TARGET_ALTIVEC"
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vrfiz %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vperm_<mode>"
- [(set (match_operand:V 0 "register_operand" "=v")
- (unspec:V [(match_operand:V 1 "register_operand" "v")
- (match_operand:V 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")]
- UNSPEC_VPERM))]
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vperm_<mode>_uns"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM_UNS))]
"TARGET_ALTIVEC"
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
@@ -1515,185 +1431,11 @@
"vrefp %0,%1"
[(set_attr "type" "vecfloat")])
-(define_expand "vcondv4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (if_then_else:V4SI
- (match_operator 3 "comparison_operator"
- [(match_operand:V4SI 4 "register_operand" "v")
- (match_operand:V4SI 5 "register_operand" "v")])
- (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-(define_expand "vconduv4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (if_then_else:V4SI
- (match_operator 3 "comparison_operator"
- [(match_operand:V4SI 4 "register_operand" "v")
- (match_operand:V4SI 5 "register_operand" "v")])
- (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-(define_expand "vcondv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (if_then_else:V4SF
- (match_operator 3 "comparison_operator"
- [(match_operand:V4SF 4 "register_operand" "v")
- (match_operand:V4SF 5 "register_operand" "v")])
- (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-(define_expand "vcondv8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (if_then_else:V8HI
- (match_operator 3 "comparison_operator"
- [(match_operand:V8HI 4 "register_operand" "v")
- (match_operand:V8HI 5 "register_operand" "v")])
- (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-(define_expand "vconduv8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (if_then_else:V8HI
- (match_operator 3 "comparison_operator"
- [(match_operand:V8HI 4 "register_operand" "v")
- (match_operand:V8HI 5 "register_operand" "v")])
- (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-(define_expand "vcondv16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (if_then_else:V16QI
- (match_operator 3 "comparison_operator"
- [(match_operand:V16QI 4 "register_operand" "v")
- (match_operand:V16QI 5 "register_operand" "v")])
- (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-(define_expand "vconduv16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (if_then_else:V16QI
- (match_operator 3 "comparison_operator"
- [(match_operand:V16QI 4 "register_operand" "v")
- (match_operand:V16QI 5 "register_operand" "v")])
- (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "
-{
- if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}
- ")
-
-
-(define_insn "altivec_vsel_v4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")]
- UNSPEC_VSEL4SI))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsel_v4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")]
- UNSPEC_VSEL4SF))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsel_v8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")]
- UNSPEC_VSEL8HI))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsel_v16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")]
- UNSPEC_VSEL16QI))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
(define_insn "altivec_vsldoi_<mode>"
- [(set (match_operand:V 0 "register_operand" "=v")
- (unspec:V [(match_operand:V 1 "register_operand" "v")
- (match_operand:V 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")]
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:QI 3 "immediate_operand" "i")]
UNSPEC_VLSDOI))]
"TARGET_ALTIVEC"
"vsldoi %0,%1,%2,%3"
@@ -1747,50 +1489,92 @@
"vupklsh %0,%1"
[(set_attr "type" "vecperm")])
-;; AltiVec predicates.
+;; Compare vectors producing a vector result and a predicate, setting CR6 to
+;; indicate a combined status
+(define_insn "*altivec_vcmpequ<VI_char>_p"
+ [(set (reg:CC 74)
+ (unspec:CC [(eq:CC (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VI 0 "register_operand" "=v")
+ (eq:VI (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "vcmpequ<VI_char>. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_expand "cr6_test_for_zero"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (reg:CC 74)
- (const_int 0)))]
- "TARGET_ALTIVEC"
- "")
+(define_insn "*altivec_vcmpgts<VI_char>_p"
+ [(set (reg:CC 74)
+ (unspec:CC [(gt:CC (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VI 0 "register_operand" "=v")
+ (gt:VI (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "vcmpgts<VI_char>. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_expand "cr6_test_for_zero_reverse"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (reg:CC 74)
- (const_int 0)))
- (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
- "TARGET_ALTIVEC"
- "")
+(define_insn "*altivec_vcmpgtu<VI_char>_p"
+ [(set (reg:CC 74)
+ (unspec:CC [(gtu:CC (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VI 0 "register_operand" "=v")
+ (gtu:VI (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "vcmpgtu<VI_char>. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_expand "cr6_test_for_lt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (reg:CC 74)
- (const_int 0)))]
- "TARGET_ALTIVEC"
- "")
+(define_insn "*altivec_vcmpeqfp_p"
+ [(set (reg:CC 74)
+ (unspec:CC [(eq:CC (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:V4SF 0 "register_operand" "=v")
+ (eq:V4SF (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpeqfp. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_expand "cr6_test_for_lt_reverse"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (reg:CC 74)
- (const_int 0)))
- (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
- "TARGET_ALTIVEC"
- "")
+(define_insn "*altivec_vcmpgtfp_p"
+ [(set (reg:CC 74)
+ (unspec:CC [(gt:CC (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:V4SF 0 "register_operand" "=v")
+ (gt:V4SF (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpgtfp. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-;; We can get away with generating the opcode on the fly (%3 below)
-;; because all the predicates have the same scheduling parameters.
+(define_insn "*altivec_vcmpgefp_p"
+ [(set (reg:CC 74)
+ (unspec:CC [(ge:CC (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:V4SF 0 "register_operand" "=v")
+ (ge:V4SF (match_dup 1)
+ (match_dup 2)))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "vcmpgefp. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_insn "altivec_predicate_<mode>"
+(define_insn "altivec_vcmpbfp_p"
[(set (reg:CC 74)
- (unspec:CC [(match_operand:V 1 "register_operand" "v")
- (match_operand:V 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] UNSPEC_PREDICATE))
- (clobber (match_scratch:V 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
+ (unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")]
+ UNSPEC_VCMPBFP))
+ (set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_dup 1)
+ (match_dup 2)]
+ UNSPEC_VCMPBFP))]
+ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
+ "vcmpbfp. %0,%1,%2"
+ [(set_attr "type" "veccmp")])
(define_insn "altivec_mtvscr"
[(set (reg:SI 110)
@@ -1959,95 +1743,6 @@
"stvewx %1,%y0"
[(set_attr "type" "vecstore")])
-(define_expand "vec_init<mode>"
- [(match_operand:V 0 "register_operand" "")
- (match_operand 1 "" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_init (operands[0], operands[1]);
- DONE;
-})
-
-(define_expand "vec_setv4si"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:SI 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_setv8hi"
- [(match_operand:V8HI 0 "register_operand" "")
- (match_operand:HI 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_setv16qi"
- [(match_operand:V16QI 0 "register_operand" "")
- (match_operand:QI 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_setv4sf"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_extractv4si"
- [(match_operand:SI 0 "register_operand" "")
- (match_operand:V4SI 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_extractv8hi"
- [(match_operand:HI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_extractv16qi"
- [(match_operand:QI 0 "register_operand" "")
- (match_operand:V16QI 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
-(define_expand "vec_extractv4sf"
- [(match_operand:SF 0 "register_operand" "")
- (match_operand:V4SF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_ALTIVEC"
-{
- rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
- DONE;
-})
-
;; Generate
;; vspltis? SCRATCH0,0
;; vsubu?m SCRATCH2,SCRATCH1,%1
@@ -2069,7 +1764,7 @@
;; vspltisw SCRATCH1,-1
;; vslw SCRATCH2,SCRATCH1,SCRATCH1
;; vandc %0,%1,SCRATCH2
-(define_expand "absv4sf2"
+(define_expand "altivec_absv4sf2"
[(set (match_dup 2)
(vec_duplicate:V4SI (const_int -1)))
(set (match_dup 3)
@@ -2102,66 +1797,6 @@
operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
})
-;; Vector shift left in bits. Currently supported ony for shift
-;; amounts that can be expressed as byte shifts (divisible by 8).
-;; General shift amounts can be supported using vslo + vsl. We're
-;; not expecting to see these yet (the vectorizer currently
-;; generates only shifts divisible by byte_size).
-(define_expand "vec_shl_<mode>"
- [(set (match_operand:V 0 "register_operand" "=v")
- (unspec:V [(match_operand:V 1 "register_operand" "v")
- (match_operand:QI 2 "reg_or_short_operand" "")]
- UNSPEC_VECSH))]
- "TARGET_ALTIVEC"
- "
-{
- rtx bitshift = operands[2];
- rtx byteshift = gen_reg_rtx (QImode);
- HOST_WIDE_INT bitshift_val;
- HOST_WIDE_INT byteshift_val;
-
- if (! CONSTANT_P (bitshift))
- FAIL;
- bitshift_val = INTVAL (bitshift);
- if (bitshift_val & 0x7)
- FAIL;
- byteshift_val = bitshift_val >> 3;
- byteshift = gen_rtx_CONST_INT (QImode, byteshift_val);
- emit_insn (gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
- byteshift));
- DONE;
-}")
-
-;; Vector shift left in bits. Currently supported ony for shift
-;; amounts that can be expressed as byte shifts (divisible by 8).
-;; General shift amounts can be supported using vsro + vsr. We're
-;; not expecting to see these yet (the vectorizer currently
-;; generates only shifts divisible by byte_size).
-(define_expand "vec_shr_<mode>"
- [(set (match_operand:V 0 "register_operand" "=v")
- (unspec:V [(match_operand:V 1 "register_operand" "v")
- (match_operand:QI 2 "reg_or_short_operand" "")]
- UNSPEC_VECSH))]
- "TARGET_ALTIVEC"
- "
-{
- rtx bitshift = operands[2];
- rtx byteshift = gen_reg_rtx (QImode);
- HOST_WIDE_INT bitshift_val;
- HOST_WIDE_INT byteshift_val;
-
- if (! CONSTANT_P (bitshift))
- FAIL;
- bitshift_val = INTVAL (bitshift);
- if (bitshift_val & 0x7)
- FAIL;
- byteshift_val = 16 - (bitshift_val >> 3);
- byteshift = gen_rtx_CONST_INT (QImode, byteshift_val);
- emit_insn (gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
- byteshift));
- DONE;
-}")
-
(define_insn "altivec_vsumsws_nomode"
[(set (match_operand 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
@@ -2204,16 +1839,6 @@
DONE;
}")
-(define_insn "vec_realign_load_<mode>"
- [(set (match_operand:V 0 "register_operand" "=v")
- (unspec:V [(match_operand:V 1 "register_operand" "v")
- (match_operand:V 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")]
- UNSPEC_REALIGN_LOAD))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
(define_expand "neg<mode>2"
[(use (match_operand:VI 0 "register_operand" ""))
(use (match_operand:VI 1 "register_operand" ""))]
@@ -2665,7 +2290,7 @@
DONE;
}")
-(define_expand "negv4sf2"
+(define_expand "altivec_negv4sf2"
[(use (match_operand:V4SF 0 "register_operand" ""))
(use (match_operand:V4SF 1 "register_operand" ""))]
"TARGET_ALTIVEC"
@@ -2994,29 +2619,6 @@
emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2]));
DONE;
}")
-(define_expand "vec_interleave_highv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "register_operand" "")]
- UNSPEC_INTERHI_V4SF))]
- "TARGET_ALTIVEC"
- "
-{
- emit_insn (gen_altivec_vmrghsf (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_interleave_lowv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "register_operand" "")]
- UNSPEC_INTERLO_V4SF))]
- "TARGET_ALTIVEC"
- "
-{
- emit_insn (gen_altivec_vmrglsf (operands[0], operands[1], operands[2]));
- DONE;
-}")
(define_expand "vec_interleave_high<mode>"
[(set (match_operand:VI 0 "register_operand" "")
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index a937d99397d..81326aa6d57 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -17,14 +17,14 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Available constraint letters: "e", "k", "u", "A", "B", "C", "D"
+
;; Register constraints
-(define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS
- ? FLOAT_REGS : NO_REGS"
+(define_register_constraint "f" "rs6000_constraints[RS6000_CONSTRAINT_f]"
"@internal")
-(define_register_constraint "d" "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- ? FLOAT_REGS : NO_REGS"
+(define_register_constraint "d" "rs6000_constraints[RS6000_CONSTRAINT_d]"
"@internal")
(define_register_constraint "b" "BASE_REGS"
@@ -54,6 +54,28 @@
(define_register_constraint "z" "XER_REGS"
"@internal")
+;; Use w as a prefix to add VSX modes
+;; vector double (V2DF)
+(define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]"
+ "@internal")
+
+;; vector float (V4SF)
+(define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]"
+ "@internal")
+
+;; scalar double (DF)
+(define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
+ "@internal")
+
+;; any VSX register
+(define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
+ "@internal")
+
+;; Altivec style load/store that ignores the bottom bits of the address
+(define_memory_constraint "wZ"
+ "Indexed or indirect memory operand, ignoring the bottom 4 bits"
+ (match_operand 0 "altivec_indexed_or_indirect_operand"))
+
;; Integer constraints
(define_constraint "I"
@@ -173,3 +195,7 @@ usually better to use @samp{m} or @samp{es} in @code{asm} statements)"
(define_constraint "W"
"vector constant that does not require memory"
(match_operand 0 "easy_vector_constant"))
+
+(define_constraint "j"
+ "Zero vector constant"
+ (match_test "(op == const0_rtx || op == CONST0_RTX (GET_MODE (op)))"))
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index b6b443bf3f8..3e5c1a1a8df 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -38,6 +38,37 @@
|| ALTIVEC_REGNO_P (REGNO (op))
|| REGNO (op) > LAST_VIRTUAL_REGISTER")))
+;; Return 1 if op is a VSX register.
+(define_predicate "vsx_register_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || VSX_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is a vector register that operates on floating point vectors
+;; (either altivec or VSX).
+(define_predicate "vfloat_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || VFLOAT_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is a vector register that operates on integer vectors
+;; (only altivec, VSX doesn't support integer vectors)
+(define_predicate "vint_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || VINT_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is a vector register to do logical operations on (and, or,
+;; xor, etc.)
+(define_predicate "vlogical_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || VLOGICAL_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
;; Return 1 if op is XER register.
(define_predicate "xer_operand"
(and (match_code "reg")
@@ -234,6 +265,10 @@
&& num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
case DFmode:
+ /* The constant 0.f is easy under VSX. */
+ if (op == CONST0_RTX (DFmode) && VECTOR_UNIT_VSX_P (DFmode))
+ return 1;
+
/* Force constants to memory before reload to utilize
compress_float_constant.
Avoid this when flag_unsafe_math_optimizations is enabled
@@ -292,6 +327,9 @@
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))
@@ -394,16 +432,36 @@
(match_code "mem")
{
op = XEXP (op, 0);
- if (TARGET_ALTIVEC
- && ALTIVEC_VECTOR_MODE (mode)
+ if (VECTOR_MEM_ALTIVEC_P (mode)
&& GET_CODE (op) == AND
&& GET_CODE (XEXP (op, 1)) == CONST_INT
&& INTVAL (XEXP (op, 1)) == -16)
op = XEXP (op, 0);
+ else if (VECTOR_MEM_VSX_P (mode)
+ && GET_CODE (op) == PRE_MODIFY)
+ op = XEXP (op, 1);
+
return indexed_or_indirect_address (op, mode);
})
+;; Return 1 if the operand is an indexed or indirect memory operand with an
+;; AND -16 in it, used to recognize when we need to switch to Altivec loads
+;; to realign loops instead of VSX (altivec silently ignores the bottom bits,
+;; while VSX uses the full address and traps)
+(define_predicate "altivec_indexed_or_indirect_operand"
+ (match_code "mem")
+{
+ op = XEXP (op, 0);
+ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
+ && GET_CODE (op) == AND
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && INTVAL (XEXP (op, 1)) == -16)
+ return indexed_or_indirect_address (XEXP (op, 0), mode);
+
+ return 0;
+})
+
;; Return 1 if the operand is an indexed or indirect address.
(define_special_predicate "indexed_or_indirect_address"
(and (match_test "REG_P (op)
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index d1ab9da9b29..3b3ba96b5cd 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -671,6 +671,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
@@ -719,6 +725,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
@@ -1483,6 +1495,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
@@ -1507,6 +1521,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
@@ -2123,6 +2143,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
@@ -2366,6 +2392,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
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,
@@ -2392,11 +2422,29 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
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 },
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6063a6c69b2..b077c83c2db 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -245,6 +245,9 @@ unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
/* Map register number to register class. */
enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER];
+/* Reload functions based on the type and the vector unit. */
+static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2];
+
/* Built in types. */
tree rs6000_builtin_types[RS6000_BTI_MAX];
tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
@@ -302,10 +305,16 @@ struct builtin_description
/* Describe the vector unit used for modes. */
enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES];
enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES];
-enum reg_class rs6000_vector_reg_class[NUM_MACHINE_MODES];
+
+/* Register classes for various constraints that are based on the target
+ switches. */
+enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
/* Describe the alignment of a vector. */
int rs6000_vector_align[NUM_MACHINE_MODES];
+
+/* Map selected modes to types for builtins. */
+static GTY(()) tree builtin_mode_to_type[MAX_MACHINE_MODE][2];
/* Target cpu costs. */
@@ -918,6 +927,11 @@ static rtx rs6000_expand_binop_builtin (enum insn_code, tree, rtx);
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,
+ enum rs6000_builtins, const char *name);
static void rs6000_common_init_builtins (void);
static void rs6000_init_libfuncs (void);
@@ -944,8 +958,7 @@ static rtx altivec_expand_ld_builtin (tree, rtx, bool *);
static rtx altivec_expand_st_builtin (tree, rtx, bool *);
static rtx altivec_expand_dst_builtin (tree, rtx, bool *);
static rtx altivec_expand_abs_builtin (enum insn_code, tree, rtx);
-static rtx altivec_expand_predicate_builtin (enum insn_code,
- const char *, tree, rtx);
+static rtx altivec_expand_predicate_builtin (enum insn_code, tree, rtx);
static rtx altivec_expand_stv_builtin (enum insn_code, tree);
static rtx altivec_expand_vec_init_builtin (tree, tree, rtx);
static rtx altivec_expand_vec_set_builtin (tree);
@@ -1008,12 +1021,9 @@ static tree rs6000_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
static bool rs6000_must_pass_in_stack (enum machine_mode, const_tree);
static bool rs6000_scalar_mode_supported_p (enum machine_mode);
static bool rs6000_vector_mode_supported_p (enum machine_mode);
-static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
- enum machine_mode);
+static rtx rs6000_emit_vector_compare_inner (enum rtx_code, rtx, rtx);
static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
enum machine_mode);
-static int get_vsel_insn (enum machine_mode);
-static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
static tree rs6000_stack_protect_fail (void);
static rtx rs6000_legitimize_reload_address (rtx, enum machine_mode, int, int,
@@ -1069,6 +1079,12 @@ bool (*rs6000_cannot_change_mode_class_ptr) (enum machine_mode,
enum reg_class)
= rs6000_cannot_change_mode_class;
+static enum reg_class rs6000_secondary_reload (bool, rtx, enum reg_class,
+ 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);
@@ -1084,6 +1100,17 @@ struct GTY(()) toc_hash_struct
};
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 GTY(()) builtin_hash_struct
+{
+ tree type;
+ enum machine_mode mode[4]; /* return value + 3 arguments. */
+ unsigned char uns_p[4]; /* and whether the types are unsigned. */
+};
+
+static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table;
/* Default register names. */
char rs6000_reg_names[][8] =
@@ -1414,6 +1441,12 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_INSTANTIATE_DECLS
#define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls
+#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
+
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
@@ -1437,7 +1470,9 @@ rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
unsigned HOST_WIDE_INT reg_size;
if (FP_REGNO_P (regno))
- reg_size = UNITS_PER_FP_WORD;
+ reg_size = (VECTOR_MEM_VSX_P (mode)
+ ? UNITS_PER_VSX_WORD
+ : UNITS_PER_FP_WORD);
else if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
reg_size = UNITS_PER_SPE_WORD;
@@ -1465,22 +1500,45 @@ rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
static int
rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
{
+ int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1;
+
+ /* VSX registers that overlap the FPR registers are larger than for non-VSX
+ implementations. Don't allow an item to be split between a FP register
+ and an Altivec register. */
+ if (VECTOR_MEM_VSX_P (mode))
+ {
+ if (FP_REGNO_P (regno))
+ return FP_REGNO_P (last_regno);
+
+ if (ALTIVEC_REGNO_P (regno))
+ return ALTIVEC_REGNO_P (last_regno);
+ }
+
/* The GPRs can hold any mode, but values bigger than one register
cannot go past R31. */
if (INT_REGNO_P (regno))
- return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
+ return INT_REGNO_P (last_regno);
- /* The float registers can only hold floating modes and DImode.
- This excludes the 32-bit decimal float mode for now. */
+ /* The float registers (except for VSX vector modes) can only hold floating
+ modes and DImode. This excludes the 32-bit decimal float mode for
+ now. */
if (FP_REGNO_P (regno))
- return
- ((SCALAR_FLOAT_MODE_P (mode)
- && (mode != TDmode || (regno % 2) == 0)
- && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
- || (GET_MODE_CLASS (mode) == MODE_INT
+ {
+ if (SCALAR_FLOAT_MODE_P (mode)
+ && (mode != TDmode || (regno % 2) == 0)
+ && FP_REGNO_P (last_regno))
+ return 1;
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
- || (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
- && PAIRED_VECTOR_MODE (mode)));
+ return 1;
+
+ if (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
+ && PAIRED_VECTOR_MODE (mode))
+ return 1;
+
+ return 0;
+ }
/* The CR register can only hold CC modes. */
if (CR_REGNO_P (regno))
@@ -1497,8 +1555,9 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
return 1;
- /* We cannot put TImode anywhere except general register and it must be
- able to fit within the register set. */
+ /* We cannot put TImode anywhere except general register and it must be able
+ to fit within the register set. In the future, allow TImode in the
+ Altivec or VSX registers. */
return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
}
@@ -1575,23 +1634,141 @@ rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
}
}
-/* Map enum rs6000_vector to string. */
-static const char *
-rs6000_debug_vector_unit[] = {
- "none",
- "altivec",
- "vsx",
- "paired",
- "spe",
- "other"
-};
+/* Print various interesting information with -mdebug=reg. */
+static void
+rs6000_debug_reg_global (void)
+{
+ const char *nl = (const char *)0;
+ int m;
+ char costly_num[20];
+ char nop_num[20];
+ const char *costly_str;
+ const char *nop_str;
+
+ /* Map enum rs6000_vector to string. */
+ static const char *rs6000_debug_vector_unit[] = {
+ "none",
+ "altivec",
+ "vsx",
+ "paired",
+ "spe",
+ "other"
+ };
+
+ fprintf (stderr, "Register information: (last virtual reg = %d)\n",
+ LAST_VIRTUAL_REGISTER);
+ rs6000_debug_reg_print (0, 31, "gr");
+ rs6000_debug_reg_print (32, 63, "fp");
+ rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
+ LAST_ALTIVEC_REGNO,
+ "vs");
+ rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
+ rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
+ rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
+ rs6000_debug_reg_print (MQ_REGNO, MQ_REGNO, "mq");
+ rs6000_debug_reg_print (XER_REGNO, XER_REGNO, "xer");
+ rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave");
+ rs6000_debug_reg_print (VSCR_REGNO, VSCR_REGNO, "vscr");
+ rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a");
+ rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f");
+
+ fprintf (stderr,
+ "\n"
+ "d reg_class = %s\n"
+ "f reg_class = %s\n"
+ "v reg_class = %s\n"
+ "wa reg_class = %s\n"
+ "wd reg_class = %s\n"
+ "wf reg_class = %s\n"
+ "ws reg_class = %s\n\n",
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_f]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_v]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wa]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]]);
+
+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
+ if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
+ {
+ nl = "\n";
+ fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n",
+ GET_MODE_NAME (m),
+ rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
+ rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]);
+ }
+
+ if (nl)
+ fputs (nl, stderr);
+
+ switch (rs6000_sched_costly_dep)
+ {
+ case max_dep_latency:
+ costly_str = "max_dep_latency";
+ break;
+
+ case no_dep_costly:
+ costly_str = "no_dep_costly";
+ break;
+
+ case all_deps_costly:
+ costly_str = "all_deps_costly";
+ break;
+
+ case true_store_to_load_dep_costly:
+ costly_str = "true_store_to_load_dep_costly";
+ break;
+
+ case store_to_load_dep_costly:
+ costly_str = "store_to_load_dep_costly";
+ break;
+
+ default:
+ costly_str = costly_num;
+ sprintf (costly_num, "%d", (int)rs6000_sched_costly_dep);
+ break;
+ }
+
+ switch (rs6000_sched_insert_nops)
+ {
+ case sched_finish_regroup_exact:
+ nop_str = "sched_finish_regroup_exact";
+ break;
+
+ case sched_finish_pad_groups:
+ nop_str = "sched_finish_pad_groups";
+ break;
+
+ case sched_finish_none:
+ nop_str = "sched_finish_none";
+ break;
+
+ default:
+ nop_str = nop_num;
+ sprintf (nop_num, "%d", (int)rs6000_sched_insert_nops);
+ break;
+ }
+
+ fprintf (stderr,
+ "always_hint = %s\n"
+ "align_branch_targets = %s\n"
+ "sched_restricted_insns_priority = %d\n"
+ "sched_costly_dep = %s\n"
+ "sched_insert_nops = %s\n\n",
+ rs6000_always_hint ? "true" : "false",
+ rs6000_align_branch_targets ? "true" : "false",
+ (int)rs6000_sched_restricted_insns_priority,
+ costly_str, nop_str);
+}
/* Initialize the various global tables that are based on register size. */
static void
rs6000_init_hard_regno_mode_ok (void)
{
int r, m, c;
- bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS);
+ int align64;
+ int align32;
/* Precalculate REGNO_REG_CLASS. */
rs6000_regno_regclass[0] = GENERAL_REGS;
@@ -1627,57 +1804,158 @@ rs6000_init_hard_regno_mode_ok (void)
for (m = 0; m < NUM_MACHINE_MODES; ++m)
{
rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
- rs6000_vector_reg_class[m] = NO_REGS;
+ rs6000_vector_reload[m][0] = CODE_FOR_nothing;
+ rs6000_vector_reload[m][1] = CODE_FOR_nothing;
+ }
+
+ for (c = 0; c < (int)(int)RS6000_CONSTRAINT_MAX; c++)
+ rs6000_constraints[c] = NO_REGS;
+
+ /* The VSX hardware allows native alignment for vectors, but control whether the compiler
+ believes it can use native alignment or still uses 128-bit alignment. */
+ if (TARGET_VSX && !TARGET_VSX_ALIGN_128)
+ {
+ align64 = 64;
+ align32 = 32;
+ }
+ else
+ {
+ align64 = 128;
+ align32 = 128;
+ }
+
+ /* V2DF mode, VSX only. */
+ if (TARGET_VSX)
+ {
+ rs6000_vector_unit[V2DFmode] = VECTOR_VSX;
+ rs6000_vector_mem[V2DFmode] = VECTOR_VSX;
+ rs6000_vector_align[V2DFmode] = align64;
}
- /* V4SF mode, Altivec only. */
- if (float_p && TARGET_ALTIVEC)
+ /* V4SF mode, either VSX or Altivec. */
+ if (TARGET_VSX)
+ {
+ rs6000_vector_unit[V4SFmode] = VECTOR_VSX;
+ rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
+ rs6000_vector_align[V4SFmode] = align32;
+ }
+ else if (TARGET_ALTIVEC)
{
rs6000_vector_unit[V4SFmode] = VECTOR_ALTIVEC;
rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
- rs6000_vector_align[V4SFmode] = 128;
+ rs6000_vector_align[V4SFmode] = align32;
}
- /* V16QImode, V8HImode, V4SImode are Altivec only. */
+ /* V16QImode, V8HImode, V4SImode are Altivec only, but possibly do VSX loads
+ and stores. */
if (TARGET_ALTIVEC)
{
rs6000_vector_unit[V4SImode] = VECTOR_ALTIVEC;
rs6000_vector_unit[V8HImode] = VECTOR_ALTIVEC;
rs6000_vector_unit[V16QImode] = VECTOR_ALTIVEC;
+ rs6000_vector_align[V4SImode] = align32;
+ rs6000_vector_align[V8HImode] = align32;
+ rs6000_vector_align[V16QImode] = align32;
- rs6000_vector_reg_class[V16QImode] = ALTIVEC_REGS;
- rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
- rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
-
- rs6000_vector_mem[V4SImode] = VECTOR_ALTIVEC;
- rs6000_vector_mem[V8HImode] = VECTOR_ALTIVEC;
- rs6000_vector_mem[V16QImode] = VECTOR_ALTIVEC;
- rs6000_vector_align[V4SImode] = 128;
- rs6000_vector_align[V8HImode] = 128;
- rs6000_vector_align[V16QImode] = 128;
+ if (TARGET_VSX)
+ {
+ rs6000_vector_mem[V4SImode] = VECTOR_VSX;
+ rs6000_vector_mem[V8HImode] = VECTOR_VSX;
+ rs6000_vector_mem[V16QImode] = VECTOR_VSX;
+ }
+ else
+ {
+ rs6000_vector_mem[V4SImode] = VECTOR_ALTIVEC;
+ rs6000_vector_mem[V8HImode] = VECTOR_ALTIVEC;
+ rs6000_vector_mem[V16QImode] = VECTOR_ALTIVEC;
+ }
}
/* V2DImode, prefer vsx over altivec, since the main use will be for
vectorized floating point conversions. */
- if (TARGET_ALTIVEC)
+ if (TARGET_VSX)
+ {
+ rs6000_vector_mem[V2DImode] = VECTOR_VSX;
+ rs6000_vector_unit[V2DImode] = VECTOR_NONE;
+ rs6000_vector_align[V2DImode] = align64;
+ }
+ else if (TARGET_ALTIVEC)
{
rs6000_vector_mem[V2DImode] = VECTOR_ALTIVEC;
rs6000_vector_unit[V2DImode] = VECTOR_NONE;
- rs6000_vector_reg_class[V2DImode] = ALTIVEC_REGS;
- rs6000_vector_align[V2DImode] = 128;
+ rs6000_vector_align[V2DImode] = align64;
+ }
+
+ /* DFmode, see if we want to use the VSX unit. */
+ if (TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
+ {
+ rs6000_vector_unit[DFmode] = VECTOR_VSX;
+ rs6000_vector_mem[DFmode]
+ = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
+ rs6000_vector_align[DFmode] = align64;
}
/* TODO add SPE and paired floating point vector support. */
- /* Set the VSX register classes. */
- rs6000_vector_reg_class[V4SFmode]
- = (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
- ? ALTIVEC_REGS
- : NO_REGS);
+ /* Register class constaints for the constraints that depend on compile
+ switches. */
+ if (TARGET_HARD_FLOAT && TARGET_FPRS)
+ rs6000_constraints[RS6000_CONSTRAINT_f] = FLOAT_REGS;
- rs6000_vector_reg_class[V2DFmode] = NO_REGS;
+ if (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
+ rs6000_constraints[RS6000_CONSTRAINT_d] = FLOAT_REGS;
- rs6000_vector_reg_class[DFmode] = (!float_p ? NO_REGS : FLOAT_REGS);
+ if (TARGET_VSX)
+ {
+ /* At present, we just use VSX_REGS, but we have different constraints
+ based on the use, in case we want to fine tune the default register
+ class used. wa = any VSX register, wf = register class to use for
+ V4SF, wd = register class to use for V2DF, and ws = register classs to
+ use for DF scalars. */
+ rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS;
+ if (TARGET_VSX_SCALAR_DOUBLE)
+ rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS;
+ }
+
+ if (TARGET_ALTIVEC)
+ rs6000_constraints[RS6000_CONSTRAINT_v] = ALTIVEC_REGS;
+
+ /* Set up the reload helper functions. */
+ if (TARGET_VSX || TARGET_ALTIVEC)
+ {
+ if (TARGET_64BIT)
+ {
+ rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_di_store;
+ rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_di_load;
+ rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_di_store;
+ rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_di_load;
+ rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_di_store;
+ rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_di_load;
+ rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_di_store;
+ rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_di_load;
+ rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_di_store;
+ 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;
+ }
+ else
+ {
+ rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_si_store;
+ rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_si_load;
+ rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_si_store;
+ rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_si_load;
+ rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_si_store;
+ rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_si_load;
+ rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_si_store;
+ rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_si_load;
+ rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_si_store;
+ 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;
+ }
+ }
/* Precalculate HARD_REGNO_NREGS. */
for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
@@ -1696,7 +1974,10 @@ rs6000_init_hard_regno_mode_ok (void)
{
int reg_size;
- if (c == ALTIVEC_REGS)
+ if (TARGET_VSX && VSX_REG_CLASS_P (c))
+ reg_size = UNITS_PER_VSX_WORD;
+
+ else if (c == ALTIVEC_REGS)
reg_size = UNITS_PER_ALTIVEC_WORD;
else if (c == FLOAT_REGS)
@@ -1714,56 +1995,7 @@ rs6000_init_hard_regno_mode_ok (void)
rs6000_class_max_nregs[DFmode][GENERAL_REGS] = 1;
if (TARGET_DEBUG_REG)
- {
- const char *nl = (const char *)0;
-
- fprintf (stderr, "Register information: (last virtual reg = %d)\n",
- LAST_VIRTUAL_REGISTER);
- rs6000_debug_reg_print (0, 31, "gr");
- rs6000_debug_reg_print (32, 63, "fp");
- rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
- LAST_ALTIVEC_REGNO,
- "vs");
- rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
- rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
- rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
- rs6000_debug_reg_print (MQ_REGNO, MQ_REGNO, "mq");
- rs6000_debug_reg_print (XER_REGNO, XER_REGNO, "xer");
- rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave");
- rs6000_debug_reg_print (VSCR_REGNO, VSCR_REGNO, "vscr");
- rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a");
- rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f");
-
- fprintf (stderr,
- "\n"
- "V16QI reg_class = %s\n"
- "V8HI reg_class = %s\n"
- "V4SI reg_class = %s\n"
- "V2DI reg_class = %s\n"
- "V4SF reg_class = %s\n"
- "V2DF reg_class = %s\n"
- "DF reg_class = %s\n\n",
- reg_class_names[rs6000_vector_reg_class[V16QImode]],
- reg_class_names[rs6000_vector_reg_class[V8HImode]],
- reg_class_names[rs6000_vector_reg_class[V4SImode]],
- reg_class_names[rs6000_vector_reg_class[V2DImode]],
- reg_class_names[rs6000_vector_reg_class[V4SFmode]],
- reg_class_names[rs6000_vector_reg_class[V2DFmode]],
- reg_class_names[rs6000_vector_reg_class[DFmode]]);
-
- for (m = 0; m < NUM_MACHINE_MODES; ++m)
- if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
- {
- nl = "\n";
- fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n",
- GET_MODE_NAME (m),
- rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
- rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]);
- }
-
- if (nl)
- fputs (nl, stderr);
- }
+ rs6000_debug_reg_global ();
}
#if TARGET_MACHO
@@ -1937,7 +2169,7 @@ rs6000_override_options (const char *default_cpu)
{"power7", PROCESSOR_POWER7,
POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
| MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
- | MASK_VSX}, /* Don't add MASK_ISEL by default */
+ /* | MASK_VSX */}, /* Don't add MASK_ISEL by default */
{"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
{"powerpc64", PROCESSOR_POWERPC64,
POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
@@ -2246,12 +2478,23 @@ rs6000_override_options (const char *default_cpu)
&& rs6000_cpu != PROCESSOR_POWER7
&& rs6000_cpu != PROCESSOR_CELL);
rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
- || rs6000_cpu == PROCESSOR_POWER5);
+ || rs6000_cpu == PROCESSOR_POWER5
+ || rs6000_cpu == PROCESSOR_POWER7);
rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5
|| rs6000_cpu == PROCESSOR_POWER6
|| rs6000_cpu == PROCESSOR_POWER7);
+ /* Allow debug switches to override the above settings. */
+ if (TARGET_ALWAYS_HINT > 0)
+ rs6000_always_hint = TARGET_ALWAYS_HINT;
+
+ if (TARGET_SCHED_GROUPS > 0)
+ rs6000_sched_groups = TARGET_SCHED_GROUPS;
+
+ if (TARGET_ALIGN_BRANCH_TARGETS > 0)
+ rs6000_align_branch_targets = TARGET_ALIGN_BRANCH_TARGETS;
+
rs6000_sched_restricted_insns_priority
= (rs6000_sched_groups ? 1 : 0);
@@ -2517,18 +2760,19 @@ rs6000_builtin_conversion (unsigned int tcode, tree type)
{
enum tree_code code = (enum tree_code) tcode;
- if (!TARGET_ALTIVEC)
- return NULL_TREE;
-
switch (code)
{
case FIX_TRUNC_EXPR:
switch (TYPE_MODE (type))
{
case V4SImode:
+ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
+ return NULL_TREE;
+
return TYPE_UNSIGNED (type)
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTUXS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCTSXS];
+ ? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI]
+ : rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI];
+
default:
return NULL_TREE;
}
@@ -2537,9 +2781,13 @@ rs6000_builtin_conversion (unsigned int tcode, tree type)
switch (TYPE_MODE (type))
{
case V4SImode:
+ if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
+ return NULL_TREE;
+
return TYPE_UNSIGNED (type)
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFUX]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
+ ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
+ : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
+
default:
return NULL_TREE;
}
@@ -2560,12 +2808,12 @@ rs6000_builtin_mul_widen_even (tree type)
{
case V8HImode:
return TYPE_UNSIGNED (type)
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULEUH]
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULEUH_UNS]
: rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULESH];
case V16QImode:
return TYPE_UNSIGNED (type)
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULEUB]
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULEUB_UNS]
: rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULESB];
default:
return NULL_TREE;
@@ -2583,12 +2831,12 @@ rs6000_builtin_mul_widen_odd (tree type)
{
case V8HImode:
return TYPE_UNSIGNED (type)
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULOUH]
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULOUH_UNS]
: rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULOSH];
case V16QImode:
return TYPE_UNSIGNED (type)
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULOUB]
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULOUB_UNS]
: rs6000_builtin_decls[ALTIVEC_BUILTIN_VMULOSB];
default:
return NULL_TREE;
@@ -2630,6 +2878,8 @@ rs6000_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_pac
tree
rs6000_builtin_vec_perm (tree type, tree *mask_element_type)
{
+ tree inner_type = TREE_TYPE (type);
+ bool uns_p = TYPE_UNSIGNED (inner_type);
tree d;
*mask_element_type = unsigned_char_type_node;
@@ -2637,15 +2887,21 @@ rs6000_builtin_vec_perm (tree type, tree *mask_element_type)
switch (TYPE_MODE (type))
{
case V16QImode:
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI];
+ d = (uns_p
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI_UNS]
+ : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI]);
break;
case V8HImode:
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI];
+ d = (uns_p
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI_UNS]
+ : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI]);
break;
case V4SImode:
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI];
+ d = (uns_p
+ ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI_UNS]
+ : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI]);
break;
case V4SFmode:
@@ -3475,6 +3731,9 @@ output_vec_const_move (rtx *operands)
vec = operands[1];
mode = GET_MODE (dest);
+ if (TARGET_VSX && zero_constant (vec, mode))
+ return "xxlxor %x0,%x0,%x0";
+
if (TARGET_ALTIVEC)
{
rtx splat_vec;
@@ -3698,20 +3957,21 @@ rs6000_expand_vector_init (rtx target, rtx vals)
if (n_var == 0)
{
rtx const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
- if (mode != V4SFmode && all_const_zero)
+ bool int_vector_p = (GET_MODE_CLASS (mode) == MODE_VECTOR_INT);
+ if ((int_vector_p || TARGET_VSX) && all_const_zero)
{
/* Zero register. */
emit_insn (gen_rtx_SET (VOIDmode, target,
gen_rtx_XOR (mode, target, target)));
return;
}
- else if (mode != V4SFmode && easy_vector_constant (const_vec, mode))
+ else if (int_vector_p && easy_vector_constant (const_vec, mode))
{
/* Splat immediate. */
emit_insn (gen_rtx_SET (VOIDmode, target, const_vec));
return;
}
- else if (all_same)
+ else if (all_same && int_vector_p)
; /* Splat vector element. */
else
{
@@ -5597,6 +5857,32 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
return;
}
+ /* Fix up invalid (const (plus (symbol_ref) (reg))) that seems to be created
+ in the secondary_reload phase, which evidently overwrites the CONST_INT
+ with a register. */
+ if (GET_CODE (source) == CONST && GET_CODE (XEXP (source, 0)) == PLUS
+ && mode == Pmode)
+ {
+ rtx add_op0 = XEXP (XEXP (source, 0), 0);
+ rtx add_op1 = XEXP (XEXP (source, 0), 1);
+
+ if (GET_CODE (add_op0) == SYMBOL_REF && GET_CODE (add_op1) == REG)
+ {
+ rtx tmp = (can_create_pseudo_p ()) ? gen_reg_rtx (Pmode) : dest;
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nrs6000_emit_move: bad source\n");
+ debug_rtx (source);
+ }
+
+ rs6000_emit_move (tmp, add_op0, Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_PLUS (Pmode, tmp, add_op1)));
+ return;
+ }
+ }
+
if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM
&& !gpc_reg_operand (operands[1], mode))
operands[1] = force_reg (mode, operands[1]);
@@ -7865,14 +8151,26 @@ static const struct builtin_description bdesc_3arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
{ MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
{ MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
{ MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di_uns, "__builtin_altivec_vperm_2di_uns", ALTIVEC_BUILTIN_VPERM_2DI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si_uns, "__builtin_altivec_vperm_4si_uns", ALTIVEC_BUILTIN_VPERM_4SI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi_uns, "__builtin_altivec_vperm_8hi_uns", ALTIVEC_BUILTIN_VPERM_8HI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_altivec_vperm_16qi_uns", ALTIVEC_BUILTIN_VPERM_16QI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v2di, "__builtin_altivec_vsel_2di", ALTIVEC_BUILTIN_VSEL_2DI },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v4si_uns, "__builtin_altivec_vsel_4si_uns", ALTIVEC_BUILTIN_VSEL_4SI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v8hi_uns, "__builtin_altivec_vsel_8hi_uns", ALTIVEC_BUILTIN_VSEL_8HI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v16qi_uns, "__builtin_altivec_vsel_16qi_uns", ALTIVEC_BUILTIN_VSEL_16QI_UNS },
+ { MASK_ALTIVEC, CODE_FOR_vector_select_v2di_uns, "__builtin_altivec_vsel_2di_uns", ALTIVEC_BUILTIN_VSEL_2DI_UNS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
@@ -7946,18 +8244,18 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
{ MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
{ MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
+ { MASK_ALTIVEC, CODE_FOR_vector_eqv16qi, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
+ { MASK_ALTIVEC, CODE_FOR_vector_eqv8hi, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
+ { MASK_ALTIVEC, CODE_FOR_vector_eqv4si, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
+ { MASK_ALTIVEC, CODE_FOR_vector_eqv4sf, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
+ { MASK_ALTIVEC, CODE_FOR_vector_gev4sf, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtuv16qi, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtuv8hi, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtuv4si, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtv16qi, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtv8hi, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtv4si, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtv4sf, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
{ MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
@@ -7981,14 +8279,18 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vminsw", ALTIVEC_BUILTIN_VMINSW },
{ MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vminfp", ALTIVEC_BUILTIN_VMINFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub", ALTIVEC_BUILTIN_VMULEUB },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub_uns", ALTIVEC_BUILTIN_VMULEUB_UNS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulesb, "__builtin_altivec_vmulesb", ALTIVEC_BUILTIN_VMULESB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh", ALTIVEC_BUILTIN_VMULEUH },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh_uns", ALTIVEC_BUILTIN_VMULEUH_UNS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulesh, "__builtin_altivec_vmulesh", ALTIVEC_BUILTIN_VMULESH },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub", ALTIVEC_BUILTIN_VMULOUB },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub_uns", ALTIVEC_BUILTIN_VMULOUB_UNS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh_uns", ALTIVEC_BUILTIN_VMULOUH_UNS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
- { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
+ { MASK_ALTIVEC, CODE_FOR_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
{ MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
@@ -7999,9 +8301,9 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkuwus, "__builtin_altivec_vpkuwus", ALTIVEC_BUILTIN_VPKUWUS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkswus, "__builtin_altivec_vpkswus", ALTIVEC_BUILTIN_VPKSWUS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vrlb, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vrlh, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vrlw, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
+ { MASK_ALTIVEC, CODE_FOR_vrotlv16qi3, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
+ { MASK_ALTIVEC, CODE_FOR_vrotlv8hi3, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
+ { MASK_ALTIVEC, CODE_FOR_vrotlv4si3, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
{ MASK_ALTIVEC, CODE_FOR_vashlv16qi3, "__builtin_altivec_vslb", ALTIVEC_BUILTIN_VSLB },
{ MASK_ALTIVEC, CODE_FOR_vashlv8hi3, "__builtin_altivec_vslh", ALTIVEC_BUILTIN_VSLH },
{ MASK_ALTIVEC, CODE_FOR_vashlv4si3, "__builtin_altivec_vslw", ALTIVEC_BUILTIN_VSLW },
@@ -8049,8 +8351,8 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhs", ALTIVEC_BUILTIN_VEC_VADDUHS },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsbs", ALTIVEC_BUILTIN_VEC_VADDSBS },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubs", ALTIVEC_BUILTIN_VEC_VADDUBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_avg", ALTIVEC_BUILTIN_VEC_AVG },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsw", ALTIVEC_BUILTIN_VEC_VAVGSW },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguw", ALTIVEC_BUILTIN_VEC_VAVGUW },
@@ -8075,8 +8377,8 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuw", ALTIVEC_BUILTIN_VEC_VMAXUW },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsh", ALTIVEC_BUILTIN_VEC_VMAXSH },
@@ -8091,8 +8393,8 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglw", ALTIVEC_BUILTIN_VEC_VMRGLW },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglh", ALTIVEC_BUILTIN_VEC_VMRGLH },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglb", ALTIVEC_BUILTIN_VEC_VMRGLB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsw", ALTIVEC_BUILTIN_VEC_VMINSW },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuw", ALTIVEC_BUILTIN_VEC_VMINUW },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsh", ALTIVEC_BUILTIN_VEC_VMINSH },
@@ -8109,8 +8411,8 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulouh", ALTIVEC_BUILTIN_VEC_VMULOUH },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosb", ALTIVEC_BUILTIN_VEC_VMULOSB },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuloub", ALTIVEC_BUILTIN_VEC_VMULOUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_pack", ALTIVEC_BUILTIN_VEC_PACK },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwum", ALTIVEC_BUILTIN_VEC_VPKUWUM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhum", ALTIVEC_BUILTIN_VEC_VPKUHUM },
@@ -8143,8 +8445,8 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrab", ALTIVEC_BUILTIN_VEC_VSRAB },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_srl", ALTIVEC_BUILTIN_VEC_SRL },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sro", ALTIVEC_BUILTIN_VEC_SRO },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuwm", ALTIVEC_BUILTIN_VEC_VSUBUWM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhm", ALTIVEC_BUILTIN_VEC_VSUBUHM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububm", ALTIVEC_BUILTIN_VEC_VSUBUBM },
@@ -8162,7 +8464,7 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4ubs", ALTIVEC_BUILTIN_VEC_VSUM4UBS },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum2s", ALTIVEC_BUILTIN_VEC_SUM2S },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
{ 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
{ 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
@@ -8326,30 +8628,45 @@ struct builtin_description_predicates
{
const unsigned int mask;
const enum insn_code icode;
- const char *opcode;
const char *const name;
const enum rs6000_builtins code;
};
static const struct builtin_description_predicates bdesc_altivec_preds[] =
{
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpbfp.", "__builtin_altivec_vcmpbfp_p", ALTIVEC_BUILTIN_VCMPBFP_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpeqfp.", "__builtin_altivec_vcmpeqfp_p", ALTIVEC_BUILTIN_VCMPEQFP_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgefp.", "__builtin_altivec_vcmpgefp_p", ALTIVEC_BUILTIN_VCMPGEFP_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgtfp.", "__builtin_altivec_vcmpgtfp_p", ALTIVEC_BUILTIN_VCMPGTFP_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpequw.", "__builtin_altivec_vcmpequw_p", ALTIVEC_BUILTIN_VCMPEQUW_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtsw.", "__builtin_altivec_vcmpgtsw_p", ALTIVEC_BUILTIN_VCMPGTSW_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtuw.", "__builtin_altivec_vcmpgtuw_p", ALTIVEC_BUILTIN_VCMPGTUW_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtuh.", "__builtin_altivec_vcmpgtuh_p", ALTIVEC_BUILTIN_VCMPGTUH_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtsh.", "__builtin_altivec_vcmpgtsh_p", ALTIVEC_BUILTIN_VCMPGTSH_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpequh.", "__builtin_altivec_vcmpequh_p", ALTIVEC_BUILTIN_VCMPEQUH_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpequb.", "__builtin_altivec_vcmpequb_p", ALTIVEC_BUILTIN_VCMPEQUB_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtsb.", "__builtin_altivec_vcmpgtsb_p", ALTIVEC_BUILTIN_VCMPGTSB_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P },
-
- { MASK_ALTIVEC, CODE_FOR_nothing, NULL, "__builtin_vec_vcmpeq_p", ALTIVEC_BUILTIN_VCMPEQ_P },
- { MASK_ALTIVEC, CODE_FOR_nothing, NULL, "__builtin_vec_vcmpgt_p", ALTIVEC_BUILTIN_VCMPGT_P },
- { MASK_ALTIVEC, CODE_FOR_nothing, NULL, "__builtin_vec_vcmpge_p", ALTIVEC_BUILTIN_VCMPGE_P }
+ { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp_p, "__builtin_altivec_vcmpbfp_p",
+ ALTIVEC_BUILTIN_VCMPBFP_P },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_vector_eq_v4sf_p,
+ "__builtin_altivec_vcmpeqfp_p", ALTIVEC_BUILTIN_VCMPEQFP_P },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_vector_ge_v4sf_p,
+ "__builtin_altivec_vcmpgefp_p", ALTIVEC_BUILTIN_VCMPGEFP_P },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_vector_gt_v4sf_p,
+ "__builtin_altivec_vcmpgtfp_p", ALTIVEC_BUILTIN_VCMPGTFP_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_eq_v4si_p, "__builtin_altivec_vcmpequw_p",
+ ALTIVEC_BUILTIN_VCMPEQUW_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_gt_v4si_p, "__builtin_altivec_vcmpgtsw_p",
+ ALTIVEC_BUILTIN_VCMPGTSW_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtu_v4si_p, "__builtin_altivec_vcmpgtuw_p",
+ ALTIVEC_BUILTIN_VCMPGTUW_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_eq_v8hi_p, "__builtin_altivec_vcmpequh_p",
+ ALTIVEC_BUILTIN_VCMPEQUH_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_gt_v8hi_p, "__builtin_altivec_vcmpgtsh_p",
+ ALTIVEC_BUILTIN_VCMPGTSH_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtu_v8hi_p, "__builtin_altivec_vcmpgtuh_p",
+ ALTIVEC_BUILTIN_VCMPGTUH_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_eq_v16qi_p, "__builtin_altivec_vcmpequb_p",
+ ALTIVEC_BUILTIN_VCMPEQUB_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_gt_v16qi_p, "__builtin_altivec_vcmpgtsb_p",
+ ALTIVEC_BUILTIN_VCMPGTSB_P },
+ { MASK_ALTIVEC, CODE_FOR_vector_gtu_v16qi_p, "__builtin_altivec_vcmpgtub_p",
+ ALTIVEC_BUILTIN_VCMPGTUB_P },
+
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpeq_p",
+ ALTIVEC_BUILTIN_VCMPEQ_P },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpgt_p",
+ ALTIVEC_BUILTIN_VCMPGT_P },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpge_p",
+ ALTIVEC_BUILTIN_VCMPGE_P }
};
/* SPE predicates. */
@@ -8453,6 +8770,11 @@ static struct builtin_description bdesc_1arg[] =
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vec_float_sisf", VECTOR_BUILTIN_FLOAT_V4SI_V4SF },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vec_uns_float_sisf", VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
+
/* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
end with SPE_BUILTIN_EVSUBFUSIAAW. */
{ 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
@@ -8649,8 +8971,7 @@ rs6000_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
}
static rtx
-altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
- tree exp, rtx target)
+altivec_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target)
{
rtx pat, scratch;
tree cr6_form = CALL_EXPR_ARG (exp, 0);
@@ -8689,8 +9010,7 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
scratch = gen_reg_rtx (mode0);
- pat = GEN_FCN (icode) (scratch, op0, op1,
- gen_rtx_SYMBOL_REF (Pmode, opcode));
+ pat = GEN_FCN (icode) (scratch, op0, op1);
if (! pat)
return 0;
emit_insn (pat);
@@ -8957,11 +9277,12 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
|| 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
@@ -8970,6 +9291,10 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
error ("argument 3 must be a 4-bit unsigned literal");
return const0_rtx;
}
+ break;
+
+ default:
+ break;
}
if (target == 0
@@ -9009,16 +9334,16 @@ altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
switch (fcode)
{
case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
- icode = CODE_FOR_altivec_lvx_v16qi;
+ icode = CODE_FOR_vector_load_v16qi;
break;
case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
- icode = CODE_FOR_altivec_lvx_v8hi;
+ icode = CODE_FOR_vector_load_v8hi;
break;
case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
- icode = CODE_FOR_altivec_lvx_v4si;
+ icode = CODE_FOR_vector_load_v4si;
break;
case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
- icode = CODE_FOR_altivec_lvx_v4sf;
+ icode = CODE_FOR_vector_load_v4sf;
break;
default:
*expandedp = false;
@@ -9062,16 +9387,16 @@ altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
switch (fcode)
{
case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
- icode = CODE_FOR_altivec_stvx_v16qi;
+ icode = CODE_FOR_vector_store_v16qi;
break;
case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
- icode = CODE_FOR_altivec_stvx_v8hi;
+ icode = CODE_FOR_vector_store_v8hi;
break;
case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
- icode = CODE_FOR_altivec_stvx_v4si;
+ icode = CODE_FOR_vector_store_v4si;
break;
case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
- icode = CODE_FOR_altivec_stvx_v4sf;
+ icode = CODE_FOR_vector_store_v4sf;
break;
default:
*expandedp = false;
@@ -9415,8 +9740,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
dp = bdesc_altivec_preds;
for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
if (dp->code == fcode)
- return altivec_expand_predicate_builtin (dp->icode, dp->opcode,
- exp, target);
+ return altivec_expand_predicate_builtin (dp->icode, exp, target);
/* LV* are funky. We initialized them differently. */
switch (fcode)
@@ -9910,13 +10234,13 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
bool success;
if (fcode == RS6000_BUILTIN_RECIP)
- return rs6000_expand_binop_builtin (CODE_FOR_recipdf3, exp, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_recipdf3, exp, target);
if (fcode == RS6000_BUILTIN_RECIPF)
- return rs6000_expand_binop_builtin (CODE_FOR_recipsf3, exp, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_recipsf3, exp, target);
if (fcode == RS6000_BUILTIN_RSQRTF)
- return rs6000_expand_unop_builtin (CODE_FOR_rsqrtsf2, exp, target);
+ return rs6000_expand_unop_builtin (CODE_FOR_rsqrtsf2, exp, target);
if (fcode == RS6000_BUILTIN_BSWAP_HI)
return rs6000_expand_unop_builtin (CODE_FOR_bswaphi2, exp, target);
@@ -10025,6 +10349,8 @@ rs6000_init_builtins (void)
V2SI_type_node = build_vector_type (intSI_type_node, 2);
V2SF_type_node = build_vector_type (float_type_node, 2);
+ V2DI_type_node = build_vector_type (intDI_type_node, 2);
+ V2DF_type_node = build_vector_type (double_type_node, 2);
V4HI_type_node = build_vector_type (intHI_type_node, 4);
V4SI_type_node = build_vector_type (intSI_type_node, 4);
V4SF_type_node = build_vector_type (float_type_node, 4);
@@ -10034,6 +10360,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);
@@ -10047,6 +10374,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;
@@ -10057,9 +10385,36 @@ rs6000_init_builtins (void)
uintHI_type_internal_node = unsigned_intHI_type_node;
intSI_type_internal_node = intSI_type_node;
uintSI_type_internal_node = unsigned_intSI_type_node;
+ intDI_type_internal_node = intDI_type_node;
+ uintDI_type_internal_node = unsigned_intDI_type_node;
float_type_internal_node = float_type_node;
+ double_type_internal_node = float_type_node;
void_type_internal_node = void_type_node;
+ /* Initialize the modes for builtin_function_type, mapping a machine mode to
+ tree type node. */
+ builtin_mode_to_type[QImode][0] = integer_type_node;
+ builtin_mode_to_type[HImode][0] = integer_type_node;
+ builtin_mode_to_type[SImode][0] = intSI_type_node;
+ builtin_mode_to_type[SImode][1] = unsigned_intSI_type_node;
+ builtin_mode_to_type[DImode][0] = intDI_type_node;
+ builtin_mode_to_type[DImode][1] = unsigned_intDI_type_node;
+ builtin_mode_to_type[SFmode][0] = float_type_node;
+ builtin_mode_to_type[DFmode][0] = double_type_node;
+ builtin_mode_to_type[V2SImode][0] = V2SI_type_node;
+ builtin_mode_to_type[V2SFmode][0] = V2SF_type_node;
+ builtin_mode_to_type[V2DImode][0] = V2DI_type_node;
+ builtin_mode_to_type[V2DImode][1] = unsigned_V2DI_type_node;
+ builtin_mode_to_type[V2DFmode][0] = V2DF_type_node;
+ builtin_mode_to_type[V4HImode][0] = V4HI_type_node;
+ builtin_mode_to_type[V4SImode][0] = V4SI_type_node;
+ builtin_mode_to_type[V4SImode][1] = unsigned_V4SI_type_node;
+ builtin_mode_to_type[V4SFmode][0] = V4SF_type_node;
+ builtin_mode_to_type[V8HImode][0] = V8HI_type_node;
+ builtin_mode_to_type[V8HImode][1] = unsigned_V8HI_type_node;
+ builtin_mode_to_type[V16QImode][0] = V16QI_type_node;
+ builtin_mode_to_type[V16QImode][1] = unsigned_V16QI_type_node;
+
tdecl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
get_identifier ("__bool char"),
bool_char_type_node);
@@ -10083,6 +10438,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);
tdecl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
@@ -10154,31 +10510,30 @@ rs6000_init_builtins (void)
rs6000_common_init_builtins ();
if (TARGET_PPC_GFXOPT)
{
- tree ftype = build_function_type_list (float_type_node,
- float_type_node,
- float_type_node,
- NULL_TREE);
+ tree ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode,
+ RS6000_BUILTIN_RECIPF,
+ "__builtin_recipdivf");
def_builtin (MASK_PPC_GFXOPT, "__builtin_recipdivf", ftype,
RS6000_BUILTIN_RECIPF);
- ftype = build_function_type_list (float_type_node,
- float_type_node,
- NULL_TREE);
+ ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode,
+ RS6000_BUILTIN_RSQRTF,
+ "__builtin_rsqrtf");
def_builtin (MASK_PPC_GFXOPT, "__builtin_rsqrtf", ftype,
RS6000_BUILTIN_RSQRTF);
}
if (TARGET_POPCNTB)
{
- tree ftype = build_function_type_list (double_type_node,
- double_type_node,
- double_type_node,
- NULL_TREE);
+ tree ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
+ RS6000_BUILTIN_RECIP,
+ "__builtin_recipdiv");
def_builtin (MASK_POPCNTB, "__builtin_recipdiv", ftype,
RS6000_BUILTIN_RECIP);
}
if (TARGET_POWERPC)
{
+ /* Don't use builtin_function_type here, as it maps HI/QI to SI. */
tree ftype = build_function_type_list (unsigned_intHI_type_node,
unsigned_intHI_type_node,
NULL_TREE);
@@ -10851,7 +11206,7 @@ altivec_init_builtins (void)
def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v8hi", ftype,
ALTIVEC_BUILTIN_VEC_SET_V8HI);
- ftype = build_function_type_list (V8HI_type_node, V16QI_type_node,
+ ftype = build_function_type_list (V16QI_type_node, V16QI_type_node,
intQI_type_node,
integer_type_node, NULL_TREE);
def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v16qi", ftype,
@@ -10860,7 +11215,7 @@ altivec_init_builtins (void)
ftype = build_function_type_list (V4SF_type_node, V4SF_type_node,
float_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v4sf", ftype,
+ def_builtin (MASK_ALTIVEC|MASK_VSX, "__builtin_vec_set_v4sf", ftype,
ALTIVEC_BUILTIN_VEC_SET_V4SF);
/* Access to the vec_extract patterns. */
@@ -10881,480 +11236,295 @@ altivec_init_builtins (void)
ftype = build_function_type_list (float_type_node, V4SF_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v4sf", ftype,
+ def_builtin (MASK_ALTIVEC|MASK_VSX, "__builtin_vec_ext_v4sf", ftype,
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);
+ for (i = 0; i < 4; i++)
+ {
+ ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]);
+ ret = (ret * 2) + bh->uns_p[i];
+ }
- 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);
+ return ret;
+}
- tree v2si_ftype_v2si_v2si
- = build_function_type_list (opaque_V2SI_type_node,
- opaque_V2SI_type_node,
- opaque_V2SI_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 v2sf_ftype_v2sf_v2sf_spe
- = build_function_type_list (opaque_V2SF_type_node,
- opaque_V2SF_type_node,
- opaque_V2SF_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])
+ && (p1->uns_p[0] == p2->uns_p[0])
+ && (p1->uns_p[1] == p2->uns_p[1])
+ && (p1->uns_p[2] == p2->uns_p[2])
+ && (p1->uns_p[3] == p2->uns_p[3]));
+}
- tree v2sf_ftype_v2sf_v2sf
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node,
- V2SF_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,
+ enum rs6000_builtins builtin, const char *name)
+{
+ struct builtin_hash_struct h;
+ struct builtin_hash_struct *h2;
+ void **found;
+ int num_args = 3;
+ int i;
+ tree ret_type = NULL_TREE;
+ tree arg_type[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
+ tree args;
+
+ /* 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;
+ h.uns_p[0] = 0;
+ h.uns_p[1] = 0;
+ h.uns_p[2] = 0;
+ h.uns_p[3] = 0;
+
+ /* If the builtin is a type that produces unsigned results or takes unsigned
+ arguments, and it is returned as a decl for the vectorizer (such as
+ widening multiplies, permute), make sure the arguments and return value
+ are type correct. */
+ switch (builtin)
+ {
+ /* unsigned 2 argument functions. */
+ case ALTIVEC_BUILTIN_VMULEUB_UNS:
+ case ALTIVEC_BUILTIN_VMULEUH_UNS:
+ case ALTIVEC_BUILTIN_VMULOUB_UNS:
+ case ALTIVEC_BUILTIN_VMULOUH_UNS:
+ h.uns_p[0] = 1;
+ h.uns_p[1] = 1;
+ h.uns_p[2] = 1;
+ break;
+ /* unsigned 3 argument functions. */
+ case ALTIVEC_BUILTIN_VPERM_16QI_UNS:
+ case ALTIVEC_BUILTIN_VPERM_8HI_UNS:
+ case ALTIVEC_BUILTIN_VPERM_4SI_UNS:
+ case ALTIVEC_BUILTIN_VPERM_2DI_UNS:
+ case ALTIVEC_BUILTIN_VSEL_16QI_UNS:
+ case ALTIVEC_BUILTIN_VSEL_8HI_UNS:
+ case ALTIVEC_BUILTIN_VSEL_4SI_UNS:
+ case ALTIVEC_BUILTIN_VSEL_2DI_UNS:
+ h.uns_p[0] = 1;
+ h.uns_p[1] = 1;
+ h.uns_p[2] = 1;
+ h.uns_p[3] = 1;
+ break;
- tree v2si_ftype_int_int
- = build_function_type_list (opaque_V2SI_type_node,
- integer_type_node, integer_type_node,
- NULL_TREE);
+ /* signed permute functions with unsigned char mask. */
+ case ALTIVEC_BUILTIN_VPERM_16QI:
+ case ALTIVEC_BUILTIN_VPERM_8HI:
+ case ALTIVEC_BUILTIN_VPERM_4SI:
+ case ALTIVEC_BUILTIN_VPERM_4SF:
+ case ALTIVEC_BUILTIN_VPERM_2DI:
+ case ALTIVEC_BUILTIN_VPERM_2DF:
+ h.uns_p[3] = 1;
+ break;
- tree opaque_ftype_opaque
- = build_function_type_list (opaque_V4SI_type_node,
- opaque_V4SI_type_node, NULL_TREE);
+ /* unsigned args, signed return. */
+ case VSX_BUILTIN_XVCVUXDDP_UNS:
+ case VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF:
+ h.uns_p[1] = 1;
+ break;
- tree v2si_ftype_v2si
- = build_function_type_list (opaque_V2SI_type_node,
- opaque_V2SI_type_node, NULL_TREE);
+ /* signed args, unsigned return. */
+ case VSX_BUILTIN_XVCVDPUXDS_UNS:
+ case VECTOR_BUILTIN_FIXUNS_V4SF_V4SI:
+ h.uns_p[0] = 1;
+ break;
- tree v2sf_ftype_v2sf_spe
- = build_function_type_list (opaque_V2SF_type_node,
- opaque_V2SF_type_node, NULL_TREE);
+ default:
+ break;
+ }
- tree v2sf_ftype_v2sf
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, NULL_TREE);
+ /* Figure out how many args are present. */
+ while (num_args > 0 && h.mode[num_args] == VOIDmode)
+ num_args--;
- tree v2sf_ftype_v2si
- = build_function_type_list (opaque_V2SF_type_node,
- opaque_V2SI_type_node, NULL_TREE);
+ if (num_args == 0)
+ fatal_error ("internal error: builtin function %s had no type", name);
- tree v2si_ftype_v2sf
- = build_function_type_list (opaque_V2SI_type_node,
- opaque_V2SF_type_node, NULL_TREE);
+ ret_type = builtin_mode_to_type[h.mode[0]][h.uns_p[0]];
+ if (!ret_type && h.uns_p[0])
+ ret_type = builtin_mode_to_type[h.mode[0]][0];
- tree v2si_ftype_v2si_char
- = build_function_type_list (opaque_V2SI_type_node,
- opaque_V2SI_type_node,
- char_type_node, NULL_TREE);
+ if (!ret_type)
+ fatal_error ("internal error: builtin function %s had an unexpected "
+ "return type %s", name, GET_MODE_NAME (h.mode[0]));
- tree v2si_ftype_int_char
- = build_function_type_list (opaque_V2SI_type_node,
- integer_type_node, char_type_node, NULL_TREE);
+ for (i = 0; i < num_args; i++)
+ {
+ int m = (int) h.mode[i+1];
+ int uns_p = h.uns_p[i+1];
- tree v2si_ftype_char
- = build_function_type_list (opaque_V2SI_type_node,
- char_type_node, NULL_TREE);
+ arg_type[i] = builtin_mode_to_type[m][uns_p];
+ if (!arg_type[i] && uns_p)
+ arg_type[i] = builtin_mode_to_type[m][0];
- tree int_ftype_int_int
- = build_function_type_list (integer_type_node,
- integer_type_node, integer_type_node,
- NULL_TREE);
+ if (!arg_type[i])
+ fatal_error ("internal error: builtin function %s, argument %d "
+ "had unexpected argument type %s", name, i,
+ GET_MODE_NAME (m));
+ }
- 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);
+ found = htab_find_slot (builtin_hash_table, &h, INSERT);
+ if (*found == NULL)
+ {
+ h2 = GGC_NEW (struct builtin_hash_struct);
+ *h2 = h;
+ *found = (void *)h2;
+ args = void_list_node;
+
+ for (i = num_args - 1; i >= 0; i--)
+ args = tree_cons (NULL_TREE, arg_type[i], args);
+
+ h2->type = build_function_type (ret_type, args);
+ }
+
+ 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;
+
+ if (!TARGET_PAIRED_FLOAT)
+ {
+ builtin_mode_to_type[V2SImode][0] = opaque_V2SI_type_node;
+ builtin_mode_to_type[V2SFmode][0] = opaque_V2SF_type_node;
+ }
- /* Add the simple ternary operators. */
+ /* 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)
+ 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)
{
- mode0 = VOIDmode;
- mode1 = VOIDmode;
- mode2 = VOIDmode;
- mode3 = VOIDmode;
+ 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->code, 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 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 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. */
- d = (struct builtin_description *) bdesc_2arg;
+ /* Add the binary operators. */
+ d = 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)
+ 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)
{
- mode0 = VOIDmode;
- mode1 = VOIDmode;
- mode2 = VOIDmode;
+ 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 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->code, d->name);
}
def_builtin (d->mask, d->name, type, d->code);
@@ -11366,54 +11536,44 @@ rs6000_common_init_builtins (void)
{
enum machine_mode mode0, mode1;
tree type;
+ int mask = d->mask;
bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
&& d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
+ if ((mask != 0 && (mask & target_flags) == 0)
+ || (mask == 0 && !TARGET_PAIRED_FLOAT))
+ continue;
+
if (is_overloaded)
- {
- mode0 = VOIDmode;
- mode1 = VOIDmode;
- }
+ {
+ 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 == 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
- 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->code, d->name);
+ }
def_builtin (d->mask, d->name, type, d->code);
}
@@ -12257,6 +12417,446 @@ rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
return NULL_TREE;
}
+enum reload_reg_type {
+ GPR_REGISTER_TYPE,
+ VECTOR_REGISTER_TYPE,
+ OTHER_REGISTER_TYPE
+};
+
+static enum reload_reg_type
+rs6000_reload_register_type (enum reg_class rclass)
+{
+ switch (rclass)
+ {
+ case GENERAL_REGS:
+ case BASE_REGS:
+ return GPR_REGISTER_TYPE;
+
+ case FLOAT_REGS:
+ case ALTIVEC_REGS:
+ case VSX_REGS:
+ return VECTOR_REGISTER_TYPE;
+
+ default:
+ return OTHER_REGISTER_TYPE;
+ }
+}
+
+/* Inform reload about cases where moving X with a mode MODE to a register in
+ RCLASS requires an extra scratch or immediate register. Return the class
+ needed for the immediate register.
+
+ For VSX and Altivec, we may need a register to convert sp+offset into
+ reg+sp. */
+
+static enum reg_class
+rs6000_secondary_reload (bool in_p,
+ rtx x,
+ enum reg_class rclass,
+ enum machine_mode mode,
+ secondary_reload_info *sri)
+{
+ enum reg_class ret = ALL_REGS;
+ enum insn_code icode;
+ bool default_p = false;
+
+ sri->icode = CODE_FOR_nothing;
+
+ /* Convert vector loads and stores into gprs to use an additional base
+ register. */
+ icode = rs6000_vector_reload[mode][in_p != false];
+ if (icode != CODE_FOR_nothing)
+ {
+ ret = NO_REGS;
+ sri->icode = CODE_FOR_nothing;
+ sri->extra_cost = 0;
+
+ if (GET_CODE (x) == MEM)
+ {
+ rtx addr = XEXP (x, 0);
+
+ /* Loads to and stores from gprs can do reg+offset, and wouldn't need
+ an extra register in that case, but it would need an extra
+ register if the addressing is reg+reg or (reg+reg)&(-16). */
+ if (rclass == GENERAL_REGS || rclass == BASE_REGS)
+ {
+ if (!legitimate_indirect_address_p (addr, false)
+ && !rs6000_legitimate_offset_address_p (TImode, addr, false))
+ {
+ sri->icode = icode;
+ /* account for splitting the loads, and converting the
+ address from reg+reg to reg. */
+ sri->extra_cost = (((TARGET_64BIT) ? 3 : 5)
+ + ((GET_CODE (addr) == AND) ? 1 : 0));
+ }
+ }
+ /* Loads to and stores from vector registers can only do reg+reg
+ addressing. Altivec registers can also do (reg+reg)&(-16). */
+ else if (rclass == VSX_REGS || rclass == ALTIVEC_REGS
+ || rclass == FLOAT_REGS || rclass == NO_REGS)
+ {
+ if (!VECTOR_MEM_ALTIVEC_P (mode)
+ && GET_CODE (addr) == AND
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && INTVAL (XEXP (addr, 1)) == -16
+ && (legitimate_indirect_address_p (XEXP (addr, 0), false)
+ || legitimate_indexed_address_p (XEXP (addr, 0), false)))
+ {
+ sri->icode = icode;
+ sri->extra_cost = ((GET_CODE (XEXP (addr, 0)) == PLUS)
+ ? 2 : 1);
+ }
+ else if (!legitimate_indirect_address_p (addr, false)
+ && (rclass == NO_REGS
+ || !legitimate_indexed_address_p (addr, false)))
+ {
+ sri->icode = icode;
+ sri->extra_cost = 1;
+ }
+ else
+ icode = CODE_FOR_nothing;
+ }
+ /* Any other loads, including to pseudo registers which haven't been
+ assigned to a register yet, default to require a scratch
+ register. */
+ else
+ {
+ sri->icode = icode;
+ sri->extra_cost = 2;
+ }
+ }
+ else if (REG_P (x))
+ {
+ int regno = true_regnum (x);
+
+ icode = CODE_FOR_nothing;
+ if (regno < 0 || regno >= FIRST_PSEUDO_REGISTER)
+ default_p = true;
+ else
+ {
+ enum reg_class xclass = REGNO_REG_CLASS (regno);
+ enum reload_reg_type rtype1 = rs6000_reload_register_type (rclass);
+ enum reload_reg_type rtype2 = rs6000_reload_register_type (xclass);
+
+ /* If memory is needed, use default_secondary_reload to create the
+ stack slot. */
+ if (rtype1 != rtype2 || rtype1 == OTHER_REGISTER_TYPE)
+ default_p = true;
+ else
+ ret = NO_REGS;
+ }
+ }
+ else
+ default_p = true;
+ }
+ else
+ default_p = true;
+
+ if (default_p)
+ ret = default_secondary_reload (in_p, x, rclass, mode, sri);
+
+ gcc_assert (ret != ALL_REGS);
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr,
+ "\nrs6000_secondary_reload, return %s, in_p = %s, rclass = %s, "
+ "mode = %s",
+ reg_class_names[ret],
+ in_p ? "true" : "false",
+ reg_class_names[rclass],
+ GET_MODE_NAME (mode));
+
+ if (default_p)
+ fprintf (stderr, ", default secondary reload");
+
+ if (sri->icode != CODE_FOR_nothing)
+ fprintf (stderr, ", reload func = %s, extra cost = %d\n",
+ insn_data[sri->icode].name, sri->extra_cost);
+ else
+ fprintf (stderr, "\n");
+
+ debug_rtx (x);
+ }
+
+ return ret;
+}
+
+/* Fixup reload addresses for Altivec or VSX loads/stores to change SP+offset
+ to SP+reg addressing. */
+
+void
+rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
+{
+ int regno = true_regnum (reg);
+ enum machine_mode mode = GET_MODE (reg);
+ enum reg_class rclass;
+ rtx addr;
+ rtx and_op2 = NULL_RTX;
+ rtx addr_op1;
+ rtx addr_op2;
+ rtx scratch_or_premodify = scratch;
+ rtx and_rtx;
+ rtx cc_clobber;
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nrs6000_secondary_reload_inner, type = %s\n",
+ store_p ? "store" : "load");
+ fprintf (stderr, "reg:\n");
+ debug_rtx (reg);
+ fprintf (stderr, "mem:\n");
+ debug_rtx (mem);
+ fprintf (stderr, "scratch:\n");
+ debug_rtx (scratch);
+ }
+
+ gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
+ gcc_assert (GET_CODE (mem) == MEM);
+ rclass = REGNO_REG_CLASS (regno);
+ addr = XEXP (mem, 0);
+
+ switch (rclass)
+ {
+ /* GPRs can handle reg + small constant, all other addresses need to use
+ the scratch register. */
+ case GENERAL_REGS:
+ case BASE_REGS:
+ if (GET_CODE (addr) == AND)
+ {
+ and_op2 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+
+ if (GET_CODE (addr) == PRE_MODIFY)
+ {
+ scratch_or_premodify = XEXP (addr, 0);
+ gcc_assert (REG_P (scratch_or_premodify));
+ gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+ addr = XEXP (addr, 1);
+ }
+
+ if (GET_CODE (addr) == PLUS
+ && (!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, false));
+
+ if (!REG_P (addr_op2)
+ && (GET_CODE (addr_op2) != CONST_INT
+ || !satisfies_constraint_I (addr_op2)))
+ {
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr,
+ "\nMove plus addr to register %s, mode = %s: ",
+ rs6000_reg_names[REGNO (scratch)],
+ GET_MODE_NAME (mode));
+ debug_rtx (addr_op2);
+ }
+ rs6000_emit_move (scratch, addr_op2, Pmode);
+ addr_op2 = scratch;
+ }
+
+ emit_insn (gen_rtx_SET (VOIDmode,
+ scratch_or_premodify,
+ gen_rtx_PLUS (Pmode,
+ addr_op1,
+ addr_op2)));
+
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
+ }
+ else if (!legitimate_indirect_address_p (addr, false)
+ && !rs6000_legitimate_offset_address_p (TImode, addr, false))
+ {
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nMove addr to register %s, mode = %s: ",
+ rs6000_reg_names[REGNO (scratch_or_premodify)],
+ GET_MODE_NAME (mode));
+ debug_rtx (addr);
+ }
+ rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
+ }
+ break;
+
+ /* Float/Altivec registers can only handle reg+reg addressing. Move
+ other addresses into a scratch register. */
+ case FLOAT_REGS:
+ case VSX_REGS:
+ case ALTIVEC_REGS:
+
+ /* With float regs, we need to handle the AND ourselves, since we can't
+ use the Altivec instruction with an implicit AND -16. Allow scalar
+ loads to float registers to use reg+offset even if VSX. */
+ if (GET_CODE (addr) == AND
+ && (rclass != ALTIVEC_REGS || GET_MODE_SIZE (mode) != 16
+ || GET_CODE (XEXP (addr, 1)) != CONST_INT
+ || INTVAL (XEXP (addr, 1)) != -16
+ || !VECTOR_MEM_ALTIVEC_P (mode)))
+ {
+ and_op2 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+
+ /* If we aren't using a VSX load, save the PRE_MODIFY register and use it
+ as the address later. */
+ if (GET_CODE (addr) == PRE_MODIFY
+ && (!VECTOR_MEM_VSX_P (mode)
+ || and_op2 != NULL_RTX
+ || !legitimate_indexed_address_p (XEXP (addr, 1), false)))
+ {
+ scratch_or_premodify = XEXP (addr, 0);
+ gcc_assert (legitimate_indirect_address_p (scratch_or_premodify,
+ false));
+ gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+ addr = XEXP (addr, 1);
+ }
+
+ if (legitimate_indirect_address_p (addr, false) /* reg */
+ || legitimate_indexed_address_p (addr, false) /* reg+reg */
+ || GET_CODE (addr) == PRE_MODIFY /* VSX pre-modify */
+ || (GET_CODE (addr) == AND /* Altivec memory */
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && INTVAL (XEXP (addr, 1)) == -16
+ && VECTOR_MEM_ALTIVEC_P (mode))
+ || (rclass == FLOAT_REGS /* legacy float mem */
+ && GET_MODE_SIZE (mode) == 8
+ && and_op2 == NULL_RTX
+ && scratch_or_premodify == scratch
+ && rs6000_legitimate_offset_address_p (mode, addr, false)))
+ ;
+
+ else if (GET_CODE (addr) == PLUS)
+ {
+ addr_op1 = XEXP (addr, 0);
+ addr_op2 = XEXP (addr, 1);
+ gcc_assert (REG_P (addr_op1));
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nMove plus addr to register %s, mode = %s: ",
+ rs6000_reg_names[REGNO (scratch)], GET_MODE_NAME (mode));
+ debug_rtx (addr_op2);
+ }
+ rs6000_emit_move (scratch, addr_op2, Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode,
+ scratch_or_premodify,
+ gen_rtx_PLUS (Pmode,
+ addr_op1,
+ scratch)));
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
+ }
+
+ else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
+ || GET_CODE (addr) == CONST_INT || REG_P (addr))
+ {
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nMove addr to register %s, mode = %s: ",
+ rs6000_reg_names[REGNO (scratch_or_premodify)],
+ GET_MODE_NAME (mode));
+ debug_rtx (addr);
+ }
+
+ rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
+ }
+
+ else
+ gcc_unreachable ();
+
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* If the original address involved a pre-modify that we couldn't use the VSX
+ memory instruction with update, and we haven't taken care of already,
+ store the address in the pre-modify register and use that as the
+ address. */
+ if (scratch_or_premodify != scratch && scratch_or_premodify != addr)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, scratch_or_premodify, addr));
+ addr = scratch_or_premodify;
+ }
+
+ /* If the original address involved an AND -16 and we couldn't use an ALTIVEC
+ memory instruction, recreate the AND now, including the clobber which is
+ generated by the general ANDSI3/ANDDI3 patterns for the
+ andi. instruction. */
+ if (and_op2 != NULL_RTX)
+ {
+ if (! legitimate_indirect_address_p (addr, false))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
+ addr = scratch;
+ }
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nAnd addr to register %s, mode = %s: ",
+ rs6000_reg_names[REGNO (scratch)], GET_MODE_NAME (mode));
+ debug_rtx (and_op2);
+ }
+
+ and_rtx = gen_rtx_SET (VOIDmode,
+ scratch,
+ gen_rtx_AND (Pmode,
+ addr,
+ and_op2));
+
+ cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, and_rtx, cc_clobber)));
+ addr = scratch;
+ }
+
+ /* Adjust the address if it changed. */
+ if (addr != XEXP (mem, 0))
+ {
+ mem = change_address (mem, mode, addr);
+ if (TARGET_DEBUG_ADDR)
+ fprintf (stderr, "\nrs6000_secondary_reload_inner, mem adjusted.\n");
+ }
+
+ /* Now create the move. */
+ if (store_p)
+ emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
+
+ 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. */
@@ -12518,6 +13118,13 @@ rs6000_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
&& (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+ /* Memory, and FP/altivec registers can go into fp/altivec registers under
+ VSX. */
+ if (TARGET_VSX
+ && (regno == -1 || VSX_REGNO_P (regno))
+ && VSX_REG_CLASS_P (rclass))
+ return NO_REGS;
+
/* Memory, and AltiVec registers can go into AltiVec registers. */
if ((regno == -1 || ALTIVEC_REGNO_P (regno))
&& rclass == ALTIVEC_REGS)
@@ -14225,55 +14832,34 @@ output_e500_flip_gt_bit (rtx dst, rtx src)
return string;
}
-/* Return insn index for the vector compare instruction for given CODE,
- and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is
- not available. */
+/* Return insn for VSX or Altivec comparisons. */
-static int
-get_vec_cmp_insn (enum rtx_code code,
- enum machine_mode dest_mode,
- enum machine_mode op_mode)
+static rtx
+rs6000_emit_vector_compare_inner (enum rtx_code code, rtx op0, rtx op1)
{
- if (!TARGET_ALTIVEC)
- return INSN_NOT_AVAILABLE;
+ rtx mask;
+ enum machine_mode mode = GET_MODE (op0);
switch (code)
{
- case EQ:
- if (dest_mode == V16QImode && op_mode == V16QImode)
- return UNSPEC_VCMPEQUB;
- if (dest_mode == V8HImode && op_mode == V8HImode)
- return UNSPEC_VCMPEQUH;
- if (dest_mode == V4SImode && op_mode == V4SImode)
- return UNSPEC_VCMPEQUW;
- if (dest_mode == V4SImode && op_mode == V4SFmode)
- return UNSPEC_VCMPEQFP;
+ default:
break;
+
case GE:
- if (dest_mode == V4SImode && op_mode == V4SFmode)
- return UNSPEC_VCMPGEFP;
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
+ return NULL_RTX;
+
+ case EQ:
case GT:
- if (dest_mode == V16QImode && op_mode == V16QImode)
- return UNSPEC_VCMPGTSB;
- if (dest_mode == V8HImode && op_mode == V8HImode)
- return UNSPEC_VCMPGTSH;
- if (dest_mode == V4SImode && op_mode == V4SImode)
- return UNSPEC_VCMPGTSW;
- if (dest_mode == V4SImode && op_mode == V4SFmode)
- return UNSPEC_VCMPGTFP;
- break;
case GTU:
- if (dest_mode == V16QImode && op_mode == V16QImode)
- return UNSPEC_VCMPGTUB;
- if (dest_mode == V8HImode && op_mode == V8HImode)
- return UNSPEC_VCMPGTUH;
- if (dest_mode == V4SImode && op_mode == V4SImode)
- return UNSPEC_VCMPGTUW;
- break;
- default:
- break;
+ mask = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode,
+ mask,
+ gen_rtx_fmt_ee (code, mode, op0, op1)));
+ return mask;
}
- return INSN_NOT_AVAILABLE;
+
+ return NULL_RTX;
}
/* Emit vector compare for operands OP0 and OP1 using code RCODE.
@@ -14284,129 +14870,114 @@ rs6000_emit_vector_compare (enum rtx_code rcode,
rtx op0, rtx op1,
enum machine_mode dmode)
{
- int vec_cmp_insn;
rtx mask;
- enum machine_mode dest_mode;
- enum machine_mode op_mode = GET_MODE (op1);
+ bool swap_operands = false;
+ bool try_again = false;
- gcc_assert (TARGET_ALTIVEC);
+ gcc_assert (VECTOR_UNIT_ALTIVEC_OR_VSX_P (dmode));
gcc_assert (GET_MODE (op0) == GET_MODE (op1));
- /* Floating point vector compare instructions uses destination V4SImode.
- Move destination to appropriate mode later. */
- if (dmode == V4SFmode)
- dest_mode = V4SImode;
- else
- dest_mode = dmode;
-
- mask = gen_reg_rtx (dest_mode);
- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
+ /* See if the comparison works as is. */
+ mask = rs6000_emit_vector_compare_inner (rcode, op0, op1);
+ if (mask)
+ return mask;
- if (vec_cmp_insn == INSN_NOT_AVAILABLE)
+ switch (rcode)
{
- bool swap_operands = false;
- bool try_again = false;
- switch (rcode)
- {
- case LT:
- rcode = GT;
- swap_operands = true;
- try_again = true;
- break;
- case LTU:
- rcode = GTU;
- swap_operands = true;
- try_again = true;
- break;
- case NE:
- case UNLE:
- case UNLT:
- case UNGE:
- case UNGT:
- /* Invert condition and try again.
- e.g., A != B becomes ~(A==B). */
- {
- enum rtx_code rev_code;
- enum insn_code nor_code;
- rtx eq_rtx;
+ case LT:
+ rcode = GT;
+ swap_operands = true;
+ try_again = true;
+ break;
+ case LTU:
+ rcode = GTU;
+ swap_operands = true;
+ try_again = true;
+ break;
+ case NE:
+ case UNLE:
+ case UNLT:
+ case UNGE:
+ case UNGT:
+ /* Invert condition and try again.
+ e.g., A != B becomes ~(A==B). */
+ {
+ enum rtx_code rev_code;
+ enum insn_code nor_code;
+ rtx mask2;
- rev_code = reverse_condition_maybe_unordered (rcode);
- eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1,
- dest_mode);
+ rev_code = reverse_condition_maybe_unordered (rcode);
+ if (rev_code == UNKNOWN)
+ return NULL_RTX;
- nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code;
- gcc_assert (nor_code != CODE_FOR_nothing);
- emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
+ nor_code = optab_handler (one_cmpl_optab, (int)dmode)->insn_code;
+ if (nor_code == CODE_FOR_nothing)
+ return NULL_RTX;
- if (dmode != dest_mode)
- {
- rtx temp = gen_reg_rtx (dest_mode);
- convert_move (temp, mask, 0);
- return temp;
- }
- return mask;
- }
- break;
- case GE:
- case GEU:
- case LE:
- case LEU:
- /* Try GT/GTU/LT/LTU OR EQ */
+ mask2 = rs6000_emit_vector_compare (rev_code, op0, op1, dmode);
+ if (!mask2)
+ return NULL_RTX;
+
+ mask = gen_reg_rtx (dmode);
+ emit_insn (GEN_FCN (nor_code) (mask, mask2));
+ return mask;
+ }
+ break;
+ case GE:
+ case GEU:
+ case LE:
+ case LEU:
+ /* Try GT/GTU/LT/LTU OR EQ */
+ {
+ rtx c_rtx, eq_rtx;
+ enum insn_code ior_code;
+ enum rtx_code new_code;
+
+ switch (rcode)
{
- rtx c_rtx, eq_rtx;
- enum insn_code ior_code;
- enum rtx_code new_code;
+ case GE:
+ new_code = GT;
+ break;
- switch (rcode)
- {
- case GE:
- new_code = GT;
- break;
+ case GEU:
+ new_code = GTU;
+ break;
- case GEU:
- new_code = GTU;
- break;
+ case LE:
+ new_code = LT;
+ break;
- case LE:
- new_code = LT;
- break;
+ case LEU:
+ new_code = LTU;
+ break;
- case LEU:
- new_code = LTU;
- break;
+ default:
+ gcc_unreachable ();
+ }
- default:
- gcc_unreachable ();
- }
+ ior_code = optab_handler (ior_optab, (int)dmode)->insn_code;
+ if (ior_code == CODE_FOR_nothing)
+ return NULL_RTX;
- c_rtx = rs6000_emit_vector_compare (new_code,
- op0, op1, dest_mode);
- eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
- dest_mode);
+ c_rtx = rs6000_emit_vector_compare (new_code, op0, op1, dmode);
+ if (!c_rtx)
+ return NULL_RTX;
- ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code;
- gcc_assert (ior_code != CODE_FOR_nothing);
- emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
- if (dmode != dest_mode)
- {
- rtx temp = gen_reg_rtx (dest_mode);
- convert_move (temp, mask, 0);
- return temp;
- }
- return mask;
- }
- break;
- default:
- gcc_unreachable ();
- }
+ eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1, dmode);
+ if (!eq_rtx)
+ return NULL_RTX;
- if (try_again)
- {
- vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
- /* You only get two chances. */
- gcc_assert (vec_cmp_insn != INSN_NOT_AVAILABLE);
- }
+ mask = gen_reg_rtx (dmode);
+ emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
+ return mask;
+ }
+ break;
+ default:
+ return NULL_RTX;
+ }
+ if (try_again)
+ {
if (swap_operands)
{
rtx tmp;
@@ -14414,91 +14985,84 @@ rs6000_emit_vector_compare (enum rtx_code rcode,
op0 = op1;
op1 = tmp;
}
- }
- emit_insn (gen_rtx_SET (VOIDmode, mask,
- gen_rtx_UNSPEC (dest_mode,
- gen_rtvec (2, op0, op1),
- vec_cmp_insn)));
- if (dmode != dest_mode)
- {
- rtx temp = gen_reg_rtx (dest_mode);
- convert_move (temp, mask, 0);
- return temp;
+ mask = rs6000_emit_vector_compare_inner (rcode, op0, op1);
+ if (mask)
+ return mask;
}
- return mask;
-}
-
-/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
- valid insn doesn exist for given mode. */
-static int
-get_vsel_insn (enum machine_mode mode)
-{
- switch (mode)
- {
- case V4SImode:
- return UNSPEC_VSEL4SI;
- break;
- case V4SFmode:
- return UNSPEC_VSEL4SF;
- break;
- case V8HImode:
- return UNSPEC_VSEL8HI;
- break;
- case V16QImode:
- return UNSPEC_VSEL16QI;
- break;
- default:
- return INSN_NOT_AVAILABLE;
- break;
- }
- return INSN_NOT_AVAILABLE;
+ /* You only get two chances. */
+ return NULL_RTX;
}
-/* Emit vector select insn where DEST is destination using
- operands OP1, OP2 and MASK. */
-
-static void
-rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
-{
- rtx t, temp;
- enum machine_mode dest_mode = GET_MODE (dest);
- int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
-
- temp = gen_reg_rtx (dest_mode);
-
- /* For each vector element, select op1 when mask is 1 otherwise
- select op2. */
- t = gen_rtx_SET (VOIDmode, temp,
- gen_rtx_UNSPEC (dest_mode,
- gen_rtvec (3, op2, op1, mask),
- vsel_insn_index));
- emit_insn (t);
- emit_move_insn (dest, temp);
- return;
-}
-
-/* Emit vector conditional expression.
- DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands.
- CC_OP0 and CC_OP1 are the two operands for the relation operation COND. */
+/* Emit vector conditional expression. DEST is destination. OP_TRUE and
+ OP_FALSE are two VEC_COND_EXPR operands. CC_OP0 and CC_OP1 are the two
+ operands for the relation operation COND. */
int
-rs6000_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
+rs6000_emit_vector_cond_expr (rtx dest, rtx op_true, rtx op_false,
rtx cond, rtx cc_op0, rtx cc_op1)
{
enum machine_mode dest_mode = GET_MODE (dest);
enum rtx_code rcode = GET_CODE (cond);
+ enum machine_mode cc_mode = CCmode;
rtx mask;
+ rtx cond2;
+ rtx tmp;
+ bool invert_move = false;
- if (!TARGET_ALTIVEC)
+ if (VECTOR_UNIT_NONE_P (dest_mode))
return 0;
+ switch (rcode)
+ {
+ /* Swap operands if we can, and fall back to doing the operation as
+ specified, and doing a NOR to invert the test. */
+ case NE:
+ case UNLE:
+ case UNLT:
+ case UNGE:
+ case UNGT:
+ /* Invert condition and try again.
+ e.g., A = (B != C) ? D : E becomes A = (B == C) ? E : D. */
+ invert_move = true;
+ rcode = reverse_condition_maybe_unordered (rcode);
+ if (rcode == UNKNOWN)
+ return 0;
+ break;
+
+ /* Mark unsigned tests with CCUNSmode. */
+ case GTU:
+ case GEU:
+ case LTU:
+ case LEU:
+ cc_mode = CCUNSmode;
+ break;
+
+ default:
+ break;
+ }
+
/* Get the vector mask for the given relational operations. */
mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
- rs6000_emit_vector_select (dest, op1, op2, mask);
+ if (!mask)
+ return 0;
+ if (invert_move)
+ {
+ tmp = op_true;
+ op_true = op_false;
+ op_false = tmp;
+ }
+
+ cond2 = gen_rtx_fmt_ee (NE, cc_mode, mask, const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode,
+ dest,
+ gen_rtx_IF_THEN_ELSE (dest_mode,
+ cond2,
+ op_true,
+ op_false)));
return 1;
}
@@ -14749,6 +15313,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
enum rtx_code c;
rtx target;
+ /* VSX/altivec have direct min/max insns. */
+ if ((code == SMAX || code == SMIN) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode,
+ dest,
+ gen_rtx_fmt_ee (code, mode, op0, op1)));
+ return;
+ }
+
if (code == SMAX || code == SMIN)
c = GE;
else
@@ -16414,6 +16987,19 @@ uses_TOC (void)
rtx
create_TOC_reference (rtx symbol)
{
+ if (TARGET_DEBUG_ADDR)
+ {
+ if (GET_CODE (symbol) == SYMBOL_REF)
+ fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n",
+ XSTR (symbol, 0));
+ else
+ {
+ fprintf (stderr, "\ncreate_TOC_reference, code %s:\n",
+ GET_RTX_NAME (GET_CODE (symbol)));
+ debug_rtx (symbol);
+ }
+ }
+
if (!can_create_pseudo_p ())
df_set_regs_ever_live (TOC_REGISTER, true);
return gen_rtx_PLUS (Pmode,
@@ -16722,6 +17308,7 @@ emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
/* Some cases that need register indexed addressing. */
if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_VSX && VSX_VECTOR_MODE (mode))
|| (TARGET_E500_DOUBLE && mode == DFmode)
|| (TARGET_SPE_ABI
&& SPE_VECTOR_MODE (mode)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 1c686c2bb17..3153243b30d 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1280,12 +1280,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.
-#define IRA_COVER_CLASSES \
+ 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, \
- /*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 \
+}
+
+#define IRA_COVER_CLASSES_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 \
}
@@ -1306,9 +1318,20 @@ extern enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) rs6000_regno_regclass[(REGNO)]
#endif
-/* Register classes for altivec registers (and eventually other vector
- units). */
-extern enum reg_class rs6000_vector_reg_class[];
+/* Register classes for various constraints that are based on the target
+ switches. */
+enum r6000_reg_class_enum {
+ RS6000_CONSTRAINT_d, /* fpr registers for double values */
+ RS6000_CONSTRAINT_f, /* fpr registers for single values */
+ RS6000_CONSTRAINT_v, /* Altivec registers */
+ RS6000_CONSTRAINT_wa, /* Any VSX register */
+ RS6000_CONSTRAINT_wd, /* VSX register for V2DF */
+ RS6000_CONSTRAINT_wf, /* VSX register for V4SF */
+ RS6000_CONSTRAINT_ws, /* VSX register for DF */
+ RS6000_CONSTRAINT_MAX
+};
+
+extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS GENERAL_REGS
@@ -2493,24 +2516,40 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_VMINSW,
ALTIVEC_BUILTIN_VMINFP,
ALTIVEC_BUILTIN_VMULEUB,
+ ALTIVEC_BUILTIN_VMULEUB_UNS,
ALTIVEC_BUILTIN_VMULESB,
ALTIVEC_BUILTIN_VMULEUH,
+ ALTIVEC_BUILTIN_VMULEUH_UNS,
ALTIVEC_BUILTIN_VMULESH,
ALTIVEC_BUILTIN_VMULOUB,
+ ALTIVEC_BUILTIN_VMULOUB_UNS,
ALTIVEC_BUILTIN_VMULOSB,
ALTIVEC_BUILTIN_VMULOUH,
+ ALTIVEC_BUILTIN_VMULOUH_UNS,
ALTIVEC_BUILTIN_VMULOSH,
ALTIVEC_BUILTIN_VNMSUBFP,
ALTIVEC_BUILTIN_VNOR,
ALTIVEC_BUILTIN_VOR,
+ ALTIVEC_BUILTIN_VSEL_2DF, /* needed for VSX */
+ ALTIVEC_BUILTIN_VSEL_2DI, /* needed for VSX */
ALTIVEC_BUILTIN_VSEL_4SI,
ALTIVEC_BUILTIN_VSEL_4SF,
ALTIVEC_BUILTIN_VSEL_8HI,
ALTIVEC_BUILTIN_VSEL_16QI,
+ ALTIVEC_BUILTIN_VSEL_2DI_UNS,
+ ALTIVEC_BUILTIN_VSEL_4SI_UNS,
+ ALTIVEC_BUILTIN_VSEL_8HI_UNS,
+ ALTIVEC_BUILTIN_VSEL_16QI_UNS,
+ ALTIVEC_BUILTIN_VPERM_2DF, /* needed for VSX */
+ ALTIVEC_BUILTIN_VPERM_2DI, /* needed for VSX */
ALTIVEC_BUILTIN_VPERM_4SI,
ALTIVEC_BUILTIN_VPERM_4SF,
ALTIVEC_BUILTIN_VPERM_8HI,
ALTIVEC_BUILTIN_VPERM_16QI,
+ ALTIVEC_BUILTIN_VPERM_2DI_UNS,
+ ALTIVEC_BUILTIN_VPERM_4SI_UNS,
+ ALTIVEC_BUILTIN_VPERM_8HI_UNS,
+ ALTIVEC_BUILTIN_VPERM_16QI_UNS,
ALTIVEC_BUILTIN_VPKUHUM,
ALTIVEC_BUILTIN_VPKUWUM,
ALTIVEC_BUILTIN_VPKPX,
@@ -3138,6 +3177,219 @@ enum rs6000_builtins
RS6000_BUILTIN_RSQRTF,
RS6000_BUILTIN_BSWAP_HI,
+ /* VSX builtins. */
+ VSX_BUILTIN_LXSDUX,
+ VSX_BUILTIN_LXSDX,
+ VSX_BUILTIN_LXVD2UX,
+ VSX_BUILTIN_LXVD2X,
+ VSX_BUILTIN_LXVDSX,
+ VSX_BUILTIN_LXVW4UX,
+ VSX_BUILTIN_LXVW4X,
+ VSX_BUILTIN_STXSDUX,
+ VSX_BUILTIN_STXSDX,
+ VSX_BUILTIN_STXVD2UX,
+ VSX_BUILTIN_STXVD2X,
+ VSX_BUILTIN_STXVW4UX,
+ VSX_BUILTIN_STXVW4X,
+ VSX_BUILTIN_XSABSDP,
+ VSX_BUILTIN_XSADDDP,
+ VSX_BUILTIN_XSCMPODP,
+ VSX_BUILTIN_XSCMPUDP,
+ VSX_BUILTIN_XSCPSGNDP,
+ VSX_BUILTIN_XSCVDPSP,
+ VSX_BUILTIN_XSCVDPSXDS,
+ VSX_BUILTIN_XSCVDPSXWS,
+ VSX_BUILTIN_XSCVDPUXDS,
+ VSX_BUILTIN_XSCVDPUXWS,
+ VSX_BUILTIN_XSCVSPDP,
+ VSX_BUILTIN_XSCVSXDDP,
+ VSX_BUILTIN_XSCVUXDDP,
+ VSX_BUILTIN_XSDIVDP,
+ VSX_BUILTIN_XSMADDADP,
+ VSX_BUILTIN_XSMADDMDP,
+ VSX_BUILTIN_XSMAXDP,
+ VSX_BUILTIN_XSMINDP,
+ VSX_BUILTIN_XSMOVDP,
+ VSX_BUILTIN_XSMSUBADP,
+ VSX_BUILTIN_XSMSUBMDP,
+ VSX_BUILTIN_XSMULDP,
+ VSX_BUILTIN_XSNABSDP,
+ VSX_BUILTIN_XSNEGDP,
+ VSX_BUILTIN_XSNMADDADP,
+ VSX_BUILTIN_XSNMADDMDP,
+ VSX_BUILTIN_XSNMSUBADP,
+ VSX_BUILTIN_XSNMSUBMDP,
+ VSX_BUILTIN_XSRDPI,
+ VSX_BUILTIN_XSRDPIC,
+ VSX_BUILTIN_XSRDPIM,
+ VSX_BUILTIN_XSRDPIP,
+ VSX_BUILTIN_XSRDPIZ,
+ VSX_BUILTIN_XSREDP,
+ VSX_BUILTIN_XSRSQRTEDP,
+ VSX_BUILTIN_XSSQRTDP,
+ VSX_BUILTIN_XSSUBDP,
+ VSX_BUILTIN_XSTDIVDP_FE,
+ VSX_BUILTIN_XSTDIVDP_FG,
+ VSX_BUILTIN_XSTSQRTDP_FE,
+ VSX_BUILTIN_XSTSQRTDP_FG,
+ VSX_BUILTIN_XVABSDP,
+ VSX_BUILTIN_XVABSSP,
+ VSX_BUILTIN_XVADDDP,
+ VSX_BUILTIN_XVADDSP,
+ VSX_BUILTIN_XVCMPEQDP,
+ VSX_BUILTIN_XVCMPEQSP,
+ VSX_BUILTIN_XVCMPGEDP,
+ VSX_BUILTIN_XVCMPGESP,
+ VSX_BUILTIN_XVCMPGTDP,
+ VSX_BUILTIN_XVCMPGTSP,
+ VSX_BUILTIN_XVCMPEQDP_P,
+ VSX_BUILTIN_XVCMPEQSP_P,
+ VSX_BUILTIN_XVCMPGEDP_P,
+ VSX_BUILTIN_XVCMPGESP_P,
+ VSX_BUILTIN_XVCMPGTDP_P,
+ VSX_BUILTIN_XVCMPGTSP_P,
+ VSX_BUILTIN_XVCPSGNDP,
+ VSX_BUILTIN_XVCPSGNSP,
+ VSX_BUILTIN_XVCVDPSP,
+ VSX_BUILTIN_XVCVDPSXDS,
+ VSX_BUILTIN_XVCVDPSXWS,
+ VSX_BUILTIN_XVCVDPUXDS,
+ VSX_BUILTIN_XVCVDPUXDS_UNS,
+ VSX_BUILTIN_XVCVDPUXWS,
+ VSX_BUILTIN_XVCVSPDP,
+ VSX_BUILTIN_XVCVSPSXDS,
+ VSX_BUILTIN_XVCVSPSXWS,
+ VSX_BUILTIN_XVCVSPUXDS,
+ VSX_BUILTIN_XVCVSPUXWS,
+ VSX_BUILTIN_XVCVSXDDP,
+ VSX_BUILTIN_XVCVSXDSP,
+ VSX_BUILTIN_XVCVSXWDP,
+ VSX_BUILTIN_XVCVSXWSP,
+ VSX_BUILTIN_XVCVUXDDP,
+ VSX_BUILTIN_XVCVUXDDP_UNS,
+ VSX_BUILTIN_XVCVUXDSP,
+ VSX_BUILTIN_XVCVUXWDP,
+ VSX_BUILTIN_XVCVUXWSP,
+ VSX_BUILTIN_XVDIVDP,
+ VSX_BUILTIN_XVDIVSP,
+ VSX_BUILTIN_XVMADDDP,
+ VSX_BUILTIN_XVMADDSP,
+ VSX_BUILTIN_XVMAXDP,
+ VSX_BUILTIN_XVMAXSP,
+ VSX_BUILTIN_XVMINDP,
+ VSX_BUILTIN_XVMINSP,
+ VSX_BUILTIN_XVMSUBDP,
+ VSX_BUILTIN_XVMSUBSP,
+ VSX_BUILTIN_XVMULDP,
+ VSX_BUILTIN_XVMULSP,
+ VSX_BUILTIN_XVNABSDP,
+ VSX_BUILTIN_XVNABSSP,
+ VSX_BUILTIN_XVNEGDP,
+ VSX_BUILTIN_XVNEGSP,
+ VSX_BUILTIN_XVNMADDDP,
+ VSX_BUILTIN_XVNMADDSP,
+ VSX_BUILTIN_XVNMSUBDP,
+ VSX_BUILTIN_XVNMSUBSP,
+ VSX_BUILTIN_XVRDPI,
+ VSX_BUILTIN_XVRDPIC,
+ VSX_BUILTIN_XVRDPIM,
+ VSX_BUILTIN_XVRDPIP,
+ VSX_BUILTIN_XVRDPIZ,
+ VSX_BUILTIN_XVREDP,
+ VSX_BUILTIN_XVRESP,
+ VSX_BUILTIN_XVRSPI,
+ VSX_BUILTIN_XVRSPIC,
+ VSX_BUILTIN_XVRSPIM,
+ VSX_BUILTIN_XVRSPIP,
+ VSX_BUILTIN_XVRSPIZ,
+ VSX_BUILTIN_XVRSQRTEDP,
+ VSX_BUILTIN_XVRSQRTESP,
+ VSX_BUILTIN_XVSQRTDP,
+ VSX_BUILTIN_XVSQRTSP,
+ VSX_BUILTIN_XVSUBDP,
+ VSX_BUILTIN_XVSUBSP,
+ VSX_BUILTIN_XVTDIVDP_FE,
+ VSX_BUILTIN_XVTDIVDP_FG,
+ VSX_BUILTIN_XVTDIVSP_FE,
+ VSX_BUILTIN_XVTDIVSP_FG,
+ VSX_BUILTIN_XVTSQRTDP_FE,
+ VSX_BUILTIN_XVTSQRTDP_FG,
+ VSX_BUILTIN_XVTSQRTSP_FE,
+ VSX_BUILTIN_XVTSQRTSP_FG,
+ 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_XXSEL_2DI_UNS,
+ VSX_BUILTIN_XXSEL_4SI_UNS,
+ VSX_BUILTIN_XXSEL_8HI_UNS,
+ VSX_BUILTIN_XXSEL_16QI_UNS,
+ 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_VPERM_2DI_UNS,
+ VSX_BUILTIN_VPERM_4SI_UNS,
+ VSX_BUILTIN_VPERM_8HI_UNS,
+ VSX_BUILTIN_VPERM_16QI_UNS,
+ VSX_BUILTIN_XXPERMDI_2DF,
+ VSX_BUILTIN_XXPERMDI_2DI,
+ VSX_BUILTIN_XXPERMDI_4SF,
+ VSX_BUILTIN_XXPERMDI_4SI,
+ VSX_BUILTIN_XXPERMDI_8HI,
+ VSX_BUILTIN_XXPERMDI_16QI,
+ 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_BUILTIN_VEC_INIT_V2DF,
+ VSX_BUILTIN_VEC_INIT_V2DI,
+ VSX_BUILTIN_VEC_SET_V2DF,
+ VSX_BUILTIN_VEC_SET_V2DI,
+ VSX_BUILTIN_VEC_EXT_V2DF,
+ VSX_BUILTIN_VEC_EXT_V2DI,
+
+ /* VSX overloaded builtins, add the overloaded functions not present in
+ Altivec. */
+ VSX_BUILTIN_VEC_MUL,
+ VSX_BUILTIN_OVERLOADED_FIRST = VSX_BUILTIN_VEC_MUL,
+ VSX_BUILTIN_VEC_MSUB,
+ VSX_BUILTIN_VEC_NMADD,
+ VSX_BUITLIN_VEC_NMSUB,
+ 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,
+ VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,
+ VECTOR_BUILTIN_FIX_V4SF_V4SI,
+ VECTOR_BUILTIN_FIXUNS_V4SF_V4SI,
+
+ /* Power7 builtins, that aren't VSX instructions. */
+ POWER7_BUILTIN_BPERMD,
+
RS6000_BUILTIN_COUNT
};
@@ -3151,6 +3403,8 @@ enum rs6000_builtin_type_index
RS6000_BTI_V16QI,
RS6000_BTI_V2SI,
RS6000_BTI_V2SF,
+ RS6000_BTI_V2DI,
+ RS6000_BTI_V2DF,
RS6000_BTI_V4HI,
RS6000_BTI_V4SI,
RS6000_BTI_V4SF,
@@ -3158,13 +3412,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 */
@@ -3174,7 +3431,10 @@ enum rs6000_builtin_type_index
RS6000_BTI_UINTHI, /* unsigned_intHI_type_node */
RS6000_BTI_INTSI, /* intSI_type_node */
RS6000_BTI_UINTSI, /* unsigned_intSI_type_node */
+ RS6000_BTI_INTDI, /* intDI_type_node */
+ RS6000_BTI_UINTDI, /* unsigned_intDI_type_node */
RS6000_BTI_float, /* float_type_node */
+ RS6000_BTI_double, /* double_type_node */
RS6000_BTI_void, /* void_type_node */
RS6000_BTI_MAX
};
@@ -3185,6 +3445,8 @@ enum rs6000_builtin_type_index
#define opaque_p_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI])
#define opaque_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V4SI])
#define V16QI_type_node (rs6000_builtin_types[RS6000_BTI_V16QI])
+#define V2DI_type_node (rs6000_builtin_types[RS6000_BTI_V2DI])
+#define V2DF_type_node (rs6000_builtin_types[RS6000_BTI_V2DF])
#define V2SI_type_node (rs6000_builtin_types[RS6000_BTI_V2SI])
#define V2SF_type_node (rs6000_builtin_types[RS6000_BTI_V2SF])
#define V4HI_type_node (rs6000_builtin_types[RS6000_BTI_V4HI])
@@ -3194,13 +3456,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])
@@ -3211,7 +3476,10 @@ enum rs6000_builtin_type_index
#define uintHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTHI])
#define intSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTSI])
#define uintSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTSI])
+#define intDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTDI])
+#define uintDI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTDI])
#define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
+#define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double])
#define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index a2fdc34342c..ae1ea99d0a3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -15322,6 +15322,7 @@
(include "sync.md")
+(include "vector.md")
(include "altivec.md")
(include "spe.md")
(include "dfp.md")
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 00bd1b0e7a0..ac61ffc582e 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -119,6 +119,38 @@ mvsx
Target Report Mask(VSX)
Use vector/scalar (VSX) instructions
+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)
+
+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-align-128
+Target Undocumented Report Var(TARGET_VSX_ALIGN_128)
+; If -mvsx, set alignment to 128 bits instead of 32/64
+
+mallow-movmisalign
+Target Undocumented Var(TARGET_ALLOW_MOVMISALIGN) Init(-1)
+; Allow/disallow the movmisalign in DF/DI vectors
+
+mallow-df-permute
+Target Undocumented Var(TARGET_ALLOW_DF_PERMUTE)
+; Allow/disallow permutation of DF/DI vectors
+
+msched-groups
+Target Undocumented Report Var(TARGET_SCHED_GROUPS) Init(-1)
+; Explicitly set/unset whether rs6000_sched_groups is set
+
+malways-hint
+Target Undocumented Report Var(TARGET_ALWAYS_HINT) Init(-1)
+; Explicitly set/unset whether rs6000_always_hint is set
+
+malign-branch-targets
+Target Undocumented Report Var(TARGET_ALIGN_BRANCH_TARGETS) Init(-1)
+; Explicitly set/unset whether rs6000_align_branch_targets is set
+
mupdate
Target Report Var(TARGET_UPDATE) Init(1)
Generate load/store with update instructions
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 695f5799f11..0b8e311078d 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -59,6 +59,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \
$(srcdir)/config/rs6000/constraints.md \
$(srcdir)/config/rs6000/darwin.md \
$(srcdir)/config/rs6000/sync.md \
+ $(srcdir)/config/rs6000/vector.md \
$(srcdir)/config/rs6000/altivec.md \
$(srcdir)/config/rs6000/spe.md \
$(srcdir)/config/rs6000/dfp.md \
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
new file mode 100644
index 00000000000..1546db7a74f
--- /dev/null
+++ b/gcc/config/rs6000/vector.md
@@ -0,0 +1,700 @@
+;; Expander definitions for vector support. No instructions are in this file,
+;; this file provides the generic vector expander, and the actual vector
+;; instructions will be in altivec.md.
+
+;; Copyright (C) 2009
+;; Free Software Foundation, Inc.
+;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Vector int modes
+(define_mode_iterator VEC_I [V16QI V8HI V4SI])
+
+;; Vector float modes
+(define_mode_iterator VEC_F [V4SF])
+
+;; Vector arithmetic modes
+(define_mode_iterator VEC_A [V16QI V8HI V4SI V4SF])
+
+;; Vector modes that need alginment via permutes
+(define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
+
+;; Vector logical modes
+(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
+
+;; Vector modes for moves. Don't do TImode here.
+(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
+
+;; Vector comparison modes
+(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
+
+;; 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])
+
+;; Base type from vector mode
+(define_mode_attr VEC_base [(V16QI "QI")
+ (V8HI "HI")
+ (V4SI "SI")
+ (V2DI "DI")
+ (V4SF "SF")
+ (V2DF "DF")
+ (TI "TI")])
+
+;; Same size integer type for floating point data
+(define_mode_attr VEC_int [(V4SF "v4si")
+ (V2DF "v2di")])
+
+(define_mode_attr VEC_INT [(V4SF "V4SI")
+ (V2DF "V2DI")])
+
+;; constants for unspec
+(define_constants
+ [(UNSPEC_PREDICATE 400)])
+
+
+;; Vector move instructions.
+(define_expand "mov<mode>"
+ [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
+ (match_operand:VEC_M 1 "any_operand" ""))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+{
+ if (can_create_pseudo_p ())
+ {
+ if (CONSTANT_P (operands[1])
+ && !easy_vector_constant (operands[1], <MODE>mode))
+ operands[1] = force_const_mem (<MODE>mode, operands[1]);
+
+ else if (!vlogical_operand (operands[0], <MODE>mode)
+ && !vlogical_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ }
+})
+
+;; Generic vector floating point load/store instructions.
+(define_expand "vector_load_<mode>"
+ [(set (match_operand:VEC_M 0 "vfloat_operand" "")
+ (match_operand:VEC_M 1 "memory_operand" ""))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_store_<mode>"
+ [(set (match_operand:VEC_M 0 "memory_operand" "")
+ (match_operand:VEC_M 1 "vfloat_operand" ""))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+;; Splits if a GPR register was chosen for the move
+(define_split
+ [(set (match_operand:VEC_L 0 "nonimmediate_operand" "")
+ (match_operand:VEC_L 1 "input_operand" ""))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)
+ && reload_completed
+ && gpr_or_gpr_p (operands[0], operands[1])"
+ [(pc)]
+{
+ rs6000_split_multireg_move (operands[0], operands[1]);
+ DONE;
+})
+
+
+;; Reload patterns for vector operations. We may need an addtional base
+;; register to convert the reg+offset addressing to reg+reg for vector
+;; registers and reg+reg or (reg+reg)&(-16) addressing to just an index
+;; register for gpr registers.
+(define_expand "reload_<VEC_R:mode>_<P:mptrsize>_store"
+ [(parallel [(match_operand:VEC_R 0 "memory_operand" "m")
+ (match_operand:VEC_R 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "register_operand" "=&b")])]
+ "<P:tptrsize>"
+{
+ rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true);
+ DONE;
+})
+
+(define_expand "reload_<VEC_R:mode>_<P:mptrsize>_load"
+ [(parallel [(match_operand:VEC_R 0 "gpc_reg_operand" "=&r")
+ (match_operand:VEC_R 1 "memory_operand" "m")
+ (match_operand:P 2 "register_operand" "=&b")])]
+ "<P:tptrsize>"
+{
+ rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false);
+ DONE;
+})
+
+;; Reload sometimes tries to move the address to a GPR, and can generate
+;; invalid RTL for addresses involving AND -16. Allow addresses involving
+;; reg+reg, reg+small constant, or just reg, all wrapped in an AND -16.
+
+(define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_cint_operand" "rI"))
+ (const_int -16)))]
+ "TARGET_ALTIVEC && (reload_in_progress || reload_completed)"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (plus:P (match_dup 1)
+ (match_dup 2)))
+ (parallel [(set (match_dup 0)
+ (and:P (match_dup 0)
+ (const_int -16)))
+ (clobber:CC (scratch:CC))])])
+
+;; The normal ANDSI3/ANDDI3 won't match if reload decides to move an AND -16
+;; address to a register because there is no clobber of a (scratch), so we add
+;; it here.
+(define_insn_and_split "*vec_reload_and_reg_<mptrsize>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (and:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (const_int -16)))]
+ "TARGET_ALTIVEC && (reload_in_progress || reload_completed)"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0)
+ (and:P (match_dup 1)
+ (const_int -16)))
+ (clobber:CC (scratch:CC))])])
+
+;; Generic floating point vector arithmetic support
+(define_expand "add<mode>3"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "sub<mode>3"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "mul<mode>3"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD"
+ "
+{
+ emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_expand "abs<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:VEC_F 0 "register_operand" "")
+ (smin:VEC_F (match_operand:VEC_F 1 "register_operand" "")
+ (match_operand:VEC_F 2 "register_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "smax<mode>3"
+ [(set (match_operand:VEC_F 0 "register_operand" "")
+ (smax:VEC_F (match_operand:VEC_F 1 "register_operand" "")
+ (match_operand:VEC_F 2 "register_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+
+(define_expand "ftrunc<mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+
+;; Vector comparisons
+(define_expand "vcond<mode>"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (if_then_else:VEC_F
+ (match_operator 3 "comparison_operator"
+ [(match_operand:VEC_F 4 "vfloat_operand" "")
+ (match_operand:VEC_F 5 "vfloat_operand" "")])
+ (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}")
+
+(define_expand "vcond<mode>"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (if_then_else:VEC_I
+ (match_operator 3 "comparison_operator"
+ [(match_operand:VEC_I 4 "vint_operand" "")
+ (match_operand:VEC_I 5 "vint_operand" "")])
+ (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}")
+
+(define_expand "vcondu<mode>"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (if_then_else:VEC_I
+ (match_operator 3 "comparison_operator"
+ [(match_operand:VEC_I 4 "vint_operand" "")
+ (match_operand:VEC_I 5 "vint_operand" "")])
+ (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}")
+
+(define_expand "vector_eq<mode>"
+ [(set (match_operand:VEC_C 0 "vlogical_operand" "")
+ (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
+ (match_operand:VEC_C 2 "vlogical_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_gt<mode>"
+ [(set (match_operand:VEC_C 0 "vlogical_operand" "")
+ (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
+ (match_operand:VEC_C 2 "vlogical_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_ge<mode>"
+ [(set (match_operand:VEC_C 0 "vlogical_operand" "")
+ (ge:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
+ (match_operand:VEC_C 2 "vlogical_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_gtu<mode>"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_geu<mode>"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
+;; which is in the reverse order that we want
+(define_expand "vector_select_<mode>"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (if_then_else:VEC_L
+ (ne:CC (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_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_select_<mode>_uns"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (if_then_else:VEC_L
+ (ne:CCUNS (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_P (<MODE>mode)"
+ "")
+
+;; Expansions that compare vectors producing a vector result and a predicate,
+;; setting CR6 to indicate a combined status
+(define_expand "vector_eq_<mode>_p"
+ [(parallel
+ [(set (reg:CC 74)
+ (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand" "")
+ (match_operand:VEC_A 2 "vlogical_operand" ""))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VEC_A 0 "vlogical_operand" "")
+ (eq:VEC_A (match_dup 1)
+ (match_dup 2)))])]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_gt_<mode>_p"
+ [(parallel
+ [(set (reg:CC 74)
+ (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand" "")
+ (match_operand:VEC_A 2 "vlogical_operand" ""))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VEC_A 0 "vlogical_operand" "")
+ (gt:VEC_A (match_dup 1)
+ (match_dup 2)))])]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_ge_<mode>_p"
+ [(parallel
+ [(set (reg:CC 74)
+ (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand" "")
+ (match_operand:VEC_F 2 "vfloat_operand" ""))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (ge:VEC_F (match_dup 1)
+ (match_dup 2)))])]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "vector_gtu_<mode>_p"
+ [(parallel
+ [(set (reg:CC 74)
+ (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" ""))]
+ UNSPEC_PREDICATE))
+ (set (match_operand:VEC_I 0 "vlogical_operand" "")
+ (gtu:VEC_I (match_dup 1)
+ (match_dup 2)))])]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "")
+
+;; AltiVec predicates.
+
+(define_expand "cr6_test_for_zero"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (reg:CC 74)
+ (const_int 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+(define_expand "cr6_test_for_zero_reverse"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (reg:CC 74)
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+(define_expand "cr6_test_for_lt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (reg:CC 74)
+ (const_int 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+(define_expand "cr6_test_for_lt_reverse"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (reg:CC 74)
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+
+;; Vector logical instructions
+(define_expand "xor<mode>3"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (xor:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
+ (match_operand:VEC_L 2 "vlogical_operand" "")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "ior<mode>3"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
+ (match_operand:VEC_L 2 "vlogical_operand" "")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "and<mode>3"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (and:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
+ (match_operand:VEC_L 2 "vlogical_operand" "")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "one_cmpl<mode>2"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "nor<mode>3"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (not:VEC_L (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
+ (match_operand:VEC_L 2 "vlogical_operand" ""))))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+(define_expand "andc<mode>3"
+ [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+ (and:VEC_L (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))
+ (match_operand:VEC_L 1 "vlogical_operand" "")))]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+ "")
+
+;; Same size conversions
+(define_expand "float<VEC_int><mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
+ DONE;
+}")
+
+(define_expand "unsigned_float<VEC_int><mode>2"
+ [(set (match_operand:VEC_F 0 "vfloat_operand" "")
+ (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
+ DONE;
+}")
+
+(define_expand "fix_trunc<mode><VEC_int>2"
+ [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
+ (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
+ DONE;
+}")
+
+(define_expand "fixuns_trunc<mode><VEC_int>2"
+ [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
+ (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
+ "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
+ "
+{
+ emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
+ DONE;
+}")
+
+
+;; Vector initialization, set, extract
+(define_expand "vec_init<mode>"
+ [(match_operand:VEC_E 0 "vlogical_operand" "")
+ (match_operand:VEC_E 1 "" "")]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+{
+ rs6000_expand_vector_init (operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_set<mode>"
+ [(match_operand:VEC_E 0 "vlogical_operand" "")
+ (match_operand:<VEC_base> 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+{
+ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extract<mode>"
+ [(match_operand:<VEC_base> 0 "register_operand" "")
+ (match_operand:VEC_E 1 "vlogical_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+{
+ rs6000_expand_vector_extract (operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+;; Interleave patterns
+(define_expand "vec_interleave_highv4sf"
+ [(set (match_operand:V4SF 0 "vfloat_operand" "")
+ (vec_merge:V4SF
+ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (const_int 5)))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "")
+
+(define_expand "vec_interleave_lowv4sf"
+ [(set (match_operand:V4SF 0 "vfloat_operand" "")
+ (vec_merge:V4SF
+ (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (const_int 5)))]
+ "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
+ "")
+
+
+;; Align vector loads with a permute.
+(define_expand "vec_realign_load_<mode>"
+ [(match_operand:VEC_K 0 "vlogical_operand" "")
+ (match_operand:VEC_K 1 "vlogical_operand" "")
+ (match_operand:VEC_K 2 "vlogical_operand" "")
+ (match_operand:V16QI 3 "vlogical_operand" "")]
+ "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+{
+ emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+})
+
+
+;; Vector shift left in bits. Currently supported ony for shift
+;; amounts that can be expressed as byte shifts (divisible by 8).
+;; General shift amounts can be supported using vslo + vsl. We're
+;; not expecting to see these yet (the vectorizer currently
+;; generates only shifts divisible by byte_size).
+(define_expand "vec_shl_<mode>"
+ [(match_operand:VEC_L 0 "vlogical_operand" "")
+ (match_operand:VEC_L 1 "vlogical_operand" "")
+ (match_operand:QI 2 "reg_or_short_operand" "")]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx bitshift = operands[2];
+ rtx shift;
+ rtx insn;
+ HOST_WIDE_INT bitshift_val;
+ HOST_WIDE_INT byteshift_val;
+
+ if (! CONSTANT_P (bitshift))
+ FAIL;
+ bitshift_val = INTVAL (bitshift);
+ if (bitshift_val & 0x7)
+ FAIL;
+ byteshift_val = bitshift_val >> 3;
+ shift = gen_rtx_CONST_INT (QImode, byteshift_val);
+ insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
+ shift);
+
+ emit_insn (insn);
+ DONE;
+}")
+
+;; Vector shift right in bits. Currently supported ony for shift
+;; amounts that can be expressed as byte shifts (divisible by 8).
+;; General shift amounts can be supported using vsro + vsr. We're
+;; not expecting to see these yet (the vectorizer currently
+;; generates only shifts divisible by byte_size).
+(define_expand "vec_shr_<mode>"
+ [(match_operand:VEC_L 0 "vlogical_operand" "")
+ (match_operand:VEC_L 1 "vlogical_operand" "")
+ (match_operand:QI 2 "reg_or_short_operand" "")]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx bitshift = operands[2];
+ rtx shift;
+ rtx insn;
+ HOST_WIDE_INT bitshift_val;
+ HOST_WIDE_INT byteshift_val;
+
+ if (! CONSTANT_P (bitshift))
+ FAIL;
+ bitshift_val = INTVAL (bitshift);
+ if (bitshift_val & 0x7)
+ FAIL;
+ byteshift_val = 16 - (bitshift_val >> 3);
+ shift = gen_rtx_CONST_INT (QImode, byteshift_val);
+ insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
+ shift);
+
+ emit_insn (insn);
+ DONE;
+}")
+
+;; Expanders for rotate each element in a vector
+(define_expand "vrotl<mode>3"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "TARGET_ALTIVEC"
+ "")
+
+;; Expanders for arithmetic shift left on each vector element
+(define_expand "vashl<mode>3"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "TARGET_ALTIVEC"
+ "")
+
+;; Expanders for logical shift right on each vector element
+(define_expand "vlshr<mode>3"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "TARGET_ALTIVEC"
+ "")
+
+;; Expanders for arithmetic shift right on each vector element
+(define_expand "vashr<mode>3"
+ [(set (match_operand:VEC_I 0 "vint_operand" "")
+ (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
+ (match_operand:VEC_I 2 "vint_operand" "")))]
+ "TARGET_ALTIVEC"
+ "")