static basic_block make_forwarder_block (basic_block bb, int redirect_latch, int redirect_nonlatch, edge except, int conn_latch) { edge e, next_e, fallthru; basic_block dummy; rtx insn; insn = PREV_INSN (first_insn_after_basic_block_note (bb)); /* For empty block split_block will return NULL. */ if (BB_END (bb) == insn) emit_note_after (NOTE_INSN_DELETED, insn); fallthru = split_block (bb, insn); dummy = fallthru->src; bb = fallthru->dest; bb->aux = xmalloc (sizeof (int)); HEADER_BLOCK (dummy) = 0; HEADER_BLOCK (bb) = 1; /* Redirect back edges we want to keep. */ for (e = dummy->pred; e; e = next_e) { next_e = e->pred_next; if (e == except || !((redirect_latch && LATCH_EDGE (e)) || (redirect_nonlatch && !LATCH_EDGE (e)))) { dummy->frequency -= EDGE_FREQUENCY (e); dummy->count -= e->count; if (dummy->frequency < 0) dummy->frequency = 0; if (dummy->count < 0) dummy->count = 0; redirect_edge_with_latch_update (e, bb); } } alloc_aux_for_edge (fallthru, sizeof (int)); LATCH_EDGE (fallthru) = conn_latch; return dummy; }
/* 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; } }
static void *dll_u_alloc(const void *context, size_t size) { mps_pool_t *pool_ptr = (mps_pool_t *)context ; HQASSERT(pool_ptr != NULL, "ICU alloc context invalid") ; if (*pool_ptr != NULL && size != 0 && (size + HEADER_SIZE > size)) { void * p; mps_res_t res; res = mps_alloc(&p, *pool_ptr, size + HEADER_SIZE); if (!res) { header_s *header; header = p; header->size = size + HEADER_SIZE; return HEADER_BLOCK(header) ; } } return NULL ; }
/* Takes care of merging natural loops with shared headers. */ static void canonicalize_loop_headers (void) { basic_block header; edge e; /* Compute the dominators. */ calculate_dominance_info (CDI_DOMINATORS); alloc_aux_for_blocks (sizeof (int)); alloc_aux_for_edges (sizeof (int)); /* Split blocks so that each loop has only single latch. */ FOR_EACH_BB (header) { int num_latches = 0; int have_abnormal_edge = 0; for (e = header->pred; e; e = e->pred_next) { basic_block latch = e->src; if (e->flags & EDGE_ABNORMAL) have_abnormal_edge = 1; if (latch != ENTRY_BLOCK_PTR && dominated_by_p (CDI_DOMINATORS, latch, header)) { num_latches++; LATCH_EDGE (e) = 1; } } if (have_abnormal_edge) HEADER_BLOCK (header) = 0; else HEADER_BLOCK (header) = num_latches; } free_dominance_info (CDI_DOMINATORS); if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest)) { basic_block bb; /* We could not redirect edges freely here. On the other hand, we can simply split the edge from entry block. */ bb = split_edge (ENTRY_BLOCK_PTR->succ); alloc_aux_for_edge (bb->succ, sizeof (int)); LATCH_EDGE (bb->succ) = 0; alloc_aux_for_block (bb, sizeof (int)); HEADER_BLOCK (bb) = 0; } FOR_EACH_BB (header) { int num_latch; int want_join_latch; int max_freq, is_heavy; edge heavy; if (!HEADER_BLOCK (header)) continue; num_latch = HEADER_BLOCK (header); want_join_latch = (num_latch > 1); if (!want_join_latch) continue; /* Find a heavy edge. */ is_heavy = 1; heavy = NULL; max_freq = 0; for (e = header->pred; e; e = e->pred_next) if (LATCH_EDGE (e) && EDGE_FREQUENCY (e) > max_freq) max_freq = EDGE_FREQUENCY (e); for (e = header->pred; e; e = e->pred_next) if (LATCH_EDGE (e) && EDGE_FREQUENCY (e) >= max_freq / HEAVY_EDGE_RATIO) { if (heavy) { is_heavy = 0; break; } else heavy = e; } if (is_heavy) { basic_block new_header = make_forwarder_block (header, true, true, heavy, 0); if (num_latch > 2) make_forwarder_block (new_header, true, false, NULL, 1); } else make_forwarder_block (header, true, false, NULL, 1); } free_aux_for_blocks (); free_aux_for_edges (); }