]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/61289 (Bad jump threading generates infinite loop)
authorJeff Law <law@redhat.com>
Thu, 5 Jun 2014 18:25:02 +0000 (12:25 -0600)
committerJeff Law <law@gcc.gnu.org>
Thu, 5 Jun 2014 18:25:02 +0000 (12:25 -0600)
PR tree-optimization/61289
* tree-ssa-threadedge.c (invalidate_equivalences): Remove SRC_MAP and
DST_MAP parameters.   Invalidate by walking all the SSA_NAME_VALUES
looking for those which match LHS.  All callers changed.
(record_temporary_equivalences_from_phis): Remove SRC_MAP and DST_MAP
parameters and code which manipulated them.  All callers changed.
(record_temporary_equivalences_from_stmts_at_dest): Remove SRC_MAP
and DST_MAP parameters.  Simplify invalidation code by just calling
invalidate_equivalences.  All callers changed.
(thread_across_edge): Simplify now that we don't need to maintain
the map of equivalences to invalidate.

        PR tree-optimization/61289
* g++.dg/pr61289.C: New test.
* g++.dg/pr61289-2.C: New test.

From-SVN: r211287

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr61289-2.c [new file with mode: 0644]
gcc/testsuite/g++.dg/pr61289.C [new file with mode: 0644]
gcc/tree-ssa-threadedge.c

index 4d88dd2129dda3bbd1849c06020c832fe666fcdb..94a30d45e8bad14c8ef05c56dcf6c7609c50210a 100644 (file)
@@ -1,3 +1,17 @@
+2014-06-05  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/61289
+       * tree-ssa-threadedge.c (invalidate_equivalences): Remove SRC_MAP and
+       DST_MAP parameters.   Invalidate by walking all the SSA_NAME_VALUES
+       looking for those which match LHS.  All callers changed.
+       (record_temporary_equivalences_from_phis): Remove SRC_MAP and DST_MAP
+       parameters and code which manipulated them.  All callers changed.
+       (record_temporary_equivalences_from_stmts_at_dest): Remove SRC_MAP
+       and DST_MAP parameters.  Simplify invalidation code by just calling
+       invalidate_equivalences.  All callers changed.
+       (thread_across_edge): Simplify now that we don't need to maintain
+       the map of equivalences to invalidate.
+
 2014-06-05  Kai Tietz  <ktietz@redhat.com>
            Richard Henderson  <rth@redhat.com>
 
index 54a4026d39ee319e4c8a59e2875f8fabdac3c171..5fb5103deb85e8bfcb171a0c5902b26751a8c462 100644 (file)
@@ -1,3 +1,9 @@
+2014-06-05  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/61289
+       * g++.dg/pr61289.C: New test.
+       * g++.dg/pr61289-2.C: New test.
+
 2014-06-05  Richard Biener  <rguenther@suse.de>
            Paolo Carlini  <paolo.carlini@oracle.com>
 
diff --git a/gcc/testsuite/g++.dg/pr61289-2.c b/gcc/testsuite/g++.dg/pr61289-2.c
new file mode 100644 (file)
index 0000000..4cc3ebe
--- /dev/null
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-exceptions" } */
+struct S
+{
+  inline int fn1 () const { return s; }
+  __attribute__ ((noinline, noclone)) S *fn2 (int);
+  __attribute__ ((noinline, noclone)) void fn3 ();
+  __attribute__ ((noinline, noclone)) static S *fn4 (int);
+  S (int i) : s (i) {}
+  int s;
+};
+
+int a = 0;
+S *b = 0;
+
+S *
+S::fn2 (int i)
+{
+  a++;
+  if (a == 1)
+    return b;
+  if (a > 3)
+    __builtin_abort ();
+  b = this;
+  return new S (i + s);
+}
+
+S *
+S::fn4 (int i)
+{
+  b = new S (i);
+  return b;
+}
+
+void
+S::fn3 ()
+{
+  delete this;
+}
+
+void
+foo ()
+{
+  S *c = S::fn4 (20);
+  for (int i = 0; i < 2;)
+    {
+      S *d = c->fn2 (c->fn1 () + 10);
+      if (c != d)
+{
+  c->fn3 ();
+  c = d;
+  ++i;
+}
+    }
+  c->fn3 ();
+}
+
+int
+main ()
+{
+  foo ();
+}
diff --git a/gcc/testsuite/g++.dg/pr61289.C b/gcc/testsuite/g++.dg/pr61289.C
new file mode 100644 (file)
index 0000000..ea7ccea
--- /dev/null
@@ -0,0 +1,63 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-exceptions" } */
+
+struct S
+{
+  inline int fn1 () const { return s; }
+  __attribute__ ((noinline, noclone)) S *fn2 (int);
+  __attribute__ ((noinline, noclone)) void fn3 ();
+  __attribute__ ((noinline, noclone)) static S *fn4 (int);
+  S (int i) : s (i) {}
+  int s;
+};
+
+int a = 0;
+S *b = 0;
+
+S *
+S::fn2 (int i)
+{
+  a++;
+  if (a == 1)
+    return b;
+  if (a > 3)
+    __builtin_abort ();
+  b = this;
+  return new S (i + s);
+}
+
+S *
+S::fn4 (int i)
+{
+  b = new S (i);
+  return b;
+}
+
+void
+S::fn3 ()
+{
+  delete this;
+}
+
+void
+foo ()
+{
+  S *c = S::fn4 (20);
+  for (int i = 0; i < 2;)
+    {
+      S *d = c->fn2 (c->fn1 () + 10);
+      if (d != c)
+{
+  c->fn3 ();
+  c = d;
+  ++i;
+}
+    }
+  c->fn3 ();
+}
+
+int
+main ()
+{
+  foo ();
+}
index 69e5a6b5629e2c62e3521d554c20ad5611bf790c..ba9e1fe30f4444ab448a1fd16447b644d4d9a9f4 100644 (file)
@@ -200,9 +200,7 @@ record_temporary_equivalence (tree x, tree y, vec<tree> *stack)
    traversing back edges less painful.  */
 
 static bool
-record_temporary_equivalences_from_phis (edge e, vec<tree> *stack,
-                                        bool backedge_seen,
-                                        bitmap src_map, bitmap dst_map)
+record_temporary_equivalences_from_phis (edge e, vec<tree> *stack)
 {
   gimple_stmt_iterator gsi;
 
@@ -230,14 +228,6 @@ record_temporary_equivalences_from_phis (edge e, vec<tree> *stack,
        stmt_count++;
 
       record_temporary_equivalence (dst, src, stack);
-
-      /* If we have crossed a backedge, then start recording equivalences
-        we might need to invalidate.  */
-      if (backedge_seen && TREE_CODE (src) == SSA_NAME)
-       {
-         bitmap_set_bit (src_map, SSA_NAME_VERSION (src));
-         bitmap_set_bit (dst_map, SSA_NAME_VERSION (dst));
-       }
     }
   return true;
 }
@@ -295,29 +285,15 @@ fold_assignment_stmt (gimple stmt)
 /* A new value has been assigned to LHS.  If necessary, invalidate any
    equivalences that are no longer valid.  */
 static void
-invalidate_equivalences (tree lhs, vec<tree> *stack,
-                        bitmap src_map, bitmap dst_map)
+invalidate_equivalences (tree lhs, vec<tree> *stack)
 {
-  /* SRC_MAP contains the source SSA_NAMEs for equivalences created by PHI
-     nodes.  If an entry in SRC_MAP changes, there's some destination that
-     has been recorded as equivalent to the source and that equivalency
-     needs to be eliminated.  */
-  if (bitmap_bit_p (src_map, SSA_NAME_VERSION (lhs)))
-    {
-      unsigned int i;
-      bitmap_iterator bi;
-
-      /* We know that the LHS of STMT was used as the RHS in an equivalency
-        created by a PHI.  All the LHS of such PHIs were recorded into DST_MAP.
-        So we can iterate over them to see if any have the LHS of STMT as
-        an equivalence, and if so, remove the equivalence as it is no longer
-        valid.  */
-      EXECUTE_IF_SET_IN_BITMAP (dst_map, 0, i, bi)
-       {
-         if (SSA_NAME_VALUE (ssa_name (i)) == lhs)
-           record_temporary_equivalence (ssa_name (i), NULL_TREE, stack);
-       }
-    }
+
+  for (unsigned int i = 1; i < num_ssa_names; i++)
+    if (ssa_name (i) && SSA_NAME_VALUE (ssa_name (i)) == lhs)
+      record_temporary_equivalence (ssa_name (i), NULL_TREE, stack);
+
+  if (SSA_NAME_VALUE (lhs))
+    record_temporary_equivalence (lhs, NULL_TREE, stack);
 }
 
 /* Try to simplify each statement in E->dest, ultimately leading to
@@ -342,9 +318,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
                                                  vec<tree> *stack,
                                                  tree (*simplify) (gimple,
                                                                    gimple),
-                                                 bool backedge_seen,
-                                                 bitmap src_map,
-                                                 bitmap dst_map)
+                                                 bool backedge_seen)
 {
   gimple stmt = NULL;
   gimple_stmt_iterator gsi;
@@ -400,19 +374,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
 
          if (backedge_seen)
            FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
-             {
-               /* This call only invalidates equivalences created by
-                  PHI nodes.  This is by design to keep the cost of
-                  of invalidation reasonable.  */
-               invalidate_equivalences (op, stack, src_map, dst_map);
-
-               /* However, conditionals can imply values for real
-                  operands as well.  And those won't be recorded in the
-                  maps.  In fact, those equivalences may be recorded totally
-                  outside the threading code.  We can just create a new
-                  temporary NULL equivalence here.  */
-               record_temporary_equivalence (op, NULL_TREE, stack);
-             }
+             invalidate_equivalences (op, stack);
 
          continue;
        }
@@ -452,8 +414,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
              if (backedge_seen)
                {
                  tree lhs = gimple_get_lhs (stmt);
-                 record_temporary_equivalence (lhs, NULL_TREE, stack);
-                 invalidate_equivalences (lhs, stack, src_map, dst_map);
+                 invalidate_equivalences (lhs, stack);
                }
              continue;
            }
@@ -531,11 +492,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
              || is_gimple_min_invariant (cached_lhs)))
        record_temporary_equivalence (gimple_get_lhs (stmt), cached_lhs, stack);
       else if (backedge_seen)
-       record_temporary_equivalence (gimple_get_lhs (stmt), NULL_TREE, stack);
-
-      if (backedge_seen)
-       invalidate_equivalences (gimple_get_lhs (stmt), stack,
-                                src_map, dst_map);
+       invalidate_equivalences (gimple_get_lhs (stmt), stack);
     }
   return stmt;
 }
@@ -982,9 +939,7 @@ thread_through_normal_block (edge e,
                             tree (*simplify) (gimple, gimple),
                             vec<jump_thread_edge *> *path,
                             bitmap visited,
-                            bool *backedge_seen_p,
-                            bitmap src_map,
-                            bitmap dst_map)
+                            bool *backedge_seen_p)
 {
   /* If we have traversed a backedge, then we do not want to look
      at certain expressions in the table that can not be relied upon.
@@ -994,16 +949,14 @@ thread_through_normal_block (edge e,
     simplify = dummy_simplify;
 
   /* PHIs create temporary equivalences.  */
-  if (!record_temporary_equivalences_from_phis (e, stack, *backedge_seen_p,
-                                               src_map, dst_map))
+  if (!record_temporary_equivalences_from_phis (e, stack))
     return 0;
 
   /* Now walk each statement recording any context sensitive
      temporary equivalences we can detect.  */
   gimple stmt
     = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
-                                                       *backedge_seen_p,
-                                                       src_map, dst_map);
+                                                       *backedge_seen_p);
 
   /* If we didn't look at all the statements, the most likely reason is
      there were too many and thus duplicating this block is not profitable.
@@ -1112,8 +1065,6 @@ thread_across_edge (gimple dummy_cond,
                    tree (*simplify) (gimple, gimple))
 {
   bitmap visited = BITMAP_ALLOC (NULL);
-  bitmap src_map = BITMAP_ALLOC (NULL);
-  bitmap dst_map = BITMAP_ALLOC (NULL);
   bool backedge_seen;
 
   stmt_count = 0;
@@ -1129,16 +1080,13 @@ thread_across_edge (gimple dummy_cond,
   int threaded = thread_through_normal_block (e, dummy_cond,
                                              handle_dominating_asserts,
                                              stack, simplify, path,
-                                             visited, &backedge_seen,
-                                             src_map, dst_map);
+                                             visited, &backedge_seen);
   if (threaded > 0)
     {
       propagate_threaded_block_debug_into (path->last ()->e->dest,
                                           e->dest);
       remove_temporary_equivalences (stack);
       BITMAP_FREE (visited);
-      BITMAP_FREE (src_map);
-      BITMAP_FREE (dst_map);
       register_jump_thread (path);
       return;
     }
@@ -1160,8 +1108,6 @@ thread_across_edge (gimple dummy_cond,
       if (threaded < 0)
        {
          BITMAP_FREE (visited);
-         BITMAP_FREE (src_map);
-         BITMAP_FREE (dst_map);
          remove_temporary_equivalences (stack);
          return;
        }
@@ -1190,26 +1136,15 @@ thread_across_edge (gimple dummy_cond,
        {
          remove_temporary_equivalences (stack);
          BITMAP_FREE (visited);
-         BITMAP_FREE (src_map);
-         BITMAP_FREE (dst_map);
          return;
        }
 
-    /* We need to restore the state of the maps to this point each loop
-       iteration.  */
-    bitmap src_map_copy = BITMAP_ALLOC (NULL);
-    bitmap dst_map_copy = BITMAP_ALLOC (NULL);
-    bitmap_copy (src_map_copy, src_map);
-    bitmap_copy (dst_map_copy, dst_map);
-
     /* Look at each successor of E->dest to see if we can thread through it.  */
     FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
       {
        /* Push a fresh marker so we can unwind the equivalences created
           for each of E->dest's successors.  */
        stack->safe_push (NULL_TREE);
-       bitmap_copy (src_map, src_map_copy);
-       bitmap_copy (dst_map, dst_map_copy);
      
        /* Avoid threading to any block we have already visited.  */
        bitmap_clear (visited);
@@ -1245,8 +1180,7 @@ thread_across_edge (gimple dummy_cond,
          found = thread_through_normal_block (path->last ()->e, dummy_cond,
                                               handle_dominating_asserts,
                                               stack, simplify, path, visited,
-                                              &backedge_seen,
-                                              src_map, dst_map) > 0;
+                                              &backedge_seen) > 0;
 
        /* If we were able to thread through a successor of E->dest, then
           record the jump threading opportunity.  */
@@ -1265,10 +1199,6 @@ thread_across_edge (gimple dummy_cond,
        remove_temporary_equivalences (stack);
       }
     BITMAP_FREE (visited);
-    BITMAP_FREE (src_map);
-    BITMAP_FREE (dst_map);
-    BITMAP_FREE (src_map_copy);
-    BITMAP_FREE (dst_map_copy);
   }
 
   remove_temporary_equivalences (stack);