patch: optimized constant vector initializers
Aldy Hernandez
aldyh@redhat.com
Mon Mar 31 21:44:00 GMT 2003
When Stan and I worked on the vector initializer code, we ended up
treating vector initializers like we currently treat constructors,
which is inefficient for constants. For example, for:
vecfoo = (vecfoo_type) {1, 1, 1, 1};
...we dump to memory, then load into vecfoo. Most SIMD architectures
provide either instructions or combination of instructions to load
constants. In AltiVec, for example, there are instruction combos for
loading anything from -255 to +255 (provided all elements are the
same). Obviously, there is a fine line between "neat trick" and code
bloat.
The patch below leaves vector constants as constants, instead of
treating them like constructors. So things like {1, 2} get generated
as:
(const_vector:V2SI [
(const_int 1 [0x1])
(const_int 2 [0x2])
whereas {1, foo()} will be treated as a constructor.
I have also provided code for PowerPC SIMD variants using this new
feature. Other back-end maintainers should do something similar for
easily synthesized constants in their architectures.
I have been careful not to overdo it in the AltiVec arena, and only
recognize constants that *I* consider useful and are not too
complicated to generate.
Surprisingly, the generic parts of the patch are quite small.
Are the generic parts OK for mainline?
2003-02-31 Aldy Hernandez <aldyh@redhat.com>
* testsuite/gcc.c-torture/execute/simd-3.c: New.
* expr.h (is_zeros_p): New prototype.
* expr.c (expand_expr): Handle VECTOR_CST.
(is_zeros_p): Un constify.
(const_vector_from_tree): New.
* varasm.c (output_constant): Handle VECTOR_CST.
* c-typeck.c (digest_init): Build a vector constant from a
VECTOR_TYPE.
* config/rs6000/rs6000.c: Remove prototype for
easy_vector_constant.
(easy_vector_constant): Add mode parameter. Rewrite to handle
more easy constants.
(rs6000_emit_move): Pass mode to easy_vector_constant.
Call emit_easy_vector_insn for SPE V2SI vector constant moves.
(emit_easy_vector_insn): New.
(easy_vector_same): New.
(EASY_VECTOR_15): New macro.
(EASY_VECTOR_15_ADD_SELF): New macro.
(bdesc_2arg): Rename to xorv2si3.
(easy_vector_constant_add_self): New.
(input_operand): Allow vector constants.
* config/rs6000/rs6000.h (PREDICATE_CODES): Add
easy_vector_constant, easy_vector_constant_add_self.
(EXTRA_CONSTRAINT): Add 'W'.
* config/rs6000/rs6000-protos.h: Add prototype for
easy_vector_constant, emit_easy_vector_insn.
* config/rs6000/altivec.md (xorv8hi3): New.
(xorv16qi3): New.
Remove all _const0 patterns.
(movv4si_internal): Rewrite to use code. Add vector constant to
vector alternative. Add splitter.
(movv8hi_internal): Same.
(movv16qi_internal): Same.
(movv4sf_internal): Same.
Change the unspecs for vspltis* to use constants.
* config/rs6000/spe.md ("xorv4hi3"): New.
("spe_evxor"): Rename to xorv2si3.
("xorv1di3"): New.
Remove all _const0 patterns.
(movv2si_internal): Rewrite to use code. Add vector constant to
alternatives. Add splitter.
(movv4hi_internal): Add vector constant to alternatives.
(movv1di_internal): Same.
(movv2sf_internal): Same.
Index: testsuite/gcc.c-torture/execute/simd-3.c
===================================================================
RCS file: testsuite/gcc.c-torture/execute/simd-3.c
diff -N testsuite/gcc.c-torture/execute/simd-3.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.c-torture/execute/simd-3.c 31 Mar 2003 21:26:26 -0000
***************
*** 0 ****
--- 1,34 ----
+ typedef int __attribute__((mode(V4SI))) vecint;
+ typedef int __attribute__((mode(SI))) siint;
+
+ vecint i, j, k;
+
+ union {
+ vecint v;
+ siint i[4];
+ } res;
+
+ /* This should go away once we can use == and != on vector types. */
+ void
+ verify (siint a1, siint a2, siint a3, siint a4,
+ siint b1, siint b2, siint b3, siint b4)
+ {
+ if (a1 != b1
+ || a2 != b2
+ || a3 != b3
+ || a4 != b4)
+ abort ();
+ }
+
+ int
+ main ()
+ {
+ i = (vecint) { 5, 5, 5, 5 };
+ j = (vecint) { 10, 10, 10, 10 };
+ k = i + j;
+ res.v = k;
+
+ verify (res.i[0], res.i[1], res.i[2], res.i[3], 15, 15, 15, 15);
+
+ exit (0);
+ }
Index: expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.131
diff -c -p -r1.131 expr.h
*** expr.h 13 Mar 2003 16:05:23 -0000 1.131
--- expr.h 31 Mar 2003 21:26:26 -0000
*************** extern rtx expand_assignment PARAMS ((tr
*** 474,479 ****
--- 474,481 ----
extern rtx store_expr PARAMS ((tree, rtx, int));
#endif
+ extern int is_zeros_p PARAMS ((tree));
+
/* Given an rtx that may include add and multiply operations,
generate them as insns and return a pseudo-reg containing the
value.
Useful after calling expand_expr with 1 as sum_ok. */
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.516
diff -c -p -r1.516 expr.c
*** expr.c 24 Mar 2003 08:31:29 -0000 1.516
--- expr.c 31 Mar 2003 21:26:30 -0000
*************** static rtx clear_storage_via_libcall PAR
*** 155,161 ****
static tree clear_storage_libcall_fn PARAMS ((int));
static rtx compress_float_constant PARAMS ((rtx, rtx));
static rtx get_subtarget PARAMS ((rtx));
- static int is_zeros_p PARAMS ((tree));
static int mostly_zeros_p PARAMS ((tree));
static void store_constructor_field PARAMS ((rtx, unsigned
HOST_WIDE_INT,
HOST_WIDE_INT, enum machine_mode,
--- 155,160 ----
*************** static rtx do_store_flag PARAMS ((tree,
*** 175,180 ****
--- 174,180 ----
static void emit_single_push_insn PARAMS ((enum machine_mode, rtx,
tree));
#endif
static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx,
rtx));
+ static rtx const_vector_from_tree PARAMS ((tree));
/* Record for each mode whether we can move a register directly to or
from an object of that mode in memory. If we can't, we won't try
*************** store_expr (exp, target, want_value)
*** 4702,4708 ****
/* Return 1 if EXP just contains zeros. */
! static int
is_zeros_p (exp)
tree exp;
{
--- 4702,4708 ----
/* Return 1 if EXP just contains zeros. */
! int
is_zeros_p (exp)
tree exp;
{
*************** expand_expr (exp, target, tmode, modifie
*** 6842,6847 ****
--- 6842,6850 ----
return temp;
+ case VECTOR_CST:
+ return const_vector_from_tree (exp);
+
case CONST_DECL:
return expand_expr (DECL_INITIAL (exp), target, VOIDmode,
modifier);
*************** vector_mode_valid_p (mode)
*** 10327,10332 ****
--- 10330,10372 ----
/* If we have support for the inner mode, we can safely emulate it.
We may not have V2DI, but me can emulate with a pair of DIs. */
return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
+ }
+
+ /* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
+ static rtx
+ const_vector_from_tree (exp)
+ tree exp;
+ {
+ rtvec v;
+ int units, i;
+ tree link, elt;
+ enum machine_mode inner, mode;
+
+ mode = TYPE_MODE (TREE_TYPE (exp));
+
+ if (is_zeros_p (exp))
+ return CONST0_RTX (mode);
+
+ units = GET_MODE_NUNITS (mode);
+ inner = GET_MODE_INNER (mode);
+
+ v = rtvec_alloc (units);
+
+ link = TREE_VECTOR_CST_ELTS (exp);
+ for (i = 0; link; link = TREE_CHAIN (link), ++i)
+ {
+ elt = TREE_VALUE (link);
+
+ if (TREE_CODE (elt) == REAL_CST)
+ RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
+ inner);
+ else
+ RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
+ TREE_INT_CST_HIGH (elt),
+ inner);
+ }
+
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
}
#include "gt-expr.h"
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.335
diff -c -p -r1.335 varasm.c
*** varasm.c 15 Mar 2003 16:30:35 -0000 1.335
--- varasm.c 31 Mar 2003 21:26:31 -0000
*************** output_constant (exp, size, align)
*** 4015,4020 ****
--- 4015,4031 ----
thissize = MIN (TREE_STRING_LENGTH (exp), size);
assemble_string (TREE_STRING_POINTER (exp), thissize);
}
+ else if (TREE_CODE (exp) == VECTOR_CST)
+ {
+ int elt_size;
+ tree link;
+
+ elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
+
+ link = TREE_VECTOR_CST_ELTS (exp);
+ for (; link; link = TREE_CHAIN (link))
+ output_constant (TREE_VALUE (link), elt_size, align);
+ }
else
abort ();
break;
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.227
diff -c -p -r1.227 c-typeck.c
*** c-typeck.c 24 Mar 2003 08:31:28 -0000 1.227
--- c-typeck.c 31 Mar 2003 21:26:33 -0000
*************** digest_init (type, init, require_constan
*** 4759,4764 ****
--- 4759,4772 ----
}
}
+ /* Build a VECTOR_CST from a *constant* vector constructor. If the
+ vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
+ below and handle as a constructor. */
+ if (code == VECTOR_TYPE
+ && comptypes (TREE_TYPE (inside_init), type)
+ && TREE_CONSTANT (inside_init))
+ return build_vector (type, TREE_OPERAND (inside_init, 1));
+
/* Any type can be initialized
from an expression of the same type, optionally with braces. */
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.446
diff -c -p -r1.446 rs6000.c
*** config/rs6000/rs6000.c 31 Mar 2003 17:46:57 -0000 1.446
--- config/rs6000/rs6000.c 31 Mar 2003 21:26:37 -0000
*************** Boston, MA 02111-1307, USA. */
*** 55,60 ****
--- 55,67 ----
#define TARGET_NO_PROTOTYPE 0
#endif
+ #define EASY_VECTOR_15(n, x, y) ((n) >= -16 && (n) <= 15 \
+ && easy_vector_same (x, y))
+
+ #define EASY_VECTOR_15_ADD_SELF(n, x, y) ((n) >= 0x10 && (n) <= 0x1e \
+ && !((n) & 1) \
+ && easy_vector_same (x, y))
+
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
*************** static int first_altivec_reg_to_save PAR
*** 266,272 ****
static unsigned int compute_vrsave_mask PARAMS ((void));
static void is_altivec_return_reg PARAMS ((rtx, void *));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
! static int easy_vector_constant PARAMS ((rtx));
static bool is_ev64_opaque_type PARAMS ((tree));
static rtx rs6000_dwarf_register_span PARAMS ((rtx));
--- 273,280 ----
static unsigned int compute_vrsave_mask PARAMS ((void));
static void is_altivec_return_reg PARAMS ((rtx, void *));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
! int easy_vector_constant PARAMS ((rtx, enum machine_mode));
! static int easy_vector_same PARAMS ((rtx, enum machine_mode));
static bool is_ev64_opaque_type PARAMS ((tree));
static rtx rs6000_dwarf_register_span PARAMS ((rtx));
*************** easy_fp_constant (op, mode)
*** 1416,1463 ****
abort ();
}
! /* Return 1 if the operand is a CONST_INT and can be put into a
! register with one instruction. */
static int
! easy_vector_constant (op)
rtx op;
{
! rtx elt;
! int units, i;
! if (GET_CODE (op) != CONST_VECTOR)
return 0;
! units = CONST_VECTOR_NUNITS (op);
! /* We can generate 0 easily. Look for that. */
! for (i = 0; i < units; ++i)
! {
! elt = CONST_VECTOR_ELT (op, i);
! /* We could probably simplify this by just checking for equality
! with CONST0_RTX for the current mode, but let's be safe
! instead. */
! switch (GET_CODE (elt))
{
! case CONST_INT:
! if (INTVAL (elt) != 0)
! return 0;
! break;
! case CONST_DOUBLE:
! if (CONST_DOUBLE_LOW (elt) != 0 || CONST_DOUBLE_HIGH (elt) != 0)
! return 0;
! break;
! default:
! return 0;
}
}
! /* We could probably generate a few other constants trivially, but
! gcc doesn't generate them yet. FIXME later. */
! return 1;
}
/* Return 1 if the operand is the constant 0. This works for scalars
--- 1424,1572 ----
abort ();
}
! /* Return non zero if all elements of a vector have the same value.
*/
static int
! easy_vector_same (op, mode)
! rtx op;
! enum machine_mode mode ATTRIBUTE_UNUSED;
! {
! int units, i, cst;
!
! units = CONST_VECTOR_NUNITS (op);
!
! cst = INTVAL (CONST_VECTOR_ELT (op, 0));
! for (i = 1; i < units; ++i)
! if (INTVAL (CONST_VECTOR_ELT (op, i)) != cst)
! break;
! if (i == units)
! return 1;
! return 0;
! }
!
! /* Return 1 if the operand is a CONST_INT and can be put into a
! register without using memory. */
!
! int
! easy_vector_constant (op, mode)
rtx op;
+ enum machine_mode mode;
{
! int cst, cst2;
! if (GET_CODE (op) != CONST_VECTOR
! || (!TARGET_ALTIVEC
! && !TARGET_SPE))
return 0;
! if (zero_constant (op, mode)
! && ((TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
! || (TARGET_SPE && SPE_VECTOR_MODE (mode))))
! return 1;
! if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
! return 0;
!
! cst = INTVAL (CONST_VECTOR_ELT (op, 0));
! cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
!
! /* Limit SPE vectors to 15 bits signed. These we can generate with:
! li r0, CONSTANT1
! evmergelo r0, r0, r0
! li r0, CONSTANT2
! I don't know how efficient it would be to allow bigger constants,
! considering we'll have an extra 'ori' for every 'li'. I doubt 5
! instructions is better than a 64-bit memory load, but I don't
! have the e500 timing specs. */
! if (TARGET_SPE && mode == V2SImode
! && cst >= -0x7fff && cst <= 0x7fff
! && cst2 >= -0x7fff && cst <= 0x7fff)
! return 1;
!
! if (TARGET_ALTIVEC && EASY_VECTOR_15 (cst, op, mode))
! return 1;
!
! if (TARGET_ALTIVEC && EASY_VECTOR_15_ADD_SELF (cst, op, mode))
! return 1;
!
! return 0;
! }
! /* Same as easy_vector_constant but only for EASY_VECTOR_15_ADD_SELF.
*/
!
! int
! easy_vector_constant_add_self (op, mode)
! rtx op;
! enum machine_mode mode;
! {
! int cst;
!
! if (!easy_vector_constant (op, mode))
! return 0;
!
! cst = INTVAL (CONST_VECTOR_ELT (op, 0));
!
! return TARGET_ALTIVEC && EASY_VECTOR_15_ADD_SELF (cst, op, mode);
! }
!
! char *
! output_vec_const_move (operands)
! rtx *operands;
! {
! int cst, cst2;
! enum machine_mode mode;
! rtx dest, vec;
!
! dest = operands[0];
! vec = operands[1];
!
! cst = INTVAL (CONST_VECTOR_ELT (vec, 0));
! cst2 = INTVAL (CONST_VECTOR_ELT (vec, 1));
! mode = GET_MODE (dest);
!
! if (TARGET_ALTIVEC)
! {
! if (zero_constant (vec, mode))
! return "vxor %0,%0,%0";
! else if (EASY_VECTOR_15 (cst, vec, mode))
{
! operands[1] = GEN_INT (cst);
! switch (mode)
! {
! case V4SImode:
! return "vspltisw %0,%1";
! case V8HImode:
! return "vspltish %0,%1";
! case V16QImode:
! return "vspltisb %0,%1";
! default:
! abort ();
! }
}
+ else if (EASY_VECTOR_15_ADD_SELF (cst, vec, mode))
+ return "#";
+ else
+ abort ();
}
! if (TARGET_SPE)
! {
! /* Vector constant 0 is handled as a splitter of V2SI, and in
the
! pattern of V1DI, V4HI, and V2SF.
!
! FIXME: We should probabl return # and add post reload
! splitters for these, but this way is so easy ;-).
! */
! operands[1] = GEN_INT (cst);
! operands[2] = GEN_INT (cst2);
! if (cst == cst2)
! return "li %0,%1\n\tevmergelo %0,%0,%0";
! else
! return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
! }
!
! abort ();
}
/* Return 1 if the operand is the constant 0. This works for scalars
*************** input_operand (op, mode)
*** 1990,1995 ****
--- 2099,2109 ----
|| GET_CODE (op) == CONST_DOUBLE))
return 1;
+ /* Allow easy vector constants. */
+ if (GET_CODE (op) == CONST_VECTOR
+ && easy_vector_constant (op, mode))
+ return 1;
+
/* For floating-point or multi-word mode, the only remaining valid
type
is a register. */
if (GET_MODE_CLASS (mode) == MODE_FLOAT
*************** rs6000_emit_move (dest, source, mode)
*** 2744,2750 ****
case V2SImode:
case V1DImode:
if (CONSTANT_P (operands[1])
! && !easy_vector_constant (operands[1]))
operands[1] = force_const_mem (mode, operands[1]);
break;
--- 2858,2864 ----
case V2SImode:
case V1DImode:
if (CONSTANT_P (operands[1])
! && !easy_vector_constant (operands[1], mode))
operands[1] = force_const_mem (mode, operands[1]);
break;
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.260
diff -c -p -r1.260 rs6000.h
*** config/rs6000/rs6000.h 31 Mar 2003 17:46:55 -0000 1.260
--- config/rs6000/rs6000.h 31 Mar 2003 21:26:38 -0000
*************** enum reg_class
*** 1292,1297 ****
--- 1292,1298 ----
'S' is a constant that can be placed into a 64-bit mask operand
'T' is a constant that can be placed into a 32-bit mask operand
'U' is for V.4 small data references.
+ 'W' is a vector constant that can be easily generated (no mem
refs).
't' is for AND masks that can be performed by two rldic{l,r}
insns. */
#define EXTRA_CONSTRAINT(OP, C) \
*************** enum reg_class
*** 1305,1310 ****
--- 1306,1312 ----
&& (fixed_regs[CR0_REGNO] \
|| !logical_operand (OP, DImode)) \
&& !mask64_operand (OP, DImode)) \
+ : (C) == 'W' ? (easy_vector_constant (OP, GET_MODE (OP))) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
*************** extern char rs6000_reg_names[][8]; /* re
*** 2740,2745 ****
--- 2742,2749 ----
{"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
{"easy_fp_constant", {CONST_DOUBLE}}, \
+ {"easy_vector_constant", {CONST_VECTOR}}, \
+ {"easy_vector_constant_add_self", {CONST_VECTOR}}, \
{"zero_fp_constant", {CONST_DOUBLE}}, \
{"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"lwa_operand", {SUBREG, MEM, REG}}, \
Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.49
diff -c -p -r1.49 rs6000-protos.h
*** config/rs6000/rs6000-protos.h 28 Jan 2003 23:26:28 -0000 1.49
--- config/rs6000/rs6000-protos.h 31 Mar 2003 21:26:38 -0000
*************** extern int got_operand PARAMS ((rtx, enu
*** 54,59 ****
--- 54,61 ----
extern int got_no_const_operand PARAMS ((rtx, enum machine_mode));
extern int num_insns_constant PARAMS ((rtx, enum machine_mode));
extern int easy_fp_constant PARAMS ((rtx, enum machine_mode));
+ extern int easy_vector_constant PARAMS ((rtx, enum machine_mode));
+ extern char *output_vec_const_move PARAMS ((rtx *));
extern int zero_fp_constant PARAMS ((rtx, enum machine_mode));
extern int zero_constant PARAMS ((rtx, enum machine_mode));
extern int volatile_mem_operand PARAMS ((rtx, enum machine_mode));
Index: config/rs6000/altivec.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/altivec.md,v
retrieving revision 1.5
diff -c -p -r1.5 altivec.md
*** config/rs6000/altivec.md 7 Jan 2003 02:54:13 -0000 1.5
--- config/rs6000/altivec.md 31 Mar 2003 21:26:38 -0000
***************
*** 19,24 ****
--- 19,30 ----
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
+ (define_constants
+ [(UNSPEC_VSPLTISW 141)
+ (UNSPEC_VSPLTISH 140)
+ (UNSPEC_VSPLTISB 139)
+ ])
+
;; Generic LVX load instruction.
(define_insn "altivec_lvx_4si"
[(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
***************
*** 85,102 ****
"{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
(define_insn "*movv4si_internal"
! [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
! (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r"))]
"TARGET_ALTIVEC"
! "@
! stvx %1,%y0
! lvx %0,%y1
! vor %0,%1,%1
! stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
! lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
! mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
! (set_attr "length" "*,*,*,16,16,16")])
(define_expand "movv8hi"
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
--- 91,127 ----
"{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
(define_insn "*movv4si_internal"
! [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
! (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r,W"))]
"TARGET_ALTIVEC"
! "*
! {
! 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 \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw
%Z1,%Z0\";
! case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz
%Z0,%Z1\";
! case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
! case 6: return output_vec_const_move (operands);
! default: abort();
! }
! }"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
! (set_attr "length" "*,*,*,16,16,16,*")])
!
! (define_split
! [(set (match_operand:V4SI 0 "altivec_register_operand" "")
! (match_operand:V4SI 1 "easy_vector_constant_add_self" ""))]
! "TARGET_ALTIVEC && reload_completed"
! [(set (match_dup 0)
! (unspec:V4SI [(match_dup 3)] UNSPEC_VSPLTISW))
! (set (match_dup 0)
! (plus:V4SI (match_dup 0)
! (match_dup 0)))]
! "
! { operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0))
>> 1); }")
(define_expand "movv8hi"
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
***************
*** 105,122 ****
"{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
(define_insn "*movv8hi_internal1"
! [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
! (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r"))]
"TARGET_ALTIVEC"
! "@
! stvx %1,%y0
! lvx %0,%y1
! vor %0,%1,%1
! stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
! lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
! mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
! (set_attr "length" "*,*,*,16,16,16")])
(define_expand "movv16qi"
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
--- 130,166 ----
"{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
(define_insn "*movv8hi_internal1"
! [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
! (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r,W"))]
"TARGET_ALTIVEC"
! "*
! {
! 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 \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw
%Z1,%Z0\";
! case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz
%Z0,%Z1\";
! case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
! case 6: return output_vec_const_move (operands);
! default: abort ();
! }
! }"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
! (set_attr "length" "*,*,*,16,16,16,*")])
!
! (define_split
! [(set (match_operand:V8HI 0 "altivec_register_operand" "")
! (match_operand:V8HI 1 "easy_vector_constant_add_self" ""))]
! "TARGET_ALTIVEC && reload_completed"
! [(set (match_dup 0)
! (unspec:V8HI [(match_dup 3)] UNSPEC_VSPLTISH))
! (set (match_dup 0)
! (plus:V8HI (match_dup 0)
! (match_dup 0)))]
! "
! { operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0))
>> 1); }")
(define_expand "movv16qi"
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
***************
*** 125,142 ****
"{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
(define_insn "*movv16qi_internal1"
! [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
! (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r"))]
"TARGET_ALTIVEC"
! "@
! stvx %1,%y0
! lvx %0,%y1
! vor %0,%1,%1
! stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
! lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
! mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
! (set_attr "length" "*,*,*,16,16,16")])
(define_expand "movv4sf"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
--- 169,205 ----
"{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
(define_insn "*movv16qi_internal1"
! [(set (match_operand:V16QI 0 "nonimmediate_operand"
"=m,v,v,o,r,r,v")
! (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r,W"))]
"TARGET_ALTIVEC"
! "*
! {
! 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 \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw
%Z1,%Z0\";
! case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz
%Z0,%Z1\";
! case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
! case 6: return output_vec_const_move (operands);
! default: abort ();
! }
! }"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
! (set_attr "length" "*,*,*,16,16,16,*")])
!
! (define_split
! [(set (match_operand:V16QI 0 "altivec_register_operand" "")
! (match_operand:V16QI 1 "easy_vector_constant_add_self" ""))]
! "TARGET_ALTIVEC && reload_completed"
! [(set (match_dup 0)
! (unspec:V16QI [(match_dup 3)] UNSPEC_VSPLTISB))
! (set (match_dup 0)
! (plus:V16QI (match_dup 0)
! (match_dup 0)))]
! "
! { operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0))
>> 1); }")
(define_expand "movv4sf"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
***************
*** 145,162 ****
"{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
(define_insn "*movv4sf_internal1"
! [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r")
! (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r"))]
"TARGET_ALTIVEC"
! "@
! stvx %1,%y0
! lvx %0,%y1
! vor %0,%1,%1
! stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
! lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
! mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
! (set_attr "length" "*,*,*,16,16,16")])
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
--- 208,232 ----
"{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
(define_insn "*movv4sf_internal1"
! [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
! (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r,W"))]
"TARGET_ALTIVEC"
! "*
! {
! 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 \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw
%Z1,%Z0\";
! case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz
%Z0,%Z1\";
! case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
! case 6: return output_vec_const_move (operands);
! default: abort ();
! }
! }"
! [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
! (set_attr "length" "*,*,*,16,16,16,*")])
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
***************
*** 186,221 ****
}"
[(set_attr "type" "*")])
- ;; Vector clears
- (define_insn "*movv4si_const0"
- [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
- (match_operand:V4SI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
- (define_insn "*movv4sf_const0"
- [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
- (match_operand:V4SF 1 "zero_constant" ""))]
-
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
- (define_insn "*movv8hi_const0"
- [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
- (match_operand:V8HI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
- (define_insn "*movv16qi_const0"
- [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
- (match_operand:V16QI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
;; Simple binary operations.
(define_insn "addv16qi3"
--- 256,261 ----
***************
*** 1279,1284 ****
--- 1319,1325 ----
"vsumsws %0,%1,%2"
[(set_attr "type" "veccomplex")])
+ ;; Vector xor's
(define_insn "xorv4si3"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(xor:V4SI (match_operand:V4SI 1 "register_operand" "v")
***************
*** 1287,1292 ****
--- 1328,1349 ----
"vxor %0,%1,%2"
[(set_attr "type" "vecsimple")])
+ (define_insn "xorv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (xor:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+ (define_insn "xorv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (xor:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
(define_insn "altivec_vspltb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
***************
*** 1294,1299 ****
--- 1351,1357 ----
"TARGET_ALTIVEC"
"vspltb %0,%1,%2"
[(set_attr "type" "vecperm")])
+ ;; End of vector xor's
(define_insn "altivec_vsplth"
[(set (match_operand:V8HI 0 "register_operand" "=v")
***************
*** 1313,1333 ****
(define_insn "altivec_vspltisb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
! (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")]
139))]
"TARGET_ALTIVEC"
"vspltisb %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltish"
[(set (match_operand:V8HI 0 "register_operand" "=v")
! (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")]
140))]
"TARGET_ALTIVEC"
"vspltish %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltisw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
! (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")]
141))]
"TARGET_ALTIVEC"
"vspltisw %0,%1"
[(set_attr "type" "vecperm")])
--- 1371,1394 ----
(define_insn "altivec_vspltisb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
! (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")]
! UNSPEC_VSPLTISB))]
"TARGET_ALTIVEC"
"vspltisb %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltish"
[(set (match_operand:V8HI 0 "register_operand" "=v")
! (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")]
! UNSPEC_VSPLTISH))]
"TARGET_ALTIVEC"
"vspltish %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltisw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
! (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")]
! UNSPEC_VSPLTISW))]
"TARGET_ALTIVEC"
"vspltisw %0,%1"
[(set_attr "type" "vecperm")])
Index: config/rs6000/spe.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/spe.md,v
retrieving revision 1.10
diff -c -p -r1.10 spe.md
*** config/rs6000/spe.md 26 Mar 2003 16:24:54 -0000 1.10
--- config/rs6000/spe.md 31 Mar 2003 21:26:39 -0000
***************
*** 2147,2182 ****
[(set_attr "type" "vecstore")
(set_attr "length" "4")])
- ;; SPE vector clears
-
- (define_insn "*movv2si_const0"
- [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
- (match_operand:V2SI 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
- (define_insn "*movv2sf_const0"
- [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
- (match_operand:V2SF 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
- (define_insn "*movv4hi_const0"
- [(set (match_operand:V4HI 0 "gpc_reg_operand" "=r")
- (match_operand:V4HI 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
- (define_insn "*movv1di_const0"
- [(set (match_operand:V1DI 0 "gpc_reg_operand" "=r")
- (match_operand:V1DI 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
;; Vector move instructions.
(define_expand "movv2si"
--- 2147,2152 ----
***************
*** 2185,2200 ****
"TARGET_SPE"
"{ rs6000_emit_move (operands[0], operands[1], V2SImode); DONE; }")
-
(define_insn "*movv2si_internal"
! [(set (match_operand:V2SI 0 "nonimmediate_operand" "=m,r,r")
! (match_operand:V2SI 1 "input_operand" "r,m,r"))]
"TARGET_SPE"
! "@
! evstdd%X0 %1,%y0
! evldd%X1 %0,%y1
! evor %0,%1,%1"
! [(set_attr "type" "vecload,vecload,vecsimple")])
(define_expand "movv1di"
[(set (match_operand:V1DI 0 "nonimmediate_operand" "")
--- 2155,2185 ----
"TARGET_SPE"
"{ rs6000_emit_move (operands[0], operands[1], V2SImode); DONE; }")
(define_insn "*movv2si_internal"
! [(set (match_operand:V2SI 0 "nonimmediate_operand" "=m,r,r,r")
! (match_operand:V2SI 1 "input_operand" "r,m,r,W"))]
"TARGET_SPE"
! "*
! {
! switch (which_alternative)
! {
! case 0: return \"evstdd%X0 %1,%y0\";
! case 1: return \"evldd%X1 %0,%y1\";
! case 2: return \"evor %0,%1,%1\";
! case 3: return output_vec_const_move (operands);
! default: abort ();
! }
! }"
! [(set_attr "type" "vecload,vecstore,*,*")
! (set_attr "length" "*,*,*,12")])
!
! (define_split
! [(set (match_operand:V2SI 0 "register_operand" "")
! (match_operand:V2SI 1 "zero_constant" ""))]
! "TARGET_SPE && reload_completed"
! [(set (match_dup 0)
! (xor:V2SI (match_dup 0) (match_dup 0)))]
! "")
(define_expand "movv1di"
[(set (match_operand:V1DI 0 "nonimmediate_operand" "")
***************
*** 2203,2216 ****
"{ rs6000_emit_move (operands[0], operands[1], V1DImode); DONE; }")
(define_insn "*movv1di_internal"
! [(set (match_operand:V1DI 0 "nonimmediate_operand" "=m,r,r")
! (match_operand:V1DI 1 "input_operand" "r,m,r"))]
"TARGET_SPE"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
! evor %0,%1,%1"
! [(set_attr "type" "vecload,vecload,vecsimple")])
(define_expand "movv4hi"
[(set (match_operand:V4HI 0 "nonimmediate_operand" "")
--- 2188,2203 ----
"{ rs6000_emit_move (operands[0], operands[1], V1DImode); DONE; }")
(define_insn "*movv1di_internal"
! [(set (match_operand:V1DI 0 "nonimmediate_operand" "=m,r,r,r")
! (match_operand:V1DI 1 "input_operand" "r,m,r,W"))]
"TARGET_SPE"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
! evor %0,%1,%1
! evxor %0,%0,%0"
! [(set_attr "type" "vecload,vecstore,*,*")
! (set_attr "length" "*,*,*,*")])
(define_expand "movv4hi"
[(set (match_operand:V4HI 0 "nonimmediate_operand" "")
***************
*** 2226,2232 ****
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
evor %0,%1,%1"
! [(set_attr "type" "vecload,vecload,vecsimple")])
(define_expand "movv2sf"
[(set (match_operand:V2SF 0 "nonimmediate_operand" "")
--- 2213,2219 ----
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
evor %0,%1,%1"
! [(set_attr "type" "vecload")])
(define_expand "movv2sf"
[(set (match_operand:V2SF 0 "nonimmediate_operand" "")
***************
*** 2235,2248 ****
"{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }")
(define_insn "*movv2sf_internal"
! [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,r,r")
! (match_operand:V2SF 1 "input_operand" "r,m,r"))]
"TARGET_SPE"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
! evor %0,%1,%1"
! [(set_attr "type" "vecload,vecload,vecsimple")])
(define_insn "spe_evmwhssfaa"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
--- 2222,2237 ----
"{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }")
(define_insn "*movv2sf_internal"
! [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,r,r,r")
! (match_operand:V2SF 1 "input_operand" "r,m,r,W"))]
"TARGET_SPE"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
! evor %0,%1,%1
! evxor %0,%0,%0"
! [(set_attr "type" "vecload,vecstore,*,*")
! (set_attr "length" "*,*,*,*")])
(define_insn "spe_evmwhssfaa"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
More information about the Gcc-patches
mailing list