* [patch] generic simd support
@ 2002-05-21 17:45 Aldy Hernandez
2002-05-22 14:09 ` Daniel Egger
2002-05-30 15:42 ` Richard Henderson
0 siblings, 2 replies; 5+ messages in thread
From: Aldy Hernandez @ 2002-05-21 17:45 UTC (permalink / raw)
To: gcc-patches, gcc; +Cc: gdb
hi guys.
as promised...
months ago it was discussed that we could enable certain operators on
simd types (+, -, etc), provided they conform to the valarrays
specification.
this will provide a basis for hardware assisted valarrays.
of course, this isn't terribly interesting unless we can provide
simd support for targets that don't have simd hardware. this patch
does both.
if the hardware doesn't have simd support, gcc will now synthesize the
instructions from the underlying type. if we declare a variable
V4SI, and we have no hardware V4SI, gcc will implement the operation on
4 SIs. the operators presently supported are +, -, *, /, and unary
minus. more to come as i can find out what the corresponding
valarray implementation does.
this will provide a basis for future auto-vectorization work,
and will give us a generic mechanism for testing SIMD operations
(and vector initializers) which have been here-to mostly untested
(except on selected platforms). i am including a test for this as
well.
in addition to all this wonderful stuff, the gdb folks want to start
adding generic testcases for simd extensions, and this will allow them
to do just that.
i have also revised the vector extension documentation. thanks to the
altivec work, we can now use vectors in arguments and return values.
i have modified the documentation to reflect these and other changes.
on my TODO list are:
- provide support for == and !=. these are a bit trickier
because do_jump() synthesizes these at the tree level not
the rtl level and we need a new tree code and what-not.
(perhaps do the rest of the relational operators when i figure
out what the valarray counterparts do).
- synthesize bigger SIMD types from architecture present smaller
SIMD types. for example, if we have V2SI but no V4SI and we
want V4SI, we should be able to use a pair of V2SI's to do
the operation. presently we use 4 SIs.
and... [much later] future work should include:
- providing generic builtins for common vector operations in
addition to the operations in the valarrays specs. this way
we could write truly portable SIMD programs that will work
regardless of the hardware.
say, provide:
__builtin_simd_adds /* add saturated */
__builtin_simd_select
__builtin_simd_splat
etc
enough dreaming. on to the current patch.
tested on darwin *without* [hardware] simd support ;-). will be testing
on x86 shortly.
how does this look for mainline?
2002-05-21 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.
(emit_no_conflict_block): Emit all the instructions regardless, if
we have a vector type.
* c-typeck.c (build_binary_op): Allow vectors in binops.
Allow vectors in conditional operatiors.
(build_unary_op): Allow vectors in unary minus.
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 22 May 2002 00:42:53 -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 22 May 2002 00:42:53 -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.70
diff -c -p -r1.70 extend.texi
*** doc/extend.texi 11 May 2002 16:25:04 -0000 1.70
--- doc/extend.texi 22 May 2002 00:42:59 -0000
*************** A floating point value, as wide as a SI
*** 4300,4327 ****
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)
--- 4300,4351 ----
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.103
diff -c -p -r1.103 simplify-rtx.c
*** simplify-rtx.c 9 May 2002 12:02:28 -0000 1.103
--- simplify-rtx.c 22 May 2002 00:43:01 -0000
*************** simplify_subreg (outermode, op, innermod
*** 2238,2243 ****
--- 2238,2261 ----
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, new;
+
+ /* 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.456
diff -c -p -r1.456 expr.c
*** expr.c 17 May 2002 22:46:22 -0000 1.456
--- expr.c 22 May 2002 00:43:14 -0000
*************** try_tablejump (index_type, index_expr, m
*** 10759,10761 ****
--- 10759,10793 ----
table_label, default_label);
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;
+ }
+
Index: expr.h
===================================================================
RCS file: /cvs/uberbaum/gcc/expr.h,v
retrieving revision 1.113
diff -c -p -r1.113 expr.h
*** expr.h 31 Mar 2002 09:52:33 -0000 1.113
--- expr.h 22 May 2002 00:43:14 -0000
*************** extern void do_jump_by_parts_greater_rtx
*** 789,791 ****
--- 789,793 ----
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.75
diff -c -p -r1.75 defaults.h
*** defaults.h 17 May 2002 23:25:19 -0000 1.75
--- defaults.h 22 May 2002 00:43:15 -0000
*************** You Lose! You must define PREFERRED_DEB
*** 503,506 ****
--- 503,510 ----
#define UNLIKELY_EXECUTED_TEXT_SECTION_NAME "text.unlikely"
#endif
+ #ifndef VECTOR_MODE_SUPPORTED_P
+ #define VECTOR_MODE_SUPPORTED_P(MODE) 0
+ #endif
+
#endif /* ! GCC_DEFAULTS_H */
Index: c-common.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-common.c,v
retrieving revision 1.327
diff -c -p -r1.327 c-common.c
*** c-common.c 19 May 2002 21:53:52 -0000 1.327
--- c-common.c 22 May 2002 00:43:18 -0000
*************** c_common_type_for_mode (mode, unsignedp)
*** 1573,1610 ****
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;
}
--- 1573,1605 ----
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,
*** 4988,4995 ****
(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;
--- 4983,5003 ----
(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 ("architecture does not support `%s' and I am unable to emulate it",
! 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
*** 5533,5538 ****
--- 5541,5557 ----
}
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 ("architecture does not support `%s' and I am unable to emulate it",
+ 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.132
diff -c -p -r1.132 optabs.c
*** optabs.c 20 May 2002 08:30:03 -0000 1.132
--- optabs.c 22 May 2002 00:43:21 -0000
*************** expand_binop (mode, binoptab, op0, op1,
*** 1503,1508 ****
--- 1503,1565 ----
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)
+ {
+ 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 cascade to 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_no_conflict_block (seq, target, op0, op1, NULL);
+
+ return target;
+ }
+
/* We need to open-code the complex type operations: '+, -, * and /' */
/* At this point we allow operations between two similar complex
*************** expand_unop (mode, unoptab, op0, target,
*** 2296,2301 ****
--- 2353,2394 ----
return target;
}
+ if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT)
+ {
+ 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 cascade to 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_no_conflict_block (seq, target, op0, 0, NULL);
+
+ return target;
+ }
+
/* It can't be done in this mode. Can we do it in a wider mode? */
if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
*************** emit_no_conflict_block (insns, target, o
*** 2747,2753 ****
{
rtx prev, next, first, last, insn;
! if (GET_CODE (target) != REG || reload_in_progress)
return emit_insns (insns);
else
for (insn = insns; insn; insn = NEXT_INSN (insn))
--- 2840,2855 ----
{
rtx prev, next, first, last, insn;
! if (GET_CODE (target) != REG
! /* ?? 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)
return emit_insns (insns);
else
for (insn = insns; insn; insn = NEXT_INSN (insn))
Index: c-typeck.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-typeck.c,v
retrieving revision 1.194
diff -c -p -r1.194 c-typeck.c
*** c-typeck.c 26 Apr 2002 21:56:55 -0000 1.194
--- c-typeck.c 22 May 2002 00:43:25 -0000
*************** build_binary_op (code, orig_op0, orig_op
*** 2047,2055 ****
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;
--- 2047,2055 ----
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
*** 2198,2206 ****
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)
{
--- 2198,2208 ----
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
*** 2343,2351 ****
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);
--- 2345,2355 ----
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)
*** 2764,2770 ****
case NEGATE_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
! || typecode == COMPLEX_TYPE))
{
error ("wrong type argument to unary minus");
return error_mark_node;
--- 2768,2775 ----
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
*** 4080,4086 ****
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);
--- 4085,4091 ----
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);
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [patch] generic simd support 2002-05-21 17:45 [patch] generic simd support Aldy Hernandez @ 2002-05-22 14:09 ` Daniel Egger 2002-05-30 15:42 ` Richard Henderson 1 sibling, 0 replies; 5+ messages in thread From: Daniel Egger @ 2002-05-22 14:09 UTC (permalink / raw) To: Aldy Hernandez; +Cc: GCC Patches, GCC Developer Mailinglist, gdb Am Mit, 2002-05-22 um 02.44 schrieb Aldy Hernandez: > as promised... Yay, I like it; haven't found the time to bootstrap it... Your idention after some if's looks weird though, either there's a problem with your and/or my mailer or you have some ill formed tabs in it. -- Servus, Daniel ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch] generic simd support 2002-05-21 17:45 [patch] generic simd support Aldy Hernandez 2002-05-22 14:09 ` Daniel Egger @ 2002-05-30 15:42 ` Richard Henderson 2002-06-16 2:10 ` Aldy Hernandez 1 sibling, 1 reply; 5+ messages in thread From: Richard Henderson @ 2002-05-30 15:42 UTC (permalink / raw) To: Aldy Hernandez; +Cc: gcc-patches, gcc, gdb On Wed, May 22, 2002 at 10:44:29AM +1000, Aldy Hernandez wrote: > ! error ("architecture does not support `%s' and I am unable to emulate it", Better just "unable to emulate %s". > + /* 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. > ! /* ?? 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? Otherwise it looks reasonable. r~ ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch] generic simd support 2002-05-30 15:42 ` Richard Henderson @ 2002-06-16 2:10 ` Aldy Hernandez 2002-06-16 10:59 ` Richard Henderson 0 siblings, 1 reply; 5+ messages in thread From: Aldy Hernandez @ 2002-06-16 2:10 UTC (permalink / raw) To: Richard Henderson, gcc-patches, gcc, gdb 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)); \f /* 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; + } \f /* 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 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch] generic simd support 2002-06-16 2:10 ` Aldy Hernandez @ 2002-06-16 10:59 ` Richard Henderson 0 siblings, 0 replies; 5+ messages in thread From: Richard Henderson @ 2002-06-16 10:59 UTC (permalink / raw) To: Aldy Hernandez; +Cc: gcc-patches, gcc, gdb On Sun, Jun 16, 2002 at 07:10:00PM +1000, Aldy Hernandez wrote: > * 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. Ok. r~ ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-06-16 17:59 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-05-21 17:45 [patch] generic simd support Aldy Hernandez 2002-05-22 14:09 ` Daniel Egger 2002-05-30 15:42 ` Richard Henderson 2002-06-16 2:10 ` Aldy Hernandez 2002-06-16 10:59 ` Richard Henderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox