void FpuStackAllocator::allocate() { int num_blocks = allocator()->block_count(); for (int i = 0; i < num_blocks; i++) { // Set up to process block BlockBegin* block = allocator()->block_at(i); intArray* fpu_stack_state = block->fpu_stack_state(); #ifndef PRODUCT if (TraceFPUStack) { tty->cr(); tty->print_cr("------- Begin of new Block %d -------", block->block_id()); } #endif assert(fpu_stack_state != NULL || block->end()->as_Base() != NULL || block->is_set(BlockBegin::exception_entry_flag), "FPU stack state must be present due to linear-scan order for FPU stack allocation"); // note: exception handler entries always start with an empty fpu stack // because stack merging would be too complicated if (fpu_stack_state != NULL) { sim()->read_state(fpu_stack_state); } else { sim()->clear(); } #ifndef PRODUCT if (TraceFPUStack) { tty->print("Reading FPU state for block %d:", block->block_id()); sim()->print(); tty->cr(); } #endif allocate_block(block); CHECK_BAILOUT(); } }
bool FpuStackAllocator::merge_fpu_stack_with_successors(BlockBegin* block) { #ifndef PRODUCT if (TraceFPUStack) { tty->print_cr("Propagating FPU stack state for B%d at LIR_Op position %d to successors:", block->block_id(), pos()); sim()->print(); tty->cr(); } #endif bool changed = false; int number_of_sux = block->number_of_sux(); if (number_of_sux == 1 && block->sux_at(0)->number_of_preds() > 1) { // The successor has at least two incoming edges, so a stack merge will be necessary // If this block is the first predecessor, cleanup the current stack and propagate it // If this block is not the first predecessor, a stack merge will be necessary BlockBegin* sux = block->sux_at(0); intArray* state = sux->fpu_stack_state(); LIR_List* instrs = new LIR_List(_compilation); if (state != NULL) { // Merge with a successors that already has a FPU stack state // the block must only have one successor because critical edges must been split FpuStackSim* cur_sim = sim(); FpuStackSim* sux_sim = temp_sim(); sux_sim->read_state(state); merge_fpu_stack(instrs, cur_sim, sux_sim); } else { // propagate current FPU stack state to successor without state // clean up stack first so that there are no dead values on the stack if (ComputeExactFPURegisterUsage) { FpuStackSim* cur_sim = sim(); ResourceBitMap live_fpu_regs = block->sux_at(0)->fpu_register_usage(); assert(live_fpu_regs.size() == FrameMap::nof_fpu_regs, "missing register usage"); merge_cleanup_fpu_stack(instrs, cur_sim, live_fpu_regs); } intArray* state = sim()->write_state(); if (TraceFPUStack) { tty->print_cr("Setting FPU stack state of B%d (merge path)", sux->block_id()); sim()->print(); tty->cr(); } sux->set_fpu_stack_state(state); } if (instrs->instructions_list()->length() > 0) { lir()->insert_before(pos(), instrs); set_pos(instrs->instructions_list()->length() + pos()); changed = true; } } else { // Propagate unmodified Stack to successors where a stack merge is not necessary intArray* state = sim()->write_state(); for (int i = 0; i < number_of_sux; i++) { BlockBegin* sux = block->sux_at(i); #ifdef ASSERT for (int j = 0; j < sux->number_of_preds(); j++) { assert(block == sux->pred_at(j), "all critical edges must be broken"); } // check if new state is same if (sux->fpu_stack_state() != NULL) { intArray* sux_state = sux->fpu_stack_state(); assert(state->length() == sux_state->length(), "overwriting existing stack state"); for (int j = 0; j < state->length(); j++) { assert(state->at(j) == sux_state->at(j), "overwriting existing stack state"); } } #endif #ifndef PRODUCT if (TraceFPUStack) { tty->print_cr("Setting FPU stack state of B%d", sux->block_id()); sim()->print(); tty->cr(); } #endif sux->set_fpu_stack_state(state); } } #ifndef PRODUCT // assertions that FPU stack state conforms to all successors' states intArray* cur_state = sim()->write_state(); for (int i = 0; i < number_of_sux; i++) { BlockBegin* sux = block->sux_at(i); intArray* sux_state = sux->fpu_stack_state(); assert(sux_state != NULL, "no fpu state"); assert(cur_state->length() == sux_state->length(), "incorrect length"); for (int i = 0; i < cur_state->length(); i++) { assert(cur_state->at(i) == sux_state->at(i), "element not equal"); } } #endif return changed; }