aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr89595.c39
-rw-r--r--gcc/tree-ssa-dom.c62
4 files changed, 105 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d48a67..544d3ea 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7092764..26f1716 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..ebd834f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr89595.c
@@ -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;
+}
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index aa4e24b..b0d56fc 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -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;
}
}