Hi!

As mentioned in the PR, since r269453 dom can process stmts newly added
by fold_stmt.  The problem is that at the start of the pass we construct
vr_values with the current number of SSA names and size the tables based on
that.  When we process a stmt which sets on lhs a new SSA_NAME above that
number, get_value_range returns for that address of a shared constant VR_VARYING
variable, but if we manage to find some smaller range, update_value_range
happily updates that shared range to this.

Based on IRC discussion, this is a minimal fix, approved by Richard on IRC.

Bootstrapped/regtested on {x86_64,i686,powerpc64le}-linux and bootstrapped
on {aarch64,s390x}-linux (profiledbootstrap for all; where aarch64-linux
profiledbootstrap would previously fail), committed to trunk.

2019-03-11  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89655
        PR bootstrap/89656
        * vr-values.c (vr_values::update_value_range): If
        old_vr->varying_p (), don't update it, make new_vr also VARYING
        and return false.

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

--- gcc/vr-values.c.jj  2019-01-24 19:54:20.792500923 +0100
+++ gcc/vr-values.c     2019-03-11 12:46:34.526494064 +0100
@@ -189,8 +189,13 @@ vr_values::update_value_range (const_tre
         because VR_RANGE and VR_ANTI_RANGE need to be considered
         the same.  We may not have is_new when transitioning to
         UNDEFINED.  If old_vr->type is VARYING, we shouldn't be
-        called.  */
-      if (new_vr->undefined_p ())
+        called, if we are anyway, keep it VARYING.  */
+      if (old_vr->varying_p ())
+       {
+         new_vr->set_varying ();
+         is_new = false;
+       }
+      else if (new_vr->undefined_p ())
        {
          old_vr->set_varying ();
          new_vr->set_varying ();
--- gcc/testsuite/gcc.c-torture/compile/pr89655.c.jj    2019-03-11 
13:45:27.279823237 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr89655.c       2019-03-11 
13:45:10.482097642 +0100
@@ -0,0 +1,15 @@
+/* PR middle-end/89655 */
+
+int a, b, d;
+char *c;
+
+void
+foo (void)
+{
+  int f = a;
+  for (;;)
+    {
+      for (f = 0; f < (a > 3 ? : a); f++)
+       b = c[f] ? c[(f + 2 > a - 1 ? a - 1 : 2) * d] : 0;
+    }
+}

        Jakub

Reply via email to