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; } }
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 CE_Eliminator::block_do(BlockBegin* block) { // 1) find conditional expression // check if block ends with an If If* if_ = block->end()->as_If(); if (if_ == NULL) return; // check if If works on int or object types // (we cannot handle If's working on long, float or doubles yet, // since IfOp doesn't support them - these If's show up if cmp // operations followed by If's are eliminated) ValueType* if_type = if_->x()->type(); if (!if_type->is_int() && !if_type->is_object()) return; BlockBegin* t_block = if_->tsux(); BlockBegin* f_block = if_->fsux(); Instruction* t_cur = t_block->next(); Instruction* f_cur = f_block->next(); // one Constant may be present between BlockBegin and BlockEnd Value t_const = NULL; Value f_const = NULL; if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) { t_const = t_cur; t_cur = t_cur->next(); } if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) { f_const = f_cur; f_cur = f_cur->next(); } // check if both branches end with a goto Goto* t_goto = t_cur->as_Goto(); if (t_goto == NULL) return; Goto* f_goto = f_cur->as_Goto(); if (f_goto == NULL) return; // check if both gotos merge into the same block BlockBegin* sux = t_goto->default_sux(); if (sux != f_goto->default_sux()) return; // check if at least one word was pushed on sux_state // inlining depths must match ValueStack* if_state = if_->state(); ValueStack* sux_state = sux->state(); if (if_state->scope()->level() > sux_state->scope()->level()) { while (sux_state->scope() != if_state->scope()) { if_state = if_state->caller_state(); assert(if_state != NULL, "states do not match up"); } } else if (if_state->scope()->level() < sux_state->scope()->level()) { while (sux_state->scope() != if_state->scope()) { sux_state = sux_state->caller_state(); assert(sux_state != NULL, "states do not match up"); } } if (sux_state->stack_size() <= if_state->stack_size()) return; // check if phi function is present at end of successor stack and that // only this phi was pushed on the stack Value sux_phi = sux_state->stack_at(if_state->stack_size()); if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return; if (sux_phi->type()->size() != sux_state->stack_size() - if_state->stack_size()) return; // get the values that were pushed in the true- and false-branch Value t_value = t_goto->state()->stack_at(if_state->stack_size()); Value f_value = f_goto->state()->stack_at(if_state->stack_size()); // backend does not support floats assert(t_value->type()->base() == f_value->type()->base(), "incompatible types"); if (t_value->type()->is_float_kind()) return; // check that successor has no other phi functions but sux_phi // this can happen when t_block or f_block contained additonal stores to local variables // that are no longer represented by explicit instructions for_each_phi_fun(sux, phi, if (phi != sux_phi) return; );