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; } }