loop-init.c (loop_optimizer_init, [...]): Do not destroy dominance information.
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Sat, 17 Jul 2004 18:08:10 +0000 (20:08 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Sat, 17 Jul 2004 18:08:10 +0000 (18:08 +0000)
* loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Do not
destroy dominance information.
* passes.c (rest_of_handle_loop2):  Free dominance information.
* tree-cfg.c (cleanup_tree_cfg): Remove unreachable blocks before
jump threading.
(thread_jumps): Update dominance information and remove unreachable
blocks.
* tree-ssa-phiopt.c (replace_phi_with_stmt):  Update dominance
information and remove the unreachable block.

From-SVN: r84873

gcc/ChangeLog
gcc/loop-init.c
gcc/passes.c
gcc/tree-cfg.c
gcc/tree-ssa-phiopt.c

index 50b998b1da2bebcaf49b6a51c075f69b0ea65b23..c86cd8e7a5ee4a068006616e90882e02abbf3bb3 100644 (file)
@@ -1,3 +1,15 @@
+2004-07-17  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       * loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Do not
+       destroy dominance information.
+       * passes.c (rest_of_handle_loop2):  Free dominance information.
+       * tree-cfg.c (cleanup_tree_cfg): Remove unreachable blocks before
+       jump threading.
+       (thread_jumps): Update dominance information and remove unreachable
+       blocks.
+       * tree-ssa-phiopt.c (replace_phi_with_stmt):  Update dominance
+       information and remove the unreachable block.
+
 2004-07-17  Graham Stott  <graham.stott@btinternet.com>
 
        * emit-rtl.c (reorder_insns): Don't set BB for a BARRIER insn.
index ff441e8c56d2091b36cf21e2e9386a53963b7a02..35fa12ea3e64b4884bca9d44e8ea04024bd37436 100644 (file)
@@ -55,7 +55,6 @@ loop_optimizer_init (FILE *dumpfile)
     {
       /* No loops.  */
       flow_loops_free (loops);
-      free_dominance_info (CDI_DOMINATORS);
       free (loops);
 
       return NULL;
@@ -105,7 +104,6 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile)
 
   /* Clean up.  */
   flow_loops_free (loops);
-  free_dominance_info (CDI_DOMINATORS);
   free (loops);
 
   /* Checking.  */
index 60b4c08d20256bde62d561e41484d6012882b8a0..108d18583adbdb4824e03f79ea65aca1e3c57d77 100644 (file)
@@ -1380,6 +1380,8 @@ rest_of_handle_loop2 (void)
       loop_optimizer_finalize (loops, dump_file);
     }
 
+  free_dominance_info (CDI_DOMINATORS);
+
   /* Finalize layout changes.  */
   FOR_EACH_BB (bb)
     if (bb->next_bb != EXIT_BLOCK_PTR)
index ac2d5da3c8d85cf7a92295d3662728e0a66bcaae..c80dcf1d086c97cf3106dcd8e98c4fd543111d78 100644 (file)
@@ -733,8 +733,8 @@ cleanup_tree_cfg (void)
   while (something_changed)
     {
       something_changed = cleanup_control_flow ();
-      something_changed |= thread_jumps ();
       something_changed |= delete_unreachable_blocks ();
+      something_changed |= thread_jumps ();
     }
 
   /* Merging the blocks creates no new opportunities for the other
@@ -3904,7 +3904,7 @@ static bool
 thread_jumps (void)
 {
   edge e, next, last, old;
-  basic_block bb, dest, tmp;
+  basic_block bb, dest, tmp, old_dest, dom;
   tree phi;
   int arg;
   bool retval = false;
@@ -3991,11 +3991,9 @@ thread_jumps (void)
 
          /* Perform the redirection.  */
          retval = true;
+         old_dest = e->dest;
          e = redirect_edge_and_branch (e, dest);
 
-         /* TODO -- updating dominators in this case is simple.  */
-         free_dominance_info (CDI_DOMINATORS);
-
          if (!old)
            {
              /* Update PHI nodes.   We know that the new argument should
@@ -4009,6 +4007,49 @@ thread_jumps (void)
                  add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
                }
            }
+
+         /* Update the dominators.  */
+         if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
+           {
+             /* Remove the unreachable blocks (observe that if all blocks
+                were reachable before, only those in the path we threaded
+                over and did not have any predecessor outside of the path
+                become unreachable).  */
+             for (; old_dest != dest; old_dest = tmp)
+               {
+                 tmp = old_dest->succ->dest;
+
+                 if (old_dest->pred)
+                   break;
+
+                 delete_basic_block (old_dest);
+               }
+             /* If the dominator of the destination was in the path, set its
+                dominator to the start of the redirected edge.  */
+             if (get_immediate_dominator (CDI_DOMINATORS, old_dest) == NULL)
+               set_immediate_dominator (CDI_DOMINATORS, old_dest, bb);
+
+             /* Now proceed like if we forwarded just over one edge at a time.
+                Algorithm for forwarding over edge A --> B then is
+
+                if (idom (B) == A)
+                  idom (B) = idom (A);
+                recount_idom (A);  */
+
+             for (; old_dest != dest; old_dest = tmp)
+               {
+                 tmp = old_dest->succ->dest;
+
+                 if (get_immediate_dominator (CDI_DOMINATORS, tmp) == old_dest)
+                   {
+                     dom = get_immediate_dominator (CDI_DOMINATORS, old_dest);
+                     set_immediate_dominator (CDI_DOMINATORS, tmp, dom);
+                   }
+
+                 dom = recount_dominator (CDI_DOMINATORS, old_dest);
+                 set_immediate_dominator (CDI_DOMINATORS, old_dest, dom);
+               }
+           }
        }
 
       /* Reset the forwardable bit on our block since it's no longer in
index bc14dc48d808cfa7c965ccb9199ee4e57e201899..50c845e76379bb61800f271b03c653a3600bbb6c 100644 (file)
@@ -236,6 +236,8 @@ static void
 replace_phi_with_stmt (block_stmt_iterator bsi, basic_block bb,
                       basic_block cond_block, tree phi, tree new)
 {
+  basic_block block_to_remove;
+
   /* Insert our new statement at the head of our block.  */
   bsi_insert_after (&bsi, new, BSI_NEW_STMT);
   
@@ -250,21 +252,23 @@ replace_phi_with_stmt (block_stmt_iterator bsi, basic_block bb,
   release_phi_node (phi);
   bb_ann (bb)->phi_nodes = NULL;
   
-  /* Disconnect the edge leading into the empty block.  That will
-     make the empty block unreachable and it will be removed later.  */
+  /* Remove the empty basic block.  */
   if (cond_block->succ->dest == bb)
     {
       cond_block->succ->flags |= EDGE_FALLTHRU;
       cond_block->succ->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
-      ssa_remove_edge (cond_block->succ->succ_next);
+
+      block_to_remove = cond_block->succ->succ_next->dest;
     }
   else
     {
       cond_block->succ->succ_next->flags |= EDGE_FALLTHRU;
       cond_block->succ->succ_next->flags
        &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
-      ssa_remove_edge (cond_block->succ);
+
+      block_to_remove = cond_block->succ->dest;
     }
+  delete_basic_block (block_to_remove);
   
   /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
   bsi = bsi_last (cond_block);