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]

[PATCH] Fix VRP single-bit signed precision handling (PR tree-optimization/54676)


Hi!

This patch fixes two spots where signed 1-bit precision isn't handled
properly in VRP.  With that type, build_int_cst (TREE_TYPE (min), 1)
will overflow and thus adding it to something or subtracting leads to
ICEs or bad code.  In the first spot min is different from max, which
for 1-bit precision implies either all values, or none (but we don't have
empty ranges and fallback to varying for those anyway).
In the second case we can optimize if the anti range is singleton, then
the corresponding range is singleton too (the other value).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2012-09-25  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/54676
	* tree-vrp.c (set_and_canonicalize_value_range): Handle
	one bit precision properly.

	* gcc.dg/pr54676.c: New test.

--- gcc/tree-vrp.c.jj	2012-09-17 11:13:12.000000000 +0200
+++ gcc/tree-vrp.c	2012-09-24 10:06:10.814376659 +0200
@@ -501,8 +501,19 @@ set_and_canonicalize_value_range (value_
      to adjust them.  */
   if (tree_int_cst_lt (max, min))
     {
-      tree one = build_int_cst (TREE_TYPE (min), 1);
-      tree tmp = int_const_binop (PLUS_EXPR, max, one);
+      tree one, tmp;
+
+      /* For one bit precision if max < min, then the swapped
+	 range covers all values, so for VR_RANGE it is varying and
+	 for VR_ANTI_RANGE empty range, so drop to varying as well.  */
+      if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
+	{
+	  set_value_range_to_varying (vr);
+	  return;
+	}
+
+      one = build_int_cst (TREE_TYPE (min), 1);
+      tmp = int_const_binop (PLUS_EXPR, max, one);
       max = int_const_binop (MINUS_EXPR, min, one);
       min = tmp;
 
@@ -531,6 +542,24 @@ set_and_canonicalize_value_range (value_
 	  set_value_range_to_varying (vr);
 	  return;
 	}
+      else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
+	       && !TYPE_UNSIGNED (TREE_TYPE (min))
+	       && (is_min || is_max))
+	{
+	  /* For signed 1-bit precision, one is not in-range and
+	     thus adding/subtracting it would result in overflows.  */
+	  if (operand_equal_p (min, max, 0))
+	    {
+	      min = max = is_min ? vrp_val_max (TREE_TYPE (min))
+				 : vrp_val_min (TREE_TYPE (min));
+	      t = VR_RANGE;
+	    }
+	  else
+	    {
+	      set_value_range_to_varying (vr);
+	      return;
+	    }
+	}
       else if (is_min
 	       /* As a special exception preserve non-null ranges.  */
 	       && !(TYPE_UNSIGNED (TREE_TYPE (min))
--- gcc/testsuite/gcc.dg/pr54676.c.jj	2012-09-24 10:52:48.911691835 +0200
+++ gcc/testsuite/gcc.dg/pr54676.c	2012-09-24 10:52:30.000000000 +0200
@@ -0,0 +1,23 @@
+/* PR tree-optimization/54676 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-fre -ftree-vrp" } */
+
+struct S
+{
+  int s:1;
+};
+
+struct S bar (void);
+
+int a;
+
+void
+foo (int x)
+{
+  struct S s = bar ();
+  while (!a)
+    {
+      int l = 94967295;
+      a = x || (s.s &= l);
+    }
+}

	Jakub


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