/* 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.
#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. */
/* 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. */
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;
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;
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
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",
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",
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)
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);
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))
{
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. */
}
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);
/* 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);
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))
return fallthru;
}
+/* Try to make the edge fallthru. */
+
void
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)
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
}
}
+/* 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",
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)
/* 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",
/* 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)