BlockBegin* LoopFinder::insert_caching_block(LoopList* loops, BlockBegin* from, BlockBegin* to) { if (from->next() && from->next()->as_CachingChange() != NULL && from->end()->default_sux() == to) { // we already have a caching change block // check that the precision flags are the same #ifdef ASSERT CachingChange* cc = from->next()->as_CachingChange(); assert(cc->pred_block()->is_set(BlockBegin::single_precision_flag) == from->is_set(BlockBegin::single_precision_flag), "consistency check"); assert(cc->sux_block()->is_set(BlockBegin::single_precision_flag) == to->is_set(BlockBegin::single_precision_flag), "consistency check"); #endif return NULL; } else { // insert a caching change block, making it close to any single successor int bci = -1; BlockLoopInfo* bli = get_block_info(to); if (bli->nof_preds() == 1) { bci = to->bci(); } else { bci = from->end()->bci(); } BlockBegin* cc = new_block(to->scope(), bci); BlockEnd* e = new Goto(to, false); cc->set_end(e); cc->set_next(new CachingChange(from, to), bci)->set_next(e, bci); if (PrintLoops && Verbose) { tty->print_cr("Added caching block B%d (dest B%d)", cc->block_id(), to->block_id()); } BlockEnd* from_end = from->end(); from_end->substitute_sux(to, cc); cc->join(from_end->state()); assert(cc->state() != NULL, "illegal operation"); ValueStack* end_state = cc->state()->copy(); cc->end()->set_state(end_state); to->join(end_state); assert(cc->end()->state() != NULL, "should have state"); loops->update_loops(from, to, cc); return cc; } }
// Gather backedges of natural loops: an edge a -> b where b dominates a LoopList* LoopFinder::find_backedges(boolArray* visited) { int i; LoopList* backedges = new LoopList(); for (i = 0; i < max_blocks(); i++) { if (visited->at(i)) { BlockLoopInfo* bli = _info->at(i); BlockBegin* bb = bli->block(); BlockEnd* be = bb->end(); int n = be->number_of_sux(); for (int i = 0; i < n; i++) { BlockBegin* sux = be->sux_at(i); if (bli->is_dom_block(sux->block_id())) { bli->mark_backedge_start(); backedges->push(new Loop(sux, bb)); } } } } // backedges contains single pairs of blocks which are a backedge. // some of these loops may share entry points, so walk over the backedges // and merge loops which have the same entry point if (backedges->length() > 1) { backedges->sort(sort_by_start_block); Loop* current_loop = backedges->at(0); for (i = 1; i < backedges->length();) { Loop* this_loop = backedges->at(i); if (current_loop->start() == this_loop->start()) { // same entry point assert(this_loop->ends()->length() == 1, "should only have one end at this point"); #ifndef PRODUCT if (PrintLoops && Verbose) { tty->print_cr("Merging loops with same start"); current_loop->print(); this_loop->print(); } #endif BlockBegin* e = this_loop->ends()->at(0); current_loop->add_end(e); backedges->remove(this_loop); } else { // start processing the next loop entry point i++; } } } return backedges; }
BlockListScanInfo(BlockList* blocks) : _info(new RegisterManager()), _had_call(false) { for (int n = 0; n < blocks->length(); n++) { BlockBegin* b = blocks->at(n); if (b->lir() != NULL) { traverse(b, b->lir()->instructions_list()); } // Registers may be used to hold the value // on the top of stack so check for that. check_stack(b->state()); check_stack(b->end()->state()); } if (_had_call) { for (int i = 0; i < FrameMap::nof_caller_save_cpu_regs; i++) { _info->lock(FrameMap::caller_save_cpu_reg_at(i)->as_rinfo()); } } }
void FpuStackAllocator::allocate() { int num_blocks = allocator()->block_count(); for (int i = 0; i < num_blocks; i++) { // Set up to process block BlockBegin* block = allocator()->block_at(i); intArray* fpu_stack_state = block->fpu_stack_state(); #ifndef PRODUCT if (TraceFPUStack) { tty->cr(); tty->print_cr("------- Begin of new Block %d -------", block->block_id()); } #endif assert(fpu_stack_state != NULL || block->end()->as_Base() != NULL || block->is_set(BlockBegin::exception_entry_flag), "FPU stack state must be present due to linear-scan order for FPU stack allocation"); // note: exception handler entries always start with an empty fpu stack // because stack merging would be too complicated if (fpu_stack_state != NULL) { sim()->read_state(fpu_stack_state); } else { sim()->clear(); } #ifndef PRODUCT if (TraceFPUStack) { tty->print("Reading FPU state for block %d:", block->block_id()); sim()->print(); tty->cr(); } #endif allocate_block(block); CHECK_BAILOUT(); } }