When DSE removes a trivially dead def we have to reset niter information on loops since that might refer to it. The patch also adds verification to make sure this does not happen.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. 2022-02-14 Richard Biener <rguent...@suse.de> PR tree-optimization/104528 * tree-ssa.h (find_released_ssa_name): Declare. * tree-ssa.cc (find_released_ssa_name): Export. * cfgloop.cc (verify_loop_structure): Look for released SSA names in loops nb_iterations. * tree-ssa-dse.cc (pass_dse::execute): Release number of iteration estimates. * gfortran.dg/pr104528.f: New testcase. --- gcc/cfgloop.cc | 13 ++++++++ gcc/testsuite/gfortran.dg/pr104528.f | 44 ++++++++++++++++++++++++++++ gcc/tree-ssa-dse.cc | 8 +++++ gcc/tree-ssa.cc | 2 +- gcc/tree-ssa.h | 1 + 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gfortran.dg/pr104528.f diff --git a/gcc/cfgloop.cc b/gcc/cfgloop.cc index 78fd6d5db1b..5ffcc77d93f 100644 --- a/gcc/cfgloop.cc +++ b/gcc/cfgloop.cc @@ -31,6 +31,8 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "gimple-iterator.h" #include "dumpfile.h" +#include "tree-ssa.h" +#include "tree-pretty-print.h" static void flow_loops_cfg_dump (FILE *); @@ -1561,6 +1563,17 @@ verify_loop_structure (void) err = 1; } } + + /* Check cached number of iterations for released SSA names. */ + tree ref; + if (loop->nb_iterations + && (ref = walk_tree (&loop->nb_iterations, + find_released_ssa_name, NULL, NULL))) + { + error ("loop %d%'s number of iterations %qE references the" + " released SSA name %qE", i, loop->nb_iterations, ref); + err = 1; + } } /* Check irreducible loops. */ diff --git a/gcc/testsuite/gfortran.dg/pr104528.f b/gcc/testsuite/gfortran.dg/pr104528.f new file mode 100644 index 00000000000..5b43feba97b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr104528.f @@ -0,0 +1,44 @@ +! { dg-do compile } +! { dg-options "-O2 -fpeel-loops -ftree-loop-vectorize -fno-tree-scev-cprop --param iv-max-considered-uses=2" } + REAL FUNCTION FOO(M, N, A, W) + + INTEGER M, N + + REAL W(*) + COMPLEX A(*) + + INTEGER II, JI, JJ, KK, LL, MP + + EXTERNAL BAR + + INTEGER QUX + EXTERNAL QUX + + CALL BAR(II) + + IF (M .EQ. 0) THEN + IF (N .EQ. 0) THEN + DO 140 KK = II, II + MP + W(KK) = 0 + 140 CONTINUE + ELSE + KK = II + MP + END IF + + DO 130 JI = KK, KK + MP + DO 120 LL = JJ, JJ + MP + DO 110 KK = II, II + MP + W(KK) = (A(KK)) + 110 CONTINUE + 120 CONTINUE + 130 CONTINUE + + IF (W(KK) .EQ. 0) THEN + FOO = W(QUX(MP, W, 1)) + END IF + + END IF + + RETURN + + END diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index 47997df2125..2b22a61ad97 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-modref-tree.h" #include "ipa-modref.h" #include "target.h" +#include "tree-ssa-loop-niter.h" /* This file implements dead store elimination. @@ -1418,6 +1419,8 @@ unsigned int pass_dse::execute (function *fun) { unsigned todo = 0; + bool released_def = false; + need_eh_cleanup = BITMAP_ALLOC (NULL); need_ab_cleanup = BITMAP_ALLOC (NULL); auto_sbitmap live_bytes (param_dse_max_object_size); @@ -1460,6 +1463,7 @@ pass_dse::execute (function *fun) if (gsi_remove (&gsi, true) && need_eh_cleanup) bitmap_set_bit (need_eh_cleanup, bb->index); release_defs (stmt); + released_def = true; } } if (gsi_end_p (gsi)) @@ -1481,6 +1485,7 @@ pass_dse::execute (function *fun) } remove_phi_node (&si, true); removed_phi = true; + released_def = true; } else gsi_next (&si); @@ -1506,6 +1511,9 @@ pass_dse::execute (function *fun) BITMAP_FREE (need_eh_cleanup); BITMAP_FREE (need_ab_cleanup); + if (released_def) + free_numbers_of_iterations_estimates (fun); + return todo; } diff --git a/gcc/tree-ssa.cc b/gcc/tree-ssa.cc index 8fe0682981d..430875ae37a 100644 --- a/gcc/tree-ssa.cc +++ b/gcc/tree-ssa.cc @@ -272,7 +272,7 @@ target_for_debug_bind (tree var) /* Called via walk_tree, look for SSA_NAMEs that have already been released. */ -static tree +tree find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_) { struct walk_stmt_info *wi = (struct walk_stmt_info *) data_; diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h index 36ddea276b5..008535454a8 100644 --- a/gcc/tree-ssa.h +++ b/gcc/tree-ssa.h @@ -49,6 +49,7 @@ extern void init_tree_ssa (function *, int size = 0); extern void delete_tree_ssa (function *); extern bool tree_ssa_useless_type_conversion (tree); extern tree tree_ssa_strip_useless_type_conversions (tree); +extern tree find_released_ssa_name (tree *, int *, void *); extern bool ssa_defined_default_def_p (tree t); -- 2.34.1