void LoopFinder::compute_loop_exits_and_entries(LoopList* loops) { // create loop exits for each loop int loop_index = loops->length() - 1; for (; loop_index >= 0; loop_index--) { Loop* loop = loops->at(loop_index); int n = loop->nof_blocks() - 1; // mark all nodes belonging to this loop for (; n >= 0; n --) { BlockBegin* bb = loop->block_no(n); bb->set_loop_index(loop_index); } find_loop_entries(loop->start(), loop); // search for blocks that have successors outside the loop n = loop->nof_blocks() - 1; for (; n >= 0; n--) { BlockBegin* bb = loop->block_no(n); find_loop_exits(bb, loop); } } }
// 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; } }