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]

Fix PR21959


Given

     1	unsigned char i;
     2	signed char i.0;
     3	
     4	L0:
     5	  i_2 = PHI <0, i_9>
     6	  i.0_6 = (signed char) i_2;
     7	  if (i.0_6 < 0)
     8	    break;
     9	  i_9 = i_2 + 1;
    10	  goto L0;


We cannot remove the predicate at line 7.  But VRP was removing
it because SCEV was lying to it.

Since i_2 is an unsigned variable, its range is assumed to be
VARYING because its scev is {0, +, 1} and unsigned types may wrap
around.

However, when VRP calls scev_probably_wraps_p on line 6, it sees
an scev {0, +, 1} of signed type, so it assumes that it won't
wrap around.  However, that signed type was the result of a cast
operation that changed the sign, and I've been told that cast
operations are implementation defined.

So, the sensible thing here is for scev_probably_wraps_p to
return true on a casting operation of this nature.

BTW, Sebastian could you change the semantics of compare_trees?
compare_trees(a, b) == -1 when a > b is not intuitive.  Also,
could we not be using something like compare_values here?  Or
even tree_int_cst_compare?  (I guess not, because we do scevs on
floating point too?).

Bootstrapped and tested x86, x86-64, ia64 and ppc64.


Diego.


	PR 21959
	* tree-ssa-loop-niter.c (scev_probably_wraps_p): Handle type
	casts between unsigned and signed types with different size
	or precision.

testsuite/ChangeLog

	PR 21959
	* gcc.dg/tree-ssa/pr21959.c: New test.

Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.31
diff -d -u -p -r2.31 tree-ssa-loop-niter.c
--- tree-ssa-loop-niter.c	25 Jun 2005 02:01:41 -0000	2.31
+++ tree-ssa-loop-niter.c	28 Jun 2005 00:42:10 -0000
@@ -1649,6 +1649,41 @@ scev_probably_wraps_p (tree type, tree b
       return true;
     }
 
+  /* If AT_STMT represents a cast operation, we may not be able to
+     take advantage of the undefinedness of signed type evolutions.
+     See PR 21959 for a test case.  Essentially, given a cast
+     operation
+     		unsigned char i;
+		signed char i.0;
+		...
+     		i.0_6 = (signed char) i_2;
+		if (i.0_6 < 0)
+		  ...
+
+     where i_2 and i.0_6 have the scev {0, +, 1}, we would consider
+     i_2 to wrap around, but not i.0_6, because it is of a signed
+     type.  This causes VRP to erroneously fold the predicate above
+     because it thinks that i.0_6 cannot be negative.  */
+  if (TREE_CODE (at_stmt) == MODIFY_EXPR)
+    {
+      tree rhs = TREE_OPERAND (at_stmt, 1);
+      tree outer_t = TREE_TYPE (rhs);
+
+      if (!TYPE_UNSIGNED (outer_t)
+	  && (TREE_CODE (rhs) == NOP_EXPR || TREE_CODE (rhs) == CONVERT_EXPR))
+	{
+	  tree inner_t = TREE_TYPE (TREE_OPERAND (rhs, 0));
+
+	  /* If the inner type is unsigned and its size and/or
+	     precision are smaller to that of the outer type, then the
+	     expression may wrap around.  */
+	  if (TYPE_UNSIGNED (inner_t)
+	      && (TYPE_SIZE (inner_t) <= TYPE_SIZE (outer_t)
+		  || TYPE_PRECISION (inner_t) <= TYPE_PRECISION (outer_t)))
+	    return true;
+	}
+    }
+
   /* After having set INIT_IS_MAX, we can return false: when not using
      wrapping arithmetic, signed types don't wrap.  */
   if (!flag_wrapv && !TYPE_UNSIGNED (type))
Index: testsuite/gcc.dg/tree-ssa/pr21959.c
===================================================================
RCS file: testsuite/gcc.dg/tree-ssa/pr21959.c
diff -N testsuite/gcc.dg/tree-ssa/pr21959.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/tree-ssa/pr21959.c	28 Jun 2005 00:42:17 -0000
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+unsigned char c[0xFF];
+void f(void)
+{
+  unsigned char i;
+  c[128] = 128;
+  i = 0;
+  while (1)
+  {
+    /* This predicate should not be folded out.  */
+    if (((signed char) i) < 0) break;
+    c[i] = ' ';
+    i++;
+  }
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */


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