Index: c-family/c-common.c =================================================================== --- c-family/c-common.c (revision 191613) +++ c-family/c-common.c (working copy) @@ -11147,11 +11147,105 @@ convert_vector_to_pointer_for_subscript c_common_mark_addressable_vec (*vecp); type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); type = build_pointer_type (type); type1 = build_pointer_type (TREE_TYPE (*vecp)); *vecp = build1 (ADDR_EXPR, type1, *vecp); *vecp = convert (type, *vecp); } } +/* Convert scalar to vector for the range of operations. */ +enum stv_conv +scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1) +{ + tree type0 = TREE_TYPE (op0); + tree type1 = TREE_TYPE (op1); + bool integer_only_op = false; + enum stv_conv ret = stv_firstarg; + + gcc_assert (TREE_CODE (type0) == VECTOR_TYPE + || TREE_CODE (type1) == VECTOR_TYPE); + switch (code) + { + case RSHIFT_EXPR: + case LSHIFT_EXPR: + if (TREE_CODE (type0) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + else + return stv_firstarg; + } + break; + + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case BIT_AND_EXPR: + integer_only_op = true; + /* ... fall through ... */ + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case RDIV_EXPR: + case EQ_EXPR: + case NE_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + /* What about UNLT_EXPR? */ + if (TREE_CODE (type0) == VECTOR_TYPE) + { + tree tmp; + ret = stv_secondarg; + /* Swap TYPE0 with TYPE1 and OP0 with OP1 */ + tmp = type0; type0 = type1; type1 = tmp; + tmp = op0; op0 = op1; op1 = tmp; + } + + if (TREE_CODE (type0) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + return ret; + } + else if (!integer_only_op + /* Allow integer --> real conversion if safe. */ + && (TREE_CODE (type0) == REAL_TYPE + || TREE_CODE (type0) == INTEGER_TYPE) + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1))) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + return ret; + } + default: + break; + } + + return stv_nothing; +} + #include "gt-c-family-c-common.h" Index: c-family/c-common.h =================================================================== --- c-family/c-common.h (revision 191613) +++ c-family/c-common.h (working copy) @@ -1116,11 +1116,22 @@ struct GTY(()) tree_userdef_literal { #define USERDEF_LITERAL_NUM_STRING(NODE) \ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string) #define USERDEF_LITERAL_TYPE(NODE) \ (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE))) extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string); extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree); +/* Possibe cases of scalar_to_vector conversion. */ +enum stv_conv { + stv_error, /* Error occured. */ + stv_nothing, /* Nothing happened. */ + stv_firstarg, /* First argument must be expanded. */ + stv_secondarg /* Second argument must be expanded. */ +}; + +extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code, + tree op0, tree op1); + #endif /* ! GCC_C_COMMON_H */ Index: testsuite/g++.dg/ext/vector5.C =================================================================== --- testsuite/g++.dg/ext/vector5.C (revision 191613) +++ testsuite/g++.dg/ext/vector5.C (working copy) @@ -1,8 +1,8 @@ // PR c++/30022 // { dg-do compile } void foo() { int __attribute__((vector_size(8))) v; - v = 1/v; // { dg-error "invalid operands of types" } + v = 1/v; } Index: testsuite/c-c++-common/init-vec-1.c =================================================================== --- testsuite/c-c++-common/init-vec-1.c (revision 191610) +++ testsuite/c-c++-common/init-vec-1.c (working copy) @@ -1,4 +1,4 @@ /* Don't ICE or emit spurious errors when init a vector with a scalar. */ /* { dg-do compile } */ typedef float v2sf __attribute__ ((vector_size (8))); -v2sf a = 0.0; /* { dg-error "incompatible types" } */ +v2sf a = 0.0; /* { dg-error "incompatible types|cannot convert" } */ Index: testsuite/c-c++-common/torture/vector-shift1.c =================================================================== --- testsuite/c-c++-common/torture/vector-shift1.c (revision 191610) +++ testsuite/c-c++-common/torture/vector-shift1.c (working copy) @@ -1,10 +1,11 @@ +/* { dg-do run } */ #define vector __attribute__((vector_size(8*sizeof(short)))) int main (int argc, char *argv[]) { vector short v0 = {argc,2,3,4,5,6,7}; vector short v1 = {2,2,2,2,2,2,2}; vector short r1,r2,r3,r4; int i = 8; r1 = v0 << 1; r2 = v0 >> 1; Index: testsuite/c-c++-common/scal-to-vec1.c =================================================================== --- testsuite/c-c++-common/scal-to-vec1.c (revision 191610) +++ testsuite/c-c++-common/scal-to-vec1.c (working copy) @@ -6,21 +6,21 @@ __attribute__((vector_size((elcount)*sizeof(type)))) type #define vidx(type, vec, idx) (*((type *) &(vec) + idx)) extern float sfl; extern int sint; extern long long sll; int main (int argc, char *argv[]) { - vector(8, short) v0 = {argc, 1,2,3,4,5,6,7}; + vector(8, short) v0 = {(short)argc, 1,2,3,4,5,6,7}; vector(8, short) v1; vector(4, float) f0 = {1., 2., 3., 4.}; vector(4, float) f1, f2; vector(4, int) i0 = {1,2,3,4}; vector(4, int) i1, i2; int i = 12; @@ -28,16 +28,16 @@ int main (int argc, char *argv[]) { v1 = i + v0; /* { dg-error "conversion of scalar to vector" } */ v1 = 99999 + v0; /* { dg-error "conversion of scalar to vector" } */ f1 = d + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = 1.3 + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = sll + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar to vector" } */ /* convert.c should take care of this. */ - i1 = sfl + i0; /* { dg-error "can't convert value to a vector" } */ - i1 = 1.5 + i0; /* { dg-error "can't convert value to a vector" } */ - v1 = d + v0; /* { dg-error "can't convert value to a vector" } */ + i1 = sfl + i0; /* { dg-error "can't convert value to a vector|invalid operands" } */ + i1 = 1.5 + i0; /* { dg-error "can't convert value to a vector|invalid operands" } */ + v1 = d + v0; /* { dg-error "can't convert value to a vector|invalid operands" } */ return 0; } Index: testsuite/c-c++-common/vector-scalar.c =================================================================== --- testsuite/c-c++-common/vector-scalar.c (revision 0) +++ testsuite/c-c++-common/vector-scalar.c (revision 0) @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +typedef float vecf __attribute__ ((vector_size (4 * sizeof (float)))); +typedef short veci __attribute__ ((vector_size (8 * sizeof (short)))); + +void f (vecf *d, veci *i) +{ + (void) ((*d *= 2) < 0); + (void) ((((*i - 1) >> 2) != 0) | *i); +} Property changes on: testsuite/c-c++-common/vector-scalar.c ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision URL Added: svn:eol-style + native Index: c/c-typeck.c =================================================================== --- c/c-typeck.c (revision 191613) +++ c/c-typeck.c (working copy) @@ -33,38 +33,31 @@ along with GCC; see the file COPYING3. #include "langhooks.h" #include "c-tree.h" #include "c-lang.h" #include "flags.h" #include "intl.h" #include "target.h" #include "tree-iterator.h" #include "bitmap.h" #include "gimple.h" #include "c-family/c-objc.h" +#include "c-family/c-common.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ enum impl_conv { ic_argpass, ic_assign, ic_init, ic_return }; -/* Possibe cases of scalar_to_vector conversion. */ -enum stv_conv { - stv_error, /* Error occured. */ - stv_nothing, /* Nothing happened. */ - stv_firstarg, /* First argument must be expanded. */ - stv_secondarg /* Second argument must be expanded. */ -}; - /* The level of nesting inside "__alignof__". */ int in_alignof; /* The level of nesting inside "sizeof". */ int in_sizeof; /* The level of nesting inside "typeof". */ int in_typeof; /* The argument of last parsed sizeof expression, only to be tested @@ -9368,102 +9361,20 @@ push_cleanup (tree decl, tree cleanup, b bool stmt_expr; code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR; stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup); add_stmt (stmt); stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list); list = push_stmt_list (); TREE_OPERAND (stmt, 0) = list; STATEMENT_LIST_STMT_EXPR (list) = stmt_expr; } - -/* Convert scalar to vector for the range of operations. */ -static enum stv_conv -scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1) -{ - tree type0 = TREE_TYPE (op0); - tree type1 = TREE_TYPE (op1); - bool integer_only_op = false; - enum stv_conv ret = stv_firstarg; - - gcc_assert (TREE_CODE (type0) == VECTOR_TYPE - || TREE_CODE (type1) == VECTOR_TYPE); - switch (code) - { - case RSHIFT_EXPR: - case LSHIFT_EXPR: - if (TREE_CODE (type0) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) - { - if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) - { - error_at (loc, "conversion of scalar to vector " - "involves truncation"); - return stv_error; - } - else - return stv_firstarg; - } - break; - - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case BIT_AND_EXPR: - integer_only_op = true; - /* ... fall through ... */ - - case PLUS_EXPR: - case MINUS_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case TRUNC_MOD_EXPR: - case RDIV_EXPR: - if (TREE_CODE (type0) == VECTOR_TYPE) - { - tree tmp; - ret = stv_secondarg; - /* Swap TYPE0 with TYPE1 and OP0 with OP1 */ - tmp = type0; type0 = type1; type1 = tmp; - tmp = op0; op0 = op1; op1 = tmp; - } - - if (TREE_CODE (type0) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) - { - if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) - { - error_at (loc, "conversion of scalar to vector " - "involves truncation"); - return stv_error; - } - return ret; - } - else if (!integer_only_op - /* Allow integer --> real conversion if safe. */ - && (TREE_CODE (type0) == REAL_TYPE - || TREE_CODE (type0) == INTEGER_TYPE) - && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1))) - { - if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) - { - error_at (loc, "conversion of scalar to vector " - "involves truncation"); - return stv_error; - } - return ret; - } - default: - break; - } - - return stv_nothing; -} /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. LOCATION is the operator's location. This function differs from `build' in several ways: the data type of the result is computed and recorded in it, warnings are generated if arg data types are invalid, special handling for addition and subtraction of pointers is known, and some optimization is done (operations on narrow ints are done in the narrower type when that gives the same result). Index: c/Make-lang.in =================================================================== --- c/Make-lang.in (revision 191613) +++ c/Make-lang.in (working copy) @@ -185,12 +185,12 @@ c/c-objc-common.o : c/c-objc-common.c c/ c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \ $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \ gt-c-c-parser.h langhooks.h \ $(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \ c-family/c-objc.h c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \ langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \ - c-family/c-objc.h + c-family/c-objc.h c-family/c-common.h Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 191613) +++ cp/typeck.c (working copy) @@ -3855,20 +3855,53 @@ cp_build_binary_op (location_t location, || (!null_ptr_cst_p (orig_op1) && !TYPE_PTR_OR_PTRMEM_P (type1))) && (complain & tf_warning)) { source_location loc = expansion_point_location_if_in_system_header (input_location); warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic"); } + /* In case when one of the operands of the binary operation is + a vector and another is a scalar -- convert scalar to vector. */ + if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE)) + { + enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1); + + switch (convert_flag) + { + case stv_error: + return error_mark_node; + case stv_firstarg: + { + op0 = convert (TREE_TYPE (type1), op0); + op0 = build_vector_from_val (type1, op0); + type0 = TREE_TYPE (op0); + code0 = TREE_CODE (type0); + converted = 1; + break; + } + case stv_secondarg: + { + op1 = convert (TREE_TYPE (type0), op1); + op1 = build_vector_from_val (type0, op1); + type1 = TREE_TYPE (op1); + code1 = TREE_CODE (type1); + converted = 1; + break; + } + default: + break; + } + } + switch (code) { case MINUS_EXPR: /* Subtraction of two similar pointers. We must subtract them as integers, then divide by object size. */ if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) return pointer_diff (op0, op1, common_pointer_type (type0, type1), complain); @@ -3978,21 +4011,27 @@ cp_build_binary_op (location_t location, case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: result_type = boolean_type_node; break; /* Shift operations: result has same type as first operand; always convert second operand to int. Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + { + result_type = type0; + converted = 1; + } + else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) { result_type = type0; converted = 1; } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -4015,21 +4054,27 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } break; case LSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + { + result_type = type0; + converted = 1; + } + else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) { result_type = type0; converted = 1; } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; Index: fold-const.c =================================================================== --- fold-const.c (revision 191613) +++ fold-const.c (working copy) @@ -12886,21 +12886,21 @@ fold_binary_loc (location_t loc, if (TREE_INT_CST_HIGH (arg01) == 0 && TREE_INT_CST_LOW (arg01) == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1)) { if (TYPE_UNSIGNED (itype)) { itype = signed_type_for (itype); arg00 = fold_convert_loc (loc, itype, arg00); } return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR, - type, arg00, build_int_cst (itype, 0)); + type, arg00, build_zero_cst (itype)); } } /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y. */ if (integer_zerop (arg1) && TREE_CODE (arg0) == BIT_XOR_EXPR) return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)); /* (X ^ Y) == Y becomes X == 0. We know that Y has no side-effects. */