use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class GenerationContext method completePrologue.
/**
* Fills in the rest of the method prologue.
* PRECONDITION: arguments & temps have been setup/initialized.
*
* @param isOutermost is this the outermost context (i.e. not an inlined context)
*/
private void completePrologue(boolean isOutermost) {
// Deal with Uninteruptible code.
if (!isOutermost && requiresUnintMarker()) {
Instruction s = Empty.create(UNINT_BEGIN);
appendInstruction(prologue, s, PROLOGUE_BCI);
}
// since it's the second time reenter
if (method.isForOsrSpecialization()) {
// do nothing
} else if (method.isSynchronized() && !options.ESCAPE_INVOKEE_THREAD_LOCAL) {
Operand lockObject = getLockObject();
Instruction s = MonitorOp.create(MONITORENTER, lockObject, new TrueGuardOperand());
appendInstruction(prologue, s, SYNCHRONIZED_MONITORENTER_BCI);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class GenerateMachineSpecificMagic method generateMagic.
/**
* "Semantic inlining" of methods of the Magic class.
* Based on the methodName, generate a sequence of opt instructions
* that implement the magic, updating the stack as necessary
*
* @param bc2ir the bc2ir object generating the ir containing this magic
* @param gc == bc2ir.gc
* @param meth the RVMMethod that is the magic method
* @return {@code true} if and only if magic was generated
*/
public static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) throws MagicNotImplementedException {
Atom methodName = meth.getName();
PhysicalRegisterSet phys = gc.getTemps().getPhysicalRegisterSet().asIA32();
if (methodName == MagicNames.getESIAsThread) {
RegisterOperand rop = gc.getTemps().makeTROp();
bc2ir.markGuardlessNonNull(rop);
bc2ir.push(rop);
} else if (methodName == MagicNames.setESIAsThread) {
Operand val = bc2ir.popRef();
if (val instanceof RegisterOperand) {
bc2ir.appendInstruction(Move.create(REF_MOVE, gc.getTemps().makeTROp(), val));
} else {
String msg = " Unexpected operand Magic.setESIAsThread";
throw MagicNotImplementedException.UNEXPECTED(msg);
}
} else if (methodName == MagicNames.getFramePointer) {
gc.forceFrameAllocation();
RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
RVMField f = ArchEntrypoints.framePointerField;
RegisterOperand pr = new RegisterOperand(phys.getESI(), TypeReference.Address);
bc2ir.appendInstruction(GetField.create(GETFIELD, val, pr.copy(), new AddressConstantOperand(f.getOffset()), new LocationOperand(f), new TrueGuardOperand()));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.getJTOC || methodName == MagicNames.getTocPointer) {
TypeReference t = (methodName == MagicNames.getJTOC ? TypeReference.IntArray : TypeReference.Address);
RegisterOperand val = gc.getTemps().makeTemp(t);
AddressConstantOperand addr = new AddressConstantOperand(Magic.getTocPointer());
bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.synchronizeInstructionCache) {
// nothing required on Intel
} else if (methodName == MagicNames.prefetch) {
bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress()));
} else if (methodName == MagicNames.pause) {
bc2ir.appendInstruction(Empty.create(PAUSE));
} else if (methodName == MagicNames.illegalInstruction) {
bc2ir.appendInstruction(Empty.create(ILLEGAL_INSTRUCTION));
} else if (methodName == MagicNames.getCallerFramePointer) {
Operand fp = bc2ir.popAddress();
RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
bc2ir.appendInstruction(Load.create(REF_LOAD, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.setCallerFramePointer) {
Operand val = bc2ir.popAddress();
Operand fp = bc2ir.popAddress();
bc2ir.appendInstruction(Store.create(REF_STORE, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
} else if (methodName == MagicNames.getCompiledMethodID) {
Operand fp = bc2ir.popAddress();
RegisterOperand val = gc.getTemps().makeTempInt();
bc2ir.appendInstruction(Load.create(INT_LOAD, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.setCompiledMethodID) {
Operand val = bc2ir.popInt();
Operand fp = bc2ir.popAddress();
bc2ir.appendInstruction(Store.create(INT_STORE, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
} else if (methodName == MagicNames.getReturnAddressLocation) {
Operand fp = bc2ir.popAddress();
Instruction s = bc2ir._binaryHelper(REF_ADD, fp, offsetOperand(STACKFRAME_RETURN_ADDRESS_OFFSET), TypeReference.Address);
bc2ir.appendInstruction(s);
} else {
// Distinguish between magics that we know we don't implement
// (and never plan to implement) and those (usually new ones)
// that we want to be warned that we don't implement.
String msg = " Magic method not implemented: " + meth;
if (methodName == MagicNames.returnToNewStack) {
throw MagicNotImplementedException.EXPECTED(msg);
} else {
return false;
// throw MagicNotImplementedException.UNEXPECTED(msg);
}
}
return true;
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class AnnotatedLSTNode method getFixedDistanceFromPhiIterator.
/**
* Get fixed distance from the phi iterator
*
* @param op the operand to test
* @return the fixed distance
*/
public int getFixedDistanceFromPhiIterator(Operand op) {
if (op.similar(phiLoopIterator)) {
return 0;
} else {
Instruction opInstr = definingInstruction(op);
if (opInstr.getOpcode() == INT_ADD_opcode) {
Operand val1 = Binary.getVal1(opInstr);
Operand val2 = Binary.getVal2(opInstr);
if (val1.isConstant()) {
return val1.asIntConstant().value + getFixedDistanceFromPhiIterator(val2);
} else {
if (VM.VerifyAssertions)
VM._assert(val2.isConstant());
return getFixedDistanceFromPhiIterator(val1) + val2.asIntConstant().value;
}
} else if (opInstr.getOpcode() == INT_SUB_opcode) {
Operand val1 = Binary.getVal1(opInstr);
Operand val2 = Binary.getVal2(opInstr);
if (val1.isConstant()) {
return val1.asIntConstant().value - getFixedDistanceFromPhiIterator(val2);
} else {
if (VM.VerifyAssertions)
VM._assert(val2.isConstant());
return getFixedDistanceFromPhiIterator(val1) - val2.asIntConstant().value;
}
}
}
throw new Error("Value isn't fixed distance from phi iterator");
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand 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.Operand in project JikesRVM by JikesRVM.
the class LocalCopyProp method perform.
/**
* Perform local constant propagation for a method.
*
* @param ir the IR to optimize
*/
@Override
public void perform(IR ir) {
HashMap<Register, Operand> info = new HashMap<Register, Operand>();
for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) {
if (bb.isEmpty())
continue;
container.counter2++;
if (bb.getInfrequent()) {
container.counter1++;
if (ir.options.FREQ_FOCUS_EFFORT)
continue;
}
// iterate over all instructions in the basic block
for (Instruction s = bb.firstRealInstruction(), sentinel = bb.lastInstruction(); s != sentinel; s = s.nextInstructionInCodeOrder()) {
if (!info.isEmpty()) {
// PROPAGATE COPIES
int numUses = s.getNumberOfPureUses();
if (numUses > 0) {
boolean didSomething = false;
for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements(); ) {
Operand use = e.nextElement();
if (use instanceof RegisterOperand) {
RegisterOperand rUse = (RegisterOperand) use;
Operand value = info.get(rUse.getRegister());
if (value != null) {
didSomething = true;
value = value.copy();
if (value instanceof RegisterOperand) {
// preserve program point specific typing!
((RegisterOperand) value).copyTypeFrom(rUse);
}
s.replaceOperand(use, value);
}
}
}
if (didSomething) {
Simplifier.simplify(ir.isHIR(), ir.regpool, ir.options, s);
}
}
// KILL
boolean killPhysicals = s.isTSPoint() || s.operator().implicitDefs != 0;
// premature optimization.
if (killPhysicals) {
HashSet<Register> toRemove = new HashSet<Register>();
for (Map.Entry<Register, Operand> entry : info.entrySet()) {
Register eR = entry.getValue().asRegister().getRegister();
if (killPhysicals && eR.isPhysical()) {
// delay the removal to avoid ConcurrentModification with iterator.
toRemove.add(entry.getKey());
}
}
// Now perform the removals.
for (final Register aToRemove : toRemove) {
info.remove(aToRemove);
}
}
for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements(); ) {
Operand def = e.nextElement();
if (def != null && def.isRegister()) {
Register r = def.asRegister().getRegister();
info.remove(r);
// also must kill any registers mapped to r
// TODO: use a better data structure for efficiency.
// I'm being lazy for now in the name of avoiding
// premature optimization.
HashSet<Register> toRemove = new HashSet<Register>();
for (Map.Entry<Register, Operand> entry : info.entrySet()) {
Register eR = ((RegisterOperand) entry.getValue()).getRegister();
if (eR == r) {
// delay the removal to avoid ConcurrentModification
// with iterator.
toRemove.add(entry.getKey());
}
}
// Now perform the removals.
for (final Register register : toRemove) {
info.remove(register);
}
}
}
}
// GEN
if (Move.conforms(s)) {
Operand val = Move.getVal(s);
if (val.isRegister()) {
RegisterOperand rhs = val.asRegister();
if (!rhs.getRegister().isPhysical()) {
RegisterOperand lhs = Move.getResult(s);
/* Only gen if the move instruction does not represent a Magic <==> non-Magic coercion */
if (lhs.getType().isReferenceType() == rhs.getType().isReferenceType()) {
info.put(lhs.getRegister(), val);
}
}
}
}
}
info.clear();
}
}
Aggregations