re PR tree-optimization/92131 (incorrect assumption that (ao >= 0) is always false)
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 23 Oct 2019 11:34:48 +0000 (11:34 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 23 Oct 2019 11:34:48 +0000 (11:34 +0000)
PR tree-optimization/92131
* tree-vrp.c (extract_range_from_plus_minus_expr): If the resulting
range would be symbolic, drop to varying for any explicit overflow
in the constant part or if neither range is a singleton.

From-SVN: r277314

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20191023-1.c [new file with mode: 0644]
gcc/tree-vrp.c

index 958c9ae3802d2788c3e2e8e4ba9236cd5baf6a1e..3ff5227cbecfcbedb60eacf17e1c749cc0f67b60 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-23  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR tree-optimization/92131
+       * tree-vrp.c (extract_range_from_plus_minus_expr): If the resulting
+       range would be symbolic, drop to varying for any explicit overflow
+       in the constant part or if neither range is a singleton.
+
 2019-10-23  Martin Liska  <mliska@suse.cz>
 
        PR middle-end/81669
index 482ff0ccabc9388a06f942dc7380a4262a2b87e2..c578af30ce825b8229a188fecba2aa909fe9cd8d 100644 (file)
@@ -1,3 +1,7 @@
+2019-10-23  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/execute/20191023-1.c: New test.
+
 2019-10-23  Martin Liska  <mliska@suse.cz>
 
        PR ipa/91969
diff --git a/gcc/testsuite/gcc.c-torture/execute/20191023-1.c b/gcc/testsuite/gcc.c-torture/execute/20191023-1.c
new file mode 100644 (file)
index 0000000..3811ebc
--- /dev/null
@@ -0,0 +1,73 @@
+/* PR tree-optimization/92131 */
+/* Testcase by Armin Rigo <arigo@tunes.org> */
+
+long b, c, d, e, f, i;
+char g, h, j, k;
+int *aa;
+
+static void error (void) __attribute__((noipa));
+static void error (void) { __builtin_abort(); }
+
+static void see_me_here (void) __attribute__((noipa));
+static void see_me_here (void) {}
+
+static void aaa (void) __attribute__((noipa));
+static void aaa (void) {}
+
+static void a (void) __attribute__((noipa));
+static void a (void) {
+  long am, ao;
+  if (aa == 0) {
+    aaa();
+    if (j)
+      goto ay;
+  }
+  return;
+ay:
+  aaa();
+  if (k) {
+    aaa();
+    goto az;
+  }
+  return;
+az:
+  if (i)
+    if (g)
+      if (h)
+        if (e)
+          goto bd;
+  return;
+bd:
+  am = 0;
+  while (am < e) {
+    switch (c) {
+    case 8:
+      goto bh;
+    case 4:
+      return;
+    }
+  bh:
+    if (am >= 0)
+      b = -am;
+    ao = am + b;
+    f = ao & 7;
+    if (f == 0)
+      see_me_here();
+    if (ao >= 0)
+      am++;
+    else
+      error();
+  }
+}
+
+int main (void)
+{
+    j++;
+    k++;
+    i++;
+    g++;
+    h++;
+    e = 1;
+    a();
+    return 0;
+}
index 8d4f16e9e1f0a61e3ce39085132c68d1d67758a8..ad9be74daf0a1918159d5eb8caf5f97fc1aa9b33 100644 (file)
@@ -1652,7 +1652,7 @@ extract_range_from_plus_minus_expr (value_range_base *vr,
   value_range_kind vr0_kind = vr0.kind (), vr1_kind = vr1.kind ();
   tree vr0_min = vr0.min (), vr0_max = vr0.max ();
   tree vr1_min = vr1.min (), vr1_max = vr1.max ();
-  tree min = NULL, max = NULL;
+  tree min = NULL_TREE, max = NULL_TREE;
 
   /* This will normalize things such that calculating
      [0,0] - VR_VARYING is not dropped to varying, but is
@@ -1715,18 +1715,19 @@ extract_range_from_plus_minus_expr (value_range_base *vr,
       combine_bound (code, wmin, min_ovf, expr_type, min_op0, min_op1);
       combine_bound (code, wmax, max_ovf, expr_type, max_op0, max_op1);
 
-      /* If we have overflow for the constant part and the resulting
-        range will be symbolic, drop to VR_VARYING.  */
-      if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
-         || ((bool)max_ovf && sym_max_op0 != sym_max_op1))
+      /* If the resulting range will be symbolic, we need to eliminate any
+        explicit or implicit overflow introduced in the above computation
+        because compare_values could make an incorrect use of it.  That's
+        why we require one of the ranges to be a singleton.  */
+      if ((sym_min_op0 != sym_min_op1 || sym_max_op0 != sym_max_op1)
+         && ((bool)min_ovf || (bool)max_ovf
+             || (min_op0 != max_op0 && min_op1 != max_op1)))
        {
          vr->set_varying (expr_type);
          return;
        }
 
       /* Adjust the range for possible overflow.  */
-      min = NULL_TREE;
-      max = NULL_TREE;
       set_value_range_with_overflow (kind, min, max, expr_type,
                                     wmin, wmax, min_ovf, max_ovf);
       if (kind == VR_VARYING)