use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.
/**
* Generate a branching dynamic type check.
* This routine assumes that the CFG and code order are already
* correctly established.
* This routine must either remove s or mutate it.
*
* @param s The Instruction that is to be replaced by a
* branching type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The TypeReference to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param trueBlock The BasicBlock to continue at if the typecheck
* evaluates to true
* @param falseBlock The BasicBlock to continue at if the typecheck
* evaluates to false.
* @param oldGuard A suitable guard operand (not necessarily related
* the instruction that is to be replaced).
* @param falseProb The probability that typecheck will branch to the falseBlock
* @return the opt instruction immediately before the instruction to
* continue expansion.
*/
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
continueAt.copyPosition(s);
s.insertBefore(continueAt);
s.remove();
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// A resolved class (cases 5 and 6 in DynamicTypeCheck)
if (LHSclass.isFinal()) {
// For a final class, we can do a PTR compare of
// rhsTIB and the TIB of the class
Operand classTIB = getTIB(continueAt, ir, LHSclass);
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
} else {
// A non-resolved class or interface. Case 3 of DynamicTypeCheck
// Branch on the result of a call to
// RuntimeEntrypoints.instance
RegisterOperand result = ir.regpool.makeTempInt();
RVMMethod target = Entrypoints.instanceOfMethod;
Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
Operand classTIB = getTIB(continueAt, ir, LHSArray);
RVMType innermostElementType = LHSArray.getInnermostElementType();
if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
// [^k of primitive or [^k of final class. Just like final classes,
// a PTR compare of rhsTIB and the TIB of the class gives the answer.
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
// TODO: branch probability calculation is somewhat bogus for this case.
Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(shortcircuit);
BasicBlock myBlock = shortcircuit.getBasicBlock();
BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
// must come after the splitNodeAt
myBlock.insertOut(trueBlock);
RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
if (innermostElementType.isJavaLangObjectType()) {
IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(dimTest);
// BasicBlock testBlock =
mainBlock.splitNodeWithLinksAt(dimTest, ir);
mainBlock.insertOut(trueBlock);
mainBlock.insertOut(falseBlock);
RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
// Not a case we want to handle inline
RVMMethod target = Entrypoints.instanceOfMethod;
RegisterOperand callResult = ir.regpool.makeTempInt();
Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class GenerationContext method getConditionalBranchProfileOperand.
// /////////
// Profile data
// /////////
BranchProfileOperand getConditionalBranchProfileOperand(int bcIndex, boolean backwards) {
float prob;
BranchProfile bp;
if (branchProfiles != null && ((bp = branchProfiles.getEntry(bcIndex)) != null)) {
prob = ((ConditionalBranchProfile) bp).getTakenProbability();
} else {
if (branchProfiles != null) {
VM.sysWrite("Warning: conditional branch profile entry not found");
}
if (backwards) {
prob = 0.9f;
} else {
prob = 0.5f;
}
}
// we were completely wrong.
if (options.inverseFrequencyCounters()) {
prob = 1f - prob;
}
return new BranchProfileOperand(prob);
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class BranchOptimizations method generateCondMove.
/**
* Attempt to generate a straight-line sequence using conditional move
* instructions, to replace a diamond control flow structure.
*
* <p>Suppose we have the following code, where e{n} is an expression:
* <pre>
* if (a op b) {
* x = e2;
* y = e3;
* } else {
* z = e4;
* x = e5;
* }
* </pre>
* We would transform this to:
* <pre>
* t1 = a;
* t2 = b;
* t3 = e2;
* t4 = e3;
* t5 = e4;
* t6 = e5;
* COND MOVE [if (t1 op t2) x := t3 else x := t6 ];
* COND MOVE [if (t1 op t2) y := t4 else y := y];
* COND MOVE [if (t1 op t2) z := z else z := t5];
* </pre>
*
* <p>Note that we rely on other optimizations (eg. copy propagation) to
* clean up some of this unnecessary mess.
*
* <p>Note that in this example, we've increased the shortest path by 2
* expression evaluations, 2 moves, and 3 cond moves, but eliminated one
* conditional branch.
*
* <p>We apply a cost heuristic to guide this transformation:
* We will eliminate a conditional branch iff it increases the shortest
* path by no more than 'k' operations. Currently, we count each
* instruction (alu, move, or cond move) as 1 evaluation.
* The parameter k is specified by OPT\_Options.COND_MOVE_CUTOFF.
*
* <p> In the example above, since we've increased the shortest path by
* 6 instructions, we will only perform the transformation if {@code k >= 7}.
*
* <p> TODO items
* <ul>
* <li> consider smarter cost heuristics
* <li> enhance downstream code generation to avoid redundant evaluation
* of condition codes.
* </ul>
*
* @param ir governing IR
* @param bb basic block of cb
* @param cb conditional branch instruction
* @return true if the transformation succeeds, false otherwise
*/
private boolean generateCondMove(IR ir, BasicBlock bb, Instruction cb) {
final boolean VERBOSE = false;
if (!VM.BuildForIA32)
return false;
if (!IfCmp.conforms(cb))
return false;
if (VERBOSE)
System.out.println("CondMove: Looking to optimize " + cb);
// Don't generate CMOVs for branches that can be folded.
if (IfCmp.getVal1(cb).isConstant() && IfCmp.getVal2(cb).isConstant()) {
if (VERBOSE)
System.out.println("CondMove: fail - could be folded");
return false;
}
// see if bb is the root of an if-then-else.
Diamond diamond = Diamond.buildDiamond(bb);
if (diamond == null) {
if (VERBOSE)
System.out.println("CondMove: fail - no diamond");
return false;
}
BasicBlock taken = diamond.getTaken();
BasicBlock notTaken = diamond.getNotTaken();
// has a taboo instruction (eg., a PEI, store or divide).
if (taken != null && hasCMTaboo(taken)) {
if (VERBOSE)
System.out.println("CondMove: fail - taken branch has taboo instruction");
return false;
}
if (notTaken != null && hasCMTaboo(notTaken)) {
if (VERBOSE)
System.out.println("CondMove: fail - not taken branch has taboo instruction");
return false;
}
ConditionOperand cond = IfCmp.getCond(cb);
// Do not generate when we don't know the branch probability or
// when branch probability is high. CMOVs reduce performance of
// the out-of-order engine (Intel Optimization Guide -
// Assembly/Compiler Coding Rule 2).
// Ignore in the case of an abs() method as we can create tighter
// instructions.
BranchProfileOperand profile = IfCmp.getBranchProfile(cb);
if ((Math.abs(profile.takenProbability - 0.5) >= ir.options.CONTROL_WELL_PREDICTED_CUTOFF) && !(cb.position() != null && cb.position().method.getName() == ABS && cond.isFLOATINGPOINT())) {
if (VERBOSE)
System.out.println("CondMove: fail - branch could be well predicted by branch predictor: " + profile.takenProbability);
return false;
}
// if we must generate FCMP, make sure the condition code is OK
if (cond.isFLOATINGPOINT()) {
if (!fpConditionOK(cond)) {
// Condition not OK, but maybe if we flip the operands
if (!fpConditionOK(cond.flipOperands())) {
// still not ok so flip operands back
cond.flipOperands();
// controlling just floating point moves
if (!VM.BuildForSSE2Full || hasFloatingPointDef(taken, true) || hasFloatingPointDef(notTaken, true)) {
if (VERBOSE)
System.out.println("CondMove: fail - fp condition not OK: " + cond);
return false;
}
} else {
// flip operands
Operand val1 = IfCmp.getVal1(cb);
Operand val2 = IfCmp.getVal2(cb);
IfCmp.setVal1(cb, val2);
IfCmp.setVal2(cb, val1);
}
}
}
if (!cond.isFLOATINGPOINT()) {
// compares or for unsigned compares in x87
if (VM.BuildForSSE2Full || !cond.isUNSIGNED()) {
if (hasFloatingPointDef(taken, false) || hasFloatingPointDef(notTaken, false)) {
if (VERBOSE)
System.out.println("CondMove: fail - not allowed integer condition controlling floating conditional move");
return false;
}
}
}
// For now, do not generate CMOVs for longs.
if (hasLongDef(taken) || hasLongDef(notTaken)) {
return false;
}
// count the number of expression evaluations in each side of the
// diamond
int takenCost = 0;
int notTakenCost = 0;
if (taken != null)
takenCost = evaluateCost(taken);
if (notTaken != null)
notTakenCost = evaluateCost(notTaken);
// evaluate whether it's profitable.
int shortestCost = Math.min(takenCost, notTakenCost);
int xformCost = 2 * (takenCost + notTakenCost);
int k = ir.options.CONTROL_COND_MOVE_CUTOFF;
if (xformCost - shortestCost > k) {
if (VERBOSE)
System.out.println("CondMove: fail - cost too high");
return false;
}
// Perform the transformation!
doCondMove(ir, diamond, cb);
return true;
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method basic_long_ifcmp.
private static void basic_long_ifcmp(Instruction s, IR ir, ConditionOperand cond, Register xh, Register xl, Operand yh, Operand yl) {
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
RegisterOperand th = ir.regpool.makeTempInt();
RegisterOperand tl = ir.regpool.makeTempInt();
// tricky... ((xh^yh)|(xl^yl) == 0) <==> (lhll == rhrl)!!
s.insertBefore(MIR_Move.create(IA32_MOV, th, new RegisterOperand(xh, TypeReference.Int)));
s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, th.copyD2D(), yh));
s.insertBefore(MIR_Move.create(IA32_MOV, tl, new RegisterOperand(xl, TypeReference.Int)));
s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, tl.copyD2D(), yl));
s.insertBefore(MIR_BinaryAcc.create(IA32_OR, th.copyD2D(), tl.copyD2U()));
MIR_CondBranch.mutate(s, IA32_JCC, new IA32ConditionOperand(cond), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
} else {
// Do the naive thing and generate multiple compare/branch implementation.
IA32ConditionOperand cond1;
IA32ConditionOperand cond2;
IA32ConditionOperand cond3;
if (cond.isLESS()) {
cond1 = IA32ConditionOperand.LT();
cond2 = IA32ConditionOperand.GT();
cond3 = IA32ConditionOperand.LLT();
} else if (cond.isGREATER()) {
cond1 = IA32ConditionOperand.GT();
cond2 = IA32ConditionOperand.LT();
cond3 = IA32ConditionOperand.LGT();
} else if (cond.isLESS_EQUAL()) {
cond1 = IA32ConditionOperand.LT();
cond2 = IA32ConditionOperand.GT();
cond3 = IA32ConditionOperand.LLE();
} else if (cond.isGREATER_EQUAL()) {
cond1 = IA32ConditionOperand.GT();
cond2 = IA32ConditionOperand.LT();
cond3 = IA32ConditionOperand.LGE();
} else {
// I don't think we use the unsigned compares for longs,
// so defer actually implementing them until we find a test case. --dave
cond1 = cond2 = cond3 = null;
OptimizingCompilerException.TODO();
}
BasicBlock myBlock = s.getBasicBlock();
BasicBlock test2Block = myBlock.createSubBlock(s.getBytecodeIndex(), ir, 0.25f);
BasicBlock falseBlock = myBlock.splitNodeAt(s, ir);
BasicBlock trueBlock = IfCmp.getTarget(s).target.getBasicBlock();
falseBlock.recomputeNormalOut(ir);
myBlock.insertOut(test2Block);
myBlock.insertOut(falseBlock);
myBlock.insertOut(trueBlock);
test2Block.insertOut(falseBlock);
test2Block.insertOut(trueBlock);
ir.cfg.linkInCodeOrder(myBlock, test2Block);
ir.cfg.linkInCodeOrder(test2Block, falseBlock);
s.remove();
myBlock.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), yh)));
myBlock.appendInstruction(CPOS(s, MIR_CondBranch2.create(IA32_JCC2, cond1, trueBlock.makeJumpTarget(), new BranchProfileOperand(), cond2, falseBlock.makeJumpTarget(), new BranchProfileOperand())));
test2Block.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xl, TypeReference.Int), yl)));
test2Block.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, cond3, trueBlock.makeJumpTarget(), new BranchProfileOperand())));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method fp_ifcmp.
// the fcmoi/fcmoip was generated by burs
// we do the rest of the expansion here because in some
// cases we must remove a trailing goto, and we
// can't do that in burs!
private static Instruction fp_ifcmp(Instruction s) {
Instruction nextInstr = s.nextInstructionInCodeOrder();
BranchOperand testFailed;
BasicBlock bb = s.getBasicBlock();
Instruction lastInstr = bb.lastRealInstruction();
if (lastInstr.operator() == IA32_JMP) {
// We're in trouble if there is another instruction between s and lastInstr!
if (VM.VerifyAssertions)
VM._assert(s.nextInstructionInCodeOrder() == lastInstr);
// Set testFailed to target of GOTO
testFailed = MIR_Branch.getClearTarget(lastInstr);
nextInstr = lastInstr.nextInstructionInCodeOrder();
lastInstr.remove();
} else {
// Set testFailed to label of next (fallthrough basic block)
testFailed = bb.nextBasicBlockInCodeOrder().makeJumpTarget();
}
// Translate condition operand respecting IA32 FCOMI/COMISS/COMISD
Instruction fcomi = s.prevInstructionInCodeOrder();
Operand val1 = MIR_Compare.getVal1(fcomi);
Operand val2 = MIR_Compare.getVal2(fcomi);
ConditionOperand c = IfCmp.getCond(s);
BranchOperand target = IfCmp.getTarget(s).copy().asBranch();
BranchProfileOperand branchProfile = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
// propagate the original probability to the second condition.
switch(c.value) {
// (i.e. UNORDERED is a goto to testFailed)
case ConditionOperand.CMPL_EQUAL:
if (VM.VerifyAssertions)
VM._assert(!c.branchIfUnordered());
// Check whether val1 and val2 operands are the same
if (!val1.similar(val2)) {
s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.EQ(), // ZF == 1
target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy())));
} else {
// As val1 == val2 result of compare must be == or UNORDERED
s.insertBefore(// PF == 0
MIR_CondBranch.create(// PF == 0
IA32_JCC, // PF == 0
IA32ConditionOperand.PO(), target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
}
break;
case ConditionOperand.CMPL_GREATER:
if (VM.VerifyAssertions)
VM._assert(!c.branchIfUnordered());
s.insertBefore(// CF == 0 and ZF == 0
MIR_CondBranch.create(// CF == 0 and ZF == 0
IA32_JCC, // CF == 0 and ZF == 0
IA32ConditionOperand.LGT(), target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
break;
case ConditionOperand.CMPG_LESS:
if (VM.VerifyAssertions)
VM._assert(!c.branchIfUnordered());
s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.LLT(), // CF == 1
target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy())));
break;
case ConditionOperand.CMPL_GREATER_EQUAL:
if (VM.VerifyAssertions)
VM._assert(!c.branchIfUnordered());
s.insertBefore(// CF == 0
MIR_CondBranch.create(// CF == 0
IA32_JCC, // CF == 0
IA32ConditionOperand.LGE(), target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
break;
case ConditionOperand.CMPG_LESS_EQUAL:
s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.LGT(), // ZF == 0 and CF == 0
(BranchOperand) (testFailed.copy()), branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, target));
break;
// (i.e. UNORDERED is a goto to target)
case ConditionOperand.CMPL_NOT_EQUAL:
if (VM.VerifyAssertions)
VM._assert(c.branchIfUnordered());
// Check whether val1 and val2 operands are the same
if (!val1.similar(val2)) {
s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
target, new BranchProfileOperand(0f), IA32ConditionOperand.NE(), // ZF == 0
(BranchOperand) (target.copy()), branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
} else {
// As val1 == val2 result of compare must be == or UNORDERED
s.insertBefore(// PF == 1
MIR_CondBranch.create(// PF == 1
IA32_JCC, // PF == 1
IA32ConditionOperand.PE(), target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
}
break;
case ConditionOperand.CMPL_LESS:
if (VM.VerifyAssertions)
VM._assert(c.branchIfUnordered());
s.insertBefore(// CF == 1
MIR_CondBranch.create(// CF == 1
IA32_JCC, // CF == 1
IA32ConditionOperand.LLT(), target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
break;
case ConditionOperand.CMPG_GREATER_EQUAL:
if (VM.VerifyAssertions)
VM._assert(c.branchIfUnordered());
s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
target, new BranchProfileOperand(0f), IA32ConditionOperand.LLT(), // CF == 1
testFailed, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (target.copy())));
break;
case ConditionOperand.CMPG_GREATER:
if (VM.VerifyAssertions)
VM._assert(c.branchIfUnordered());
s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
target, new BranchProfileOperand(0f), IA32ConditionOperand.LGT(), // ZF == 0 and CF == 0
(BranchOperand) (target.copy()), branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
break;
case ConditionOperand.CMPL_LESS_EQUAL:
if (VM.VerifyAssertions)
VM._assert(c.branchIfUnordered());
s.insertBefore(// CF == 1 or ZF == 1
MIR_CondBranch.create(// CF == 1 or ZF == 1
IA32_JCC, // CF == 1 or ZF == 1
IA32ConditionOperand.LLE(), target, branchProfile));
s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
break;
default:
OptimizingCompilerException.UNREACHABLE();
}
s.remove();
return nextInstr;
}
Aggregations