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