From 1a438d160e1dc845882c2ecba99513a09a931623 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 7 Mar 2019 12:46:44 +0000 Subject: [PATCH] re PR tree-optimization/89595 (DOM miscompiles code) 2019-03-07 Richard Biener 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 | 10 +++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/torture/pr89595.c | 39 ++++++++++++++++ gcc/tree-ssa-dom.c | 62 +++++++++++++++++++++----- 4 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr89595.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4d48a674e44..544d3ea275d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-03-07 Richard Biener + + 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 PR c++/89585 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7092764419c..26f1716df9a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-03-07 Richard Biener + + PR tree-optimization/89595 + * gcc.dg/torture/pr89595.c: New testcase. + 2019-03-07 Jakub Jelinek 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 00000000000..ebd834f32a4 --- /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 aa4e24bc358..b0d56fcf3e3 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; } } -- 2.30.2