+
+/* Returns true if we can duplicate basic block BB. */
+
+bool
+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",
+ cfg_hooks->name);
+
+ if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR)
+ return false;
+
+ return cfg_hooks->can_duplicate_block_p (bb);
+}
+
+/* Duplicates basic block BB and redirects edge E to it. Returns the
+ new basic block. The new basic block is placed after the basic block
+ AFTER. */
+
+basic_block
+duplicate_block (basic_block bb, edge e, basic_block after)
+{
+ edge s, n;
+ basic_block new_bb;
+ gcov_type new_count = e ? e->count : 0;
+ edge_iterator ei;
+
+ if (!cfg_hooks->duplicate_block)
+ internal_error ("%s does not support duplicate_block",
+ cfg_hooks->name);
+
+ if (bb->count < new_count)
+ new_count = bb->count;
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (can_duplicate_block_p (bb));
+#endif
+
+ new_bb = cfg_hooks->duplicate_block (bb);
+ if (after)
+ move_block_after (new_bb, after);
+
+ new_bb->loop_depth = bb->loop_depth;
+ new_bb->flags = bb->flags;
+ FOR_EACH_EDGE (s, ei, bb->succs)
+ {
+ /* Since we are creating edges from a new block to successors
+ of another block (which therefore are known to be disjoint), there
+ is no need to actually check for duplicated edges. */
+ n = unchecked_make_edge (new_bb, s->dest, s->flags);
+ n->probability = s->probability;
+ if (e && bb->count)
+ {
+ /* Take care for overflows! */
+ n->count = s->count * (new_count * 10000 / bb->count) / 10000;
+ s->count -= n->count;
+ }
+ else
+ n->count = s->count;
+ n->aux = s->aux;
+ }
+
+ if (e)
+ {
+ new_bb->count = new_count;
+ bb->count -= new_count;
+
+ new_bb->frequency = EDGE_FREQUENCY (e);
+ bb->frequency -= EDGE_FREQUENCY (e);
+
+ redirect_edge_and_branch_force (e, new_bb);
+
+ if (bb->count < 0)
+ bb->count = 0;
+ if (bb->frequency < 0)
+ bb->frequency = 0;
+ }
+ else
+ {
+ new_bb->count = bb->count;
+ new_bb->frequency = bb->frequency;
+ }
+
+ set_bb_original (new_bb, bb);
+ set_bb_copy (bb, new_bb);
+
+ /* Add the new block to the copy of the loop of BB, or directly to the loop
+ of BB if the loop is not being copied. */
+ if (current_loops != NULL)
+ {
+ struct loop *cloop = bb->loop_father;
+ struct loop *copy = get_loop_copy (cloop);
+ add_bb_to_loop (new_bb, copy ? copy : cloop);
+ }
+
+ return new_bb;
+}
+
+/* Return 1 if BB ends with a call, possibly followed by some
+ instructions that must stay with the call, 0 otherwise. */
+
+bool
+block_ends_with_call_p (basic_block bb)
+{
+ if (!cfg_hooks->block_ends_with_call_p)
+ internal_error ("%s does not support block_ends_with_call_p", cfg_hooks->name);
+
+ return (cfg_hooks->block_ends_with_call_p) (bb);
+}
+
+/* Return 1 if BB ends with a conditional branch, 0 otherwise. */
+
+bool
+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",
+ cfg_hooks->name);
+
+ return (cfg_hooks->block_ends_with_condjump_p) (bb);
+}
+
+/* Add fake edges to the function exit for any non constant and non noreturn
+ calls, volatile inline assembly in the bitmap of blocks specified by
+ BLOCKS or to the whole CFG if BLOCKS is zero. Return the number of blocks
+ that were split.
+
+ The goal is to expose cases in which entering a basic block does not imply
+ that all subsequent instructions must be executed. */
+
+int
+flow_call_edges_add (sbitmap blocks)
+{
+ if (!cfg_hooks->flow_call_edges_add)
+ internal_error ("%s does not support flow_call_edges_add",
+ cfg_hooks->name);
+
+ return (cfg_hooks->flow_call_edges_add) (blocks);
+}
+
+/* This function is called immediately after edge E is added to the
+ edge vector E->dest->preds. */
+
+void
+execute_on_growing_pred (edge e)
+{
+ if (cfg_hooks->execute_on_growing_pred)
+ cfg_hooks->execute_on_growing_pred (e);
+}
+
+/* This function is called immediately before edge E is removed from
+ the edge vector E->dest->preds. */
+
+void
+execute_on_shrinking_pred (edge e)
+{
+ if (cfg_hooks->execute_on_shrinking_pred)
+ cfg_hooks->execute_on_shrinking_pred (e);
+}
+
+/* This is used inside loop versioning when we want to insert
+ stmts/insns on the edges, which have a different behavior
+ in tree's and in RTL, so we made a CFG hook. */
+void
+lv_flush_pending_stmts (edge e)
+{
+ if (cfg_hooks->flush_pending_stmts)
+ cfg_hooks->flush_pending_stmts (e);
+}
+
+/* Loop versioning uses the duplicate_loop_to_header_edge to create
+ a new version of the loop basic-blocks, the parameters here are
+ exactly the same as in duplicate_loop_to_header_edge or
+ tree_duplicate_loop_to_header_edge; while in tree-ssa there is
+ additional work to maintain ssa information that's why there is
+ a need to call the tree_duplicate_loop_to_header_edge rather
+ than duplicate_loop_to_header_edge when we are in tree mode. */
+bool
+cfg_hook_duplicate_loop_to_header_edge (struct loop *loop, edge e,
+ unsigned int ndupl,
+ sbitmap wont_exit, edge orig,
+ VEC (edge, heap) **to_remove,
+ int flags)
+{
+ gcc_assert (cfg_hooks->cfg_hook_duplicate_loop_to_header_edge);
+ return cfg_hooks->cfg_hook_duplicate_loop_to_header_edge (loop, e,
+ ndupl, wont_exit,
+ orig, to_remove,
+ flags);
+}
+
+/* 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
+ and store it in E1 and E2 respectively. */
+void
+extract_cond_bb_edges (basic_block b, edge *e1, edge *e2)
+{
+ gcc_assert (cfg_hooks->extract_cond_bb_edges);
+ cfg_hooks->extract_cond_bb_edges (b, e1, e2);
+}
+
+/* Responsible for updating the ssa info (PHI nodes) on the
+ new condition basic block that guards the versioned loop. */
+void
+lv_adjust_loop_header_phi (basic_block first, basic_block second,
+ basic_block new_block, edge e)
+{
+ if (cfg_hooks->lv_adjust_loop_header_phi)
+ cfg_hooks->lv_adjust_loop_header_phi (first, second, new_block, e);
+}
+
+/* Conditions in trees and RTL are different so we need
+ a different handling when we add the condition to the
+ versioning code. */
+void
+lv_add_condition_to_bb (basic_block first, basic_block second,
+ basic_block new_block, void *cond)
+{
+ gcc_assert (cfg_hooks->lv_add_condition_to_bb);
+ cfg_hooks->lv_add_condition_to_bb (first, second, new_block, cond);
+}