Commit a212e43f by Marc Glisse Committed by Marc Glisse

re PR c++/54427 (Expose more vector extensions)

2012-10-09  Marc Glisse  <marc.glisse@inria.fr>

	PR c++/54427

c/
	* c-typeck.c: Include c-common.h.
	(enum stv_conv): Moved to c-common.h.
	(scalar_to_vector): Moved to c-common.c.
	(build_binary_op): Adapt to scalar_to_vector's new prototype.
	* Make-lang.in: c-typeck.c depends on c-common.h.

c-family/
	* c-common.c (scalar_to_vector): Moved from c-typeck.c. Support
	more operations. Make error messages optional.
	* c-common.h (enum stv_conv): Moved from c-typeck.c.
	(scalar_to_vector): Declare.

cp/
	* typeck.c (cp_build_binary_op): Handle mixed scalar-vector
	operations.
	[LSHIFT_EXPR, RSHIFT_EXPR]: Likewise.

gcc/
	* fold-const.c (fold_binary_loc): Use build_zero_cst instead of
	build_int_cst for a potential vector.

testsuite/
	* c-c++-common/vector-scalar.c: New testcase.
	* g++.dg/ext/vector18.C: New testcase.
	* g++.dg/ext/vector5.C: This is not an error anymore.
	* gcc.dg/init-vec-1.c: Move ...
	* c-c++-common/init-vec-1.c: ... here. Adapt error message.
	* gcc.c-torture/execute/vector-shift1.c: Move ...
	* c-c++-common/torture/vector-shift1.c: ... here.
	* gcc.dg/scal-to-vec1.c: Move ...
	* c-c++-common/scal-to-vec1.c: ... here. Avoid narrowing for
	C++11. Adapt error messages.
	* gcc.dg/convert-vec-1.c: Move ...
	* c-c++-common/convert-vec-1.c: ... here.
	* gcc.dg/scal-to-vec2.c: Move ...
	* c-c++-common/scal-to-vec2.c: ... here.

From-SVN: r192238
parent f5220359
2012-10-09 Marc Glisse <marc.glisse@inria.fr>
PR c++/54427
* fold-const.c (fold_binary_loc): Use build_zero_cst instead of
build_int_cst for a potential vector.
2012-10-08 Uros Bizjak <ubizjak@gmail.com> 2012-10-08 Uros Bizjak <ubizjak@gmail.com>
* config/i386/atom.md (atom_sse_4): Merge atom_sse_attr attibutes. * config/i386/atom.md (atom_sse_4): Merge atom_sse_attr attibutes.
......
2012-10-09 Marc Glisse <marc.glisse@inria.fr>
PR c++/54427
* c-common.c (scalar_to_vector): Moved from c-typeck.c. Support
more operations. Make error messages optional.
* c-common.h (enum stv_conv): Moved from c-typeck.c.
(scalar_to_vector): Declare.
2012-10-08 Jason Merrill <jason@redhat.com> 2012-10-08 Jason Merrill <jason@redhat.com>
* c-common.c (c_common_reswords): Add thread_local. * c-common.c (c_common_reswords): Add thread_local.
......
...@@ -11253,6 +11253,109 @@ convert_vector_to_pointer_for_subscript (location_t loc, ...@@ -11253,6 +11253,109 @@ convert_vector_to_pointer_for_subscript (location_t loc,
} }
} }
/* Determine which of the operands, if any, is a scalar that needs to be
converted to a vector, for the range of operations. */
enum stv_conv
scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
bool complain)
{
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)
{
/* Most GENERIC binary expressions require homogeneous arguments.
LSHIFT_EXPR and RSHIFT_EXPR are exceptions and accept a first
argument that is a vector and a second one that is a scalar, so
we never return stv_secondarg for them. */
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))
{
if (complain)
error_at (loc, "conversion of scalar %qT to vector %qT "
"involves truncation", type0, type1);
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))
{
if (complain)
error_at (loc, "conversion of scalar %qT to vector %qT "
"involves truncation", type0, type1);
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))
{
if (complain)
error_at (loc, "conversion of scalar %qT to vector %qT "
"involves truncation", type0, type1);
return stv_error;
}
return ret;
}
default:
break;
}
return stv_nothing;
}
/* Return true iff ALIGN is an integral constant that is a fundamental /* Return true iff ALIGN is an integral constant that is a fundamental
alignment, as defined by [basic.align] in the c++-11 alignment, as defined by [basic.align] in the c++-11
specifications. specifications.
......
...@@ -1123,4 +1123,15 @@ extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string); ...@@ -1123,4 +1123,15 @@ 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); 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, bool);
#endif /* ! GCC_C_COMMON_H */ #endif /* ! GCC_C_COMMON_H */
2012-10-09 Marc Glisse <marc.glisse@inria.fr>
PR c++/54427
* c-typeck.c: Include c-common.h.
(enum stv_conv): Moved to c-common.h.
(scalar_to_vector): Moved to c-common.c.
(build_binary_op): Adapt to scalar_to_vector's new prototype.
* Make-lang.in: c-typeck.c depends on c-common.h.
2012-10-04 Arnaud Charlet <charlet@adacore.com> 2012-10-04 Arnaud Charlet <charlet@adacore.com>
* c-decl.c (c_write_global_declarations): Fix handling of * c-decl.c (c_write_global_declarations): Fix handling of
......
...@@ -192,5 +192,5 @@ c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ...@@ -192,5 +192,5 @@ c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_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 \ $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_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
...@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "bitmap.h" #include "bitmap.h"
#include "gimple.h" #include "gimple.h"
#include "c-family/c-objc.h" #include "c-family/c-objc.h"
#include "c-family/c-common.h"
/* Possible cases of implicit bad conversions. Used to select /* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */ diagnostic messages in convert_for_assignment. */
...@@ -50,14 +51,6 @@ enum impl_conv { ...@@ -50,14 +51,6 @@ enum impl_conv {
ic_return 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__". */ /* The level of nesting inside "__alignof__". */
int in_alignof; int in_alignof;
...@@ -9376,88 +9369,6 @@ push_cleanup (tree decl, tree cleanup, bool eh_only) ...@@ -9376,88 +9369,6 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
STATEMENT_LIST_STMT_EXPR (list) = stmt_expr; 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. /* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build. CODE is the kind of expression to build.
LOCATION is the operator's location. LOCATION is the operator's location.
...@@ -9647,7 +9558,8 @@ build_binary_op (location_t location, enum tree_code code, ...@@ -9647,7 +9558,8 @@ build_binary_op (location_t location, enum tree_code code,
a vector and another is a scalar -- convert scalar to vector. */ a vector and another is a scalar -- convert scalar to vector. */
if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE)) if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
{ {
enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1); enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1,
true);
switch (convert_flag) switch (convert_flag)
{ {
......
2012-10-09 Marc Glisse <marc.glisse@inria.fr>
PR c++/54427
* typeck.c (cp_build_binary_op): Handle mixed scalar-vector
operations.
[LSHIFT_EXPR, RSHIFT_EXPR]: Likewise.
2012-10-08 Jakub Jelinek <jakub@redhat.com> 2012-10-08 Jakub Jelinek <jakub@redhat.com>
PR c++/54858 PR c++/54858
......
...@@ -3912,6 +3912,40 @@ cp_build_binary_op (location_t location, ...@@ -3912,6 +3912,40 @@ cp_build_binary_op (location_t location,
warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic"); 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,
complain & tf_error);
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) switch (code)
{ {
case MINUS_EXPR: case MINUS_EXPR:
...@@ -4035,7 +4069,13 @@ cp_build_binary_op (location_t location, ...@@ -4035,7 +4069,13 @@ cp_build_binary_op (location_t location,
Also set SHORT_SHIFT if shifting rightward. */ Also set SHORT_SHIFT if shifting rightward. */
case RSHIFT_EXPR: 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 (type0)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
&& TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
...@@ -4072,7 +4112,13 @@ cp_build_binary_op (location_t location, ...@@ -4072,7 +4112,13 @@ cp_build_binary_op (location_t location,
break; break;
case LSHIFT_EXPR: 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 (type0)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
&& TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
......
...@@ -12857,7 +12857,7 @@ fold_binary_loc (location_t loc, ...@@ -12857,7 +12857,7 @@ fold_binary_loc (location_t loc,
arg00 = fold_convert_loc (loc, itype, arg00); arg00 = fold_convert_loc (loc, itype, arg00);
} }
return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR, 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));
} }
} }
......
2012-10-09 Marc Glisse <marc.glisse@inria.fr>
PR c++/54427
* c-c++-common/vector-scalar.c: New testcase.
* g++.dg/ext/vector18.C: New testcase.
* g++.dg/ext/vector5.C: This is not an error anymore.
* gcc.dg/init-vec-1.c: Move ...
* c-c++-common/init-vec-1.c: ... here. Adapt error message.
* gcc.c-torture/execute/vector-shift1.c: Move ...
* c-c++-common/torture/vector-shift1.c: ... here.
* gcc.dg/scal-to-vec1.c: Move ...
* c-c++-common/scal-to-vec1.c: ... here. Avoid narrowing for
C++11. Adapt error messages.
* gcc.dg/convert-vec-1.c: Move ...
* c-c++-common/convert-vec-1.c: ... here.
* gcc.dg/scal-to-vec2.c: Move ...
* c-c++-common/scal-to-vec2.c: ... here.
2012-10-08 Marc Glisse <marc.glisse@inria.fr> 2012-10-08 Marc Glisse <marc.glisse@inria.fr>
PR target/54400 PR target/54400
......
/* Don't ICE or emit spurious errors when init a vector with a scalar. */ /* Don't ICE or emit spurious errors when init a vector with a scalar. */
/* { dg-do compile } */ /* { dg-do compile } */
typedef float v2sf __attribute__ ((vector_size (8))); 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" } */
...@@ -13,7 +13,7 @@ extern int sint; ...@@ -13,7 +13,7 @@ extern int sint;
extern long long sll; extern long long sll;
int main (int argc, char *argv[]) { 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(8, short) v1;
vector(4, float) f0 = {1., 2., 3., 4.}; vector(4, float) f0 = {1., 2., 3., 4.};
...@@ -26,18 +26,18 @@ int main (int argc, char *argv[]) { ...@@ -26,18 +26,18 @@ int main (int argc, char *argv[]) {
int i = 12; int i = 12;
double d = 3.; double d = 3.;
v1 = i + v0; /* { dg-error "conversion of scalar to vector" } */ v1 = i + v0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
v1 = 99999 + v0; /* { dg-error "conversion of scalar to vector" } */ v1 = 99999 + v0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
f1 = d + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = d + f0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
f1 = 1.3 + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = 1.3 + f0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
f1 = sll + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = sll + f0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
/* convert.c should take care of this. */ /* convert.c should take care of this. */
i1 = sfl + i0; /* { 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" } */ 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" } */ v1 = d + v0; /* { dg-error "can't convert value to a vector|invalid operands" } */
return 0; return 0;
} }
/* { dg-do run } */
#define vector __attribute__((vector_size(8*sizeof(short)))) #define vector __attribute__((vector_size(8*sizeof(short))))
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {
......
/* { 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);
}
/* { dg-do compile } */
/* { dg-options "-std=c++11" } */
typedef signed char __attribute__((vector_size(128) )) vec;
template <class A, class B>
auto f (A *a, B b) -> decltype (*a + b);
void f (...) {}
void g (vec *v, long long l)
{
f (v, l);
}
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
void foo() void foo()
{ {
int __attribute__((vector_size(8))) v; int __attribute__((vector_size(8))) v;
v = 1/v; // { dg-error "invalid operands of types" } v = 1/v;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment