/** * Perform optimizations for a two way conditional branch. * * <p>Precondition: IfCmp2.conforms(cb) * * @param ir the governing IR * @param cb the instruction to optimize * @param bb the basic block holding if * @return {@code true} iff made a transformation */ private boolean processTwoTargetConditionalBranch(IR ir, Instruction cb, BasicBlock bb) { // First condition/target Instruction target1Label = IfCmp2.getTarget1(cb).target; Instruction target1Inst = firstRealInstructionFollowing(target1Label); Instruction nextLabel = firstLabelFollowing(cb); boolean endsBlock = cb.nextInstructionInCodeOrder().operator() == BBEND; if (target1Inst != null && target1Inst != cb) { if (Goto.conforms(target1Inst)) { // conditional branch to unconditional branch. // change conditional branch target to latter's target IfCmp2.setTarget1(cb, (BranchOperand) Goto.getTarget(target1Inst).copy()); bb.recomputeNormalOut(ir); // fix CFG return true; } BasicBlock target1Block = target1Label.getBasicBlock(); if (target1Block.isEmpty()) { // branch to an empty block. Change target to the next block. BasicBlock nextBlock = target1Block.getFallThroughBlock(); IfCmp2.setTarget1(cb, nextBlock.makeJumpTarget()); bb.recomputeNormalOut(ir); // fix the CFG return true; } } // Second condition/target Instruction target2Label = IfCmp2.getTarget2(cb).target; Instruction target2Inst = firstRealInstructionFollowing(target2Label); if (target2Inst != null && target2Inst != cb) { if (Goto.conforms(target2Inst)) { // conditional branch to unconditional branch. // change conditional branch target to latter's target IfCmp2.setTarget2(cb, (BranchOperand) Goto.getTarget(target2Inst).copy()); bb.recomputeNormalOut(ir); // fix CFG return true; } if ((target2Label == nextLabel) && endsBlock) { // found a conditional branch to the next instruction. Reduce to IfCmp if (VM.VerifyAssertions) VM._assert(cb.operator() == INT_IFCMP2); IfCmp.mutate( cb, INT_IFCMP, IfCmp2.getGuardResult(cb), IfCmp2.getVal1(cb), IfCmp2.getVal2(cb), IfCmp2.getCond1(cb), IfCmp2.getTarget1(cb), IfCmp2.getBranchProfile1(cb)); return true; } BasicBlock target2Block = target2Label.getBasicBlock(); if (target2Block.isEmpty()) { // branch to an empty block. Change target to the next block. BasicBlock nextBlock = target2Block.getFallThroughBlock(); IfCmp2.setTarget2(cb, nextBlock.makeJumpTarget()); bb.recomputeNormalOut(ir); // fix the CFG return true; } } // if fall through to a goto; replicate the goto if (endsBlock) { Instruction nextI = firstRealInstructionFollowing(nextLabel); if (nextI != null && Goto.conforms(nextI)) { // replicate Goto cb.insertAfter(nextI.copyWithoutLinks()); bb.recomputeNormalOut(ir); // fix the CFG return true; } } return false; }