diff mbox

[v2] extend shift count warnings to vector types

Message ID 57769A5102000078000FA72D@prv-mh.provo.novell.com
State New
Headers show

Commit Message

Jan Beulich July 1, 2016, 2:29 p.m. UTC
gcc/c/
2016-07-01  Jan Beulich  <jbeulich@suse.com>

	* c-fold.c (c_fully_fold_internal): Also emit shift count
	warnings for vector types.
	* c-typeck.c (build_binary_op): Likewise.

gcc/testsuite/
2016-07-01  Jan Beulich  <jbeulich@suse.com>

	* gcc.dg/vshift-6.c, gcc.dg/vshift-7.c: New.

Comments

Marc Glisse July 2, 2016, 9:23 a.m. UTC | #1
On Fri, 1 Jul 2016, Jan Beulich wrote:

> gcc/c/
> 2016-07-01  Jan Beulich  <jbeulich@suse.com>
>
> 	* c-fold.c (c_fully_fold_internal): Also emit shift count
> 	warnings for vector types.
> 	* c-typeck.c (build_binary_op): Likewise.

Hello,

I just wanted to advertise the function element_precision, whose goal is 
to unify handling of vectors and scalars. It is "overloaded" to apply 
TREE_TYPE the right number of times before TYPE_PRECISION. Since you are 
giving a different warning message for scalars and vectors, it probably 
wouldn't help you here though. (OTOH, if you decided that the same message 
was good enough for both...)
Jeff Law July 14, 2016, 5:59 p.m. UTC | #2
On 07/01/2016 08:29 AM, Jan Beulich wrote:
> gcc/c/
> 2016-07-01  Jan Beulich  <jbeulich@suse.com>
>
> 	* c-fold.c (c_fully_fold_internal): Also emit shift count
> 	warnings for vector types.
> 	* c-typeck.c (build_binary_op): Likewise.
>
> gcc/testsuite/
> 2016-07-01  Jan Beulich  <jbeulich@suse.com>
>
> 	* gcc.dg/vshift-6.c, gcc.dg/vshift-7.c: New.
OK.  Thanks for putting together some tests.

jeff
diff mbox

Patch

--- 2016-06-30/gcc/c/c-fold.c
+++ 2016-06-30/gcc/c/c-fold.c
@@ -320,8 +320,6 @@  c_fully_fold_internal (tree expr, bool i
       if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
 	  && TREE_CODE (orig_op1) != INTEGER_CST
 	  && TREE_CODE (op1) == INTEGER_CST
-	  && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
-	      || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
 	  && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
 	  && c_inhibit_evaluation_warnings == 0)
 	{
@@ -330,13 +328,23 @@  c_fully_fold_internal (tree expr, bool i
 			(code == LSHIFT_EXPR
 			 ? G_("left shift count is negative")
 			 : G_("right shift count is negative")));
-	  else if (compare_tree_int (op1,
-				     TYPE_PRECISION (TREE_TYPE (orig_op0)))
-		   >= 0)
+	  else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
+		    || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
+		   && compare_tree_int (op1,
+					TYPE_PRECISION (TREE_TYPE (orig_op0)))
+		      >= 0)
 	    warning_at (loc, OPT_Wshift_count_overflow,
 			(code == LSHIFT_EXPR
 			 ? G_("left shift count >= width of type")
 			 : G_("right shift count >= width of type")));
+	  else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE
+		   && compare_tree_int (op1,
+					TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0))))
+		      >= 0)
+	    warning_at (loc, OPT_Wshift_count_overflow,
+			code == LSHIFT_EXPR
+			? G_("left shift count >= width of vector element")
+			: G_("right shift count >= width of vector element"));
 	}
       if (code == LSHIFT_EXPR
 	  /* If either OP0 has been folded to INTEGER_CST...  */
--- 2016-06-30/gcc/c/c-typeck.c
+++ 2016-06-30/gcc/c/c-typeck.c
@@ -10985,21 +10985,16 @@  build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      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))
+      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 || code0 == FIXED_POINT_TYPE)
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+		|| code0 == VECTOR_TYPE)
 	       && code1 == INTEGER_TYPE)
 	{
 	  doing_shift = true;
@@ -11012,6 +11007,18 @@  build_binary_op (location_t location, en
 		    warning_at (location, OPT_Wshift_count_negative,
 				"right shift count is negative");
 		}
+	      else if (code0 == VECTOR_TYPE)
+		{
+		  if (compare_tree_int (op1,
+					TYPE_PRECISION (TREE_TYPE (type0)))
+		      >= 0)
+		    {
+		      int_const = false;
+		      if (c_inhibit_evaluation_warnings == 0)
+			warning_at (location, OPT_Wshift_count_overflow,
+				    "right shift count >= width of vector element");
+		    }
+		}
 	      else
 		{
 		  if (!integer_zerop (op1))
@@ -11035,21 +11042,16 @@  build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      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))
+      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 || code0 == FIXED_POINT_TYPE)
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+		|| code0 == VECTOR_TYPE)
 	       && code1 == INTEGER_TYPE)
 	{
 	  doing_shift = true;
@@ -11073,6 +11075,18 @@  build_binary_op (location_t location, en
 		    warning_at (location, OPT_Wshift_count_negative,
 				"left shift count is negative");
 		}
+	      else if (code0 == VECTOR_TYPE)
+		{
+		  if (compare_tree_int (op1,
+					TYPE_PRECISION (TREE_TYPE (type0)))
+		      >= 0)
+		    {
+		      int_const = false;
+		      if (c_inhibit_evaluation_warnings == 0)
+			warning_at (location, OPT_Wshift_count_overflow,
+				    "left shift count >= width of vector element");
+		    }
+		}
 	      else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
 		{
 		  int_const = false;
--- 2016-06-30/gcc/testsuite/gcc.dg/vshift-6.c
+++ 2016-06-30/gcc/testsuite/gcc.dg/vshift-6.c
@@ -0,0 +1,42 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Wshift-count-negative -Wshift-count-overflow" } */
+
+typedef unsigned int v1qi_t __attribute__((mode(QI), vector_size(1)));
+typedef unsigned int v1hi_t __attribute__((mode(HI), vector_size(2)));
+typedef unsigned int v1si_t __attribute__((mode(SI), vector_size(4)));
+
+v1qi_t test1qi(v1qi_t x, int c) {
+	switch(c) {
+	case 0: return x << -1; /* { dg-warning "shift count is negative" } */
+	case 1: return x << 7;
+	case 2: return x << 8; /* { dg-warning "shift count >= width" } */
+	case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */
+	case ~1: return x >> 7;
+	case ~2: return x >> 8; /* { dg-warning "shift count >= width" } */
+	}
+	return c < 0 ? x >> -c : x << c;
+}
+
+v1hi_t test1hi(v1hi_t x, int c) {
+	switch(c) {
+	case 0: return x << -1; /* { dg-warning "shift count is negative" } */
+	case 1: return x << 15;
+	case 2: return x << 16; /* { dg-warning "shift count >= width" } */
+	case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */
+	case ~1: return x >> 15;
+	case ~2: return x >> 16; /* { dg-warning "shift count >= width" } */
+	}
+	return c < 0 ? x >> -c : x << c;
+}
+
+v1si_t test1si(v1si_t x, int c) {
+	switch(c) {
+	case 0: return x << -1; /* { dg-warning "shift count is negative" } */
+	case 1: return x << 31;
+	case 2: return x << 32; /* { dg-warning "shift count >= width" } */
+	case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */
+	case ~1: return x >> 31;
+	case ~2: return x >> 32; /* { dg-warning "shift count >= width" } */
+	}
+	return c < 0 ? x >> -c : x << c;
+}
--- 2016-06-30/gcc/testsuite/gcc.dg/vshift-7.c
+++ 2016-06-30/gcc/testsuite/gcc.dg/vshift-7.c
@@ -0,0 +1,47 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1 -Wshift-count-negative -Wshift-count-overflow" } */
+
+typedef unsigned int v1qi_t __attribute__((mode(QI), vector_size(1)));
+typedef unsigned int v1hi_t __attribute__((mode(HI), vector_size(2)));
+typedef unsigned int v1si_t __attribute__((mode(SI), vector_size(4)));
+
+static const signed shift_neg = -1;
+static const unsigned shift_qi = 8;
+static const unsigned shift_hi = 16;
+static const unsigned shift_si = 32;
+
+v1qi_t test1qi(v1qi_t x, int c) {
+	switch(c) {
+	case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */
+	case 1: return x << (shift_qi - 1);
+	case 2: return x << shift_qi; /* { dg-warning "shift count >= width" } */
+	case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */
+	case ~1: return x >> (shift_qi - 1);
+	case ~2: return x >> shift_qi; /* { dg-warning "shift count >= width" } */
+	}
+	return c < 0 ? x >> -c : x << c;
+}
+
+v1hi_t test1hi(v1hi_t x, int c) {
+	switch(c) {
+	case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */
+	case 1: return x << (shift_hi - 1);
+	case 2: return x << shift_hi; /* { dg-warning "shift count >= width" } */
+	case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */
+	case ~1: return x >> (shift_hi - 1);
+	case ~2: return x >> shift_hi; /* { dg-warning "shift count >= width" } */
+	}
+	return c < 0 ? x >> -c : x << c;
+}
+
+v1si_t test1si(v1si_t x, int c) {
+	switch(c) {
+	case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */
+	case 1: return x << (shift_si - 1);
+	case 2: return x << shift_si; /* { dg-warning "shift count >= width" } */
+	case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */
+	case ~1: return x >> (shift_si - 1);
+	case ~2: return x >> shift_si; /* { dg-warning "shift count >= width" } */
+	}
+	return c < 0 ? x >> -c : x << c;
+}