OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cfghooks.c
index e224ad8..c4c51cc 100644 (file)
@@ -1,5 +1,6 @@
 /* Hooks for cfg representation specific functions.
-   Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2010
+   Free Software Foundation, Inc.
    Contributed by Sebastian Pop <s.pop@laposte.net>
 
 This file is part of GCC.
@@ -27,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "basic-block.h"
 #include "tree-flow.h"
 #include "timevar.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "cfgloop.h"
 
 /* A pointer to one of the hooks containers.  */
@@ -50,9 +51,21 @@ cfg_layout_rtl_register_cfg_hooks (void)
 /* Initialization of functions specific to the tree IR.  */
 
 void
-tree_register_cfg_hooks (void)
+gimple_register_cfg_hooks (void)
 {
-  cfg_hooks = &tree_cfg_hooks;
+  cfg_hooks = &gimple_cfg_hooks;
+}
+
+struct cfg_hooks
+get_cfg_hooks (void)
+{
+  return *cfg_hooks;
+}
+
+void
+set_cfg_hooks (struct cfg_hooks new_cfg_hooks)
+{
+  *cfg_hooks = new_cfg_hooks;
 }
 
 /* Returns current ir type.  */
@@ -60,7 +73,7 @@ tree_register_cfg_hooks (void)
 enum ir_type
 current_ir_type (void)
 {
-  if (cfg_hooks == &tree_cfg_hooks)
+  if (cfg_hooks == &gimple_cfg_hooks)
     return IR_GIMPLE;
   else if (cfg_hooks == &rtl_cfg_hooks)
     return IR_RTL_CFGRTL;
@@ -75,7 +88,7 @@ current_ir_type (void)
    Currently it does following: checks edge and basic block list correctness
    and calls into IL dependent checking then.  */
 
-void
+DEBUG_FUNCTION void
 verify_flow_info (void)
 {
   size_t *edge_checksum;
@@ -290,7 +303,7 @@ dump_bb (basic_block bb, FILE *outf, int indent)
   putc ('\n', outf);
 
   if (cfg_hooks->dump_bb)
-    cfg_hooks->dump_bb (bb, outf, indent);
+    cfg_hooks->dump_bb (bb, outf, indent, 0);
 }
 
 /* Redirect edge E to the given basic block DEST and update underlying program
@@ -321,7 +334,7 @@ redirect_edge_and_branch (edge e, basic_block dest)
    to the destination of the other edge going from its source.  */
 
 bool
-can_remove_branch_p (edge e)
+can_remove_branch_p (const_edge e)
 {
   if (!cfg_hooks->can_remove_branch_p)
     internal_error ("%s does not support can_remove_branch_p",
@@ -375,7 +388,6 @@ basic_block
 redirect_edge_and_branch_force (edge e, basic_block dest)
 {
   basic_block ret, src = e->src;
-  struct loop *loop;
 
   if (!cfg_hooks->redirect_edge_and_branch_force)
     internal_error ("%s does not support redirect_edge_and_branch_force",
@@ -385,16 +397,17 @@ redirect_edge_and_branch_force (edge e, basic_block dest)
     rescan_loop_exit (e, false, true);
 
   ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
-  if (ret != NULL
-      && dom_info_available_p (CDI_DOMINATORS))
+
+  if (ret != NULL && dom_info_available_p (CDI_DOMINATORS))
     set_immediate_dominator (CDI_DOMINATORS, ret, src);
 
   if (current_loops != NULL)
     {
       if (ret != NULL)
        {
-         loop = find_common_loop (single_pred (ret)->loop_father,
-                                  single_succ (ret)->loop_father);
+         struct loop *loop
+           = find_common_loop (single_pred (ret)->loop_father,
+                               single_succ (ret)->loop_father);
          add_bb_to_loop (ret, loop);
        }
       else if (find_edge (src, dest) == e)
@@ -412,6 +425,7 @@ edge
 split_block (basic_block bb, void *i)
 {
   basic_block new_bb;
+  edge res;
 
   if (!cfg_hooks->split_block)
     internal_error ("%s does not support split_block", cfg_hooks->name);
@@ -423,6 +437,7 @@ split_block (basic_block bb, void *i)
   new_bb->count = bb->count;
   new_bb->frequency = bb->frequency;
   new_bb->loop_depth = bb->loop_depth;
+  new_bb->discriminator = bb->discriminator;
 
   if (dom_info_available_p (CDI_DOMINATORS))
     {
@@ -437,7 +452,15 @@ split_block (basic_block bb, void *i)
        bb->loop_father->latch = new_bb;
     }
 
-  return make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
+  res = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
+
+  if (bb->flags & BB_IRREDUCIBLE_LOOP)
+    {
+      new_bb->flags |= BB_IRREDUCIBLE_LOOP;
+      res->flags |= EDGE_IRREDUCIBLE_LOOP;
+    }
+
+  return res;
 }
 
 /* Splits block BB just after labels.  The newly created edge is returned.  */
@@ -638,7 +661,7 @@ predict_edge (edge e, enum br_predictor predictor, int probability)
 }
 
 bool
-predicted_by_p (basic_block bb, enum br_predictor predictor)
+predicted_by_p (const_basic_block bb, enum br_predictor predictor)
 {
   if (!cfg_hooks->predict_edge)
     internal_error ("%s does not support predicted_by_p", cfg_hooks->name);
@@ -718,6 +741,8 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
   /* Redirect back edges we want to keep.  */
   for (ei = ei_start (dummy->preds); (e = ei_safe_edge (ei)); )
     {
+      basic_block e_src;
+
       if (redirect_edge_p (e))
        {
          ei_next (&ei);
@@ -734,10 +759,21 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
       if (fallthru->count < 0)
        fallthru->count = 0;
 
+      e_src = e->src;
       jump = redirect_edge_and_branch_force (e, bb);
-      if (jump != NULL
-         && new_bb_cbk != NULL)
-       new_bb_cbk (jump);
+      if (jump != NULL)
+        {
+          /* If we redirected the loop latch edge, the JUMP block now acts like
+             the new latch of the loop.  */
+          if (current_loops != NULL
+              && dummy->loop_father != NULL
+              && dummy->loop_father->header == dummy
+              && dummy->loop_father->latch == e_src)
+            dummy->loop_father->latch = jump;
+
+          if (new_bb_cbk != NULL)
+            new_bb_cbk (jump);
+        }
     }
 
   if (dom_info_available_p (CDI_DOMINATORS))
@@ -784,6 +820,8 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
   return fallthru;
 }
 
+/* Try to make the edge fallthru.  */
+
 void
 tidy_fallthru_edge (edge e)
 {
@@ -794,7 +832,9 @@ tidy_fallthru_edge (edge e)
 /* Fix up edges that now fall through, or rather should now fall through
    but previously required a jump around now deleted blocks.  Simplify
    the search by only examining blocks numerically adjacent, since this
-   is how find_basic_blocks created them.  */
+   is how they were created.
+
+   ??? This routine is currently RTL specific.  */
 
 void
 tidy_fallthru_edges (void)
@@ -817,9 +857,9 @@ tidy_fallthru_edges (void)
         a single successor.
 
         If we had a conditional branch to the next instruction when
-        find_basic_blocks was called, then there will only be one
-        out edge for the block which ended with the conditional
-        branch (since we do not create duplicate edges).
+        CFG was built, then there will only be one out edge for the
+        block which ended with the conditional branch (since we do
+        not create duplicate edges).
 
         Furthermore, the edge will be marked as a fallthru because we
         merge the flags for the duplicate edges.  So we do not want to
@@ -836,10 +876,42 @@ tidy_fallthru_edges (void)
     }
 }
 
+/* Edge E is assumed to be fallthru edge.  Emit needed jump instruction
+   (and possibly create new basic block) to make edge non-fallthru.
+   Return newly created BB or NULL if none.  */
+
+basic_block
+force_nonfallthru (edge e)
+{
+  basic_block ret, src = e->src;
+
+  if (!cfg_hooks->force_nonfallthru)
+    internal_error ("%s does not support force_nonfallthru",
+                   cfg_hooks->name);
+
+  ret = cfg_hooks->force_nonfallthru (e);
+  if (ret != NULL)
+    {
+      if (dom_info_available_p (CDI_DOMINATORS))
+       set_immediate_dominator (CDI_DOMINATORS, ret, src);
+
+      if (current_loops != NULL)
+       {
+         struct loop *loop
+           = find_common_loop (single_pred (ret)->loop_father,
+                               single_succ (ret)->loop_father);
+         rescan_loop_exit (e, false, true);
+         add_bb_to_loop (ret, loop);
+       }
+    }
+
+  return ret;
+}
+
 /* Returns true if we can duplicate basic block BB.  */
 
 bool
-can_duplicate_block_p (basic_block bb)
+can_duplicate_block_p (const_basic_block bb)
 {
   if (!cfg_hooks->can_duplicate_block_p)
     internal_error ("%s does not support can_duplicate_block_p",
@@ -870,9 +942,7 @@ duplicate_block (basic_block bb, edge e, basic_block after)
   if (bb->count < new_count)
     new_count = bb->count;
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (can_duplicate_block_p (bb));
-#endif
+  gcc_checking_assert (can_duplicate_block_p (bb));
 
   new_bb = cfg_hooks->duplicate_block (bb);
   if (after)
@@ -949,7 +1019,7 @@ block_ends_with_call_p (basic_block bb)
 /* Return 1 if BB ends with a conditional branch, 0 otherwise.  */
 
 bool
-block_ends_with_condjump_p (basic_block bb)
+block_ends_with_condjump_p (const_basic_block bb)
 {
   if (!cfg_hooks->block_ends_with_condjump_p)
     internal_error ("%s does not support block_ends_with_condjump_p",
@@ -1029,7 +1099,7 @@ cfg_hook_duplicate_loop_to_header_edge (struct loop *loop, edge e,
 
 /* Conditional jumps are represented differently in trees and RTL,
    this hook takes a basic block that is known to have a cond jump
-   at its end and extracts the taken and not taken eges out of it
+   at its end and extracts the taken and not taken edges out of it
    and store it in E1 and E2 respectively.  */
 void
 extract_cond_bb_edges (basic_block b, edge *e1, edge *e2)