use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class BranchOptimizations method generateBooleanCompare.
/**
* Attempt to generate a boolean compare opcode from a conditional branch.
*
* <pre>
* 1) IF .. GOTO A replaced by BOOLEAN_CMP x=..
* x = 0
* GOTO B
* A: x = 1
* B: ...
* </pre>
*
* <p> Precondition: <code>IfCmp.conforms(<i>cb</i>)</code>
*
* @param ir governing IR
* @param bb basic block of cb
* @param cb conditional branch instruction
* @param tb target block the branch instruction
* @return {@code true} if and only if the transformation succeeds
*/
private boolean generateBooleanCompare(IR ir, BasicBlock bb, Instruction cb, BasicBlock tb) {
if ((cb.operator() != INT_IFCMP) && (cb.operator() != REF_IFCMP)) {
return false;
}
// make sure this is the last branch in the block
if (cb.nextInstructionInCodeOrder().operator() != BBEND) {
return false;
}
Operand val1 = IfCmp.getVal1(cb);
Operand val2 = IfCmp.getVal2(cb);
ConditionOperand condition = IfCmp.getCond(cb);
// "not taken" path
BasicBlock fb = cb.getBasicBlock().getNotTakenNextBlock();
// make sure it's a diamond
if (tb.getNumberOfNormalOut() != 1) {
return false;
}
if (fb.getNumberOfNormalOut() != 1) {
return false;
}
// join block
BasicBlock jb = fb.getNormalOut().nextElement();
// make sure it's a diamond
if (!tb.pointsOut(jb)) {
return false;
}
Instruction ti = tb.firstRealInstruction();
Instruction fi = fb.firstRealInstruction();
// or both returns
if (ti == null || fi == null) {
return false;
}
if (ti.operator() != fi.operator()) {
return false;
}
if (ti.operator() != RETURN && ti.operator() != INT_MOVE) {
return false;
}
//
if (ti.operator() == RETURN) {
// make sure each of the target blocks contains only one instruction
if (ti != tb.lastRealInstruction()) {
return false;
}
if (fi != fb.lastRealInstruction()) {
return false;
}
Operand tr = Return.getVal(ti);
Operand fr = Return.getVal(fi);
// make sure we're returning constants
if (!(tr instanceof IntConstantOperand) || !(fr instanceof IntConstantOperand)) {
return false;
}
int tv = ((IntConstantOperand) tr).value;
int fv = ((IntConstantOperand) fr).value;
if (!((tv == 1 && fv == 0) || (tv == 1 && fv == 0))) {
return false;
}
RegisterOperand t = ir.regpool.makeTemp(TypeReference.Boolean);
// Cases 1) and 2)
if (tv == 0) {
condition = condition.flipCode();
}
booleanCompareHelper(cb, t, val1.copy(), val2.copy(), condition);
cb.insertAfter(Return.create(RETURN, t.copyD2U()));
} else {
// make sure each of the target blocks only does the move
if (ti != tb.lastRealInstruction() && ti.nextInstructionInCodeOrder().operator() != GOTO) {
return false;
}
if (fi != fb.lastRealInstruction() && fi.nextInstructionInCodeOrder().operator() != GOTO) {
return false;
}
RegisterOperand t = Move.getResult(ti);
// make sure both moves are to the same register
if (t.getRegister() != Move.getResult(fi).getRegister()) {
return false;
}
Operand tr = Move.getVal(ti);
Operand fr = Move.getVal(fi);
// make sure we're assigning constants
if (!(tr instanceof IntConstantOperand) || !(fr instanceof IntConstantOperand)) {
return false;
}
int tv = ((IntConstantOperand) tr).value;
int fv = ((IntConstantOperand) fr).value;
if (!((tv == 1 && fv == 0) || (tv == 0 && fv == 1))) {
return false;
}
// Cases 3) and 4)
if (tv == 0) {
condition = condition.flipCode();
}
booleanCompareHelper(cb, t.copyRO(), val1.copy(), val2.copy(), condition);
Instruction next = cb.nextInstructionInCodeOrder();
if (next.operator() == GOTO) {
Goto.setTarget(next, jb.makeJumpTarget());
} else {
cb.insertAfter(jb.makeGOTO());
}
}
// fixup CFG
bb.deleteOut(tb);
bb.deleteOut(fb);
// Note: if we processed returns,
bb.insertOut(jb);
// jb is the exit node.
return true;
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class BranchOptimizations method doCondMove.
/**
* Perform the transformation to replace conditional branch with a
* sequence using conditional moves.
*
* @param ir governing IR
* @param diamond the IR diamond structure to replace
* @param cb conditional branch instruction at the head of the diamond
*/
private void doCondMove(IR ir, Diamond diamond, Instruction cb) {
BasicBlock taken = diamond.getTaken();
BasicBlock notTaken = diamond.getNotTaken();
// for each non-branch instruction s in the diamond,
// copy s to a new instruction s'
// and store a mapping from s to s'
HashMap<Instruction, Instruction> takenInstructions = new HashMap<Instruction, Instruction>();
Instruction[] takenInstructionList = copyAndMapInstructions(taken, takenInstructions);
HashMap<Instruction, Instruction> notTakenInstructions = new HashMap<Instruction, Instruction>();
Instruction[] notTakenInstructionList = copyAndMapInstructions(notTaken, notTakenInstructions);
// Extract the values and condition from the conditional branch.
Operand val1 = IfCmp.getVal1(cb);
Operand val2 = IfCmp.getVal2(cb);
ConditionOperand cond = IfCmp.getCond(cb);
// Copy val1 and val2 to temporaries, just in case they're defined in
// the diamond. If they're not defined in the diamond, copy prop
// should clean these moves up.
RegisterOperand tempVal1 = ir.regpool.makeTemp(val1);
Operator op = IRTools.getMoveOp(tempVal1.getType());
cb.insertBefore(Move.create(op, tempVal1.copyRO(), val1.copy()));
RegisterOperand tempVal2 = ir.regpool.makeTemp(val2);
op = IRTools.getMoveOp(tempVal2.getType());
cb.insertBefore(Move.create(op, tempVal2.copyRO(), val2.copy()));
// For each instruction in each temporary set, rewrite it to def a new
// temporary, and insert it before the branch.
rewriteWithTemporaries(takenInstructionList, ir);
rewriteWithTemporaries(notTakenInstructionList, ir);
insertBefore(takenInstructionList, cb);
insertBefore(notTakenInstructionList, cb);
// For each register defined in the TAKEN branch, save a mapping to
// the corresponding conditional move.
HashMap<Register, Instruction> takenMap = new HashMap<Register, Instruction>();
// First handle the taken branch.
if (taken != null) {
for (Enumeration<Instruction> e = taken.forwardRealInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (s.isBranch())
continue;
Operand def = s.getDefs().nextElement();
// that will now be dead
if (def.asRegister().getRegister().spansBasicBlock()) {
Instruction tempS = takenInstructions.get(s);
RegisterOperand temp = (RegisterOperand) tempS.getDefs().nextElement();
op = IRTools.getCondMoveOp(def.asRegister().getType());
Instruction cmov = CondMove.create(op, def.copy().asRegister(), tempVal1.copy(), tempVal2.copy(), cond.copy().asCondition(), temp.copy(), def.copy());
takenMap.put(def.asRegister().getRegister(), cmov);
cb.insertBefore(cmov);
}
s.remove();
}
}
// For each register defined in the NOT-TAKEN branch, save a mapping to
// the corresponding conditional move.
HashMap<Register, Instruction> notTakenMap = new HashMap<Register, Instruction>();
// Next handle the not taken branch.
if (notTaken != null) {
for (Enumeration<Instruction> e = notTaken.forwardRealInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (s.isBranch())
continue;
Operand def = s.getDefs().nextElement();
// that will now be dead
if (def.asRegister().getRegister().spansBasicBlock()) {
Instruction tempS = notTakenInstructions.get(s);
RegisterOperand temp = (RegisterOperand) tempS.getDefs().nextElement();
Instruction prevCmov = takenMap.get(def.asRegister().getRegister());
if (prevCmov != null) {
// if this register was also defined in the taken branch, change
// the previous cmov with a different 'False' Value
CondMove.setFalseValue(prevCmov, temp.copy());
notTakenMap.put(def.asRegister().getRegister(), prevCmov);
} else {
// create a new cmov instruction
op = IRTools.getCondMoveOp(def.asRegister().getType());
Instruction cmov = CondMove.create(op, def.asRegister(), tempVal1.copy(), tempVal2.copy(), cond.copy().asCondition(), def.copy(), temp.copy());
cb.insertBefore(cmov);
notTakenMap.put(def.asRegister().getRegister(), cmov);
}
}
s.remove();
}
}
// Mutate the conditional branch into a GOTO.
BranchOperand target = diamond.getBottom().makeJumpTarget();
Goto.mutate(cb, GOTO, target);
// Delete a potential GOTO after cb.
Instruction next = cb.nextInstructionInCodeOrder();
if (next.operator() != BBEND) {
next.remove();
}
// Recompute the CFG.
// fix the CFG
diamond.getTop().recomputeNormalOut(ir);
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class BranchSimplifier method processIfCmp.
static boolean processIfCmp(IR ir, BasicBlock bb, Instruction s) {
RegisterOperand guard = IfCmp.getGuardResult(s);
Operand val1 = IfCmp.getVal1(s);
Operand val2 = IfCmp.getVal2(s);
{
int cond = IfCmp.getCond(s).evaluate(val1, val2);
if (cond != ConditionOperand.UNKNOWN) {
// constant fold
if (cond == ConditionOperand.TRUE) {
// branch taken
insertTrueGuard(s, guard);
Goto.mutate(s, GOTO, IfCmp.getTarget(s));
removeBranchesAfterGotos(bb);
} else {
// branch not taken
insertTrueGuard(s, guard);
s.remove();
}
return true;
}
}
if (val1.isConstant() && !val2.isConstant()) {
// Canonicalize by making second argument the constant
IfCmp.setVal1(s, val2);
IfCmp.setVal2(s, val1);
IfCmp.setCond(s, IfCmp.getCond(s).flipOperands());
}
if (val2.isIntConstant()) {
// Tricks to get compare against zero.
int value = ((IntConstantOperand) val2).value;
ConditionOperand cond = IfCmp.getCond(s);
if (value == 1) {
if (cond.isLESS()) {
IfCmp.setCond(s, ConditionOperand.LESS_EQUAL());
IfCmp.setVal2(s, new IntConstantOperand(0));
} else if (cond.isGREATER_EQUAL()) {
IfCmp.setCond(s, ConditionOperand.GREATER());
IfCmp.setVal2(s, new IntConstantOperand(0));
}
} else if (value == -1) {
if (cond.isGREATER()) {
IfCmp.setCond(s, ConditionOperand.GREATER_EQUAL());
IfCmp.setVal2(s, new IntConstantOperand(0));
} else if (cond.isLESS_EQUAL()) {
IfCmp.setCond(s, ConditionOperand.LESS());
IfCmp.setVal2(s, new IntConstantOperand(0));
}
}
}
return false;
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class InstrumentationSamplingFramework method createCheck.
/**
* Append a check to a basic block, and make it jump to the right places.
*
* @param checkBB The block to append the CBS check to.
* @param noInstBB The basic block to jump to if the CBS check fails
* @param instBB The basicBlock to jump to if the CBS check succeeds
* @param fallthroughToInstBB Should checkBB fallthrough to instBB
* (otherwise it must fallthrough to noInstBB)
* @param ir the IR that contains the blocks
*/
private void createCheck(BasicBlock checkBB, BasicBlock noInstBB, BasicBlock instBB, boolean fallthroughToInstBB, IR ir) {
appendLoad(checkBB, ir);
// Depending on where you fallthrough, set the condition correctly
ConditionOperand cond = null;
BranchOperand target = null;
BranchProfileOperand profileOperand = null;
if (fallthroughToInstBB) {
// The instrumented basic block is the fallthrough of checkBB,
// so make the branch jump to the non-instrumented block.
cond = ConditionOperand.GREATER();
target = noInstBB.makeJumpTarget();
// Taken frequently
profileOperand = new BranchProfileOperand(1.0f);
} else {
// The non-instrumented basic block is the fallthrough of checkBB,
// so make the branch jump to the instrumented block.
cond = ConditionOperand.LESS_EQUAL();
target = instBB.makeJumpTarget();
// Taken infrequently
profileOperand = new BranchProfileOperand(0.0f);
}
RegisterOperand guard = ir.regpool.makeTempValidation();
checkBB.appendInstruction(IfCmp.create(INT_IFCMP, guard, cbsReg.copyRO(), new IntConstantOperand(0), cond, target, profileOperand));
checkBB.recomputeNormalOut(ir);
// Insert the decrement and store in the block that is the
// successor of the check
prependStore(noInstBB, ir);
prependDecrement(noInstBB, ir);
// Insert a counter reset in the duplicated block.
prependCounterReset(instBB, ir);
}
Aggregations