tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore backedges when identifying...
authorRichard Biener <rguenther@suse.de>
Mon, 24 Oct 2016 11:22:42 +0000 (11:22 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 24 Oct 2016 11:22:42 +0000 (11:22 +0000)
2016-10-24  Richard Biener  <rguenther@suse.de>

* tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore
backedges when identifying the single predecessor to take
conditional info from.  Use SCEV to get at ranges for loop IVs.
* lto-streamer-out.c (lto_write_mode_table): CSE inner mode to
avoid false warning.

* gcc.dg/tree-ssa/cunroll-13.c: Disable EVRP.
* gcc.dg/tree-ssa/pr21458.c: Likewise.
* gcc.dg/tree-ssa/pr21458-2.c: New testcase for EVRP.

From-SVN: r241470

gcc/ChangeLog
gcc/lto-streamer-out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c
gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr21458.c
gcc/tree-vrp.c

index 291ef4507de8dc21990ef0aabb8bf5a55244b1ca..e8ddeb014f209a36df91bd0809431f438e24842a 100644 (file)
@@ -1,3 +1,11 @@
+2016-10-24  Richard Biener  <rguenther@suse.de>
+
+       * tree-vrp.c (evrp_dom_walker::before_dom_children): Ignore
+       backedges when identifying the single predecessor to take
+       conditional info from.  Use SCEV to get at ranges for loop IVs.
+       * lto-streamer-out.c (lto_write_mode_table): CSE inner mode to
+       avoid false warning.
+
 2016-10-24  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/78093
index 22c4140cca8a2eecb66e21662654148bd20778b7..22d8ac90724339839290e3b5b137f6da7e45720f 100644 (file)
@@ -2720,8 +2720,9 @@ lto_write_mode_table (void)
     if (streamer_mode_table[i])
       {
        machine_mode m = (machine_mode) i;
-       if (GET_MODE_INNER (m) != m)
-         streamer_mode_table[(int) GET_MODE_INNER (m)] = 1;
+       machine_mode inner_m = GET_MODE_INNER (m);
+       if (inner_m != m)
+         streamer_mode_table[(int) inner_m] = 1;
       }
   /* First stream modes that have GET_MODE_INNER (m) == m,
      so that we can refer to them afterwards.  */
index bc9bf6760327c0681cdd20432f18ffc60b7382a5..eb0f9761511f5784c36136c6b75728d33ffdddb3 100644 (file)
@@ -1,3 +1,9 @@
+2016-10-24  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/cunroll-13.c: Disable EVRP.
+       * gcc.dg/tree-ssa/pr21458.c: Likewise.
+       * gcc.dg/tree-ssa/pr21458-2.c: New testcase for EVRP.
+
 2016-10-24  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/78093
index 6e4417a75205acda6b643520061869183c91dec3..f3fe8b514687ec954633025eb734c0f29d5e4e1b 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O3 -fdisable-tree-cunrolli -fdisable-tree-vrp1 -fdump-tree-cunroll-blocks-details" } */
+/* { dg-options "-O3 -fdisable-tree-evrp -fdisable-tree-cunrolli -fdisable-tree-vrp1 -fdump-tree-cunroll-blocks-details" } */
 struct a {int a[8];int b;};
 void
 t(struct a *a)
@@ -8,7 +8,7 @@ t(struct a *a)
     a->a[i]++;
 }
 /* This pass relies on the fact that we do not eliminate the redundant test for i early.
-   It is necessary to disable all passes that do so.  At the moment it is vrp1 and cunrolli.  */
+   It is necessary to disable all passes that do so.  At the moment it is evrp, vrp1 and cunrolli.  */
 /* { dg-final { scan-tree-dump-times "Loop 1 iterates 123454 times" 1 "cunroll" } } */
 /* { dg-final { scan-tree-dump-times "Last iteration exit edge was proved true" 1 "cunroll" } } */
 /* { dg-final { scan-tree-dump-times "Exit condition of peeled iterations was eliminated" 1 "cunroll" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21458-2.c
new file mode 100644 (file)
index 0000000..2aee42f
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp-details" } */
+
+extern void g (void);
+extern void bar (int);
+
+int
+foo (int a)
+{
+  int i;
+
+  for (i = 1; i < 100; i++)
+    {
+      if (i)
+       g ();
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "Predicate evaluates to: 1" 1 "evrp" } } */
index 20ec9c9e9cf7292d86d540cc772456390cb70ed0..97d17f21cfbbaf2f4fd5aba23574eefe4dc928b1 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1" } */
 
 extern void g (void);
 extern void bar (int);
index 9675ca239b4f22227593147ff8e78c4fd2691443..fcdb3417bb3b3fa26bee8cd66ef2e5457134903c 100644 (file)
@@ -10693,12 +10693,29 @@ edge
 evrp_dom_walker::before_dom_children (basic_block bb)
 {
   tree op0 = NULL_TREE;
+  edge_iterator ei;
+  edge e;
 
   push_value_range (NULL_TREE, NULL);
-  if (single_pred_p (bb))
+
+  edge pred_e = NULL;
+  FOR_EACH_EDGE (e, ei, bb->preds)
     {
-      edge e = single_pred_edge (bb);
-      gimple *stmt = last_stmt (e->src);
+      /* Ignore simple backedges from this to allow recording conditions
+        in loop headers.  */
+      if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
+       continue;
+      if (! pred_e)
+       pred_e = e;
+      else
+       {
+         pred_e = NULL;
+         break;
+       }
+    }
+  if (pred_e)
+    {
+      gimple *stmt = last_stmt (pred_e->src);
       if (stmt
          && gimple_code (stmt) == GIMPLE_COND
          && (op0 = gimple_cond_lhs (stmt))
@@ -10715,7 +10732,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
            op1 = drop_tree_overflow (op1);
 
          /* If condition is false, invert the cond.  */
-         if (e->flags & EDGE_FALSE_VALUE)
+         if (pred_e->flags & EDGE_FALSE_VALUE)
            code = invert_tree_comparison (gimple_cond_code (stmt),
                                           HONOR_NANS (op0));
          /* Add VR when (OP0 CODE OP1) condition is true.  */
@@ -10743,11 +10760,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
     }
 
   /* Visit PHI stmts and discover any new VRs possible.  */
-  gimple_stmt_iterator gsi;
-  edge e;
-  edge_iterator ei;
   bool has_unvisited_preds = false;
-
   FOR_EACH_EDGE (e, ei, bb->preds)
     if (e->flags & EDGE_EXECUTABLE
        && !(e->src->flags & BB_VISITED))
@@ -10761,12 +10774,26 @@ evrp_dom_walker::before_dom_children (basic_block bb)
     {
       gphi *phi = gpi.phi ();
       tree lhs = PHI_RESULT (phi);
+      if (virtual_operand_p (lhs))
+       continue;
       value_range vr_result = VR_INITIALIZER;
+      bool interesting = stmt_interesting_for_vrp (phi);
       if (!has_unvisited_preds
-         && stmt_interesting_for_vrp (phi))
+         && interesting)
        extract_range_from_phi_node (phi, &vr_result);
       else
-       set_value_range_to_varying (&vr_result);
+       {
+         set_value_range_to_varying (&vr_result);
+         /* When we have an unvisited executable predecessor we can't
+            use PHI arg ranges which may be still UNDEFINED but have
+            to use VARYING for them.  But we can still resort to
+            SCEV for loop header PHIs.  */
+         struct loop *l;
+         if (interesting
+             && (l = loop_containing_stmt (phi))
+             && l->header == gimple_bb (phi))
+           adjust_range_with_scev (&vr_result, l, phi, lhs);
+       }
       update_value_range (lhs, &vr_result);
 
       /* Mark PHIs whose lhs we fully propagate for removal.  */
@@ -10778,7 +10805,8 @@ evrp_dom_walker::before_dom_children (basic_block bb)
   edge taken_edge = NULL;
 
   /* Visit all other stmts and discover any new VRs possible.  */
-  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+  for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+       !gsi_end_p (gsi); gsi_next (&gsi))
     {
       gimple *stmt = gsi_stmt (gsi);
       tree output = NULL_TREE;