OSDN Git Service

PR tree-optimization/51247
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 29 Nov 2011 21:03:09 +0000 (21:03 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 29 Nov 2011 21:03:09 +0000 (21:03 +0000)
* tree-vrp.c (extract_range_from_assert): For signed 1-bit precision
types instead of adding 1 subtract -1 and instead of subtracting 1
add -1 to avoid overflows.

* gcc.c-torture/compile/pr51247.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181818 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr51247.c [new file with mode: 0644]
gcc/tree-vrp.c

index 921b4f9..3a80278 100644 (file)
@@ -1,3 +1,10 @@
+2011-11-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/51247
+       * tree-vrp.c (extract_range_from_assert): For signed 1-bit precision
+       types instead of adding 1 subtract -1 and instead of subtracting 1
+       add -1 to avoid overflows.
+
 2011-11-29  Andrew MacLeod  <amacleod@redhat.com>
 
        PR target/50123
index a5a39e3..3d695a2 100644 (file)
@@ -1,3 +1,8 @@
+2011-11-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/51247
+       * gcc.c-torture/compile/pr51247.c: New test.
+
 2011-11-29  Andrew MacLeod  <amacleod@redhat.com>
 
        PR target/50123
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr51247.c b/gcc/testsuite/gcc.c-torture/compile/pr51247.c
new file mode 100644 (file)
index 0000000..16aa7f0
--- /dev/null
@@ -0,0 +1,16 @@
+/* PR tree-optimization/51247 */
+
+struct S { int s : 1; };
+int a;
+
+void
+foo (int x, int y)
+{
+  struct S s;
+  s.s = !!y;
+  while (1)
+    {
+      unsigned l = 94967295;
+      a = x || (s.s &= l);
+    }
+}
index 248bc61..5cbc25f 100644 (file)
@@ -1693,8 +1693,13 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
          /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
          if (cond_code == LT_EXPR)
            {
-             tree one = build_int_cst (TREE_TYPE (max), 1);
-             max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, one);
+             if (TYPE_PRECISION (TREE_TYPE (max)) == 1
+                 && !TYPE_UNSIGNED (TREE_TYPE (max)))
+               max = fold_build2 (PLUS_EXPR, TREE_TYPE (max), max,
+                                  build_int_cst (TREE_TYPE (max), -1));
+             else
+               max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max,
+                                  build_int_cst (TREE_TYPE (max), 1));
              if (EXPR_P (max))
                TREE_NO_WARNING (max) = 1;
            }
@@ -1728,8 +1733,13 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
          /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
          if (cond_code == GT_EXPR)
            {
-             tree one = build_int_cst (TREE_TYPE (min), 1);
-             min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min, one);
+             if (TYPE_PRECISION (TREE_TYPE (min)) == 1
+                 && !TYPE_UNSIGNED (TREE_TYPE (min)))
+               min = fold_build2 (MINUS_EXPR, TREE_TYPE (min), min,
+                                  build_int_cst (TREE_TYPE (min), -1));
+             else
+               min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min,
+                                  build_int_cst (TREE_TYPE (min), 1));
              if (EXPR_P (min))
                TREE_NO_WARNING (min) = 1;
            }
@@ -1915,9 +1925,19 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
                  min = positive_overflow_infinity (TREE_TYPE (var_vr->min));
                }
              else if (!POINTER_TYPE_P (TREE_TYPE (var_vr->min)))
-               min = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min),
-                                  anti_max,
-                                  build_int_cst (TREE_TYPE (var_vr->min), 1));
+               {
+                 if (TYPE_PRECISION (TREE_TYPE (var_vr->min)) == 1
+                     && !TYPE_UNSIGNED (TREE_TYPE (var_vr->min)))
+                   min = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
+                                      anti_max,
+                                      build_int_cst (TREE_TYPE (var_vr->min),
+                                                     -1));
+                 else
+                   min = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min),
+                                      anti_max,
+                                      build_int_cst (TREE_TYPE (var_vr->min),
+                                                     1));
+               }
              else
                min = fold_build_pointer_plus_hwi (anti_max, 1);
              max = real_max;
@@ -1942,9 +1962,19 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
                  max = negative_overflow_infinity (TREE_TYPE (var_vr->min));
                }
              else if (!POINTER_TYPE_P (TREE_TYPE (var_vr->min)))
-               max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
-                                  anti_min,
-                                  build_int_cst (TREE_TYPE (var_vr->min), 1));
+               {
+                 if (TYPE_PRECISION (TREE_TYPE (var_vr->min)) == 1
+                     && !TYPE_UNSIGNED (TREE_TYPE (var_vr->min)))
+                   max = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min),
+                                      anti_min,
+                                      build_int_cst (TREE_TYPE (var_vr->min),
+                                                     -1));
+                 else
+                   max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
+                                      anti_min,
+                                      build_int_cst (TREE_TYPE (var_vr->min),
+                                                     1));
+               }
              else
                max = fold_build_pointer_plus_hwi (anti_min, -1);
              min = real_min;