===================================================================
@@ -6553,6 +6553,97 @@ invoke undefined behavior at runtime. W
accesses for vector subscription can be enabled with
@option{-Warray-bounds}.
+In C vector comparison is supported within standard comparison operators:
+@code{==, !=, <, <=, >, >=}. Both integer-type and real-type vectors
+can be compared but only of the same type. The result of the
+comparison is a signed integer-type vector where the size of each
+element must be the same as the size of compared vectors element.
+Comparison is happening element by element. False value is 0, true
+value is -1 (constant of the appropriate type where all bits are set).
+Consider the following example.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a = @{1,2,3,4@};
+v4si b = @{3,2,1,4@};
+v4si c;
+
+c = a > b; /* The result would be @{0, 0,-1, 0@} */
+c = a == b; /* The result would be @{0,-1, 0,-1@} */
+@end smallexample
+
+In addition to the vector comparison C supports conditional expressions
+where the condition is a vector of signed integers. In that case result
+of the condition is used as a mask to select either from the first
+operand or from the second. Consider the following example:
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a = @{1,2,3,4@};
+v4si b = @{3,2,1,7@};
+v4si c = @{2,3,4,5@};
+v4si d = @{6,7,8,9@};
+v4si res;
+
+res = a >= b ? c : d; /* res would contain @{6, 3, 4, 9@} */
+@end smallexample
+
+The number of elements in the condition must be the same as number of
+elements in the both operands. The same stands for the size of the type
+of the elements. The type of the vector conditional is determined by
+the types of the operands which must be the same. Consider an example:
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+typedef float v4f __attribute__ ((vector_size (16)));
+
+v4si a = @{1,2,3,4@};
+v4si b = @{2,3,4,5@};
+v4f f = @{1., 5., 7., -8.@};
+v4f g = @{3., -2., 8., 1.@};
+v4si ires;
+v4f fres;
+
+fres = a <= b ? f : g; /* fres would contain @{1., 5., 7., -8.@} */
+ires = f <= g ? a : b; /* fres would contain @{1, 3, 3, 4@} */
+@end smallexample
+
+For the convenience condition in the vector conditional can be just a
+vector of signed integer type. In that case this vector is implicitly
+compared with vectors of zeroes. Consider an example:
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a = @{1,0,3,0@};
+v4si b = @{2,3,4,5@};
+v4si ires;
+
+ires = a ? b : a; /* synonym for ires = a != @{0,0,0,0@} ? a :b; */
+@end smallexample
+
+Pleas note that the conditional where the operands are vectors and the
+condition is integer works in a standard way -- returns first operand
+if the condition is true and second otherwise. Consider an example:
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a = @{1,0,3,0@};
+v4si b = @{2,3,4,5@};
+v4si ires;
+int x,y;
+
+/* standard conditional returning A or B */
+ires = x > y ? a : b;
+
+/* vector conditional where the condition is (x > y ? a : b) */
+ires = (x > y ? a : b) ? b : a;
+@end smallexample
+
+
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
===================================================================
@@ -86,6 +86,7 @@ extern int default_builtin_vectorization
extern tree default_builtin_reciprocal (unsigned int, bool, bool);
extern bool default_builtin_vector_alignment_reachable (const_tree, bool);
+
extern bool
default_builtin_support_vector_misalignment (enum machine_mode mode,
const_tree,
===================================================================
@@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
if (icode == CODE_FOR_nothing)
return 0;
- comparison = vector_compare_rtx (op0, unsignedp, icode);
rtx_op1 = expand_normal (op1);
rtx_op2 = expand_normal (op2);
+
+ if (COMPARISON_CLASS_P (op0))
+ {
+ comparison = vector_compare_rtx (op0, unsignedp, icode);
+ create_output_operand (&ops[0], target, mode);
+ create_input_operand (&ops[1], rtx_op1, mode);
+ create_input_operand (&ops[2], rtx_op2, mode);
+ create_fixed_operand (&ops[3], comparison);
+ create_fixed_operand (&ops[4], XEXP (comparison, 0));
+ create_fixed_operand (&ops[5], XEXP (comparison, 1));
+ }
+ else
+ {
+ rtx rtx_op0;
+ rtx vec;
+
+ rtx_op0 = expand_normal (op0);
+ comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
+ vec = CONST0_RTX (mode);
+
+ create_output_operand (&ops[0], target, mode);
+ create_input_operand (&ops[1], rtx_op1, mode);
+ create_input_operand (&ops[2], rtx_op2, mode);
+ create_input_operand (&ops[3], comparison, mode);
+ create_input_operand (&ops[4], rtx_op0, mode);
+ create_input_operand (&ops[5], vec, mode);
+ }
- create_output_operand (&ops[0], target, mode);
- create_input_operand (&ops[1], rtx_op1, mode);
- create_input_operand (&ops[2], rtx_op2, mode);
- create_fixed_operand (&ops[3], comparison);
- create_fixed_operand (&ops[4], XEXP (comparison, 0));
- create_fixed_operand (&ops[5], XEXP (comparison, 1));
expand_insn (icode, 6, ops);
return ops[0].value;
}
===================================================================
@@ -51,6 +51,7 @@
#define GCC_TARGET_H
#include "insn-modes.h"
+#include "gimple.h"
#ifdef ENABLE_CHECKING
===================================================================
@@ -5930,12 +5930,21 @@ extract_muldiv_1 (tree t, tree c, enum t
}
/* Return a node which has the indicated constant VALUE (either 0 or
- 1), and is of the indicated TYPE. */
+ 1 for scalars and is either {-1,-1,..} or {0,0,...} for vectors),
+ and is of the indicated TYPE. */
tree
constant_boolean_node (int value, tree type)
{
- if (type == integer_type_node)
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree tval;
+
+ gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE);
+ tval = build_int_cst (TREE_TYPE (type), value ? -1 : 0);
+ return build_vector_from_val (type, tval);
+ }
+ else if (type == integer_type_node)
return value ? integer_one_node : integer_zero_node;
else if (type == boolean_type_node)
return value ? boolean_true_node : boolean_false_node;
@@ -9073,26 +9082,28 @@ fold_comparison (location_t loc, enum tr
floating-point, we can only do some of these simplifications.) */
if (operand_equal_p (arg0, arg1, 0))
{
+ tree arg0_type = TREE_TYPE (arg0);
+
switch (code)
{
case EQ_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ if (! FLOAT_TYPE_P (arg0_type)
+ || ! HONOR_NANS (TYPE_MODE (arg0_type)))
return constant_boolean_node (1, type);
break;
case GE_EXPR:
case LE_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ if (! FLOAT_TYPE_P (arg0_type)
+ || ! HONOR_NANS (TYPE_MODE (arg0_type)))
return constant_boolean_node (1, type);
return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
case NE_EXPR:
/* For NE, we can only do this simplification if integer
or we don't honor IEEE floating point NaNs. */
- if (FLOAT_TYPE_P (TREE_TYPE (arg0))
- && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ if (FLOAT_TYPE_P (arg0_type)
+ && HONOR_NANS (TYPE_MODE (arg0_type)))
break;
/* ... fall through ... */
case GT_EXPR:
===================================================================
@@ -0,0 +1,78 @@
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*(((type *) &(vec)) + idx))
+
+#define check_compare(count, res, i0, i1, c0, c1, op, fmt0, fmt1) \
+do { \
+ int __i; \
+ for (__i = 0; __i < count; __i ++) { \
+ if ((res)[__i] != \
+ ((i0)[__i] op (i1)[__i] \
+ ? (c0)[__i] : (c1)[__i])) \
+ { \
+ __builtin_printf (fmt0 " != (" fmt1 " " #op " " fmt1 " ? " \
+ fmt0 " : " fmt0 ")", \
+ (res)[__i], (i0)[__i], (i1)[__i],\
+ (c0)[__i], (c1)[__i]); \
+ __builtin_abort (); \
+ } \
+ } \
+} while (0)
+
+#define test(count, v0, v1, c0, c1, res, fmt0, fmt1); \
+do { \
+ res = (v0 > v1) ? c0: c1; \
+ check_compare (count, res, v0, v1, c0, c1, >, fmt0, fmt1); \
+ res = (v0 >= v1) ? c0: c1; \
+ check_compare (count, res, v0, v1, c0, c1, >=, fmt0, fmt1); \
+ res = (v0 < v1) ? c0: c1; \
+ check_compare (count, res, v0, v1, c0, c1, <, fmt0, fmt1); \
+ res = (v0 <= v1) ? c0: c1; \
+ check_compare (count, res, v0, v1, c0, c1, <=, fmt0, fmt1); \
+ res = (v0 == v1) ? c0: c1; \
+ check_compare (count, res, v0, v1, c0, c1, ==, fmt0, fmt1); \
+ res = (v0 != v1) ? c0: c1; \
+ check_compare (count, res, v0, v1, c0, c1, !=, fmt0, fmt1); \
+} while (0)
+
+
+int main (int argc, char *argv[]) {
+ vector (4, int) i0 = {argc, 1, 2, 10};
+ vector (4, int) i1 = {0, argc, 2, (int)-23};
+ vector (4, int) ires;
+ vector (4, float) f0 = {1., 7., (float)argc, 4.};
+ vector (4, float) f1 = {6., 2., 8., (float)argc};
+ vector (4, float) fres;
+
+ vector (2, double) d0 = {1., (double)argc};
+ vector (2, double) d1 = {6., 2.};
+ vector (2, double) dres;
+ vector (2, long) l0 = {argc, 3};
+ vector (2, long) l1 = {5, 8};
+ vector (2, long) lres;
+
+ /* Thes tests work fine. */
+ test (4, i0, i1, f0, f1, fres, "%f", "%i");
+ test (4, f0, f1, i0, i1, ires, "%i", "%f");
+ test (2, d0, d1, l0, l1, lres, "%i", "%f");
+ test (2, l0, l1, d0, d1, dres, "%f", "%i");
+
+ /* Condition expressed with a single variable. */
+ dres = l0 ? d0 : d1;
+ check_compare (2, dres, l0, ((vector (2, long)){0, 0}), d0, d1, !=, "%f", "%i");
+
+ lres = l1 ? l0 : l1;
+ check_compare (2, lres, l1, ((vector (2, long)){0, 0}), l0, l1, !=, "%i", "%i");
+
+ fres = i0 ? f0 : f1;
+ check_compare (4, fres, i0, ((vector (4, int)){0, 0, 0, 0}),
+ f0, f1, !=, "%f", "%i");
+
+ ires = i1 ? i0 : i1;
+ check_compare (4, ires, i1, ((vector (4, int)){0, 0, 0, 0}),
+ i0, i1, !=, "%i", "%i");
+
+ return 0;
+}
+
===================================================================
@@ -0,0 +1,123 @@
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define check_compare(count, res, i0, i1, op, fmt) \
+do { \
+ int __i; \
+ for (__i = 0; __i < count; __i ++) { \
+ if ((res)[__i] != ((i0)[__i] op (i1)[__i] ? -1 : 0)) \
+ { \
+ __builtin_printf ("%i != ((" fmt " " #op " " fmt " ? -1 : 0) ", \
+ (res)[__i], (i0)[__i], (i1)[__i]); \
+ __builtin_abort (); \
+ } \
+ } \
+} while (0)
+
+#define test(count, v0, v1, res, fmt); \
+do { \
+ res = (v0 > v1); \
+ check_compare (count, res, v0, v1, >, fmt); \
+ res = (v0 < v1); \
+ check_compare (count, res, v0, v1, <, fmt); \
+ res = (v0 >= v1); \
+ check_compare (count, res, v0, v1, >=, fmt); \
+ res = (v0 <= v1); \
+ check_compare (count, res, v0, v1, <=, fmt); \
+ res = (v0 == v1); \
+ check_compare (count, res, v0, v1, ==, fmt); \
+ res = (v0 != v1); \
+ check_compare (count, res, v0, v1, !=, fmt); \
+} while (0)
+
+
+int main (int argc, char *argv[]) {
+#define INT int
+ vector (4, INT) i0;
+ vector (4, INT) i1;
+ vector (4, int) ires;
+ int i;
+
+ i0 = (vector (4, INT)){argc, 1, 2, 10};
+ i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+ test (4, i0, i1, ires, "%i");
+#undef INT
+
+#define INT unsigned int
+ vector (4, int) ures;
+ vector (4, INT) u0;
+ vector (4, INT) u1;
+
+ u0 = (vector (4, INT)){argc, 1, 2, 10};
+ u1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+ test (4, u0, u1, ures, "%u");
+#undef INT
+
+
+#define SHORT short
+ vector (8, SHORT) s0;
+ vector (8, SHORT) s1;
+ vector (8, short) sres;
+
+ s0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
+ s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
+ test (8, s0, s1, sres, "%i");
+#undef SHORT
+
+#define SHORT unsigned short
+ vector (8, SHORT) us0;
+ vector (8, SHORT) us1;
+ vector (8, short) usres;
+
+ us0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
+ us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
+ test (8, us0, us1, usres, "%u");
+#undef SHORT
+
+#define CHAR signed char
+ vector (16, CHAR) c0;
+ vector (16, CHAR) c1;
+ vector (16, signed char) cres;
+
+ c0 = (vector (16, CHAR)){argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \
+ argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 };
+
+ c1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
+ 0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0};
+ test (16, c0, c1, cres, "%i");
+#undef CHAR
+
+#define CHAR unsigned char
+ vector (16, CHAR) uc0;
+ vector (16, CHAR) uc1;
+ vector (16, signed char) ucres;
+
+ uc0 = (vector (16, CHAR)){argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \
+ argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 };
+
+ uc1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
+ 0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0};
+ test (16, uc0, uc1, ucres, "%u");
+#undef CHAR
+/* Float comparison. */
+ vector (4, float) f0;
+ vector (4, float) f1;
+ vector (4, int) ifres;
+
+ f0 = (vector (4, float)){(float)argc, 1., 2., 10.};
+ f1 = (vector (4, float)){0., 3., 2., (float)-23};
+ test (4, f0, f1, ifres, "%f");
+
+/* Double comparison. */
+ vector (2, double) d0;
+ vector (2, double) d1;
+ vector (2, long) idres;
+
+ d0 = (vector (2, double)){(double)argc, 10.};
+ d1 = (vector (2, double)){0., (double)-23};
+ test (2, d0, d1, idres, "%f");
+
+
+ return 0;
+}
+
===================================================================
@@ -0,0 +1,154 @@
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*(((type *) &(vec)) + idx))
+
+#define check_compare(type, count, res, i0, i1, c0, c1, op, fmt) \
+do { \
+ int __i; \
+ for (__i = 0; __i < count; __i ++) { \
+ if (vidx (type, res, __i) != \
+ ((vidx (type, i0, __i) op vidx (type, i1, __i)) \
+ ? vidx (type, c0, __i) : vidx (type, c1, __i))) \
+ { \
+ __builtin_printf (fmt " != ((" fmt " " #op " " fmt ") ? " fmt " : " fmt ")", \
+ vidx (type, res, __i), vidx (type, i0, __i), vidx (type, i1, __i),\
+ vidx (type, c0, __i), vidx (type, c1, __i)); \
+ __builtin_abort (); \
+ } \
+ } \
+} while (0)
+
+#define test(type, count, v0, v1, c0, c1, res, fmt); \
+do { \
+ res = (v0 > v1) ? c0: c1; \
+ check_compare (type, count, res, v0, v1, c0, c1, >, fmt); \
+ res = (v0 >= v1) ? c0: c1; \
+ check_compare (type, count, res, v0, v1, c0, c1, >=, fmt); \
+ res = (v0 < v1) ? c0: c1; \
+ check_compare (type, count, res, v0, v1, c0, c1, <, fmt); \
+ res = (v0 <= v1) ? c0: c1; \
+ check_compare (type, count, res, v0, v1, c0, c1, <=, fmt); \
+ res = (v0 == v1) ? c0: c1; \
+ check_compare (type, count, res, v0, v1, c0, c1, ==, fmt); \
+ res = (v0 != v1) ? c0: c1; \
+ check_compare (type, count, res, v0, v1, c0, c1, !=, fmt); \
+} while (0)
+
+int main (int argc, char *argv[]) {
+#define INT int
+ vector (4, INT) i0; vector (4, INT) i1;
+ vector (4, INT) ic0; vector (4, INT) ic1;
+ vector (4, INT) ires;
+
+ i0 = (vector (4, INT)){argc, 1, 2, 10};
+ i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+
+ ic0 = (vector (4, INT)){1, argc, argc, 10};
+ ic1 = (vector (4, INT)){2, 3, argc, (INT)-23};
+ test (INT, 4, i0, i1, ic0, ic1, ires, "%i");
+#undef INT
+
+#define INT unsigned int
+ vector (4, INT) ui0; vector (4, INT) ui1;
+ vector (4, INT) uic0; vector (4, INT) uic1;
+ vector (4, INT) uires;
+
+ ui0 = (vector (4, INT)){argc, 1, 2, 10};
+ ui1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+
+ uic0 = (vector (4, INT)){1, argc, argc, 10};
+ uic1 = (vector (4, INT)){2, 3, argc, (INT)-23};
+ test (INT, 4, ui0, ui1, uic0, uic1, uires, "%u");
+#undef INT
+
+#define SHORT short
+ vector (8, SHORT) s0; vector (8, SHORT) s1;
+ vector (8, SHORT) sc0; vector (8, SHORT) sc1;
+ vector (8, short) sres;
+
+ s0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
+ s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
+
+ sc0 = (vector (8, SHORT)){argc, 1, argc, 10, 6, 87, (SHORT)-5, argc};
+ sc1= (vector (8, SHORT)){0, 5, 2, (SHORT)-23, 2, 10, (SHORT)-2, argc};
+
+ test (SHORT, 8, s0, s1, sc0, sc1, sres, "%i");
+#undef SHORT
+
+#define SHORT unsigned short
+ vector (8, SHORT) us0; vector (8, SHORT) us1;
+ vector (8, SHORT) usc0; vector (8, SHORT) usc1;
+ vector (8, SHORT) usres;
+
+ us0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
+ us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
+
+ usc0 = (vector (8, SHORT)){argc, 1, argc, 10, 6, 87, (SHORT)-5, argc};
+ usc1= (vector (8, SHORT)){0, 5, 2, (SHORT)-23, 2, 10, (SHORT)-2, argc};
+
+ test (SHORT, 8, us0, us1, usc0, usc1, usres, "%u");
+#undef SHORT
+
+#define CHAR signed char
+ vector (16, CHAR) c0; vector (16, CHAR) c1;
+ vector (16, CHAR) cc0; vector (16, CHAR) cc1;
+ vector (16, CHAR) cres;
+
+ c0 = (vector (16, CHAR)){argc, 1, 2, 4, 7, 87, (CHAR)-5, 2, \
+ argc, 1, 3, 18, 6, 87, (CHAR)-5, 2 };
+
+ c1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
+ 0, 3, 2, (CHAR)-5, 28, 10, (CHAR)-2, 0};
+
+ cc0 = (vector (16, CHAR)){argc, 1, argc, 4, 7, 87, (CHAR)-23, 2, \
+ 33, 8, 3, 18, 6, 87, (CHAR)-5, 41 };
+
+ cc1 = (vector (16, CHAR)){0, 27, 2, (CHAR)-1, 12, 10, (CHAR)-2, 0, \
+ 0, 3, 0x23, (CHAR)-5, 28, 1, (CHAR)-2, 0};
+
+ test (CHAR, 16, c0, c1, cc0, cc1, cres, "%i");
+#undef CHAR
+
+#define CHAR unsigned char
+ vector (16, CHAR) uc0; vector (16, CHAR) uc1;
+ vector (16, CHAR) ucc0; vector (16, CHAR) ucc1;
+ vector (16, CHAR) ucres;
+
+ uc0 = (vector (16, CHAR)){argc, 1, 2, 4, 7, 87, (CHAR)-5, 2, \
+ argc, 1, 3, 18, 6, 87, (CHAR)-5, 2 };
+
+ uc1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
+ 0, 3, 2, (CHAR)-5, 28, 10, (CHAR)-2, 0};
+
+ ucc0 = (vector (16, CHAR)){argc, 1, argc, 4, 7, 87, (CHAR)-23, 2, \
+ 33, 8, 3, 18, 6, 87, (CHAR)-5, 41 };
+
+ ucc1 = (vector (16, CHAR)){0, 27, 2, (CHAR)-1, 12, 10, (CHAR)-2, 0, \
+ 0, 3, 0x23, (CHAR)-5, 28, 1, (CHAR)-2, 0};
+
+ test (CHAR, 16, uc0, uc1, ucc0, ucc1, ucres, "%u");
+#undef CHAR
+
+/* Float version. */
+ vector (4, float) f0 = {1., 7., (float)argc, 4.};
+ vector (4, float) f1 = {6., 2., 8., (float)argc};
+ vector (4, float) fc0 = {3., 12., 4., (float)argc};
+ vector (4, float) fc1 = {7., 5., (float)argc, 6.};
+ vector (4, float) fres;
+
+ test (float, 4, f0, f1, fc0, fc1, fres, "%f");
+
+/* Double version. */
+ vector (2, double) d0 = {1., (double)argc};
+ vector (2, double) d1 = {6., 2.};
+ vector (2, double) dc0 = {(double)argc, 7.};
+ vector (2, double) dc1 = {7., 5.};
+ vector (2, double) dres;
+
+ //test (double, 2, d0, d1, dc0, dc1, dres, "%f");
+
+
+ return 0;
+}
+
===================================================================
@@ -0,0 +1,27 @@
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+/* Check that constant folding in
+ these simple cases works. */
+vector (4, int)
+foo (vector (4, int) x)
+{
+ return (x == x) + (x != x) + (x > x)
+ + (x < x) + (x >= x) + (x <= x);
+}
+
+int
+main (int argc, char *argv[])
+{
+ vector (4, int) t = {argc, 2, argc, 42};
+ vector (4, int) r;
+ int i;
+
+ r = foo (t);
+
+ for (i = 0; i < 4; i++)
+ if (r[i] != -3)
+ __builtin_abort ();
+
+ return 0;
+}
===================================================================
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+void
+foo (vector (4, int) x, vector (4, float) y)
+{
+ vector (4, int) p4;
+ vector (4, int) r4;
+ vector (4, unsigned int) q4;
+ vector (8, int) r8;
+ vector (4, float) f4;
+
+ r4 = x > y; /* { dg-error "comparing vectors with different element types" } */
+ r8 = (x != p4); /* { dg-error "incompatible types when assigning to type" } */
+ r8 == r4; /* { dg-error "comparing vectors with different number of elements" } */
+
+ r4 ? y : p4; /* { dg-error "vectors of different types involved in vector comparison" } */
+ r4 ? r4 : r8; /* { dg-error "vectors of different length found in vector comparison" } */
+ y ? f4 : y; /* { dg-error "non-integer type in vector condition" } */
+
+ /* Do not trigger that */
+ q4 ? p4 : r4; /* { "vector comparison must be of signed integer vector type" } */
+}
===================================================================
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+/* Test if C_MAYBE_CONST are folded correctly when
+ creating VEC_COND_EXPR. */
+
+typedef int vec __attribute__((vector_size(16)));
+
+vec i,j;
+extern vec a, b, c;
+
+vec
+foo (int x)
+{
+ return (x ? i : j) ? a : b;
+}
+
+vec
+bar (int x)
+{
+ return a ? (x ? i : j) : b;
+}
+
+vec
+baz (int x)
+{
+ return a ? b : (x ? i : j);
+}
===================================================================
@@ -8440,6 +8440,37 @@ expand_expr_real_2 (sepops ops, rtx targ
case UNGE_EXPR:
case UNEQ_EXPR:
case LTGT_EXPR:
+ if (TREE_CODE (ops->type) == VECTOR_TYPE)
+ {
+ enum tree_code code = ops->code;
+ tree arg0 = ops->op0;
+ tree arg1 = ops->op1;
+ tree arg_type = TREE_TYPE (arg0);
+ tree el_type = TREE_TYPE (arg_type);
+ tree t, ifexp, if_true, if_false;
+
+ el_type = lang_hooks.types.type_for_size (TYPE_PRECISION (el_type), 0);
+
+ ifexp = build2 (code, type, arg0, arg1);
+ if_true = build_vector_from_val (type, build_int_cst (el_type, -1));
+ if_false = build_vector_from_val (type, build_int_cst (el_type, 0));
+
+ if (arg_type != type)
+ {
+ if_true = convert (arg_type, if_true);
+ if_false = convert (arg_type, if_false);
+ t = build3 (VEC_COND_EXPR, arg_type, ifexp, if_true, if_false);
+ t = convert (type, t);
+ }
+ else
+ t = build3 (VEC_COND_EXPR, type, ifexp, if_true, if_false);
+
+ return expand_expr (t,
+ modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
+ tmode != VOIDmode ? tmode : mode,
+ modifier);
+ }
+
temp = do_store_flag (ops,
modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
tmode != VOIDmode ? tmode : mode);
===================================================================
@@ -4009,6 +4009,66 @@ ep_convert_and_check (tree type, tree ex
return convert (type, expr);
}
+static tree
+fold_build_vec_cond_expr (tree ifexp, tree op1, tree op2)
+{
+ bool wrap = true;
+ bool maybe_const = false;
+ bool need_convert = false;
+ tree vcond, tmp;
+ tree res_type = TREE_TYPE (op1);
+
+ if (! COMPARISON_CLASS_P (ifexp))
+ {
+ tree intt, rt;
+
+ intt = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (res_type)),0);
+ rt = build_vector_type (intt, TYPE_VECTOR_SUBPARTS (res_type));
+
+ ifexp = build2 (NE_EXPR, rt, ifexp,
+ build_vector_from_val (rt, build_int_cst (intt, 0)));
+ }
+
+ /* Currently the expansion of VEC_COND_EXPR does not allow
+ expessions where the type of vectors you compare differs
+ form the type of vectors you select from. For the time
+ being we insert implicit conversions. */
+ if (TREE_TYPE (ifexp) != res_type)
+ {
+ tree comp_type = TREE_TYPE (ifexp);
+
+ op1 = convert (comp_type, op1);
+ op2 = convert (comp_type, op2);
+ vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
+ need_convert = true;
+ }
+ else
+ vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);
+
+
+ /* Avoid C_MAYBE_CONST in VEC_COND_EXPR. */
+
+ tmp = c_fully_fold (TREE_OPERAND (vcond, 0), false, &maybe_const);
+ TREE_OPERAND (vcond, 0) = save_expr (tmp);
+ wrap &= maybe_const;
+
+ tmp = c_fully_fold (TREE_OPERAND (vcond, 1), false, &maybe_const);
+ TREE_OPERAND (vcond, 1) = save_expr (tmp);
+ wrap &= maybe_const;
+
+ tmp = c_fully_fold (TREE_OPERAND (vcond, 2), false, &maybe_const);
+ TREE_OPERAND (vcond, 2) = save_expr (tmp);
+ wrap &= maybe_const;
+
+ if (!wrap)
+ vcond = c_wrap_maybe_const (vcond, true);
+
+ if (need_convert)
+ vcond = convert (res_type, vcond);
+
+ return vcond;
+}
+
/* Build and return a conditional expression IFEXP ? OP1 : OP2. If
IFEXP_BCP then the condition is a call to __builtin_constant_p, and
if folded to an integer constant then the unselected half may
@@ -4058,6 +4118,49 @@ build_conditional_expr (location_t colon
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
+ if (TREE_CODE (TREE_TYPE (ifexp)) == VECTOR_TYPE)
+ {
+ if (TREE_CODE (type1) != VECTOR_TYPE
+ || TREE_CODE (type2) != VECTOR_TYPE)
+ {
+ error_at (colon_loc, "vector comparison arguments must be of "
+ "type vector");
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (ifexp))) != INTEGER_TYPE)
+ {
+ error_at (colon_loc, "non-integer type in vector condition");
+ return error_mark_node;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (type1) != TYPE_VECTOR_SUBPARTS (type2)
+ || TYPE_VECTOR_SUBPARTS (TREE_TYPE (ifexp))
+ != TYPE_VECTOR_SUBPARTS (type1))
+ {
+ error_at (colon_loc, "vectors of different length found in "
+ "vector comparison");
+ return error_mark_node;
+ }
+
+ if (TREE_TYPE (type1) != TREE_TYPE (type2))
+ {
+ error_at (colon_loc, "vectors of different types involved in "
+ "vector comparison");
+ return error_mark_node;
+ }
+
+ if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (ifexp)))
+ != TYPE_SIZE (TREE_TYPE (type1)))
+ {
+ error_at (colon_loc, "vector-condition element type must be "
+ "the same as result vector element type");
+ return error_mark_node;
+ }
+
+ return fold_build_vec_cond_expr (ifexp, op1, op2);
+ }
+
/* C90 does not permit non-lvalue arrays in conditional expressions.
In C99 they will be pointers by now. */
if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
@@ -9906,6 +10009,29 @@ build_binary_op (location_t location, en
case EQ_EXPR:
case NE_EXPR:
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+ {
+ tree intt;
+ if (TREE_TYPE (type0) != TREE_TYPE (type1))
+ {
+ error_at (location, "comparing vectors with different "
+ "element types");
+ return error_mark_node;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+ {
+ error_at (location, "comparing vectors with different "
+ "number of elements");
+ return error_mark_node;
+ }
+
+ /* Always construct signed integer vector type. */
+ intt = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (type0)),0);
+ result_type = build_vector_type (intt, TYPE_VECTOR_SUBPARTS (type0));
+ converted = 1;
+ break;
+ }
if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
warning_at (location,
OPT_Wfloat_equal,
@@ -10018,6 +10144,29 @@ build_binary_op (location_t location, en
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+ {
+ tree intt;
+ if (TREE_TYPE (type0) != TREE_TYPE (type1))
+ {
+ error_at (location, "comparing vectors with different "
+ "element types");
+ return error_mark_node;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+ {
+ error_at (location, "comparing vectors with different "
+ "number of elements");
+ return error_mark_node;
+ }
+
+ /* Always construct signed integer vector type. */
+ intt = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (type0)),0);
+ result_type = build_vector_type (intt, TYPE_VECTOR_SUBPARTS (type0));
+ converted = 1;
+ break;
+ }
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == FIXED_POINT_TYPE)
@@ -10425,6 +10574,10 @@ c_objc_common_truthvalue_conversion (loc
case FUNCTION_TYPE:
gcc_unreachable ();
+ case VECTOR_TYPE:
+ error_at (location, "used vector type where scalar is required");
+ return error_mark_node;
+
default:
break;
}
===================================================================
@@ -7064,6 +7064,22 @@ gimplify_expr (tree *expr_p, gimple_seq
}
break;
+ case VEC_COND_EXPR:
+ {
+ enum gimplify_status r0, r1, r2;
+
+ r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+ post_p, is_gimple_condexpr, fb_rvalue);
+ r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ recalculate_side_effects (*expr_p);
+
+ ret = MIN (r0, MIN (r1, r2));
+ }
+ break;
+
case TARGET_MEM_REF:
{
enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
@@ -7348,6 +7364,11 @@ gimplify_expr (tree *expr_p, gimple_seq
{
tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
+ /* Vector comparisons is a valid gimple expression
+ which could be lowered down later. */
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ goto expr_2;
+
if (!AGGREGATE_TYPE_P (type))
{
tree org_type = TREE_TYPE (*expr_p);
===================================================================
@@ -704,7 +704,10 @@ DEFTREECODE (TRUTH_NOT_EXPR, "truth_not_
The others are allowed only for integer (or pointer or enumeral)
or real types.
In all cases the operands will have the same type,
- and the value is always the type used by the language for booleans. */
+ and the value is either the type used by the language for booleans
+ or an integer vector type of the same size and with the same number
+ of elements as the comparison operands. True for a vector of
+ comparison results has all bits set while false is equal to zero. */
DEFTREECODE (LT_EXPR, "lt_expr", tcc_comparison, 2)
DEFTREECODE (LE_EXPR, "le_expr", tcc_comparison, 2)
DEFTREECODE (GT_EXPR, "gt_expr", tcc_comparison, 2)
===================================================================
@@ -30,11 +30,16 @@ along with GCC; see the file COPYING3.
#include "tree-pass.h"
#include "flags.h"
#include "ggc.h"
+#include "target.h"
/* Need to include rtl.h, expr.h, etc. for optabs. */
#include "expr.h"
#include "optabs.h"
+
+static void expand_vector_operations_1 (gimple_stmt_iterator *);
+
+
/* Build a constant of type TYPE, made of VALUE's bits replicated
every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */
static tree
@@ -125,6 +130,31 @@ do_binop (gimple_stmt_iterator *gsi, tre
return gimplify_build2 (gsi, code, inner_type, a, b);
}
+
+/* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
+
+ INNER_TYPE is the type of A and B elements
+
+ returned expression is of signed integer type with the
+ size equal to the size of INNER_TYPE. */
+static tree
+do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
+ tree bitpos, tree bitsize, enum tree_code code)
+{
+ tree cond;
+ tree comp_type;
+
+ a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
+ b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
+
+ comp_type = lang_hooks.types.type_for_size (TYPE_PRECISION (inner_type), 0);
+
+ cond = gimplify_build2 (gsi, code, comp_type, a, b);
+ return gimplify_build3 (gsi, COND_EXPR, comp_type, cond,
+ build_int_cst (comp_type, -1),
+ build_int_cst (comp_type, 0));
+}
+
/* Expand vector addition to scalars. This does bit twiddling
in order to increase parallelism:
@@ -333,6 +363,24 @@ uniform_vector_p (tree vec)
return NULL_TREE;
}
+/* Try to expand vector comparison expression OP0 CODE OP1 by
+ querying optab if the following expression:
+ VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
+ can be expanded. */
+static tree
+expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
+ tree op1, enum tree_code code)
+{
+ tree t;
+ if (! expand_vec_cond_expr_p (type, TYPE_MODE (type)))
+ t = expand_vector_piecewise (gsi, do_compare, type,
+ TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
+ else
+ t = gimplify_build2 (gsi, code, type, op0, op1);
+
+ return t;
+}
+
static tree
expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
gimple assign, enum tree_code code)
@@ -375,8 +423,27 @@ expand_vector_operation (gimple_stmt_ite
case BIT_NOT_EXPR:
return expand_vector_parallel (gsi, do_unop, type,
gimple_assign_rhs1 (assign),
- NULL_TREE, code);
+ NULL_TREE, code);
+ case EQ_EXPR:
+ case NE_EXPR:
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case UNEQ_EXPR:
+ case UNGT_EXPR:
+ case UNLT_EXPR:
+ case UNGE_EXPR:
+ case UNLE_EXPR:
+ case LTGT_EXPR:
+ case ORDERED_EXPR:
+ case UNORDERED_EXPR:
+ {
+ tree rhs1 = gimple_assign_rhs1 (assign);
+ tree rhs2 = gimple_assign_rhs2 (assign);
+ return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
+ }
default:
break;
}
@@ -432,6 +499,126 @@ type_for_widest_vector_mode (enum machin
}
}
+
+
+/* Expand vector condition EXP which should have the form
+ VEC_COND_EXPR<cond, vec0, vec1> into the following
+ vector:
+ {cond[i] != 0 ? vec0[i] : vec1[i], ... }
+ i changes from 0 to TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec0)). */
+static tree
+expand_vec_cond_expr_piecewise (gimple_stmt_iterator *gsi, tree exp)
+{
+ tree cond = TREE_OPERAND (exp, 0);
+ tree vec0 = TREE_OPERAND (exp, 1);
+ tree vec1 = TREE_OPERAND (exp, 2);
+ tree type = TREE_TYPE (vec0);
+ tree lhs, rhs, notmask;
+ tree var, new_rhs;
+ optab op = NULL;
+ gimple new_stmt;
+ gimple_stmt_iterator gsi_tmp;
+ tree t;
+
+
+ if (COMPARISON_CLASS_P (cond))
+ {
+ /* Expand vector condition inside of VEC_COND_EXPR. */
+ if (! expand_vec_cond_expr_p (TREE_TYPE (cond),
+ TYPE_MODE (TREE_TYPE (cond))))
+ {
+ tree op0 = TREE_OPERAND (cond, 0);
+ tree op1 = TREE_OPERAND (cond, 1);
+
+ var = create_tmp_reg (TREE_TYPE (cond), "cond");
+ new_rhs = expand_vector_piecewise (gsi, do_compare,
+ TREE_TYPE (cond),
+ TREE_TYPE (TREE_TYPE (op1)),
+ op0, op1, TREE_CODE (cond));
+
+ new_stmt = gimple_build_assign (var, new_rhs);
+ gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
+ update_stmt (gsi_stmt (*gsi));
+ }
+ else
+ var = cond;
+ }
+ else
+ var = cond;
+
+ gsi_tmp = *gsi;
+ gsi_prev (&gsi_tmp);
+
+ /* Expand VCOND<mask, v0, v1> to ((v0 & mask) | (v1 & ~mask)) */
+ lhs = gimplify_build2 (gsi, BIT_AND_EXPR, type, var, vec0);
+ notmask = gimplify_build1 (gsi, BIT_NOT_EXPR, type, var);
+ rhs = gimplify_build2 (gsi, BIT_AND_EXPR, type, notmask, vec1);
+ t = gimplify_build2 (gsi, BIT_IOR_EXPR, type, lhs, rhs);
+
+ /* Run vecower on the expresisons we have introduced. */
+ for (; gsi_tmp.ptr != gsi->ptr; gsi_next (&gsi_tmp))
+ expand_vector_operations_1 (&gsi_tmp);
+
+ return t;
+}
+
+static bool
+is_vector_comparison (gimple_stmt_iterator *gsi, tree expr)
+{
+ tree type = TREE_TYPE (expr);
+
+ if (TREE_CODE (expr) == VEC_COND_EXPR)
+ return true;
+
+ if (COMPARISON_CLASS_P (expr) && TREE_CODE (type) == VECTOR_TYPE)
+ return true;
+
+ if (TREE_CODE (expr) == BIT_IOR_EXPR || TREE_CODE (expr) == BIT_AND_EXPR
+ || TREE_CODE (expr) == BIT_XOR_EXPR)
+ return is_vector_comparison (gsi, TREE_OPERAND (expr, 0))
+ & is_vector_comparison (gsi, TREE_OPERAND (expr, 1));
+
+ if (TREE_CODE (expr) == VAR_DECL)
+ {
+ gimple_stmt_iterator gsi_tmp;
+ tree name = DECL_NAME (expr);
+ tree var = NULL_TREE;
+
+ gsi_tmp = *gsi;
+
+ for (; gsi_tmp.ptr; gsi_prev (&gsi_tmp))
+ {
+ gimple stmt = gsi_stmt (gsi_tmp);
+
+ if (gimple_code (stmt) != GIMPLE_ASSIGN)
+ continue;
+
+ if (TREE_CODE (gimple_assign_lhs (stmt)) == VAR_DECL
+ && DECL_NAME (gimple_assign_lhs (stmt)) == name)
+ return is_vector_comparison (&gsi_tmp,
+ gimple_assign_rhs_to_tree (stmt));
+ }
+ }
+
+ if (TREE_CODE (expr) == SSA_NAME)
+ {
+ enum tree_code code;
+ gimple exprdef = SSA_NAME_DEF_STMT (expr);
+
+ if (gimple_code (exprdef) != GIMPLE_ASSIGN)
+ return false;
+
+ if (TREE_CODE (gimple_expr_type (exprdef)) != VECTOR_TYPE)
+ return false;
+
+
+ return is_vector_comparison (gsi,
+ gimple_assign_rhs_to_tree (exprdef));
+ }
+
+ return false;
+}
+
/* Process one statement. If we identify a vector operation, expand it. */
static void
@@ -450,11 +637,41 @@ expand_vector_operations_1 (gimple_stmt_
code = gimple_assign_rhs_code (stmt);
rhs_class = get_gimple_rhs_class (code);
+ lhs = gimple_assign_lhs (stmt);
+
+ if (code == VEC_COND_EXPR)
+ {
+ tree exp = gimple_assign_rhs1 (stmt);
+ tree cond = TREE_OPERAND (exp, 0);
+
+ /* Try to get rid from the useless vector comparison
+ x != {0,0,...} which is inserted by the typechecker. */
+ if (COMPARISON_CLASS_P (cond) && TREE_CODE (cond) == NE_EXPR)
+ {
+ tree el = uniform_vector_p (TREE_OPERAND (cond, 1));
+
+ if (el != NULL_TREE && TREE_CONSTANT (el)
+ && TREE_CODE (TREE_TYPE (el)) == INTEGER_TYPE
+ && tree_low_cst (el, 0) == 0
+ && is_vector_comparison (gsi, TREE_OPERAND (cond, 0)))
+ cond = TREE_OPERAND (cond, 0);
+ }
+
+ if (expand_vec_cond_expr_p (TREE_TYPE (exp),
+ TYPE_MODE (TREE_TYPE (exp))))
+ {
+ update_stmt (gsi_stmt (*gsi));
+ return;
+ }
+
+ new_rhs = expand_vec_cond_expr_piecewise (gsi, exp);
+ gimple_assign_set_rhs_from_tree (gsi, new_rhs);
+ update_stmt (gsi_stmt (*gsi));
+ }
if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
return;
- lhs = gimple_assign_lhs (stmt);
rhs1 = gimple_assign_rhs1 (stmt);
type = gimple_expr_type (stmt);
if (rhs_class == GIMPLE_BINARY_RHS)
===================================================================
@@ -888,7 +888,7 @@ EXCEPT_H = except.h $(HASHTAB_H) vecprim
TARGET_DEF = target.def target-hooks-macros.h
C_TARGET_DEF = c-family/c-target.def target-hooks-macros.h
COMMON_TARGET_DEF = common/common-target.def target-hooks-macros.h
-TARGET_H = $(TM_H) target.h $(TARGET_DEF) insn-modes.h
+TGT = $(TM_H) target.h $(TARGET_DEF) insn-modes.h
C_TARGET_H = c-family/c-target.h $(C_TARGET_DEF)
COMMON_TARGET_H = common/common-target.h $(INPUT_H) $(COMMON_TARGET_DEF)
MACHMODE_H = machmode.h mode-classes.def insn-modes.h
@@ -919,8 +919,9 @@ TREE_H = tree.h all-tree.def tree.def c-
REGSET_H = regset.h $(BITMAP_H) hard-reg-set.h
BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) cfghooks.h
GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
- vecir.h $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H) tree-ssa-operands.h \
+ vecir.h $(GGC_H) $(BASIC_BLOCK_H) $(TGT) tree-ssa-operands.h \
tree-ssa-alias.h $(INTERNAL_FN_H)
+TARGET_H = $(TGT) gimple.h
GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
COVERAGE_H = coverage.h $(GCOV_IO_H)
DEMANGLE_H = $(srcdir)/../include/demangle.h
@@ -3185,7 +3186,7 @@ tree-vect-generic.o : tree-vect-generic.
$(TM_H) $(TREE_FLOW_H) $(GIMPLE_H) tree-iterator.h $(TREE_PASS_H) \
$(FLAGS_H) $(OPTABS_H) $(MACHMODE_H) $(EXPR_H) \
langhooks.h $(FLAGS_H) $(DIAGNOSTIC_H) gt-tree-vect-generic.h $(GGC_H) \
- coretypes.h insn-codes.h
+ coretypes.h insn-codes.h target.h
df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \
===================================================================
@@ -3191,6 +3191,38 @@ verify_gimple_comparison (tree type, tre
return true;
}
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ if (TREE_CODE (op0_type) != VECTOR_TYPE
+ || TREE_CODE (op1_type) != VECTOR_TYPE)
+ {
+ error ("non-vector operands in vector comparison");
+ debug_generic_expr (op0_type);
+ debug_generic_expr (op1_type);
+ return true;
+ }
+
+ if (!useless_type_conversion_p (op0_type, op1_type)
+ && !useless_type_conversion_p (op1_type, op0_type))
+ {
+ error ("type mismatch in vector comparison");
+ debug_generic_expr (op0_type);
+ debug_generic_expr (op1_type);
+ return true;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type)
+ && TYPE_PRECISION (TREE_TYPE (op0_type))
+ != TYPE_PRECISION (TREE_TYPE (type)))
+ {
+ error ("invalid vector comparison resulting type");
+ debug_generic_expr (type);
+ return true;
+ }
+
+ return false;
+ }
+
/* For comparisons we do not have the operations type as the
effective type the comparison is carried out in. Instead
we require that either the first operand is trivially
===================================================================
@@ -5339,6 +5339,15 @@ c_parser_conditional_expression (c_parse
tree eptype = NULL_TREE;
middle_loc = c_parser_peek_token (parser)->location;
+
+ if (TREE_CODE (TREE_TYPE (cond.value)) == VECTOR_TYPE)
+ {
+ error_at (middle_loc, "cannot ommit middle operator in "
+ "vector comparison");
+ ret.value = error_mark_node;
+ return ret;
+ }
+
pedwarn (middle_loc, OPT_pedantic,
"ISO C forbids omitting the middle term of a ?: expression");
warn_for_omitted_condop (middle_loc, cond.value);
@@ -5357,9 +5366,12 @@ c_parser_conditional_expression (c_parse
}
else
{
- cond.value
- = c_objc_common_truthvalue_conversion
- (cond_loc, default_conversion (cond.value));
+ if (TREE_CODE (TREE_TYPE (cond.value)) != VECTOR_TYPE)
+ {
+ cond.value
+ = c_objc_common_truthvalue_conversion
+ (cond_loc, default_conversion (cond.value));
+ }
c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
exp1 = c_parser_expression_conv (parser);
mark_exp_read (exp1.value);
===================================================================
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.
#include "tm.h"
#include "rtl.h"
#include "tree.h"
+#include "tree-flow.h"
#include "tm_p.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -18402,27 +18403,55 @@ ix86_expand_sse_fp_minmax (rtx dest, enu
return true;
}
+rtx rtx_build_vector_from_val (enum machine_mode, HOST_WIDE_INT);
+
+/* Returns a vector of mode MODE where all the elements are ARG. */
+rtx
+rtx_build_vector_from_val (enum machine_mode mode, HOST_WIDE_INT arg)
+{
+ rtvec v;
+ int units, i;
+ enum machine_mode inner;
+
+ units = GET_MODE_NUNITS (mode);
+ inner = GET_MODE_INNER (mode);
+ v = rtvec_alloc (units);
+ for (i = 0; i < units; ++i)
+ RTVEC_ELT (v, i) = gen_rtx_CONST_INT (inner, arg);
+
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
+}
+
/* Expand an sse vector comparison. Return the register with the result. */
static rtx
ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
- rtx op_true, rtx op_false)
+ rtx op_true, rtx op_false, bool no_comparison)
{
enum machine_mode mode = GET_MODE (dest);
rtx x;
- cmp_op0 = force_reg (mode, cmp_op0);
- if (!nonimmediate_operand (cmp_op1, mode))
- cmp_op1 = force_reg (mode, cmp_op1);
+ /* Avoid useless comparison. */
+ if (no_comparison)
+ {
+ cmp_op0 = force_reg (mode, cmp_op0);
+ x = cmp_op0;
+ }
+ else
+ {
+ cmp_op0 = force_reg (mode, cmp_op0);
+ if (!nonimmediate_operand (cmp_op1, mode))
+ cmp_op1 = force_reg (mode, cmp_op1);
+
+ x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
+ }
if (optimize
|| reg_overlap_mentioned_p (dest, op_true)
|| reg_overlap_mentioned_p (dest, op_false))
dest = gen_reg_rtx (mode);
- x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
-
return dest;
}
@@ -18434,8 +18463,14 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp
{
enum machine_mode mode = GET_MODE (dest);
rtx t2, t3, x;
-
- if (op_false == CONST0_RTX (mode))
+ rtx mask_true;
+
+ if (rtx_equal_p (op_true, rtx_build_vector_from_val (mode, -1))
+ && rtx_equal_p (op_false, CONST0_RTX (mode)))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, dest, cmp));
+ }
+ else if (op_false == CONST0_RTX (mode))
{
op_true = force_reg (mode, op_true);
x = gen_rtx_AND (mode, cmp, op_true);
@@ -18512,7 +18547,7 @@ ix86_expand_fp_movcc (rtx operands[])
return true;
tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1,
- operands[2], operands[3]);
+ operands[2], operands[3], false);
ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
return true;
}
@@ -18555,7 +18590,7 @@ ix86_expand_fp_vcond (rtx operands[])
return true;
cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
- operands[1], operands[2]);
+ operands[1], operands[2], false);
ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
return true;
}
@@ -18569,12 +18604,27 @@ ix86_expand_int_vcond (rtx operands[])
enum rtx_code code = GET_CODE (operands[3]);
bool negate = false;
rtx x, cop0, cop1;
+ rtx comp, cond0, cond1;
+ bool single_var = false;
+ comp = operands[3];
cop0 = operands[4];
cop1 = operands[5];
+ /* If we have a single-variable vcond, the second comparison
+ operand is {0,0...}. Replace it with CONST0_RTX, in order
+ to get some more optimisations later. */
+ if (GET_CODE (comp) == NE && XEXP (comp, 0) == NULL_RTX
+ && XEXP (comp, 1) == NULL_RTX)
+ {
+ cond0 = cop0;
+ cond1 = CONST0_RTX (mode);
+ single_var = true;
+ }
+
+
/* XOP supports all of the comparisons on all vector int types. */
- if (!TARGET_XOP)
+ if (!TARGET_XOP && !single_var)
{
/* Canonicalize the comparison to EQ, GT, GTU. */
switch (code)
@@ -18681,8 +18731,16 @@ ix86_expand_int_vcond (rtx operands[])
}
}
- x = ix86_expand_sse_cmp (operands[0], code, cop0, cop1,
- operands[1+negate], operands[2-negate]);
+ if (single_var)
+ {
+ x = ix86_expand_sse_cmp (operands[0], code, cond0, cond1,
+ operands[1+negate], operands[2-negate], true);
+ }
+ else
+ {
+ x = ix86_expand_sse_cmp (operands[0], code, cop0, cop1,
+ operands[1+negate], operands[2-negate], false);
+ }
ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
operands[2-negate]);
@@ -18774,7 +18832,7 @@ ix86_expand_sse_unpack (rtx operands[2],
tmp = force_reg (imode, CONST0_RTX (imode));
else
tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
- operands[1], pc_rtx, pc_rtx);
+ operands[1], pc_rtx, pc_rtx, false);
emit_insn (unpack (dest, operands[1], tmp));
}