diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 2 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/call.c | 86 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/vector19.C | 56 | ||||
-rw-r--r-- | gcc/tree.c | 11 |
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); +} + @@ -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; |