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]

Logic operators ! && || for vectors


Hello,

this adds support for vector !, && and ||. In the long run, I think it would be good to be able to use TRUTH_*_EXPR with vectors, but that's probably a lot of work.

It currently restricts && and || to vector-vector operations. I'd like to also support mixed scalar-vector later, but it is a bit more complicated. With vectors, && evaluates both sides. For scal && vec, we have the choice of making it short-circuit: cond_expr((bool)scal, vec!=0, {0}) or do a vector and. For vec && scal, it seems clear we have to evaluate both operands, but then we can also make it a cond_expr instead of a BIT_AND_EXPR (technically, I think I can achieve that with save_expr and a compound_expr, I don't know if there is a better way to add statements).

The missing save_expr before build_vector_from_val are a bug I introduced when I adapted the code from the C front-end. This bit (and the vector-scalar-2.c testcase that goes with it) should probably be backported to 4.8.

The code we generate for these examples is not very good, but that's a different issue.

Bootstrap+testsuite on x86_64-linux-gnu.

2013-04-12  Marc Glisse  <marc.glisse@inria.fr>

gcc/cp/
	* typeck.c (cp_build_binary_op): Call save_expr before
	build_vector_from_val.
	<TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR, TRUTH_AND_EXPR,
	TRUTH_OR_EXPR>: Handle vectors.
	(cp_build_unary_op) <TRUTH_NOT_EXPR>: Likewise.

gcc/c-family/
	* c-common.c (warn_logical_operator): Give up for vectors.

gcc/testsuite/
	* c-c++-common/vector-scalar-2.c: New testcase.
	* g++.dg/ext/vector22.C: Likewise.
	* g++.dg/ext/vector23.C: Likewise.
	* g++.dg/ext/vector9.C: Adapt.
	* g++.dg/other/error23.C: Adapt.

--
Marc Glisse
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 197846)
+++ gcc/c-family/c-common.c	(working copy)
@@ -1624,20 +1624,24 @@ warn_logical_operator (location_t locati
   if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right))
     return;
 
   /* This warning only makes sense with logical operands.  */
   if (!(truth_value_p (TREE_CODE (op_left))
 	|| INTEGRAL_TYPE_P (TREE_TYPE (op_left)))
       || !(truth_value_p (TREE_CODE (op_right))
 	   || INTEGRAL_TYPE_P (TREE_TYPE (op_right))))
     return;
 
+  /* The range computations only work with scalars.  */
+  if (VECTOR_TYPE_P (TREE_TYPE (op_left))
+      || VECTOR_TYPE_P (TREE_TYPE (op_right)))
+    return;
 
   /* We first test whether either side separately is trivially true
      (with OR) or trivially false (with AND).  If so, do not warn.
      This is a common idiom for testing ranges of data types in
      portable code.  */
   lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
   if (!lhs)
     return;
   if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
     lhs = C_MAYBE_CONST_EXPR_EXPR (lhs);
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 197846)
+++ gcc/cp/typeck.c	(working copy)
@@ -3970,30 +3970,30 @@ cp_build_binary_op (location_t location,
     {
       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 = save_expr (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 = save_expr (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;
         }
     }
@@ -4111,20 +4111,43 @@ cp_build_binary_op (location_t location,
 		     || (TREE_CODE (op1) == INTEGER_CST
 			 && ! integer_all_onesp (op1)));
 	  common = 1;
 	}
       break;
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
+      if (VECTOR_TYPE_P (type0) != VECTOR_TYPE_P (type1))
+	{
+	  if (complain & tf_error) 
+            sorry ("%<&&%> or %<||%> with a vector and a scalar");
+	  return error_mark_node;
+	}
+      if (VECTOR_TYPE_P (type0) && VECTOR_TYPE_P (type1))
+	{
+	  if (!COMPARISON_CLASS_P (op0))
+	    op0 = cp_build_binary_op (EXPR_LOCATION (op0), NE_EXPR, op0,
+				      build_zero_cst (type0), complain);
+	  if (!COMPARISON_CLASS_P (op1))
+	    op1 = cp_build_binary_op (EXPR_LOCATION (op1), NE_EXPR, op1,
+				      build_zero_cst (type1), complain);
+
+	  if (code == TRUTH_ANDIF_EXPR || code == TRUTH_AND_EXPR)
+	    code = BIT_AND_EXPR;
+	  else /* if (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR) */
+	    code = BIT_IOR_EXPR;
+
+	  return cp_build_binary_op (location, code, op0, op1, complain);
+	}
+
       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 == INTEGER_TYPE
           && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
@@ -5476,20 +5499,23 @@ cp_build_unary_op (enum tree_code code,
 	errstring = _("wrong type argument to conjugation");
       else if (!noconvert)
 	{
 	  arg = cp_default_conversion (arg, complain);
 	  if (arg == error_mark_node)
 	    return error_mark_node;
 	}
       break;
 
     case TRUTH_NOT_EXPR:
+      if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg)))
+	return cp_build_binary_op (input_location, EQ_EXPR, arg,
+				   build_zero_cst (TREE_TYPE (arg)), complain);
       arg = perform_implicit_conversion (boolean_type_node, arg,
 					 complain);
       val = invert_truthvalue_loc (input_location, arg);
       if (arg != error_mark_node)
 	return val;
       errstring = _("in argument to unary !");
       break;
 
     case NOP_EXPR:
       break;
Index: gcc/testsuite/g++.dg/ext/vector22.C
===================================================================
--- gcc/testsuite/g++.dg/ext/vector22.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/vector22.C	(revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+typedef int veci __attribute__ ((vector_size (4 * sizeof (int))));
+typedef float vecf __attribute__ ((vector_size (4 * sizeof (float))));
+
+void f (veci *a, veci *b, int c)
+{
+  *a = !*a || *b < ++c;
+}
+void g (vecf *a, vecf *b)
+{
+  *a = (*a < 1 && !(*b > 2)) ? *a + *b : 3;
+}

Property changes on: gcc/testsuite/g++.dg/ext/vector22.C
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision URL

Index: gcc/testsuite/g++.dg/ext/vector23.C
===================================================================
--- gcc/testsuite/g++.dg/ext/vector23.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/vector23.C	(revision 0)
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+typedef int veci __attribute__ ((vector_size (4 * sizeof (int))));
+typedef float vecf __attribute__ ((vector_size (4 * sizeof (float))));
+
+void f (veci *a, veci *b, int c)
+{
+  *a = *a || c; /* { dg-message "a vector and a scalar" } */
+}

Property changes on: gcc/testsuite/g++.dg/ext/vector23.C
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: gcc/testsuite/g++.dg/ext/vector9.C
===================================================================
--- gcc/testsuite/g++.dg/ext/vector9.C	(revision 197846)
+++ gcc/testsuite/g++.dg/ext/vector9.C	(working copy)
@@ -1,10 +1,10 @@
 // PR c++/34891
 
 typedef float v4f __attribute__((vector_size(8)));
 typedef int   v4i __attribute__((vector_size(8)));
 
 void foo()
 {
   v4f v;
-  !(v4i)v; // { dg-error "v4i|argument" }
+  !(v4i)v;
 }
Index: gcc/testsuite/g++.dg/other/error23.C
===================================================================
--- gcc/testsuite/g++.dg/other/error23.C	(revision 197846)
+++ gcc/testsuite/g++.dg/other/error23.C	(working copy)
@@ -1,5 +1,5 @@
 // PR c++/34918
 // { dg-do compile }
 
 int v __attribute ((vector_size (8)));
-bool b = !(v - v);	// { dg-error "could not convert .\\(__vector.2. int\\)\\{0, 0\\}. from .__vector.2. int. to .bool.|in argument to unary" }
+bool b = !(v - v);	// { dg-error "not convert .__vector.2. int. to .bool. in initialization" }
Index: gcc/testsuite/c-c++-common/vector-scalar-2.c
===================================================================
--- gcc/testsuite/c-c++-common/vector-scalar-2.c	(revision 0)
+++ gcc/testsuite/c-c++-common/vector-scalar-2.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+typedef int veci __attribute__ ((vector_size (4 * sizeof (int))));
+
+int c;
+
+void f (veci *a)
+{
+  *a = *a + ++c;
+}
+
+/* { dg-final { scan-tree-dump-times " \\\+ 1" 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */

Property changes on: gcc/testsuite/c-c++-common/vector-scalar-2.c
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision URL


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