// recursively delete the stmts and subtrees ~TreeNode() { for (StmtMap::iterator sit = stmtMap.begin(); sit != stmtMap.end(); ++sit) { delete sit->second; } stmtMap.clear(); for (LoopList::iterator lit = loopList.begin(); lit != loopList.end(); ++lit) { delete (*lit)->node; } loopList.clear(); for (NodeMap::iterator nit = nodeMap.begin(); nit != nodeMap.end(); ++nit) { delete nit->second; } nodeMap.clear(); }
// 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; }
void LIR_LocalCaching::cache_locals() { LoopList* loops = ir()->loops(); BlockList* all_blocks = ir()->code(); WordSizeList* local_name_to_offset_map = ir()->local_name_to_offset_map(); if (loops == NULL) { // collect global scan information BlockListScanInfo gsi(ir()->code()); RegisterManager* global_scan_info = gsi.info(); // just cache registers globally. LocalMappingSetter setter(cache_locals_for_blocks(all_blocks, global_scan_info)); all_blocks->iterate_forward(&setter); } else { assert(loops->length() != 0, "should be at least one loop"); int i; // collect all the blocks that are outside of the loops BlockList* non_loop_blocks = new BlockList; for (i = 0; i < all_blocks->length(); i++) { BlockBegin* b = all_blocks->at(i); if (b->loop_index() == -1 && b->next()->as_CachingChange() == NULL) { non_loop_blocks->append(b); } } RegisterManager* global_scan_info = new RegisterManager(); // scan each of the loops and the remaining blocks recording register usage // so we know what registers are free. RegisterManagerArray scan_infos(loops->length() + 1); for (i = 0; i < loops->length(); i++) { Loop* loop = loops->at(i); BlockListScanInfo lsi(loop->blocks()); scan_infos.at_put(i, lsi.info()); // accumulate the global state global_scan_info->merge(lsi.info()); } BlockListScanInfo lsi(non_loop_blocks); scan_infos.at_put(loops->length(), lsi.info()); // accumulate the global state global_scan_info->merge(lsi.info()); // use the global mapping as a guide in the rest of the register selection process. LocalMapping* global = cache_locals_for_blocks(all_blocks, global_scan_info, true); LocalMapping* pref = new LocalMapping(local_name_to_offset_map); pref->merge(global); pref->merge(_preferred); _preferred = pref; for (i = 0; i < loops->length(); i++) { if (i < LIRCacheLoopStart || (uint)i >= (uint)LIRCacheLoopStop) { continue; } Loop* loop = loops->at(i); LocalMapping* mapping = cache_locals_for_blocks(loop->blocks(), scan_infos.at(i)); LocalMappingSetter setter(mapping); loop->blocks()->iterate_forward(&setter); _preferred->merge(mapping); mapping->join(global); } LocalMapping* mapping = cache_locals_for_blocks(non_loop_blocks, scan_infos.at(loops->length())); mapping->join(global); LocalMappingSetter setter(mapping); non_loop_blocks->iterate_forward(&setter); } }
// Returns inner loops that have may or may not have calls LoopList* LoopFinder::find_loops(LoopList* loops, bool call_free_only) { LoopList* inner = new LoopList(); LoopList* outer = new LoopList(); int lng = loops->length(); // First step: find loops that have no calls and no backedges // in the loop except its own int i; for (i = 0; i < lng; i++) { Loop* loop = loops->at(i); int k = loop->nof_blocks() - 1; bool is_outer = false; for (; k >= 0; k--) { BlockBegin* b = loop->block_no(k); // Is this innermost loop: // - no block, except end block, may be a back edge start, // otherwise we have an outer loop if (!loop->is_end(b)) { BlockLoopInfo* bli = get_block_info(b); if (bli->is_backedge_start()) { if (WantsLargerLoops) { is_outer = true; } else { loop = NULL; } break; } } } if (loop != NULL) { ScanBlocks scan(loop->blocks()); ScanResult scan_result; scan.scan(&scan_result); if (!call_free_only || (!scan_result.has_calls() && !scan_result.has_slow_cases())) { if (is_outer) { outer->append(loop); } else { inner->append(loop); } } else { #ifndef PRODUCT if (PrintLoops && Verbose) { tty->print("Discarding loop with calls: "); loop->print(); } #endif // PRODUCT } } } // find all surviving outer loops and delete any inner loops contained inside them if (inner->length() > 0) { for (i = 0; i < outer->length() ; i++) { Loop* loop = outer->at(i); int k = loop->nof_blocks() - 1; for (; k >= 0; k--) { BlockBegin* b = loop->block_no(k); if (!loop->is_end(b)) { BlockLoopInfo* bli = get_block_info(b); if (bli->is_backedge_start()) { // find the loop contained inside this loop int j; for (j = 0; j < inner->length(); j++) { Loop* inner_loop = inner->at(j); if (inner_loop->is_end(b)) { inner->remove(inner_loop); break; } } for (j = 0; j < outer->length(); j++) { Loop* outer_loop = outer->at(j); if (outer_loop == loop) { continue; } if (outer_loop->is_end(b)) { outer->remove(outer_loop); break; } } } } } } inner->appendAll(outer); } // Second step: if several loops have the same loop-end, select the one // with fewer blocks. // if several loops have the same loop-start, select the one // with fewer blocks // now check for loops that have the same header and eliminate one for (i = 0; i < inner->length() ; i++) { Loop* current_loop = inner->at(i); BlockBegin* header = current_loop->start(); for (int n = i + 1; n < inner->length(); n++) { Loop* test_loop = inner->at(n); BlockBegin* test = test_loop->start(); Loop* discarded = NULL; bool same_end = false; for (int e = 0; e < current_loop->ends()->length(); e++) { if (test_loop->is_end(current_loop->ends()->at(e))) { same_end = true; } } if (header == test_loop->start() || same_end) { // discard loop with fewer blocks if (test_loop->nof_blocks() > current_loop->nof_blocks()) { if (WantsLargerLoops) { discarded = current_loop; } else { discarded = test_loop; } } else { if (WantsLargerLoops) { discarded = test_loop; } else { discarded = current_loop; } } inner->remove(discarded); #ifndef PRODUCT if (PrintLoops && Verbose && discarded) { tty->print("Discarding overlapping loop: "); discarded->print(); } #endif // PRODUCT // restart the computation i = -1; break; } } } if (inner->length() == 0) { // we removed all the loops if (PrintLoops && Verbose) { tty->print_cr("*** deleted all loops in %s", __FILE__); } set_not_ok(); return NULL; } else { return inner; } }
TreeNode() { nodeMap.clear(); stmtMap.clear(); loopList.clear(); }