aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c2
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/call.c86
-rw-r--r--gcc/cp/typeck.c3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/vector19.C56
-rw-r--r--gcc/tree.c11
9 files changed, 170 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0b86552..542856a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/54427
+ * tree.c (signed_or_unsigned_type_for): Handle vectors.
+
2012-10-25 Jan Hubicka <jh@suse.cz>
* ipa-inline.c (recursive_inlining): Redirect to master
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index cf43137..82f1fa2 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/54427
+ * c-common.c (scalar_to_vector): Handle VEC_COND_EXPR.
+
2012-10-23 Joseph Myers <joseph@codesourcery.com>
* c-common.h (pch_cpp_save_state): Declare.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 34cfb98..840bc84 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -11474,6 +11474,8 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
integer_only_op = true;
/* ... fall through ... */
+ case VEC_COND_EXPR:
+
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9d5dde7..c7c67e2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2012-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/54427
+ * typeck.c (build_x_conditional_expr): Handle VEC_COND_EXPR.
+ * call.c (build_conditional_expr_1): Likewise.
+
2012-10-25 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/34892
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e21049b..df24105 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4373,18 +4373,90 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
arg2 = arg1 = save_expr (arg1);
}
+ /* If something has already gone wrong, just pass that fact up the
+ tree. */
+ if (error_operand_p (arg1)
+ || error_operand_p (arg2)
+ || error_operand_p (arg3))
+ return error_mark_node;
+
+ orig_arg2 = arg2;
+ orig_arg3 = arg3;
+
+ if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1)))
+ {
+ arg1 = force_rvalue (arg1, complain);
+ arg2 = force_rvalue (arg2, complain);
+ arg3 = force_rvalue (arg3, complain);
+
+ tree arg1_type = TREE_TYPE (arg1);
+ arg2_type = TREE_TYPE (arg2);
+ arg3_type = TREE_TYPE (arg3);
+
+ if (TREE_CODE (arg2_type) != VECTOR_TYPE
+ && TREE_CODE (arg3_type) != VECTOR_TYPE)
+ {
+ if (complain & tf_error)
+ error ("at least one operand of a vector conditional operator "
+ "must be a vector");
+ return error_mark_node;
+ }
+
+ if ((TREE_CODE (arg2_type) == VECTOR_TYPE)
+ != (TREE_CODE (arg3_type) == VECTOR_TYPE))
+ {
+ enum stv_conv convert_flag =
+ scalar_to_vector (input_location, VEC_COND_EXPR, arg2, arg3,
+ complain & tf_error);
+
+ switch (convert_flag)
+ {
+ case stv_error:
+ return error_mark_node;
+ case stv_firstarg:
+ {
+ arg2 = convert (TREE_TYPE (arg3_type), arg2);
+ arg2 = build_vector_from_val (arg3_type, arg2);
+ arg2_type = TREE_TYPE (arg2);
+ break;
+ }
+ case stv_secondarg:
+ {
+ arg3 = convert (TREE_TYPE (arg2_type), arg3);
+ arg3 = build_vector_from_val (arg2_type, arg3);
+ arg3_type = TREE_TYPE (arg3);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (!same_type_p (arg2_type, arg3_type)
+ || TYPE_VECTOR_SUBPARTS (arg1_type)
+ != TYPE_VECTOR_SUBPARTS (arg2_type)
+ || TYPE_SIZE (arg1_type) != TYPE_SIZE (arg2_type))
+ {
+ if (complain & tf_error)
+ error ("incompatible vector types in conditional expression: "
+ "%qT, %qT and %qT", TREE_TYPE (arg1), TREE_TYPE (orig_arg2),
+ TREE_TYPE (orig_arg3));
+ return error_mark_node;
+ }
+
+ if (!COMPARISON_CLASS_P (arg1))
+ arg1 = build2 (NE_EXPR, signed_type_for (arg1_type), arg1,
+ build_zero_cst (arg1_type));
+ return build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
+ }
+
/* [expr.cond]
The first expression is implicitly converted to bool (clause
_conv_). */
arg1 = perform_implicit_conversion_flags (boolean_type_node, arg1, complain,
LOOKUP_NORMAL);
-
- /* If something has already gone wrong, just pass that fact up the
- tree. */
- if (error_operand_p (arg1)
- || error_operand_p (arg2)
- || error_operand_p (arg3))
+ if (error_operand_p (arg1))
return error_mark_node;
/* [expr.cond]
@@ -4394,8 +4466,6 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
- orig_arg2 = arg2;
- orig_arg3 = arg3;
arg2_type = unlowered_expr_type (arg2);
arg3_type = unlowered_expr_type (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index eaa0935..2514b6f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5810,7 +5810,8 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2,
}
expr = build_conditional_expr (ifexp, op1, op2, complain);
- if (processing_template_decl && expr != error_mark_node)
+ if (processing_template_decl && expr != error_mark_node
+ && TREE_CODE (expr) != VEC_COND_EXPR)
{
tree min = build_min_non_dep (COND_EXPR, expr,
orig_ifexp, orig_op1, orig_op2);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6c0a2f7..30fced6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/54427
+ * g++.dg/ext/vector19.C: New testcase.
+
2012-10-25 Richard Biener <rguenther@suse.de>
PR tree-optimization/54902
diff --git a/gcc/testsuite/g++.dg/ext/vector19.C b/gcc/testsuite/g++.dg/ext/vector19.C
new file mode 100644
index 0000000..ec08e7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vector19.C
@@ -0,0 +1,56 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-std=c++11 -mavx2" } */
+
+// The target restrictions and the -mavx2 flag are meant to disappear
+// once vector lowering is in place.
+
+typedef double vec __attribute__((vector_size(2*sizeof(double))));
+typedef signed char vec2 __attribute__((vector_size(16)));
+typedef unsigned char vec2u __attribute__((vector_size(16)));
+
+void f (vec *x, vec *y, vec *z)
+{
+ *x = (*y < *z) ? *x : *y;
+}
+
+void g (vec *x, vec *y, vec *z)
+{
+ *x = (*y < *z) ? *x : 42;
+}
+
+void h (vec *x, vec *y, vec *z)
+{
+ *x = (*y < *z) ? 3. : *y;
+}
+
+void i1 (vec *x, vec *y, vec *z)
+{
+ auto c = *y < *z;
+ *x = c ? *x : *y;
+}
+
+void i2 (vec2 *x, vec2 *y, vec2u *z)
+{
+ *x = *y ? *x : *y;
+ *y = *z ? *x : *y;
+}
+
+void j (vec2 *x, vec2 *y, vec2 *z, vec *t)
+{
+ *x = (*y < *z) ? *x : 4.2; /* { dg-error "" } */
+ *y = (*x < *z) ? 2.5 : *y; /* { dg-error "" } */
+ *t = *t ? *t : *t; /* { dg-error "" } */
+ *z = (*x < *z) ? '1' : '0'; /* { dg-error "" } */
+ // The last one may eventually be accepted.
+}
+
+template <class A, class B>
+auto k (A *a, B b) -> decltype (*a ? *a : b);
+
+void k (...) {}
+
+void l (vec2 *v, double x)
+{
+ k (v, x);
+}
+
diff --git a/gcc/tree.c b/gcc/tree.c
index 7cb1ea1..c3642e3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10241,6 +10241,17 @@ signed_or_unsigned_type_for (int unsignedp, tree type)
if (TREE_CODE (type) == INTEGER_TYPE && TYPE_UNSIGNED (type) == unsignedp)
return type;
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree inner = TREE_TYPE (type);
+ tree inner2 = signed_or_unsigned_type_for (unsignedp, inner);
+ if (!inner2)
+ return NULL_TREE;
+ if (inner == inner2)
+ return type;
+ return build_vector_type (inner2, TYPE_VECTOR_SUBPARTS (type));
+ }
+
if (!INTEGRAL_TYPE_P (type)
&& !POINTER_TYPE_P (type))
return NULL_TREE;