src/share/vm/opto/block.cpp

Print this page
rev 5728 : 8029015: PPC64 (part 216): opto: trap based null and range checks

*** 528,550 **** add_block_at(block_no + 1, block); } // Does this block end in a multiway branch that cannot have the default case // flipped for another case? ! static bool no_flip_branch( Block *b ) { int branch_idx = b->number_of_nodes() - b->_num_succs-1; ! if( branch_idx < 1 ) return false; ! Node *bra = b->get_node(branch_idx); ! if( bra->is_Catch() ) return true; ! if( bra->is_Mach() ) { ! if( bra->is_MachNullCheck() ) return true; ! int iop = bra->as_Mach()->ideal_Opcode(); ! if( iop == Op_FastLock || iop == Op_FastUnlock ) return true; } return false; } // Check for NeverBranch at block end. This needs to become a GOTO to the // true target. NeverBranch are treated as a conditional branch that always --- 528,559 ---- add_block_at(block_no + 1, block); } // Does this block end in a multiway branch that cannot have the default case // flipped for another case? ! static bool no_flip_branch(Block *b) { int branch_idx = b->number_of_nodes() - b->_num_succs-1; ! if (branch_idx < 1) { ! return false; ! } ! Node *branch = b->get_node(branch_idx); ! if (branch->is_Catch()) { return true; ! } ! if (branch->is_Mach()) { ! if (branch->is_MachNullCheck()) { ! return true; ! } ! int iop = branch->as_Mach()->ideal_Opcode(); ! if (iop == Op_FastLock || iop == Op_FastUnlock) { return true; ! } ! // Don't flip if branch has an implicit check. ! if (branch->as_Mach()->is_TrapBasedCheckNode()) { return true; } + } return false; } // Check for NeverBranch at block end. This needs to become a GOTO to the // true target. NeverBranch are treated as a conditional branch that always
*** 698,707 **** --- 707,767 ---- i--; } } // End of for all blocks } + Block *PhaseCFG::fixup_trap_based_check(Node *branch, Block *block, int block_pos, Block *bnext) { + // Trap based checks must fall through to the successor with + // PROB_ALWAYS. + // They should be an If with 2 successors. + assert(branch->is_MachIf(), "must be If"); + assert(block->_num_succs == 2, "must have 2 successors"); + + // Get the If node and the projection for the first successor. + MachIfNode *iff = block->get_node(block->number_of_nodes()-3)->as_MachIf(); + ProjNode *proj0 = block->get_node(block->number_of_nodes()-2)->as_Proj(); + ProjNode *proj1 = block->get_node(block->number_of_nodes()-1)->as_Proj(); + ProjNode *projt = (proj0->Opcode() == Op_IfTrue) ? proj0 : proj1; + ProjNode *projf = (proj0->Opcode() == Op_IfFalse) ? proj0 : proj1; + + // Assert that proj0 and succs[0] match up. Similarly for proj1 and succs[1]. + assert(proj0->raw_out(0) == block->_succs[0]->head(), "Mismatch successor 0"); + assert(proj1->raw_out(0) == block->_succs[1]->head(), "Mismatch successor 1"); + + ProjNode *proj_always; + ProjNode *proj_never; + // We must negate the branch if the implicit check doesn't follow + // the branch's TRUE path. Then, the new TRUE branch target will + // be the old FALSE branch target. + if (iff->_prob <= 2*PROB_NEVER) { // There are small rounding errors. + proj_never = projt; + proj_always = projf; + } else { + // We must negate the branch if the trap doesn't follow the + // branch's TRUE path. Then, the new TRUE branch target will + // be the old FALSE branch target. + proj_never = projf; + proj_always = projt; + iff->negate(); + } + assert(iff->_prob <= 2*PROB_NEVER, "Trap based checks are expected to trap never!"); + // Map the successors properly + block->_succs.map(0, get_block_for_node(proj_never ->raw_out(0))); // The target of the trap. + block->_succs.map(1, get_block_for_node(proj_always->raw_out(0))); // The fall through target. + + // Place the fall through block after this block. + Block *bs1 = block->non_connector_successor(1); + if (bs1 != bnext && move_to_next(bs1, block_pos)) { + bnext = bs1; + } + // If the fall through block still is not the next block, insert a goto. + if (bs1 != bnext) { + insert_goto_at(block_pos, 1); + } + return bnext; + } + // Fix up the final control flow for basic blocks. void PhaseCFG::fixup_flow() { // Fixup final control flow for the blocks. Remove jump-to-next // block. If neither arm of an IF follows the conditional branch, we // have to add a second jump after the conditional. We place the
*** 721,732 **** Block* bs0 = block->non_connector_successor(0); // Check for multi-way branches where I cannot negate the test to // exchange the true and false targets. if (no_flip_branch(block)) { ! // Find fall through case - if must fall into its target int branch_idx = block->number_of_nodes() - block->_num_succs; for (uint j2 = 0; j2 < block->_num_succs; j2++) { const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); if (p->_con == 0) { // successor j2 is fall through case if (block->non_connector_successor(j2) != bnext) { --- 781,805 ---- Block* bs0 = block->non_connector_successor(0); // Check for multi-way branches where I cannot negate the test to // exchange the true and false targets. if (no_flip_branch(block)) { ! // Find fall through case - if must fall into its target. ! // Get the index of the branch's first successor. int branch_idx = block->number_of_nodes() - block->_num_succs; + + // The branch is 1 before the branch's first successor. + Node *branch = block->get_node(branch_idx-1); + + // Handle no-flip branches which have implicit checks and which require + // special block ordering and individual semantics of the 'fall through + // case'. + if ((TrapBasedNullChecks || TrapBasedRangeChecks) && + branch->is_Mach() && branch->as_Mach()->is_TrapBasedCheckNode()) { + bnext = fixup_trap_based_check(branch, block, i, bnext); + } else { + // Else, default handling for no-flip branches for (uint j2 = 0; j2 < block->_num_succs; j2++) { const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); if (p->_con == 0) { // successor j2 is fall through case if (block->non_connector_successor(j2) != bnext) {
*** 742,751 **** --- 815,825 ---- block->_succs.map(1, tbs0); } break; } } + } // Remove all CatchProjs for (uint j = 0; j < block->_num_succs; j++) { block->pop_node(); }