The testcase in this PR shows that IVOPTs ends up using cached
control IV information of IVs that have been elimiated by it.
IVOPTs fails to properly release that information as scev_reset
just resets ->nb_iterations but not control-IVs.

A proper fix is to avoid doing the above for each loop and instead
delay IV def removal until IVOPTs has finished and there ensure
also possibly invalidated control-IVs are released.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

IMHO this is the proper fix, I'll test and install also a patch
restoring defensive checks that avoided the ICE before.

Slightly safe might be to prune control-IVs where we do
scev_reset () now instead of delaying DEF removal.  I'm only 99%
sure IVOPTs, when processing outer loops, is not affected by
the dead IVs being still in the IL (all uses are already updated
but feeding defs are not elimiated either).

Bin?

Richard.

2019-03-21  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/89779
        * tree-ssa-loop-ivopts.c (remove_unused_ivs): Return
        to remove IV defs, delay actual removal.
        (tree_ssa_iv_optimize_loop): Likewise.  Avoid SCEV reset.
        (tree_ssa_iv_optimize): Remove eliminated IV defs at the
        very end, properly also reset loop control IV information.

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

Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c  (revision 269832)
+++ gcc/tree-ssa-loop-ivopts.c  (working copy)
@@ -7258,11 +7258,10 @@ rewrite_groups (struct ivopts_data *data
 /* Removes the ivs that are not used after rewriting.  */
 
 static void
-remove_unused_ivs (struct ivopts_data *data)
+remove_unused_ivs (struct ivopts_data *data, bitmap toremove)
 {
   unsigned j;
   bitmap_iterator bi;
-  bitmap toremove = BITMAP_ALLOC (NULL);
 
   /* Figure out an order in which to release SSA DEFs so that we don't
      release something that we'd have to propagate into a debug stmt
@@ -7384,10 +7383,6 @@ remove_unused_ivs (struct ivopts_data *d
            }
        }
     }
-
-  release_defs_bitset (toremove);
-
-  BITMAP_FREE (toremove);
 }
 
 /* Frees memory occupied by struct tree_niter_desc in *VALUE. Callback
@@ -7530,7 +7525,8 @@ loop_body_includes_call (basic_block *bo
 /* Optimizes the LOOP.  Returns true if anything changed.  */
 
 static bool
-tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
+tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
+                          bitmap toremove)
 {
   bool changed = false;
   struct iv_ca *iv_ca;
@@ -7600,12 +7596,7 @@ tree_ssa_iv_optimize_loop (struct ivopts
   rewrite_groups (data);
 
   /* Remove the ivs that are unused after rewriting.  */
-  remove_unused_ivs (data);
-
-  /* We have changed the structure of induction variables; it might happen
-     that definitions in the scev database refer to some of them that were
-     eliminated.  */
-  scev_reset ();
+  remove_unused_ivs (data, toremove);
 
 finish:
   free_loop_data (data);
@@ -7620,6 +7611,7 @@ tree_ssa_iv_optimize (void)
 {
   struct loop *loop;
   struct ivopts_data data;
+  auto_bitmap toremove;
 
   tree_ssa_iv_optimize_init (&data);
 
@@ -7629,9 +7621,19 @@ tree_ssa_iv_optimize (void)
       if (dump_file && (dump_flags & TDF_DETAILS))
        flow_loop_dump (loop, dump_file, NULL, 1);
 
-      tree_ssa_iv_optimize_loop (&data, loop);
+      tree_ssa_iv_optimize_loop (&data, loop, toremove);
     }
 
+  /* Remove eliminated IV defs.  */
+  release_defs_bitset (toremove);
+
+  /* We have changed the structure of induction variables; it might happen
+     that definitions in the scev database refer to some of them that were
+     eliminated.  */
+  scev_reset_htab ();
+  /* Likewise niter and control-IV information.  */
+  free_numbers_of_iterations_estimates (cfun);
+
   tree_ssa_iv_optimize_finalize (&data);
 }
 
Index: gcc/testsuite/gcc.dg/torture/pr89779.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr89779.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr89779.c      (working copy)
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+typedef int a;
+void h(a);
+void c(a *d, int b)
+{
+  int e, f, g;
+  for (; e; e++)
+    for (f = 0; f < 4; f++)
+      if (d)
+       for (g = e + 1; g; g++)
+         h(d[g]);
+}
+void i()
+{
+  a *j;
+  int k, l;
+  for (; k; k++)
+    c(j, l);
+}

Reply via email to