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] generic simd support


hi richard.

sorry i took so long.  i wanted to do some more testing of the patch,
but got sidetracked by that day job of mine.

> > ! 	      error ("architecture does not support `%s' and I am unable to emulate it",
> 
> Better just "unable to emulate %s".

done.

> > +   /* Open-code the vector operations if we have no hardware support
> > +      for them.  */
> 
> This function is way too big already.  Please move your code
> out into a subroutine.

done.

> > !       /* ?? I'm not sure whether this is right.  This is the path we
> > !   	    take on synthetic complex types because the target is a
> > !   	    CONCAT of register, not a register per se.  However, for
> > !   	    synthetic vector types, we don't have a CONCAT, but an
> > !   	    entire pseudo.  Get out here to avoid removing needed
> > !   	    instructions.
> > !          ?? */
> > !       || vector_mode_valid_p (GET_MODE (target))
> > !       || reload_in_progress)
> 
> Maybe you should just avoid the no-conflict block entirely?

done.

i also found a buglet on darwin because they have TARGET_ALTIVEC_ABI turned on
always, so the port was insisting on using v2-v13 to pass arguments
even when there was no -maltivec ;-).  fixed this by conditionalizing
ALTIVEC_VECTOR_MODE on TARGET_ALTIVEC as well.

> Otherwise it looks reasonable.

you said it was ok before, but since i took so long to revise the patch
i'd like a nod before i commit.

	bootstrapped and regtested on powerpc-unknown-linux-gnu
	bootstrapped and regtested on i686-pc-linux-gnu 
	  (...but, there was a comparison failure with and without my patch
	   on x86)
	regtested on darwin.

ok?

aldy

2002-06-16  Aldy Hernandez  <aldyh@redhat.com>

	* gcc.c-torture/execute/simd-1.c: New.

	* gcc.dg/simd-1.c: New.

	* doc/extend.texi (Vector Extensions): Document that we can
	specify simd types not specifically supported by the hardware.
	Document that simd types can be used as function arguments.
	Document that signness does make a difference in SIMD types.
	Misc cleanups and revisions to the "vector extensions" section.

	* simplify-rtx.c (simplify_subreg): Simplify subregs of vector
	constants.

	* expr.c (vector_mode_valid_p): New.

	* expr.h: Add vector_mode_valid_p.

	* defaults.h (VECTOR_MODE_SUPPORTED_P): Set default.

	* c-common.c (type_for_mode): Always build vector nodes regardless
	of VECTOR_MODE_SUPPORTED_P.
	(handle_mode_attribute): Error if we can't emulate a nonexisting
	vector mode.
	(handle_vector_size_attribute): Same.

	* optabs.c (expand_binop): Open-code vector operations.
	(expand_unop): Open-code vector unops.
	(expand_vector_binop): New.
	(expand_vector_unop): New.
	
	* c-typeck.c (build_binary_op): Allow vectors in binops.
	Allow vectors in conditional operatiors.
	(build_unary_op): Allow vectors in unary minus.

	* config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Conditionalize on
	TARGET_ALTIVEC.
	

Index: testsuite/gcc.c-torture/execute/simd-1.c
===================================================================
RCS file: testsuite/gcc.c-torture/execute/simd-1.c
diff -N testsuite/gcc.c-torture/execute/simd-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.c-torture/execute/simd-1.c	16 Jun 2002 09:01:44 -0000
***************
*** 0 ****
--- 1,54 ----
+ /* Origin: Aldy Hernandez <aldyh@redhat.com>
+ 
+    Purpose: Test generic SIMD support.  This test should work
+    regardless of if the target has SIMD instructions.
+ */
+ 
+ typedef int __attribute__((mode(V4SI))) vecint;
+ 
+ vecint i = { 150, 100, 150, 200 };
+ vecint j = { 10, 13, 20, 30 };
+ vecint k;
+ 
+ union {
+   vecint v;
+   int i[4];
+ } res;
+ 
+ /* This should go away once we can use == and != on vector types.  */
+ void
+ verify (int a1, int a2, int a3, int a4,
+ 	int b1, int b2, int b3, int b4)
+ {
+   if (a1 != b1
+       || a2 != b2
+       || a3 != b3
+       || a4 != b4)
+     abort ();
+ }
+ 
+ int
+ main ()
+ {
+   k = i + j;
+   res.v = k;
+ 
+   verify (res.i[0], res.i[1], res.i[2], res.i[3], 160, 113, 170, 230);
+ 
+   k = i * j;
+   res.v = k;
+ 
+   verify (res.i[0], res.i[1], res.i[2], res.i[3], 1500, 1300, 3000, 6000);
+ 
+   k = i / j;
+   res.v = k;
+ 
+   verify (res.i[0], res.i[1], res.i[2], res.i[3], 15, 7, 7, 6);
+ 
+   k = -i;
+   res.v = k;
+   verify (res.i[0], res.i[1], res.i[2], res.i[3],
+ 	  -150, -100, -150, -200);
+ 
+   exit (0);
+ }
Index: testsuite/gcc.dg/simd-1.c
===================================================================
RCS file: testsuite/gcc.dg/simd-1.c
diff -N testsuite/gcc.dg/simd-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/simd-1.c	16 Jun 2002 09:01:44 -0000
***************
*** 0 ****
--- 1,61 ----
+ /* { dg-do compile } */
+ /* { dg-options "-Wall" } */
+ 
+ /* Origin: Aldy Hernandez <aldyh@redhat.com>.  */
+ /* Purpose: Program to test generic SIMD support.  */
+ 
+ typedef int __attribute__((mode(V4SI))) v4si;
+ typedef int __attribute__((mode(V8HI))) v8hi;
+ typedef int __attribute__((mode(V2SI))) v2si;
+ typedef unsigned int __attribute__((mode(V4SI))) uv4si;
+ 
+ v4si a, b;
+ v2si c, d;
+ v8hi e;
+ uv4si f;
+ 
+ int foo __attribute__((mode(DI)));
+ int foo1 __attribute__((mode(SI)));
+ int foo2 __attribute__((mode(V4HI)));
+ 
+ void
+ hanneke ()
+ {
+   /* Assignment.  */
+   a = b;
+ 
+   /* Assignment of different types.  */
+   b = c; /* { dg-error "incompatible types in assignment" } */
+   d = a; /* { dg-error "incompatible types in assignment" } */
+ 
+   /* Casting between SIMDs of the same size.  */
+   e = (typeof (e)) a;
+ 
+   /* Different signed SIMD assignment.  */
+   f = a; /* { dg-error "incompatible types in assignment" } */
+ 
+   /* Casted different signed SIMD assignment.  */
+   f = (uv4si) a;
+ 
+   /* Assignment between scalar and SIMD of different size.  */
+   foo = a; /* { dg-error "incompatible types in assignment" } */
+ 
+   /* Casted assignment between scalar and SIMD of same size.  */
+   foo = (typeof (foo)) foo2;
+ 
+   /* Casted assignment between scalar and SIMD of different size.  */
+   foo1 = (typeof (foo1)) foo2; /* { dg-error "can't convert between vector values of different size" } */
+ 
+   /* Operators on compatible SIMD types.  */
+   a += b + b;
+   a -= b;
+   a *= b;
+   a /= b;
+   a = -b;
+ 
+   /* Operators on incompatible SIMD types.  */
+   a = b + c; /* { dg-error "can't convert between vector values of different size" } */
+   a = b - c; /* { dg-error "can't convert between vector values of different size" } */
+   a = b * c; /* { dg-error "can't convert between vector values of different size" } */
+   a = b / c; /* { dg-error "can't convert between vector values of different size" } */
+ }
Index: doc/extend.texi
===================================================================
RCS file: /cvs/uberbaum/gcc/doc/extend.texi,v
retrieving revision 1.80
diff -c -p -r1.80 extend.texi
*** doc/extend.texi	12 Jun 2002 02:56:59 -0000	1.80
--- doc/extend.texi	16 Jun 2002 09:01:50 -0000
*************** A floating point value, as wide as a SI 
*** 4373,4400 ****
  A floating point value, as wide as a DI mode integer, usually 64 bits.
  @end table
  
- Not all base types or combinations are always valid; which modes can be used
- is determined by the target machine.  For example, if targetting the i386 MMX
- extensions, only @code{V8QI}, @code{V4HI} and @code{V2SI} are allowed modes.
- 
  There are no @code{V1xx} vector modes - they would be identical to the
  corresponding base mode.
  
! There is no distinction between signed and unsigned vector modes.  This
! distinction is made by the operations that perform on the vectors, not
! by the data type.
! 
! The types defined in this manner are somewhat special, they cannot be
! used with most normal C operations (i.e., a vector addition can @emph{not}
! be represented by a normal addition of two vector type variables).  You
! can declare only variables and use them in function calls and returns, as
! well as in assignments and some casts.  It is possible to cast from one
! vector type to another, provided they are of the same size (in fact, you
! can also cast vectors to and from other datatypes of the same size).
! 
! A port that supports vector operations provides a set of built-in functions
! that can be used to operate on vectors.  For example, a function to add two
! vectors and multiply the result by a third could look like this:
  
  @example
  v4si f (v4si a, v4si b, v4si c)
--- 4373,4424 ----
  A floating point value, as wide as a DI mode integer, usually 64 bits.
  @end table
  
  There are no @code{V1xx} vector modes - they would be identical to the
  corresponding base mode.
  
! Specifying a combination that is not valid for the current architecture
! will cause gcc to synthesize the instructions using a narrower mode.
! For example, if you specify a variable of type @code{V4SI} and your
! architecture does not allow for this specific SIMD type, gcc will
! produce code that uses 4 @code{SIs}.
! 
! The types defined in this manner can be used with a subset of normal C
! operations.  Currently, gcc will allow using the following operators on
! these types: @code{+, -, *, /, unary minus}@.
! 
! The operations behave like C++ @code{valarrays}.  Addition is defined as
! the addition of the corresponding elements of the operands.  For
! example, in the code below, each of the 4 elements in @var{a} will be
! added to the corresponding 4 elements in @var{b} and the resulting
! vector will be stored in @var{c}.
! 
! @example
! typedef int v4si __attribute__ ((mode(V4SI)));
! 
! v4si a, b, c;
! 
! c = a + b;
! @end example
! 
! Subtraction, multiplication, and division operate in a similar manner.
! Likewise, the result of using the unary minus operator on a vector type
! is a vector whose elements are the negative value of the corresponding
! elements in the operand.
! 
! You can declare variables and use them in function calls and returns, as
! well as in assignments and some casts.  You can specify a vector type as
! a return type for a function.  Vector types can also be used as function
! arguments.  It is possible to cast from one vector type to another,
! provided they are of the same size (in fact, you can also cast vectors
! to and from other datatypes of the same size).
! 
! You cannot operate between vectors of different lengths or different
! signness without a cast.
! 
! A port that supports hardware vector operations, usually provides a set
! of built-in functions that can be used to operate on vectors.  For
! example, a function to add two vectors and multiply the result by a
! third could look like this:
  
  @example
  v4si f (v4si a, v4si b, v4si c)
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/uberbaum/gcc/simplify-rtx.c,v
retrieving revision 1.106
diff -c -p -r1.106 simplify-rtx.c
*** simplify-rtx.c	10 Jun 2002 22:29:14 -0000	1.106
--- simplify-rtx.c	16 Jun 2002 09:01:51 -0000
*************** simplify_subreg (outermode, op, innermod
*** 2268,2273 ****
--- 2268,2291 ----
    if (outermode == innermode && !byte)
      return op;
  
+   /* Simplify subregs of vector constants.  */
+   if (GET_CODE (op) == CONST_VECTOR)
+     {
+       int offset = byte / UNITS_PER_WORD;
+       rtx elt;
+ 
+       /* This shouldn't happen, but let's not do anything stupid.  */
+       if (GET_MODE_INNER (innermode) != outermode)
+ 	return NULL_RTX;
+ 
+       elt = CONST_VECTOR_ELT (op, offset);
+ 
+       /* ?? We probably don't need this copy_rtx because constants
+ 	 can be shared.  ?? */
+ 
+       return copy_rtx (elt);
+     }
+ 
    /* Attempt to simplify constant to non-SUBREG expression.  */
    if (CONSTANT_P (op))
      {
Index: expr.c
===================================================================
RCS file: /cvs/uberbaum/gcc/expr.c,v
retrieving revision 1.466
diff -c -p -r1.466 expr.c
*** expr.c	15 Jun 2002 20:21:22 -0000	1.466
--- expr.c	16 Jun 2002 09:01:58 -0000
*************** try_tablejump (index_type, index_expr, m
*** 10791,10794 ****
--- 10791,10824 ----
    return 1;
  }
  
+ /* Nonzero if the mode is a valid vector mode for this architecture.
+    This returns nonzero even if there is no hardware support for the
+    vector mode, but we can emulate with narrower modes.  */
+ 
+ int
+ vector_mode_valid_p (mode)
+      enum machine_mode mode;
+ {
+   enum mode_class class = GET_MODE_CLASS (mode);
+   enum machine_mode innermode;
+ 
+   /* Doh!  What's going on?  */
+   if (class != MODE_VECTOR_INT
+       && class != MODE_VECTOR_FLOAT)
+     return 0;
+ 
+   /* Hardware support.  Woo hoo!  */
+   if (VECTOR_MODE_SUPPORTED_P (mode))
+     return 1;
+ 
+   innermode = GET_MODE_INNER (mode);
+ 
+   /* We should probably return 1 if requesting V4DI and we have no DI,
+      but we have V2DI, but this is probably very unlikely.  */
+ 
+   /* 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;
+ }
+ 
  #include "gt-expr.h"
Index: expr.h
===================================================================
RCS file: /cvs/uberbaum/gcc/expr.h,v
retrieving revision 1.116
diff -c -p -r1.116 expr.h
*** expr.h	4 Jun 2002 07:07:36 -0000	1.116
--- expr.h	16 Jun 2002 09:01:59 -0000
*************** extern void do_jump_by_parts_greater_rtx
*** 786,788 ****
--- 786,790 ----
  extern void mark_seen_cases			PARAMS ((tree, unsigned char *,
  							 HOST_WIDE_INT, int));
  #endif
+ 
+ extern int vector_mode_valid_p		PARAMS ((enum machine_mode));
Index: defaults.h
===================================================================
RCS file: /cvs/uberbaum/gcc/defaults.h,v
retrieving revision 1.79
diff -c -p -r1.79 defaults.h
*** defaults.h	14 Jun 2002 00:50:30 -0000	1.79
--- defaults.h	16 Jun 2002 09:01:59 -0000
*************** You Lose!  You must define PREFERRED_DEB
*** 513,518 ****
--- 513,522 ----
  #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME "text.unlikely"
  #endif
  
+ #ifndef VECTOR_MODE_SUPPORTED_P
+ #define VECTOR_MODE_SUPPORTED_P(MODE) 0
+ #endif
+ 
  /* Determine whether __cxa_atexit, rather than atexit, is used to
     register C++ destructors for local statics and global objects. */
  #ifndef DEFAULT_USE_CXA_ATEXIT
Index: c-common.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-common.c,v
retrieving revision 1.342
diff -c -p -r1.342 c-common.c
*** c-common.c	12 Jun 2002 03:06:09 -0000	1.342
--- c-common.c	16 Jun 2002 09:02:03 -0000
*************** c_common_type_for_mode (mode, unsignedp)
*** 1599,1636 ****
    if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
      return build_pointer_type (integer_type_node);
  
! #ifdef VECTOR_MODE_SUPPORTED_P
!   if (VECTOR_MODE_SUPPORTED_P (mode))
      {
!       switch (mode)
! 	{
! 	case V16QImode:
! 	  return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
! 	case V8HImode:
! 	  return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
! 	case V4SImode:
! 	  return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
! 	case V2DImode:
! 	  return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
! 	case V2SImode:
! 	  return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
! 	case V4HImode:
! 	  return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
! 	case V8QImode:
! 	  return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
! 	case V16SFmode:
! 	  return V16SF_type_node;
! 	case V4SFmode:
! 	  return V4SF_type_node;
! 	case V2SFmode:
! 	  return V2SF_type_node;
! 	case V2DFmode:
! 	  return V2DF_type_node;
! 	default:
! 	  break;
! 	}
      }
- #endif
  
    return 0;
  }
--- 1599,1631 ----
    if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
      return build_pointer_type (integer_type_node);
  
!   switch (mode)
      {
!     case V16QImode:
!       return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
!     case V8HImode:
!       return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
!     case V4SImode:
!       return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
!     case V2DImode:
!       return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
!     case V2SImode:
!       return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
!     case V4HImode:
!       return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
!     case V8QImode:
!       return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
!     case V16SFmode:
!       return V16SF_type_node;
!     case V4SFmode:
!       return V4SF_type_node;
!     case V2SFmode:
!       return V2SF_type_node;
!     case V2DFmode:
!       return V2DF_type_node;
!     default:
!       break;
      }
  
    return 0;
  }
*************** handle_mode_attribute (node, name, args,
*** 5055,5062 ****
  		     (mode, TREE_UNSIGNED (type))))
  	error ("no data type for mode `%s'", p);
        else
! 	*node = typefm;
!         /* No need to layout the type here.  The caller should do this.  */
      }
  
    return NULL_TREE;
--- 5050,5069 ----
  		     (mode, TREE_UNSIGNED (type))))
  	error ("no data type for mode `%s'", p);
        else
! 	{
! 	  /* If this is a vector, make sure we either have hardware
! 	     support, or we can emulate it.  */
! 	  if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
! 	       || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
! 	      && !vector_mode_valid_p (mode))
! 	    {
! 	      error ("unable to emulate '%s'", GET_MODE_NAME (mode));
! 	      return NULL_TREE;
! 	    }
! 
! 	  *node = typefm;
! 	  /* No need to layout the type here.  The caller should do this.  */
! 	}
      }
  
    return NULL_TREE;
*************** handle_vector_size_attribute (node, name
*** 5600,5605 ****
--- 5607,5622 ----
  	}
  
        new_type = build_type_copy (new_type);
+ 
+       /* If this is a vector, make sure we either have hardware
+          support, or we can emulate it.  */
+       if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ 	   || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ 	  && !vector_mode_valid_p (mode))
+ 	{
+ 	  error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+ 	  return NULL_TREE;
+ 	}
  
        /* Set the debug information here, because this is the only
  	 place where we know the underlying type for a vector made
Index: optabs.c
===================================================================
RCS file: /cvs/uberbaum/gcc/optabs.c,v
retrieving revision 1.136
diff -c -p -r1.136 optabs.c
*** optabs.c	11 Jun 2002 12:21:45 -0000	1.136
--- optabs.c	16 Jun 2002 09:02:05 -0000
*************** static void emit_cmp_and_jump_insn_1 PAR
*** 120,125 ****
--- 120,130 ----
  					    enum rtx_code, int, rtx));
  static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
  					 enum machine_mode *, int *));
+ static rtx expand_vector_binop PARAMS ((enum machine_mode, optab,
+ 					rtx, rtx, rtx, int,
+ 					enum optab_methods));
+ static rtx expand_vector_unop PARAMS ((enum machine_mode, optab, rtx, rtx,
+ 				       int));
  
  /* Add a REG_EQUAL note to the last insn in INSNS.  TARGET is being set to
     the result of operation CODE applied to OP0 (and OP1 if it is a binary
*************** expand_binop (mode, binoptab, op0, op1, 
*** 1531,1536 ****
--- 1536,1547 ----
        delete_insns_since (last);
      }
  
+   /* Open-code the vector operations if we have no hardware support
+      for them.  */
+   if (class == MODE_VECTOR_INT || class == MODE_VECTOR_FLOAT)
+     return expand_vector_binop (mode, binoptab, op0, op1, target,
+ 				unsignedp, methods);
+ 
    /* We need to open-code the complex type operations: '+, -, * and /' */
  
    /* At this point we allow operations between two similar complex
*************** expand_binop (mode, binoptab, op0, op1, 
*** 1900,1905 ****
--- 1911,2022 ----
    delete_insns_since (entry_last);
    return 0;
  }
+ 
+ /* Like expand_binop, but for open-coding vectors binops.  */
+ 
+ static rtx
+ expand_vector_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
+      enum machine_mode mode;
+      optab binoptab;
+      rtx op0, op1;
+      rtx target;
+      int unsignedp;
+      enum optab_methods methods;
+ {
+   enum machine_mode submode;
+   int elts, i;
+   rtx t, a, b, res, seq;
+ 
+   submode = GET_MODE_INNER (mode);
+   elts = GET_MODE_NUNITS (mode);
+ 
+   if (!target)
+     target = gen_reg_rtx (mode);
+ 
+   start_sequence ();
+ 
+   /* FIXME: Optimally, we should try to do this in narrower vector
+      modes if available.  E.g. When trying V8SI, try V4SI, else
+      V2SI, else decay into SI.  */
+ 
+   switch (binoptab->code)
+     {
+     case PLUS:
+     case MINUS:
+     case MULT:
+     case DIV:
+       for (i = 0; i < elts; ++i)
+ 	{
+ 	  t = simplify_gen_subreg (submode, target, mode,
+ 				   i * UNITS_PER_WORD);
+ 	  a = simplify_gen_subreg (submode, op0, mode,
+ 				   i * UNITS_PER_WORD);
+ 	  b = simplify_gen_subreg (submode, op1, mode,
+ 				   i * UNITS_PER_WORD);
+ 
+ 	  res = expand_binop (submode, binoptab, a, b, t,
+ 			      unsignedp, methods);
+ 
+ 	  if (res == 0)
+ 	    break;
+ 
+ 	  emit_move_insn (t, res);
+ 	}
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   seq = get_insns ();
+   end_sequence ();
+   emit_insn (seq);
+ 
+   return target;
+ }
+ 
+ /* Like expand_unop but for open-coding vector unops.  */
+ 
+ static rtx
+ expand_vector_unop (mode, unoptab, op0, target, unsignedp)
+      enum machine_mode mode;
+      optab unoptab;
+      rtx op0;
+      rtx target;
+      int unsignedp;
+ {
+   enum machine_mode submode;
+   int elts, i;
+   rtx t, a, res, seq;
+ 
+   submode = GET_MODE_INNER (mode);
+   elts = GET_MODE_NUNITS (mode);
+ 
+   if (!target)
+     target = gen_reg_rtx (mode);
+ 
+   start_sequence ();
+ 
+   /* FIXME: Optimally, we should try to do this in narrower vector
+      modes if available.  E.g. When trying V8SI, try V4SI, else
+      V2SI, else decay into SI.  */
+ 
+   for (i = 0; i < elts; ++i)
+     {
+       t = simplify_gen_subreg (submode, target, mode, i * UNITS_PER_WORD);
+       a = simplify_gen_subreg (submode, op0, mode, i * UNITS_PER_WORD);
+ 
+       res = expand_unop (submode, unoptab, a, t, unsignedp);
+ 
+       emit_move_insn (t, res);
+     }
+ 
+   seq = get_insns ();
+   end_sequence ();
+   emit_insn (seq);
+ 
+   return target;
+ }
  
  /* Expand a binary operator which has both signed and unsigned forms.
     UOPTAB is the optab for unsigned operations, and SOPTAB is for
*************** expand_unop (mode, unoptab, op0, target,
*** 2323,2328 ****
--- 2440,2448 ----
  
        return target;
      }
+ 
+   if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT)
+     return expand_vector_unop (mode, unoptab, op0, target, unsignedp);
  
    /* It can't be done in this mode.  Can we do it in a wider mode?  */
  
Index: c-typeck.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-typeck.c,v
retrieving revision 1.195
diff -c -p -r1.195 c-typeck.c
*** c-typeck.c	23 May 2002 15:47:58 -0000	1.195
--- c-typeck.c	16 Jun 2002 09:02:10 -0000
*************** build_binary_op (code, orig_op0, orig_op
*** 2046,2054 ****
  	warning ("division by zero");
  
        if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
! 	   || code0 == COMPLEX_TYPE)
  	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
! 	      || code1 == COMPLEX_TYPE))
  	{
  	  if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
  	    resultcode = RDIV_EXPR;
--- 2046,2054 ----
  	warning ("division by zero");
  
        if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
! 	   || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
  	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
! 	      || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
  	{
  	  if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
  	    resultcode = RDIV_EXPR;
*************** build_binary_op (code, orig_op0, orig_op
*** 2197,2205 ****
  	 but don't convert the args to int!  */
        build_type = integer_type_node;
        if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
! 	   || code0 == COMPLEX_TYPE)
  	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
! 	      || code1 == COMPLEX_TYPE))
  	short_compare = 1;
        else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
  	{
--- 2197,2207 ----
  	 but don't convert the args to int!  */
        build_type = integer_type_node;
        if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
! 	   || code0 == COMPLEX_TYPE
! 	   || code0 == VECTOR_TYPE)
  	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
! 	      || code1 == COMPLEX_TYPE
! 	      || code1 == VECTOR_TYPE))
  	short_compare = 1;
        else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
  	{
*************** build_binary_op (code, orig_op0, orig_op
*** 2342,2350 ****
        break;
      }
  
!   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
        &&
!       (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
      {
        int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
  
--- 2344,2354 ----
        break;
      }
  
!   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
!        || code0 == VECTOR_TYPE)
        &&
!       (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
!        || code1 == VECTOR_TYPE))
      {
        int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
  
*************** build_unary_op (code, xarg, flag)
*** 2763,2769 ****
  
      case NEGATE_EXPR:
        if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
! 	    || typecode == COMPLEX_TYPE))
  	{
  	  error ("wrong type argument to unary minus");
  	  return error_mark_node;
--- 2767,2774 ----
  
      case NEGATE_EXPR:
        if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
! 	    || typecode == COMPLEX_TYPE
! 	    || typecode == VECTOR_TYPE))
  	{
  	  error ("wrong type argument to unary minus");
  	  return error_mark_node;
*************** convert_for_assignment (type, rhs, errty
*** 4079,4085 ****
    else if ((codel == INTEGER_TYPE || codel == REAL_TYPE 
  	    || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
  	    || codel == BOOLEAN_TYPE)
! 	   && (coder == INTEGER_TYPE || coder == REAL_TYPE 
  	       || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
  	       || coder == BOOLEAN_TYPE))
      return convert_and_check (type, rhs);
--- 4084,4090 ----
    else if ((codel == INTEGER_TYPE || codel == REAL_TYPE 
  	    || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
  	    || codel == BOOLEAN_TYPE)
! 	   && (coder == INTEGER_TYPE || coder == REAL_TYPE
  	       || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
  	       || coder == BOOLEAN_TYPE))
      return convert_and_check (type, rhs);
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.209
diff -c -p -r1.209 rs6000.h
*** config/rs6000/rs6000.h	11 Jun 2002 23:14:47 -0000	1.209
--- config/rs6000/rs6000.h	16 Jun 2002 09:02:12 -0000
*************** extern int rs6000_default_long_calls;
*** 817,826 ****
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
  #define ALTIVEC_VECTOR_MODE(MODE)	\
! 	((MODE) == V16QImode		\
! 	 || (MODE) == V8HImode		\
! 	 || (MODE) == V4SFmode		\
! 	 || (MODE) == V4SImode)
  
  /* Define this macro to be nonzero if the port is prepared to handle
     insns involving vector mode MODE.  At the very least, it must have
--- 817,827 ----
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
  #define ALTIVEC_VECTOR_MODE(MODE)	\
!         (TARGET_ALTIVEC &&		\
! 	 ((MODE) == V16QImode		\
! 	  || (MODE) == V8HImode		\
! 	  || (MODE) == V4SFmode		\
! 	  || (MODE) == V4SImode))
  
  /* Define this macro to be nonzero if the port is prepared to handle
     insns involving vector mode MODE.  At the very least, it must have


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