re PR tree-optimization/89595 (DOM miscompiles code)
authorRichard Biener <rguenther@suse.de>
Thu, 7 Mar 2019 12:46:44 +0000 (12:46 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 7 Mar 2019 12:46:44 +0000 (12:46 +0000)
2019-03-07  Richard Biener  <rguenther@suse.de>

PR tree-optimization/89595
* tree-ssa-dom.c (dom_opt_dom_walker::optimize_stmt): Take
stmt iterator as reference, take boolean output parameter to
indicate whether the stmt was removed and thus the iterator
already advanced.
(dom_opt_dom_walker::before_dom_children): Re-iterate over
stmts created by folding.

* gcc.dg/torture/pr89595.c: New testcase.

From-SVN: r269453

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr89595.c [new file with mode: 0644]
gcc/tree-ssa-dom.c

index 4d48a674e44a1c45c039bfa9815949e2229509cf..544d3ea275d4b71fbae3e7e7f304c2c797ceeea7 100644 (file)
@@ -1,3 +1,13 @@
+2019-03-07  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/89595
+       * tree-ssa-dom.c (dom_opt_dom_walker::optimize_stmt): Take
+       stmt iterator as reference, take boolean output parameter to
+       indicate whether the stmt was removed and thus the iterator
+       already advanced.
+       (dom_opt_dom_walker::before_dom_children): Re-iterate over
+       stmts created by folding.
+
 2019-03-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/89585
index 7092764419c327e67b6dd0a098c60fea812c926c..26f1716df9ad4b8b5e8575bb53844c9550160f34 100644 (file)
@@ -1,3 +1,8 @@
+2019-03-07  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/89595
+       * gcc.dg/torture/pr89595.c: New testcase.
+
 2019-03-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/89585
diff --git a/gcc/testsuite/gcc.dg/torture/pr89595.c b/gcc/testsuite/gcc.dg/torture/pr89595.c
new file mode 100644 (file)
index 0000000..ebd834f
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fgimple" } */
+
+int __attribute__((noipa))
+__GIMPLE(startwith("dom")) bar(int cond, int val)
+{
+  int i;
+
+  if (0 != 0)
+    goto bb_6;
+  else
+    goto bb_2;
+
+bb_2:
+  if (cond_5(D) != 0)
+    goto bb_4;
+  else
+    goto bb_5;
+
+bb_4:
+  i_6 = val_2(D);
+  i_1 = val_2(D) > 0 ? i_6 : 0;
+
+bb_5:
+  i_3 = __PHI (bb_4: i_1, bb_2: 0);
+  return i_3;
+
+bb_6:
+  i_4 = 1;
+  i_9 = 2;
+  goto bb_2;
+}
+
+int main()
+{
+  if (bar (1, 1) != 1)
+    __builtin_abort ();
+  return 0;
+}
index aa4e24bc358cc6905ddae2688cd3a7733991916a..b0d56fcf3e378c285c9b6c3ff891080d54fc0edd 100644 (file)
@@ -618,7 +618,7 @@ private:
      various tables mantained by DOM.  Returns the taken edge if
      the statement is a conditional with a statically determined
      value.  */
-  edge optimize_stmt (basic_block, gimple_stmt_iterator);
+  edge optimize_stmt (basic_block, gimple_stmt_iterator *, bool *);
 };
 
 /* Jump threading, redundancy elimination and const/copy propagation.
@@ -1480,10 +1480,48 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
   m_avail_exprs_stack->pop_to_marker ();
 
   edge taken_edge = NULL;
+  /* Initialize visited flag ahead of us, it has undefined state on
+     pass entry.  */
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    gimple_set_visited (gsi_stmt (gsi), false);
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
     {
+      /* Do not optimize a stmt twice, substitution might end up with
+         _3 = _3 which is not valid.  */
+      if (gimple_visited_p (gsi_stmt (gsi)))
+       {
+         gsi_next (&gsi);
+         continue;
+       }
+
+      /* Compute range information and optimize the stmt.  */
       evrp_range_analyzer.record_ranges_from_stmt (gsi_stmt (gsi), false);
-      taken_edge = this->optimize_stmt (bb, gsi);
+      bool removed_p = false;
+      taken_edge = this->optimize_stmt (bb, &gsi, &removed_p);
+      if (!removed_p)
+       gimple_set_visited (gsi_stmt (gsi), true);
+
+      /* Go back and visit stmts inserted by folding after substituting
+        into the stmt at gsi.  */
+      if (gsi_end_p (gsi))
+       {
+         gcc_checking_assert (removed_p);
+         gsi = gsi_last_bb (bb);
+         while (!gsi_end_p (gsi) && !gimple_visited_p (gsi_stmt (gsi)))
+           gsi_prev (&gsi);
+       }
+      else
+       {
+         do
+           {
+             gsi_prev (&gsi);
+           }
+         while (!gsi_end_p (gsi) && !gimple_visited_p (gsi_stmt (gsi)));
+       }
+      if (gsi_end_p (gsi))
+       gsi = gsi_start_bb (bb);
+      else
+       gsi_next (&gsi);
     }
 
   /* Now prepare to process dominated blocks.  */
@@ -1951,7 +1989,8 @@ test_for_singularity (gimple *stmt, gcond *dummy_cond,
       condition to an equality condition.  */
 
 edge
-dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
+dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
+                                  bool *removed_p)
 {
   gimple *stmt, *old_stmt;
   bool may_optimize_p;
@@ -1959,7 +1998,7 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
   bool was_noreturn;
   edge retval = NULL;
 
-  old_stmt = stmt = gsi_stmt (si);
+  old_stmt = stmt = gsi_stmt (*si);
   was_noreturn = is_gimple_call (stmt) && gimple_call_noreturn_p (stmt);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1982,9 +2021,9 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
 
       /* Try to fold the statement making sure that STMT is kept
         up to date.  */
-      if (fold_stmt (&si))
+      if (fold_stmt (si))
        {
-         stmt = gsi_stmt (si);
+         stmt = gsi_stmt (*si);
          gimple_set_modified (stmt, true);
 
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2032,8 +2071,8 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
          if (callee
              && fndecl_built_in_p (callee, BUILT_IN_CONSTANT_P))
            {
-             propagate_tree_value_into_stmt (&si, integer_zero_node);
-             stmt = gsi_stmt (si);
+             propagate_tree_value_into_stmt (si, integer_zero_node);
+             stmt = gsi_stmt (*si);
            }
        }
 
@@ -2089,9 +2128,9 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
        }
 
       update_stmt_if_modified (stmt);
-      eliminate_redundant_computations (&si, m_const_and_copies,
+      eliminate_redundant_computations (si, m_const_and_copies,
                                        m_avail_exprs_stack);
-      stmt = gsi_stmt (si);
+      stmt = gsi_stmt (*si);
 
       /* Perform simple redundant store elimination.  */
       if (gimple_assign_single_p (stmt)
@@ -2118,13 +2157,14 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
            {
              basic_block bb = gimple_bb (stmt);
              unlink_stmt_vdef (stmt);
-             if (gsi_remove (&si, true))
+             if (gsi_remove (si, true))
                {
                  bitmap_set_bit (need_eh_cleanup, bb->index);
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "  Flagged to clear EH edges.\n");
                }
              release_defs (stmt);
+             *removed_p = true;
              return retval;
            }
        }