This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++] Mixed scalar-vector operations


Hello,

this patch adds mixed scalar-vector operations to the C++ front-end. It also adds a few operators to the C front-end (comparisons in particular). This patch is mostly an import from the C front-end (with the maybe_const stuff removed).

2012-09-22 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.
	* 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.
	* 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/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 message.
	* 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.

--
Marc Glisse
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.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]