bool ShortLoopOptimizer::process(BlockBegin* loop_header) { TRACE_VALUE_NUMBERING(tty->print_cr("** loop header block")); _too_complicated_loop = false; _loop_blocks.clear(); _loop_blocks.append(loop_header); for (int i = 0; i < _loop_blocks.length(); i++) { BlockBegin* block = _loop_blocks.at(i); TRACE_VALUE_NUMBERING(tty->print_cr("processing loop block B%d", block->block_id())); if (block->is_set(BlockBegin::exception_entry_flag)) { // this would be too complicated return false; } // add predecessors to worklist for (int j = block->number_of_preds() - 1; j >= 0; j--) { BlockBegin* pred = block->pred_at(j); if (pred->is_set(BlockBegin::osr_entry_flag)) { return false; } ValueMap* pred_map = value_map_of(pred); if (pred_map != NULL) { current_map()->kill_map(pred_map); } else if (!_loop_blocks.contains(pred)) { if (_loop_blocks.length() >= ValueMapMaxLoopSize) { return false; } _loop_blocks.append(pred); } } // use the instruction visitor for killing values for (Value instr = block->next(); instr != NULL; instr = instr->next()) { instr->visit(this); if (_too_complicated_loop) { return false; } } } bool optimistic = this->_gvn->compilation()->is_optimistic(); if (UseLoopInvariantCodeMotion && optimistic) { LoopInvariantCodeMotion code_motion(this, _gvn, loop_header, &_loop_blocks); } TRACE_VALUE_NUMBERING(tty->print_cr("** loop successfully optimized")); return true; }
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); } }
GlobalValueNumbering::GlobalValueNumbering(IR* ir) : _current_map(NULL) , _value_maps(ir->linear_scan_order()->length(), NULL) { TRACE_VALUE_NUMBERING(tty->print_cr("****** start of global value numbering")); ShortLoopOptimizer short_loop_optimizer(this); int subst_count = 0; BlockList* blocks = ir->linear_scan_order(); int num_blocks = blocks->length(); BlockBegin* start_block = blocks->at(0); assert(start_block == ir->start() && start_block->number_of_preds() == 0 && start_block->dominator() == NULL, "must be start block"); assert(start_block->next()->as_Base() != NULL && start_block->next()->next() == NULL, "start block must not have instructions"); // initial, empty value map with nesting 0 set_value_map_of(start_block, new ValueMap()); for (int i = 1; i < num_blocks; i++) { BlockBegin* block = blocks->at(i); TRACE_VALUE_NUMBERING(tty->print_cr("**** processing block B%d", block->block_id())); int num_preds = block->number_of_preds(); assert(num_preds > 0, "block must have predecessors"); BlockBegin* dominator = block->dominator(); assert(dominator != NULL, "dominator must exist"); assert(value_map_of(dominator) != NULL, "value map of dominator must exist"); // create new value map with increased nesting _current_map = new ValueMap(value_map_of(dominator)); if (num_preds == 1) { assert(dominator == block->pred_at(0), "dominator must be equal to predecessor"); // nothing to do here } else if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) { // block has incoming backward branches -> try to optimize short loops if (!short_loop_optimizer.process(block)) { // loop is too complicated, so kill all memory loads because there might be // stores to them in the loop current_map()->kill_memory(); } } else { // only incoming forward branches that are already processed for (int j = 0; j < num_preds; j++) { BlockBegin* pred = block->pred_at(j); ValueMap* pred_map = value_map_of(pred); if (pred_map != NULL) { // propagate killed values of the predecessor to this block current_map()->kill_map(value_map_of(pred)); } else { // kill all memory loads because predecessor not yet processed // (this can happen with non-natural loops and OSR-compiles) current_map()->kill_memory(); } } } if (block->is_set(BlockBegin::exception_entry_flag)) { current_map()->kill_exception(); } TRACE_VALUE_NUMBERING(tty->print("value map before processing block: "); current_map()->print()); // visit all instructions of this block for (Value instr = block->next(); instr != NULL; instr = instr->next()) { assert(!instr->has_subst(), "substitution already set"); // check if instruction kills any values instr->visit(this); if (instr->hash() != 0) { Value f = current_map()->find_insert(instr); if (f != instr) { assert(!f->has_subst(), "can't have a substitution"); instr->set_subst(f); subst_count++; } } } // remember value map for successors set_value_map_of(block, current_map()); } if (subst_count != 0) { SubstitutionResolver resolver(ir); } TRACE_VALUE_NUMBERING(tty->print("****** end of global value numbering. "); ValueMap::print_statistics()); }