This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: patch: optimized constant vector initializers



On Monday, March 31, 2003, at 05:52 PM, Richard Henderson wrote:


On Mon, Mar 31, 2003 at 05:42:58PM -0400, Aldy Hernandez wrote:
- static int
! int
  is_zeros_p (exp)

Left over from a previous patch? It's not required here...

Doh, yes. I didn't see that it was defined in the same file.


You've specified bogus alignment.  Only the first element
should be aligned like this; subsequent ones will use much
less alignment, usually.  You want something like

Good catch. Fixed.


How about...

2003-02-31 Aldy Hernandez <aldyh at redhat dot com>

* testsuite/gcc.c-torture/execute/simd-3.c: New.

	* expr.c (expand_expr): Handle VECTOR_CST.
	(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 22:30:16 -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.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 22:30:18 -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,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,
*************** static rtx do_store_flag PARAMS ((tree,
*** 175,180 ****
--- 175,181 ----
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
*************** expand_expr (exp, target, tmode, modifie
*** 6842,6847 ****
--- 6843,6851 ----

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 ****
--- 10331,10373 ----
    /* 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 22:30:19 -0000
*************** output_constant (exp, size, align)
*** 4015,4020 ****
--- 4015,4037 ----
  	  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;
+ 	  unsigned int nalign;
+ 	  enum machine_mode inner;
+
+ 	  inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
+ 	  nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
+
+ 	  elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
+
+ 	  link = TREE_VECTOR_CST_ELTS (exp);
+ 	  output_constant (TREE_VALUE (link), elt_size, align);
+ 	  while ((link = TREE_CHAIN (link)) != NULL)
+ 	    output_constant (TREE_VALUE (link), elt_size, nalign);
+ 	}
        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 22:30:20 -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 22:30:22 -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 22:30:23 -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 22:30:23 -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 22:30:23 -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 22:30:24 -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")


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]