Search in sources :

Example 6 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class ConvertToLowLevelIR method lookup.

/**
 * Expand a lookupswitch.
 * @param switchInstr  The instruction to expand
 * @param ir           The containing IR
 * @return the next {@link Instruction} after the generated LIR sequence.
 */
static Instruction lookup(Instruction switchInstr, IR ir) {
    Instruction bbend = switchInstr.nextInstructionInCodeOrder();
    BasicBlock thisBB = bbend.getBasicBlock();
    BasicBlock nextBB = thisBB.nextBasicBlockInCodeOrder();
    // Blow away the old Normal ControlFlowGraph edges to prepare for new links
    thisBB.deleteNormalOut();
    switchInstr.remove();
    BranchOperand defTarget = LookupSwitch.getClearDefault(switchInstr);
    BasicBlock defaultBB = defTarget.target.getBasicBlock();
    int high = LookupSwitch.getNumberOfTargets(switchInstr) - 1;
    if (high < 0) {
        // no cases in switch; just jump to defaultBB
        thisBB.appendInstruction(Goto.create(GOTO, defTarget));
        thisBB.insertOut(defaultBB);
    } else {
        Operand match = LookupSwitch.getValue(switchInstr);
        if (match.isConstant()) {
            // switch on a constant
            int value = match.asIntConstant().value;
            int numMatches = LookupSwitch.getNumberOfMatches(switchInstr);
            BranchOperand target = LookupSwitch.getDefault(switchInstr);
            for (int i = 0; i < numMatches; i++) {
                if (value == LookupSwitch.getMatch(switchInstr, i).value) {
                    target = LookupSwitch.getTarget(switchInstr, i);
                    break;
                }
            }
            thisBB.appendInstruction(Goto.create(GOTO, target));
            thisBB.insertOut(target.target.getBasicBlock());
        } else {
            RegisterOperand reg = match.asRegister();
            // If you're not already at the end of the code order
            if (nextBB != null) {
                ir.cfg.breakCodeOrder(thisBB, nextBB);
            }
            // generate the binary search tree into thisBB
            BasicBlock lastNewBB = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, thisBB, 0, high, Integer.MIN_VALUE, Integer.MAX_VALUE);
            if (nextBB != null) {
                ir.cfg.linkInCodeOrder(lastNewBB, nextBB);
            }
        }
    }
    // skip all the instrs just inserted by _lookupswitchHelper
    if (nextBB != null) {
        return nextBB.firstInstruction();
    } else {
        return thisBB.lastInstruction();
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 7 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class ConvertToLowLevelIR method tableswitch.

/**
 * Expand a tableswitch.
 * @param s the instruction to expand
 * @param ir the containing IR
 * @return the last Instruction in the generated LIR sequence.
 */
static Instruction tableswitch(Instruction s, IR ir) {
    Instruction s2;
    int lowLimit = TableSwitch.getLow(s).value;
    int highLimit = TableSwitch.getHigh(s).value;
    int number = highLimit - lowLimit + 1;
    if (VM.VerifyAssertions) {
        // also checks that there are < 2^31 targets
        VM._assert(number > 0);
    }
    Operand val = TableSwitch.getClearValue(s);
    BranchOperand defaultLabel = TableSwitch.getClearDefault(s);
    if (number < ir.options.CONTROL_TABLESWITCH_CUTOFF) {
        // convert into a lookupswitch
        Instruction l = LookupSwitch.create(LOOKUPSWITCH, val, null, null, defaultLabel, TableSwitch.getClearDefaultBranchProfile(s), number * 3);
        for (int i = 0; i < number; i++) {
            LookupSwitch.setMatch(l, i, IC(lowLimit + i));
            LookupSwitch.setTarget(l, i, TableSwitch.getClearTarget(s, i));
            LookupSwitch.setBranchProfile(l, i, TableSwitch.getClearBranchProfile(s, i));
        }
        s.insertAfter(CPOS(s, l));
        return s.remove();
    }
    RegisterOperand reg = val.asRegister();
    BasicBlock BB1 = s.getBasicBlock();
    BasicBlock BB2 = BB1.splitNodeAt(s, ir);
    BasicBlock defaultBB = defaultLabel.target.getBasicBlock();
    /**
     ***** First basic block
     */
    RegisterOperand t;
    if (lowLimit != 0) {
        t = insertBinary(s, ir, INT_ADD, TypeReference.Int, reg, IC(-lowLimit));
    } else {
        t = reg.copyU2U();
    }
    BranchProfileOperand defaultProb = TableSwitch.getClearDefaultBranchProfile(s);
    s.replace(CPOS(s, IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), t, IC(highLimit - lowLimit), ConditionOperand.HIGHER(), defaultLabel, defaultProb)));
    // Reweight branches to account for the default branch going. If
    // the default probability was ALWAYS then when we recompute the
    // weight to be a proportion of the total number of branches.
    final boolean defaultIsAlways = defaultProb.takenProbability >= 1f;
    final float weight = defaultIsAlways ? 1f / number : 1f / (1f - defaultProb.takenProbability);
    /**
     ******** second Basic Block *****
     */
    s2 = CPOS(s, LowTableSwitch.create(LOWTABLESWITCH, t.copyRO(), number * 2));
    boolean containsDefault = false;
    for (int i = 0; i < number; i++) {
        BranchOperand b = TableSwitch.getClearTarget(s, i);
        LowTableSwitch.setTarget(s2, i, b);
        BranchProfileOperand bp = TableSwitch.getClearBranchProfile(s, i);
        if (defaultIsAlways) {
            bp.takenProbability = weight;
        } else {
            bp.takenProbability *= weight;
        }
        LowTableSwitch.setBranchProfile(s2, i, bp);
        if (b.target == defaultLabel.target) {
            containsDefault = true;
        }
    }
    // Fixup the CFG and code order.
    BB1.insertOut(BB2);
    BB1.insertOut(defaultBB);
    ir.cfg.linkInCodeOrder(BB1, BB2);
    if (!containsDefault) {
        BB2.deleteOut(defaultBB);
    }
    // This actually happens (very occasionally), and is easy to test for.
    if (BB2.getNumberOfNormalOut() == 1) {
        BB2.appendInstruction(CPOS(s, Goto.create(GOTO, LowTableSwitch.getClearTarget(s2, 0))));
    } else {
        BB2.appendInstruction(s2);
    }
    // continue at next BB
    s = BB2.lastInstruction();
    return s;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 8 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class ConvertToLowLevelIR method _lookupswitchHelper.

/**
 * Helper function to generate the binary search tree for
 * a lookupswitch bytecode
 *
 * @param switchInstr the lookupswitch instruction
 * @param defaultBB the basic block of the default case
 * @param ir the ir object
 * @param curBlock the basic block to insert instructions into
 * @param reg the RegisterOperand that contains the valued being switched on
 * @param low the low index of cases (operands of switchInstr)
 * @param high the high index of cases (operands of switchInstr)
 * @param min minimum for the current case
 * @param max maximum for the current case
 * @return the last basic block created
 */
private static BasicBlock _lookupswitchHelper(Instruction switchInstr, RegisterOperand reg, BasicBlock defaultBB, IR ir, BasicBlock curBlock, int low, int high, int min, int max) {
    if (VM.VerifyAssertions) {
        VM._assert(low <= high, "broken control logic in _lookupswitchHelper");
    }
    // find middle
    int middle = (low + high) >> 1;
    // The following are used below to store the computed branch
    // probabilities for the branches that are created to implement
    // the binary search.  Used only if basic block frequencies available
    float lessProb = 0.0f;
    float greaterProb = 0.0f;
    float equalProb = 0.0f;
    float sum = 0.0f;
    // Sum the probabilities for all targets < middle
    for (int i = low; i < middle; i++) {
        lessProb += LookupSwitch.getBranchProfile(switchInstr, i).takenProbability;
    }
    // Sum the probabilities for all targets > middle
    for (int i = middle + 1; i <= high; i++) {
        greaterProb += LookupSwitch.getBranchProfile(switchInstr, i).takenProbability;
    }
    equalProb = LookupSwitch.getBranchProfile(switchInstr, middle).takenProbability;
    // generated may not).
    if (low == 0) {
        lessProb += LookupSwitch.getDefaultBranchProfile(switchInstr).takenProbability;
    }
    // Now normalize them so they are relative to the sum of the
    // branches being considered in this piece of the subtree
    sum = lessProb + equalProb + greaterProb;
    if (sum > 0) {
        // check for divide by zero
        lessProb /= sum;
        equalProb /= sum;
        greaterProb /= sum;
    }
    IntConstantOperand val = LookupSwitch.getClearMatch(switchInstr, middle);
    int value = val.value;
    BasicBlock greaterBlock = middle == high ? defaultBB : curBlock.createSubBlock(0, ir);
    BasicBlock lesserBlock = low == middle ? defaultBB : curBlock.createSubBlock(0, ir);
    // Generate this level of tests
    BranchOperand branch = LookupSwitch.getClearTarget(switchInstr, middle);
    BasicBlock branchBB = branch.target.getBasicBlock();
    curBlock.insertOut(branchBB);
    if (low != high) {
        if (value == min) {
            curBlock.appendInstruction(IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), reg.copy(), val, ConditionOperand.EQUAL(), branchBB.makeJumpTarget(), new BranchProfileOperand(equalProb)));
        } else {
            // To compute the probability of the second compare, the first
            // probability must be removed since the second branch is
            // considered only if the first fails.
            float secondIfProb = 0.0f;
            sum = equalProb + greaterProb;
            if (sum > 0) {
                // if divide by zero, leave as is
                secondIfProb = equalProb / sum;
            }
            curBlock.appendInstruction(IfCmp2.create(INT_IFCMP2, ir.regpool.makeTempValidation(), reg.copy(), val, ConditionOperand.LESS(), lesserBlock.makeJumpTarget(), new BranchProfileOperand(lessProb), ConditionOperand.EQUAL(), branchBB.makeJumpTarget(), new BranchProfileOperand(secondIfProb)));
            curBlock.insertOut(lesserBlock);
        }
    } else {
        // Base case: middle was the only case left to consider
        if (min == max) {
            curBlock.appendInstruction(Goto.create(GOTO, branch));
            curBlock.insertOut(branchBB);
        } else {
            curBlock.appendInstruction(IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), reg.copy(), val, ConditionOperand.EQUAL(), branchBB.makeJumpTarget(), new BranchProfileOperand(equalProb)));
            BasicBlock newBlock = curBlock.createSubBlock(0, ir);
            curBlock.insertOut(newBlock);
            ir.cfg.linkInCodeOrder(curBlock, newBlock);
            curBlock = newBlock;
            curBlock.appendInstruction(defaultBB.makeGOTO());
            curBlock.insertOut(defaultBB);
        }
    }
    // Generate sublevels as needed and splice together instr & bblist
    if (middle < high) {
        curBlock.insertOut(greaterBlock);
        ir.cfg.linkInCodeOrder(curBlock, greaterBlock);
        curBlock = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, greaterBlock, middle + 1, high, value + 1, max);
    }
    if (low < middle) {
        ir.cfg.linkInCodeOrder(curBlock, lesserBlock);
        curBlock = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, lesserBlock, low, middle - 1, min, value - 1);
    }
    return curBlock;
}
Also used : IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 9 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class BranchOptimizations method processGoto.

/**
 * Perform optimizations for a Goto.
 *
 * <p> Patterns:
 * <pre>
 *    1)      GOTO A       replaced by  GOTO B
 *         A: GOTO B
 *
 *    2)      GOTO A       replaced by  IF .. GOTO B
 *         A: IF .. GOTO B              GOTO C
 *         C: ...
 *    3)   GOTO next instruction eliminated
 *    4)      GOTO A       replaced by  GOTO B
 *         A: LABEL
 *            BBEND
 *         B:
 *    5)   GOTO BBn where BBn has exactly one in edge
 *         - move BBn immediately after the GOTO in the code order,
 *           so that pattern 3) will create a fallthrough
 * </pre>
 *
 * <p> Precondition: Goto.conforms(g)
 *
 * @param ir governing IR
 * @param g the instruction to optimize
 * @param bb the basic block holding g
 * @return {@code true} if made a transformation
 */
private boolean processGoto(IR ir, Instruction g, BasicBlock bb) {
    BasicBlock targetBlock = g.getBranchTarget();
    // don't optimize jumps to a code motion landing pad
    if (targetBlock.getLandingPad())
        return false;
    Instruction targetLabel = targetBlock.firstInstruction();
    // get the first real instruction at the g target
    // NOTE: this instruction is not necessarily in targetBlock,
    // iff targetBlock has no real instructions
    Instruction targetInst = firstRealInstructionFollowing(targetLabel);
    if (targetInst == null || targetInst == g) {
        return false;
    }
    Instruction nextLabel = firstLabelFollowing(g);
    if (targetLabel == nextLabel) {
        // found a GOTO to the next instruction.  just remove it.
        g.remove();
        return true;
    }
    if (Goto.conforms(targetInst)) {
        // unconditional branch to unconditional branch.
        // replace g with goto to targetInst's target
        Instruction target2 = firstRealInstructionFollowing(targetInst.getBranchTarget().firstInstruction());
        if (target2 == targetInst) {
            // This happens in jByteMark.EmFloatPnt.denormalize() due to a while(true) {}
            return false;
        }
        Goto.setTarget(g, (BranchOperand) Goto.getTarget(targetInst).copy());
        // fix the CFG
        bb.recomputeNormalOut(ir);
        return true;
    }
    if (targetBlock.isEmpty()) {
        // GOTO an empty basic block.  Change target to the
        // next block.
        BasicBlock nextBlock = targetBlock.getFallThroughBlock();
        Goto.setTarget(g, nextBlock.makeJumpTarget());
        // fix the CFG
        bb.recomputeNormalOut(ir);
        return true;
    }
    if (mayDuplicateCondBranches && IfCmp.conforms(targetInst)) {
        // multiple conditional branches in a single basic block.
        if (!g.prevInstructionInCodeOrder().isBranch() && (targetInst.nextInstructionInCodeOrder().operator() == BBEND || targetInst.nextInstructionInCodeOrder().operator() == GOTO)) {
            Instruction copy = targetInst.copyWithoutLinks();
            g.replace(copy);
            Instruction newGoto = targetInst.getBasicBlock().getNotTakenNextBlock().makeGOTO();
            copy.insertAfter(newGoto);
            // fix the CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
    }
    // try to create a fallthrough
    if (mayReorderCode && targetBlock.getNumberOfIn() == 1) {
        BasicBlock ftBlock = targetBlock.getFallThroughBlock();
        if (ftBlock != null) {
            BranchOperand ftTarget = ftBlock.makeJumpTarget();
            targetBlock.appendInstruction(CPOS(g, Goto.create(GOTO, ftTarget)));
        }
        ir.cfg.removeFromCodeOrder(targetBlock);
        ir.cfg.insertAfterInCodeOrder(bb, targetBlock);
        // fix the CFG
        targetBlock.recomputeNormalOut(ir);
        return true;
    }
    return false;
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 10 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class BranchOptimizations method flipConditionalBranch.

/**
 * Flip a conditional branch and remove the trailing goto.
 * See comment 3) of processConditionalBranch
 *
 * <p> Precondition isFlipCandidate(cb)
 * @param cb the conditional branch instruction
 */
private void flipConditionalBranch(Instruction cb) {
    // get the trailing GOTO instruction
    Instruction g = cb.nextInstructionInCodeOrder();
    BranchOperand gTarget = (BranchOperand) (Goto.getTarget(g).copy());
    // now flip the test and set the new target
    IfCmp.setCond(cb, IfCmp.getCond(cb).flipCode());
    IfCmp.setTarget(cb, gTarget);
    // Update the branch probability.  It is now the opposite
    cb.flipBranchProbability();
    // finally, remove the trailing GOTO instruction
    g.remove();
}
Also used : Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Aggregations

BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)30 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)16 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)16 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)15 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)14 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)14 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)13 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)10 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)9 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)8 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)8 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)7 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)7 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)7 OptimizingCompilerException (org.jikesrvm.compilers.opt.OptimizingCompilerException)5 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)5 Operator (org.jikesrvm.compilers.opt.ir.Operator)4 OsrPoint (org.jikesrvm.compilers.opt.ir.OsrPoint)4 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)4 InlinedOsrTypeInfoOperand (org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand)4