tree-cfgcleanup.c File Reference

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
#include "errors.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
#include "ggc.h"
#include "langhooks.h"
#include "diagnostic.h"
#include "tree-flow.h"
#include "timevar.h"
#include "tree-dump.h"
#include "tree-pass.h"
#include "toplev.h"
#include "except.h"
#include "cfgloop.h"
#include "cfglayout.h"
#include "hashtab.h"
#include "tree-ssa-propagate.h"
#include "tree-scalar-evolution.h"

Include dependency graph for tree-cfgcleanup.c:

Go to the source code of this file.

Functions

static bool remove_fallthru_edge (VEC(edge, gc)*ev)
static bool cleanup_control_expr_graph ()
 VEC (tree, gc)
static bool tree_forwarder_block_p ()
static bool has_abnormal_incoming_edge_p ()
static bool phi_alternatives_equal ()
static bool remove_forwarder_block ()
static bool cleanup_forwarder_blocks ()
static bool cleanup_tree_cfg_1 ()
bool cleanup_tree_cfg ()
void cleanup_tree_cfg_loop ()
static void remove_forwarder_block_with_phi ()
static unsigned int merge_phi_nodes ()
static bool gate_merge_phi ()

Variables

tree_opt_pass pass_merge_phi


Function Documentation

static bool cleanup_control_expr_graph  )  [static]
 

Disconnect an unreachable block in the control expression starting
   at block BB.   

Definition at line 71 of file tree-cfgcleanup.c.

References bsi_stmt(), COND_EXPR_COND, find_taken_edge(), fold(), SWITCH_COND, and TREE_CODE.

Referenced by VEC().

00072 {
00073   edge taken_edge;
00074   bool retval = false;
00075   tree expr = bsi_stmt (bsi), val;
00076 
00077   if (!single_succ_p (bb))
00078     {
00079       edge e;
00080       edge_iterator ei;
00081 
00082       switch (TREE_CODE (expr))
00083         {
00084         case COND_EXPR:
00085           val = fold (COND_EXPR_COND (expr));
00086           break;
00087 
00088         case SWITCH_EXPR:
00089           val = fold (SWITCH_COND (expr));
00090           if (TREE_CODE (val) != INTEGER_CST)
00091             return false;
00092           break;
00093 
00094         default:
00095           gcc_unreachable ();
00096         }
00097 
00098       taken_edge = find_taken_edge (bb, val);
00099       if (!taken_edge)
00100         return false;
00101 
00102       /* Remove all the edges except the one that is always executed.  */
00103       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
00104         {
00105           if (e != taken_edge)
00106             {
00107               taken_edge->probability += e->probability;
00108               taken_edge->count += e->count;
00109               remove_edge (e);
00110               retval = true;
00111             }
00112           else
00113             ei_next (&ei);
00114         }
00115       if (taken_edge->probability > REG_BR_PROB_BASE)
00116         taken_edge->probability = REG_BR_PROB_BASE;
00117     }
00118   else
00119     taken_edge = single_succ_edge (bb);
00120 
00121   bsi_remove (&bsi, true);
00122   taken_edge->flags = EDGE_FALLTHRU;
00123 
00124   /* We removed some paths from the cfg.  */
00125   free_dominance_info (CDI_DOMINATORS);
00126 
00127   return retval;
00128 }

static bool cleanup_forwarder_blocks  )  [static]
 

Removes forwarder blocks.   

Definition at line 494 of file tree-cfgcleanup.c.

References changed, remove_forwarder_block(), and tree_forwarder_block_p().

Referenced by cleanup_tree_cfg_1().

00495 {
00496   basic_block bb;
00497   bool changed = false;
00498   basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
00499   basic_block *current = worklist;
00500 
00501   FOR_EACH_BB (bb)
00502     {
00503       if (tree_forwarder_block_p (bb, false))
00504         *current++ = bb;
00505     }
00506 
00507   while (current != worklist)
00508     {
00509       bb = *--current;
00510       changed |= remove_forwarder_block (bb, &current);
00511     }
00512 
00513   free (worklist);
00514   return changed;
00515 }

bool cleanup_tree_cfg void   ) 
 

Remove unreachable blocks and other miscellaneous clean up work.
   Return true if the flowgraph was modified, false otherwise.   

Definition at line 555 of file tree-cfgcleanup.c.

References changed, and cleanup_tree_cfg_1().

Referenced by cleanup_tree_cfg_loop(), execute_cleanup_cfg_post_optimizing(), execute_cleanup_cfg_pre_ipa(), finalize_jump_threads(), fini_pre(), make_edges(), and tree_ssa_dominator_optimize().

00556 {
00557   bool retval, changed;
00558 
00559   timevar_push (TV_TREE_CLEANUP_CFG);
00560 
00561   /* Iterate until there are no more cleanups left to do.  If any
00562      iteration changed the flowgraph, set CHANGED to true.  */
00563   changed = false;
00564   do
00565     {
00566       retval = cleanup_tree_cfg_1 ();
00567       changed |= retval;
00568     }
00569   while (retval);
00570 
00571   compact_blocks ();
00572 
00573 #ifdef ENABLE_CHECKING
00574   verify_flow_info ();
00575 #endif
00576 
00577   timevar_pop (TV_TREE_CLEANUP_CFG);
00578 
00579   return changed;
00580 }

static bool cleanup_tree_cfg_1  )  [static]
 

Do one round of CFG cleanup.   

Definition at line 520 of file tree-cfgcleanup.c.

References cleanup_forwarder_blocks(), end_recording_case_labels(), and start_recording_case_labels().

Referenced by cleanup_tree_cfg().

00521 {
00522   bool retval;
00523 
00524   retval = cleanup_control_flow ();
00525   retval |= delete_unreachable_blocks ();
00526 
00527   /* Forwarder blocks can carry line number information which is
00528      useful when debugging, so we only clean them up when
00529      optimizing.  */
00530 
00531   if (optimize > 0)
00532     {
00533       /* cleanup_forwarder_blocks can redirect edges out of
00534          SWITCH_EXPRs, which can get expensive.  So we want to enable
00535          recording of edge to CASE_LABEL_EXPR mappings around the call
00536          to cleanup_forwarder_blocks.  */
00537       start_recording_case_labels ();
00538       retval |= cleanup_forwarder_blocks ();
00539       end_recording_case_labels ();
00540     }
00541 
00542   /* Merging the blocks may create new opportunities for folding
00543      conditional branches (due to the elimination of single-valued PHI
00544      nodes).  */
00545   retval |= merge_seq_blocks ();
00546 
00547   return retval;
00548 }

void cleanup_tree_cfg_loop void   ) 
 

Cleanup cfg and repair loop structures.   

Definition at line 585 of file tree-cfgcleanup.c.

References changed, cleanup_tree_cfg(), current_loops, rewrite_into_loop_closed_ssa(), scev_reset(), and TODO_update_ssa.

00586 {
00587   bool changed = cleanup_tree_cfg ();
00588 
00589   if (changed)
00590     {
00591       bitmap changed_bbs = BITMAP_ALLOC (NULL);
00592       fix_loop_structure (current_loops, changed_bbs);
00593       calculate_dominance_info (CDI_DOMINATORS);
00594 
00595       /* This usually does nothing.  But sometimes parts of cfg that originally
00596          were inside a loop get out of it due to edge removal (since they
00597          become unreachable by back edges from latch).  */
00598       rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
00599 
00600       BITMAP_FREE (changed_bbs);
00601 
00602 #ifdef ENABLE_CHECKING
00603       verify_loop_structure (current_loops);
00604 #endif
00605       scev_reset ();
00606     }
00607 }

static bool gate_merge_phi  )  [static]
 

Definition at line 822 of file tree-cfgcleanup.c.

00823 {
00824   return 1;
00825 }

static bool has_abnormal_incoming_edge_p  )  [inline, static]
 

Return true if BB has at least one abnormal incoming edge.   

Definition at line 318 of file tree-cfgcleanup.c.

Referenced by merge_phi_nodes(), and remove_forwarder_block().

00319 {
00320   edge e;
00321   edge_iterator ei;
00322 
00323   FOR_EACH_EDGE (e, ei, bb->preds)
00324     if (e->flags & EDGE_ABNORMAL)
00325       return true;
00326 
00327   return false;
00328 }

static unsigned int merge_phi_nodes  )  [static]
 

This pass merges PHI nodes if one feeds into another.  For example,
   suppose we have the following:

  goto <bb 9> (<L9>);

<L8>:;
  tem_17 = foo ();

  # tem_6 = PHI <tem_17(8), tem_23(7)>;
<L9>:;

  # tem_3 = PHI <tem_6(9), tem_2(5)>;
<L10>:;

  Then we merge the first PHI node into the second one like so:

  goto <bb 9> (<L10>);

<L8>:;
  tem_17 = foo ();

  # tem_3 = PHI <tem_23(7), tem_2(5), tem_17(8)>;
<L10>:;
 

Definition at line 740 of file tree-cfgcleanup.c.

References bb_for_stmt(), has_abnormal_incoming_edge_p(), has_zero_uses(), PHI_ARG_DEF, PHI_CHAIN, phi_nodes(), PHI_RESULT, single_imm_use(), TREE_CODE, and tree_forwarder_block_p().

00741 {
00742   basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
00743   basic_block *current = worklist;
00744   basic_block bb;
00745 
00746   calculate_dominance_info (CDI_DOMINATORS);
00747 
00748   /* Find all PHI nodes that we may be able to merge.  */
00749   FOR_EACH_BB (bb)
00750     {
00751       basic_block dest;
00752 
00753       /* Look for a forwarder block with PHI nodes.  */
00754       if (!tree_forwarder_block_p (bb, true))
00755         continue;
00756 
00757       dest = single_succ (bb);
00758 
00759       /* We have to feed into another basic block with PHI
00760          nodes.  */
00761       if (!phi_nodes (dest)
00762           /* We don't want to deal with a basic block with
00763              abnormal edges.  */
00764           || has_abnormal_incoming_edge_p (bb))
00765         continue;
00766 
00767       if (!dominated_by_p (CDI_DOMINATORS, dest, bb))
00768         {
00769           /* If BB does not dominate DEST, then the PHI nodes at
00770              DEST must be the only users of the results of the PHI
00771              nodes at BB.  */
00772           *current++ = bb;
00773         }
00774       else
00775         {
00776           tree phi;
00777           unsigned int dest_idx = single_succ_edge (bb)->dest_idx;
00778 
00779           /* BB dominates DEST.  There may be many users of the PHI
00780              nodes in BB.  However, there is still a trivial case we
00781              can handle.  If the result of every PHI in BB is used
00782              only by a PHI in DEST, then we can trivially merge the
00783              PHI nodes from BB into DEST.  */
00784           for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00785             {
00786               tree result = PHI_RESULT (phi);
00787               use_operand_p imm_use;
00788               tree use_stmt;
00789 
00790               /* If the PHI's result is never used, then we can just
00791                  ignore it.  */
00792               if (has_zero_uses (result))
00793                 continue;
00794 
00795               /* Get the single use of the result of this PHI node.  */
00796               if (!single_imm_use (result, &imm_use, &use_stmt)
00797                   || TREE_CODE (use_stmt) != PHI_NODE
00798                   || bb_for_stmt (use_stmt) != dest
00799                   || PHI_ARG_DEF (use_stmt, dest_idx) != result)
00800                 break;
00801             }
00802 
00803           /* If the loop above iterated through all the PHI nodes
00804              in BB, then we can merge the PHIs from BB into DEST.  */
00805           if (!phi)
00806             *current++ = bb;
00807         }
00808     }
00809 
00810   /* Now let's drain WORKLIST.  */
00811   while (current != worklist)
00812     {
00813       bb = *--current;
00814       remove_forwarder_block_with_phi (bb);
00815     }
00816 
00817   free (worklist);
00818   return 0;
00819 }

static bool phi_alternatives_equal  )  [static]
 

If all the PHI nodes in DEST have alternatives for E1 and E2 and
   those alternatives are equal in each of the PHI nodes, then return
   true, else return false.   

Definition at line 335 of file tree-cfgcleanup.c.

References NULL_TREE, operand_equal_for_phi_arg_p(), PHI_ARG_DEF, PHI_CHAIN, and phi_nodes().

Referenced by remove_forwarder_block(), and remove_forwarder_block_with_phi().

00336 {
00337   int n1 = e1->dest_idx;
00338   int n2 = e2->dest_idx;
00339   tree phi;
00340 
00341   for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00342     {
00343       tree val1 = PHI_ARG_DEF (phi, n1);
00344       tree val2 = PHI_ARG_DEF (phi, n2);
00345 
00346       gcc_assert (val1 != NULL_TREE);
00347       gcc_assert (val2 != NULL_TREE);
00348 
00349       if (!operand_equal_for_phi_arg_p (val1, val2))
00350         return false;
00351     }
00352 
00353   return true;
00354 }

static bool remove_fallthru_edge VEC(edge, gc)*  ev  )  [static]
 

Remove any fallthru edge from EV.  Return true if an edge was removed.   

Definition at line 53 of file tree-cfgcleanup.c.

00054 {
00055   edge_iterator ei;
00056   edge e;
00057 
00058   FOR_EACH_EDGE (e, ei, ev)
00059     if ((e->flags & EDGE_FALLTHRU) != 0)
00060       {
00061         remove_edge (e);
00062         return true;
00063       }
00064   return false;
00065 }

static bool remove_forwarder_block  )  [static]
 

Removes forwarder block BB.  Returns false if this failed.  If a new
   forwarder block is created due to redirection of edges, it is
   stored to worklist.   

Definition at line 361 of file tree-cfgcleanup.c.

References DECL_NONLOCAL, first_stmt(), has_abnormal_incoming_edge_p(), LABEL_EXPR_LABEL, NULL_TREE, phi_alternatives_equal(), phi_nodes(), and TREE_CODE.

Referenced by cleanup_forwarder_blocks().

00362 {
00363   edge succ = single_succ_edge (bb), e, s;
00364   basic_block dest = succ->dest;
00365   tree label;
00366   tree phi;
00367   edge_iterator ei;
00368   block_stmt_iterator bsi, bsi_to;
00369   bool seen_abnormal_edge = false;
00370 
00371   /* We check for infinite loops already in tree_forwarder_block_p.
00372      However it may happen that the infinite loop is created
00373      afterwards due to removal of forwarders.  */
00374   if (dest == bb)
00375     return false;
00376 
00377   /* If the destination block consists of a nonlocal label, do not merge
00378      it.  */
00379   label = first_stmt (dest);
00380   if (label
00381       && TREE_CODE (label) == LABEL_EXPR
00382       && DECL_NONLOCAL (LABEL_EXPR_LABEL (label)))
00383     return false;
00384 
00385   /* If there is an abnormal edge to basic block BB, but not into
00386      dest, problems might occur during removal of the phi node at out
00387      of ssa due to overlapping live ranges of registers.
00388 
00389      If there is an abnormal edge in DEST, the problems would occur
00390      anyway since cleanup_dead_labels would then merge the labels for
00391      two different eh regions, and rest of exception handling code
00392      does not like it.
00393 
00394      So if there is an abnormal edge to BB, proceed only if there is
00395      no abnormal edge to DEST and there are no phi nodes in DEST.  */
00396   if (has_abnormal_incoming_edge_p (bb))
00397     {
00398       seen_abnormal_edge = true;
00399 
00400       if (has_abnormal_incoming_edge_p (dest)
00401           || phi_nodes (dest) != NULL_TREE)
00402         return false;
00403     }
00404 
00405   /* If there are phi nodes in DEST, and some of the blocks that are
00406      predecessors of BB are also predecessors of DEST, check that the
00407      phi node arguments match.  */
00408   if (phi_nodes (dest))
00409     {
00410       FOR_EACH_EDGE (e, ei, bb->preds)
00411         {
00412           s = find_edge (e->src, dest);
00413           if (!s)
00414             continue;
00415 
00416           if (!phi_alternatives_equal (dest, succ, s))
00417             return false;
00418         }
00419     }
00420 
00421   /* Redirect the edges.  */
00422   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
00423     {
00424       if (e->flags & EDGE_ABNORMAL)
00425         {
00426           /* If there is an abnormal edge, redirect it anyway, and
00427              move the labels to the new block to make it legal.  */
00428           s = redirect_edge_succ_nodup (e, dest);
00429         }
00430       else
00431         s = redirect_edge_and_branch (e, dest);
00432 
00433       if (s == e)
00434         {
00435           /* Create arguments for the phi nodes, since the edge was not
00436              here before.  */
00437           for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00438             add_phi_arg (phi, PHI_ARG_DEF (phi, succ->dest_idx), s);
00439         }
00440       else
00441         {
00442           /* The source basic block might become a forwarder.  We know
00443              that it was not a forwarder before, since it used to have
00444              at least two outgoing edges, so we may just add it to
00445              worklist.  */
00446           if (tree_forwarder_block_p (s->src, false))
00447             *(*worklist)++ = s->src;
00448         }
00449     }
00450 
00451   if (seen_abnormal_edge)
00452     {
00453       /* Move the labels to the new block, so that the redirection of
00454          the abnormal edges works.  */
00455 
00456       bsi_to = bsi_start (dest);
00457       for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
00458         {
00459           label = bsi_stmt (bsi);
00460           gcc_assert (TREE_CODE (label) == LABEL_EXPR);
00461           bsi_remove (&bsi, false);
00462           bsi_insert_before (&bsi_to, label, BSI_CONTINUE_LINKING);
00463         }
00464     }
00465 
00466   /* Update the dominators.  */
00467   if (dom_info_available_p (CDI_DOMINATORS))
00468     {
00469       basic_block dom, dombb, domdest;
00470 
00471       dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
00472       domdest = get_immediate_dominator (CDI_DOMINATORS, dest);
00473       if (domdest == bb)
00474         {
00475           /* Shortcut to avoid calling (relatively expensive)
00476              nearest_common_dominator unless necessary.  */
00477           dom = dombb;
00478         }
00479       else
00480         dom = nearest_common_dominator (CDI_DOMINATORS, domdest, dombb);
00481 
00482       set_immediate_dominator (CDI_DOMINATORS, dest, dom);
00483     }
00484 
00485   /* And kill the forwarder block.  */
00486   delete_basic_block (bb);
00487 
00488   return true;
00489 }

static void remove_forwarder_block_with_phi  )  [static]
 

Merge the PHI nodes at BB into those at BB's sole successor.   

Definition at line 612 of file tree-cfgcleanup.c.

References add_phi_arg(), DECL_NONLOCAL, first_stmt(), LABEL_EXPR_LABEL, NULL_TREE, PENDING_STMT, phi_alternatives_equal(), PHI_ARG_DEF, PHI_CHAIN, phi_nodes(), TREE_CHAIN, TREE_CODE, TREE_PURPOSE, and TREE_VALUE.

00613 {
00614   edge succ = single_succ_edge (bb);
00615   basic_block dest = succ->dest;
00616   tree label;
00617   basic_block dombb, domdest, dom;
00618 
00619   /* We check for infinite loops already in tree_forwarder_block_p.
00620      However it may happen that the infinite loop is created
00621      afterwards due to removal of forwarders.  */
00622   if (dest == bb)
00623     return;
00624 
00625   /* If the destination block consists of a nonlocal label, do not
00626      merge it.  */
00627   label = first_stmt (dest);
00628   if (label
00629       && TREE_CODE (label) == LABEL_EXPR
00630       && DECL_NONLOCAL (LABEL_EXPR_LABEL (label)))
00631     return;
00632 
00633   /* Redirect each incoming edge to BB to DEST.  */
00634   while (EDGE_COUNT (bb->preds) > 0)
00635     {
00636       edge e = EDGE_PRED (bb, 0), s;
00637       tree phi;
00638 
00639       s = find_edge (e->src, dest);
00640       if (s)
00641         {
00642           /* We already have an edge S from E->src to DEST.  If S and
00643              E->dest's sole successor edge have the same PHI arguments
00644              at DEST, redirect S to DEST.  */
00645           if (phi_alternatives_equal (dest, s, succ))
00646             {
00647               e = redirect_edge_and_branch (e, dest);
00648               PENDING_STMT (e) = NULL_TREE;
00649               continue;
00650             }
00651 
00652           /* PHI arguments are different.  Create a forwarder block by
00653              splitting E so that we can merge PHI arguments on E to
00654              DEST.  */
00655           e = single_succ_edge (split_edge (e));
00656         }
00657 
00658       s = redirect_edge_and_branch (e, dest);
00659 
00660       /* redirect_edge_and_branch must not create a new edge.  */
00661       gcc_assert (s == e);
00662 
00663       /* Add to the PHI nodes at DEST each PHI argument removed at the
00664          destination of E.  */
00665       for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00666         {
00667           tree def = PHI_ARG_DEF (phi, succ->dest_idx);
00668 
00669           if (TREE_CODE (def) == SSA_NAME)
00670             {
00671               tree var;
00672 
00673               /* If DEF is one of the results of PHI nodes removed during
00674                  redirection, replace it with the PHI argument that used
00675                  to be on E.  */
00676               for (var = PENDING_STMT (e); var; var = TREE_CHAIN (var))
00677                 {
00678                   tree old_arg = TREE_PURPOSE (var);
00679                   tree new_arg = TREE_VALUE (var);
00680 
00681                   if (def == old_arg)
00682                     {
00683                       def = new_arg;
00684                       break;
00685                     }
00686                 }
00687             }
00688 
00689           add_phi_arg (phi, def, s);
00690         }
00691 
00692       PENDING_STMT (e) = NULL;
00693     }
00694 
00695   /* Update the dominators.  */
00696   dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
00697   domdest = get_immediate_dominator (CDI_DOMINATORS, dest);
00698   if (domdest == bb)
00699     {
00700       /* Shortcut to avoid calling (relatively expensive)
00701          nearest_common_dominator unless necessary.  */
00702       dom = dombb;
00703     }
00704   else
00705     dom = nearest_common_dominator (CDI_DOMINATORS, domdest, dombb);
00706 
00707   set_immediate_dominator (CDI_DOMINATORS, dest, dom);
00708 
00709   /* Remove BB since all of BB's incoming edges have been redirected
00710      to DEST.  */
00711   delete_basic_block (bb);
00712 }

static bool tree_forwarder_block_p  )  [static]
 

Return true if basic block BB does nothing except pass control
   flow to another block and that we can safely insert a label at
   the start of the successor block.

   As a precondition, we require that BB be not equal to
   ENTRY_BLOCK_PTR.   

Definition at line 239 of file tree-cfgcleanup.c.

References bsi_end_p(), bsi_last, bsi_prev(), bsi_stmt(), DECL_NONLOCAL, LABEL_EXPR_LABEL, NULL_TREE, phi_nodes(), and TREE_CODE.

Referenced by cleanup_forwarder_blocks(), and merge_phi_nodes().

00240 {
00241   block_stmt_iterator bsi;
00242   edge_iterator ei;
00243   edge e, succ;
00244   basic_block dest;
00245 
00246   /* BB must have a single outgoing edge.  */
00247   if (single_succ_p (bb) != 1
00248       /* If PHI_WANTED is false, BB must not have any PHI nodes.
00249          Otherwise, BB must have PHI nodes.  */
00250       || (phi_nodes (bb) != NULL_TREE) != phi_wanted
00251       /* BB may not be a predecessor of EXIT_BLOCK_PTR.  */
00252       || single_succ (bb) == EXIT_BLOCK_PTR
00253       /* Nor should this be an infinite loop.  */
00254       || single_succ (bb) == bb
00255       /* BB may not have an abnormal outgoing edge.  */
00256       || (single_succ_edge (bb)->flags & EDGE_ABNORMAL))
00257     return false;
00258 
00259 #if ENABLE_CHECKING
00260   gcc_assert (bb != ENTRY_BLOCK_PTR);
00261 #endif
00262 
00263   /* Now walk through the statements backward.  We can ignore labels,
00264      anything else means this is not a forwarder block.  */
00265   for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
00266     {
00267       tree stmt = bsi_stmt (bsi);
00268 
00269       switch (TREE_CODE (stmt))
00270         {
00271         case LABEL_EXPR:
00272           if (DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt)))
00273             return false;
00274           break;
00275 
00276         default:
00277           return false;
00278         }
00279     }
00280 
00281   if (find_edge (ENTRY_BLOCK_PTR, bb))
00282     return false;
00283 
00284   if (current_loops)
00285     {
00286       basic_block dest;
00287       /* Protect loop latches, headers and preheaders.  */
00288       if (bb->loop_father->header == bb)
00289         return false;
00290       dest = EDGE_SUCC (bb, 0)->dest;
00291 
00292       if (dest->loop_father->header == dest)
00293         return false;
00294     }
00295 
00296   /* If we have an EH edge leaving this block, make sure that the
00297      destination of this block has only one predecessor.  This ensures
00298      that we don't get into the situation where we try to remove two
00299      forwarders that go to the same basic block but are handlers for
00300      different EH regions.  */
00301   succ = single_succ_edge (bb);
00302   dest = succ->dest;
00303   FOR_EACH_EDGE (e, ei, bb->preds)
00304     {
00305       if (e->flags & EDGE_EH)
00306         {
00307           if (!single_pred_p (dest))
00308             return false;
00309         }
00310     }
00311 
00312   return true;
00313 }

VEC tree  ,
gc 
[inline]
 

Try to remove superfluous control structures.   

Definition at line 136 of file tree-cfgcleanup.c.

Referenced by access_functions_are_affine_or_constant_p(), add_graph_edge(), add_may_alias_for_new_tag(), add_virtual_operand(), allocate_graph_weights(), analyze_array(), build_constraint_graph(), build_constructor_from_list(), build_constructor_single(), build_tree_conflict_graph(), clear_edges_for_node(), compute_antic_aux(), compute_call_clobbered(), compute_data_dependences_for_loop(), compute_tag_properties(), compute_vuse_representatives(), create_name_tags(), create_overlap_variables_for(), create_structure_vars(), create_variable_info_for(), dequeue_and_dump(), do_structure_copy(), dump_may_aliases_for(), erase_graph_self_edge(), expand_vector_piecewise(), find_func_aliases(), find_idf(), get_graph_weights(), gimplify_compound_lval(), gimplify_init_constructor(), gimplify_init_ctor_preeval(), gimplify_switch_expr(), handle_ptr_arith(), init_data_ref(), is_aliased_with(), linear_transform_loops(), mark_aliases_call_clobbered(), merge_graph_nodes(), move_sese_region_to_fn(), new_type_alias(), perform_var_substitution(), phi_translate(), phi_translate_set(), prune_unused_phi_nodes(), reassociate_bb(), recalculate_used_alone(), remove_dead_inserted_code(), scev_analysis(), setup_pointers_and_addressables(), simple_cst_equal(), solve_graph(), topo_visit(), VEC(), vect_analyze_data_ref_accesses(), vect_analyze_data_ref_dependences(), vect_analyze_data_refs(), vect_compute_data_refs_alignment(), vect_create_cond_for_align_checks(), vect_enhance_data_refs_alignment(), vect_mark_stmts_to_be_vectorized(), vect_update_inits_of_drs(), vect_update_misalignment_for_peel(), vect_verify_datarefs_alignment(), verify_flow_insensitive_alias_info(), verify_name_tags(), and vn_lookup_or_add().

00142 {
00143   basic_block bb;
00144   block_stmt_iterator bsi;
00145   bool retval = false;
00146   tree stmt;
00147 
00148   /* Detect cases where a mid-block call is now known not to return.  */
00149   while (VEC_length (tree, modified_noreturn_calls))
00150     {
00151       stmt = VEC_pop (tree, modified_noreturn_calls);
00152       bb = bb_for_stmt (stmt);
00153       if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
00154         split_block (bb, stmt);
00155     }
00156 
00157   FOR_EACH_BB (bb)
00158     {
00159       bsi = bsi_last (bb);
00160 
00161       /* If the last statement of the block could throw and now cannot,
00162          we need to prune cfg.  */
00163       tree_purge_dead_eh_edges (bb);
00164 
00165       if (bsi_end_p (bsi))
00166         continue;
00167 
00168       stmt = bsi_stmt (bsi);
00169 
00170       if (TREE_CODE (stmt) == COND_EXPR
00171           || TREE_CODE (stmt) == SWITCH_EXPR)
00172         retval |= cleanup_control_expr_graph (bb, bsi);
00173       /* If we had a computed goto which has a compile-time determinable
00174          destination, then we can eliminate the goto.  */
00175       else if (TREE_CODE (stmt) == GOTO_EXPR
00176                && TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
00177                && (TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0))
00178                    == LABEL_DECL))
00179         {
00180           edge e;
00181           tree label;
00182           edge_iterator ei;
00183           basic_block target_block;
00184           bool removed_edge = false;
00185 
00186           /* First look at all the outgoing edges.  Delete any outgoing
00187              edges which do not go to the right block.  For the one
00188              edge which goes to the right block, fix up its flags.  */
00189           label = TREE_OPERAND (GOTO_DESTINATION (stmt), 0);
00190           target_block = label_to_block (label);
00191           for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
00192             {
00193               if (e->dest != target_block)
00194                 {
00195                   removed_edge = true;
00196                   remove_edge (e);
00197                 }
00198               else
00199                 {
00200                   /* Turn off the EDGE_ABNORMAL flag.  */
00201                   e->flags &= ~EDGE_ABNORMAL;
00202 
00203                   /* And set EDGE_FALLTHRU.  */
00204                   e->flags |= EDGE_FALLTHRU;
00205                   ei_next (&ei);
00206                 }
00207             }
00208 
00209           /* If we removed one or more edges, then we will need to fix the
00210              dominators.  It may be possible to incrementally update them.  */
00211           if (removed_edge)
00212             free_dominance_info (CDI_DOMINATORS);
00213 
00214           /* Remove the GOTO_EXPR as it is not needed.  The CFG has all the
00215              relevant information we need.  */
00216           bsi_remove (&bsi, true);
00217           retval = true;
00218         }
00219 
00220       /* Check for indirect calls that have been turned into
00221          noreturn calls.  */
00222       else if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
00223         {
00224           free_dominance_info (CDI_DOMINATORS);
00225           retval = true;
00226         }
00227     }
00228   return retval;
00229 }


Variable Documentation

struct tree_opt_pass pass_merge_phi
 

Initial value:

 {
  "mergephi",                   
  gate_merge_phi,               
  merge_phi_nodes,              
  NULL,                         
  NULL,                         
  0,                            
  TV_TREE_MERGE_PHI,            
  PROP_cfg | PROP_ssa,          
  0,                            
  0,                            
  0,                            
  TODO_dump_func | TODO_ggc_collect     
  | TODO_verify_ssa,
  0                             
}

Definition at line 827 of file tree-cfgcleanup.c.


Generated on Sun Sep 17 18:03:37 2006 for Tree SSA by  doxygen 1.4.6