/* Redirect edge and update latch and header info. */ static void redirect_edge_with_latch_update (edge e, basic_block to) { basic_block jump; jump = redirect_edge_and_branch_force (e, to); if (jump) { alloc_aux_for_block (jump, sizeof (int)); HEADER_BLOCK (jump) = 0; alloc_aux_for_edge (jump->pred, sizeof (int)); LATCH_EDGE (jump->succ) = LATCH_EDGE (e); LATCH_EDGE (jump->pred) = 0; } }
void copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, edge *edges, unsigned n_edges, edge *new_edges, struct loop *base) { unsigned i, j; basic_block bb, new_bb, dom_bb; edge e; /* Duplicate bbs, update dominators, assign bbs to loops. */ for (i = 0; i < n; i++) { /* Duplicate. */ bb = bbs[i]; new_bb = new_bbs[i] = cfg_layout_duplicate_bb (bb, NULL); bb->rbi->duplicated = 1; /* Add to loop. */ add_bb_to_loop (new_bb, bb->loop_father->copy); add_to_dominance_info (CDI_DOMINATORS, new_bb); /* Possibly set header. */ if (bb->loop_father->header == bb && bb->loop_father != base) new_bb->loop_father->header = new_bb; /* Or latch. */ if (bb->loop_father->latch == bb && bb->loop_father != base) new_bb->loop_father->latch = new_bb; } /* Set dominators. */ for (i = 0; i < n; i++) { bb = bbs[i]; new_bb = new_bbs[i]; dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb); if (dom_bb->rbi->duplicated) { dom_bb = dom_bb->rbi->copy; set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb); } } /* Redirect edges. */ for (j = 0; j < n_edges; j++) new_edges[j] = NULL; for (i = 0; i < n; i++) { new_bb = new_bbs[i]; bb = bbs[i]; for (e = new_bb->succ; e; e = e->succ_next) { for (j = 0; j < n_edges; j++) if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest) new_edges[j] = e; if (!e->dest->rbi->duplicated) continue; redirect_edge_and_branch_force (e, e->dest->rbi->copy); } } /* Clear information about duplicates. */ for (i = 0; i < n; i++) bbs[i]->rbi->duplicated = 0; }
basic_block cfg_layout_duplicate_bb (basic_block bb, edge e) { rtx insn; edge s, n; basic_block new_bb; gcov_type new_count = e ? e->count : 0; if (bb->count < new_count) new_count = bb->count; if (!bb->pred) abort (); #ifdef ENABLE_CHECKING if (!cfg_layout_can_duplicate_bb_p (bb)) abort (); #endif insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb)); new_bb = create_basic_block (insn, insn ? get_last_insn () : NULL, EXIT_BLOCK_PTR->prev_bb); if (bb->rbi->header) { insn = bb->rbi->header; while (NEXT_INSN (insn)) insn = NEXT_INSN (insn); insn = duplicate_insn_chain (bb->rbi->header, insn); if (insn) new_bb->rbi->header = unlink_insn_chain (insn, get_last_insn ()); } if (bb->rbi->footer) { insn = bb->rbi->footer; while (NEXT_INSN (insn)) insn = NEXT_INSN (insn); insn = duplicate_insn_chain (bb->rbi->footer, insn); if (insn) new_bb->rbi->footer = unlink_insn_chain (insn, get_last_insn ()); } if (bb->global_live_at_start) { new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack); new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack); COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_start); COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end); } new_bb->loop_depth = bb->loop_depth; new_bb->flags = bb->flags; for (s = bb->succ; s; s = s->succ_next) { /* 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; } new_bb->rbi->original = bb; bb->rbi->copy = new_bb; return new_bb; }