use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.
the class NormalBURS method buildTrees.
/**
* Stage 1: Complete the expression trees and identify tree roots.
* Complete BURS trees by adding leaf nodes as needed, and
* creating tree edges by calling insertChild1() or insertChild2()
* This step is also where we introduce intermediate tree nodes for
* any LIR instruction that has > 2 "real" operands e.g., a CALL.
* We also mark nodes that must be tree roots.
*
* @param dg The dependence graph.
*/
private void buildTrees(DepGraph dg) {
DepGraphNode bbNodes = (DepGraphNode) dg.firstNode();
for (DepGraphNode n = bbNodes; n != null; n = (DepGraphNode) n.getNext()) {
// Initialize n.treeNode
AbstractBURS_TreeNode cur_parent = AbstractBURS_TreeNode.create(n);
castNode(n).setCurrentParent(cur_parent);
Instruction instr = n.instruction();
// loop for USES of an instruction
for (Enumeration<Operand> uses = instr.getUses(); uses.hasMoreElements(); ) {
// Create tree edge for next use.
Operand op = uses.nextElement();
if (op == null)
continue;
// Set child = AbstractBURS_TreeNode for operand op
AbstractBURS_TreeNode child;
if (op instanceof RegisterOperand) {
RegisterOperand regOp = (RegisterOperand) op;
// ignore validation registers
if (regOp.getRegister().isValidation())
continue;
DepGraphEdge e = DepGraphEdge.findInputEdge(n, op);
if (e == null) {
// operand is leaf
child = Register;
} else {
child = castNode(e.fromNode()).getCurrentParent();
}
} else if (op instanceof IntConstantOperand) {
child = new BURS_IntConstantTreeNode(((IntConstantOperand) op).value);
} else if (op instanceof LongConstantOperand) {
child = LongConstant;
} else if (op instanceof AddressConstantOperand) {
child = AddressConstant;
} else if (op instanceof BranchOperand && instr.isCall()) {
child = BranchTarget;
} else if (op instanceof InlinedOsrTypeInfoOperand && instr.isYieldPoint()) {
child = NullTreeNode;
} else {
continue;
}
// Attach child as child of cur_parent in correct position
if (cur_parent.getChild1() == null) {
cur_parent.setChild1(child);
} else if (cur_parent.getChild2() == null) {
cur_parent.setChild2(child);
} else {
// Create auxiliary node so as to represent
// a instruction with arity > 2 in a binary tree.
AbstractBURS_TreeNode child1 = cur_parent.getChild2();
AbstractBURS_TreeNode aux = AbstractBURS_TreeNode.create(OTHER_OPERAND_opcode);
cur_parent.setChild2(aux);
cur_parent = aux;
cur_parent.setChild1(child1);
cur_parent.setChild2(child);
}
}
// patch for calls & return
switch(instr.getOpcode()) {
case CALL_opcode:
case SYSCALL_opcode:
case YIELDPOINT_OSR_opcode:
if (cur_parent.getChild2() == null) {
cur_parent.setChild2(NullTreeNode);
}
// fall through
case RETURN_opcode:
if (cur_parent.getChild1() == null) {
cur_parent.setChild1(NullTreeNode);
}
}
if (mustBeTreeRoot(n)) {
makeTreeRoot(castNode(n).getCurrentParent());
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.
the class BasicBlock method redirectOuts.
/**
* Change all branches from this to b to branches that go to bCopy instead.
* This method also handles this.fallThrough, so `this' should still be in
* the code order when this method is called.<p>
*
* WARNING: Use this method with caution. See comment on
* BasicBlock.recomputeNormalOut()
*
* @param b the original target
* @param bCopy the future target
* @param ir the IR that contains this basic block
*/
public final void redirectOuts(BasicBlock b, BasicBlock bCopy, IR ir) {
BranchOperand copyTarget = bCopy.makeJumpTarget();
BranchOperand bTarget = b.makeJumpTarget();
// 1. update the branch instructions in 'this' to point to bCopy
for (Enumeration<Instruction> ie = enumerateBranchInstructions(); ie.hasMoreElements(); ) {
Instruction s = ie.nextElement();
s.replaceSimilarOperands(bTarget, copyTarget);
}
// 2. if this falls through to b, make it jump to bCopy
if (getFallThroughBlock() == b) {
// no copy needed.
Instruction g = Goto.create(GOTO, copyTarget);
appendInstruction(g);
}
// 3. recompute normal control flow edges.
recomputeNormalOut(ir);
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method callHelper.
/**
* Helper method for call expansion.
* @param v the call instruction
* @param ir the containing IR
* @return the last expanded instruction
*/
static Instruction callHelper(Instruction v, IR ir) {
if (!Call.hasMethod(v)) {
if (VM.VerifyAssertions)
VM._assert(Call.getAddress(v) instanceof RegisterOperand);
// nothing to do....very low level call to address already in the register.
return v;
}
MethodOperand methOp = Call.getMethod(v);
// Handle recursive invocations.
if (methOp.hasPreciseTarget() && methOp.getTarget() == ir.method) {
Call.setAddress(v, new BranchOperand(ir.firstInstructionInCodeOrder()));
return v;
}
// has been marked as a specialized call.
if (VM.runningVM) {
SpecializedMethod spMethod = methOp.spMethod;
if (spMethod != null) {
int smid = spMethod.getSpecializedMethodIndex();
Call.setAddress(v, getSpecialMethod(v, ir, smid));
return v;
}
}
// Used mainly (only?) by OSR
if (methOp.hasDesignatedTarget()) {
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, methOp.jtocOffset));
return v;
}
if (methOp.isStatic()) {
if (VM.VerifyAssertions)
VM._assert(Call.hasAddress(v));
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, Call.getClearAddress(v)));
} else if (methOp.isVirtual()) {
if (VM.VerifyAssertions)
VM._assert(Call.hasAddress(v));
if (ir.options.H2L_CALL_VIA_JTOC && methOp.hasPreciseTarget()) {
// Call to precise type can go via JTOC
RVMMethod target = methOp.getTarget();
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, target.findOrCreateJtocOffset()));
} else {
Operand tib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, tib, Call.getClearAddress(v), null, TG()));
}
} else if (methOp.isSpecial()) {
RVMMethod target = methOp.getTarget();
if (target == null || target.isObjectInitializer() || target.isStatic()) {
// target == null => we are calling an unresolved <init> method.
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, Call.getClearAddress(v)));
} else {
if (ir.options.H2L_CALL_VIA_JTOC) {
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, target.findOrCreateJtocOffset()));
} else {
// invoking a virtual method; do it via TIB of target's declaring class.
Operand tib = getTIB(v, ir, target.getDeclaringClass());
Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, tib, Call.getClearAddress(v), null, TG()));
}
}
} else {
if (VM.VerifyAssertions)
VM._assert(methOp.isInterface());
if (VM.VerifyAssertions)
VM._assert(!Call.hasAddress(v));
if (VM.BuildForIMTInterfaceInvocation) {
// SEE ALSO: FinalMIRExpansion (for hidden parameter)
Operand RHStib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(methOp.getMemberRef());
Offset offset = sig.getIMTOffset();
RegisterOperand address = null;
RegisterOperand IMT = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.IMT, RHStib.copy(), Offset.fromIntZeroExtend(TIB_INTERFACE_DISPATCH_TABLE_INDEX << LOG_BYTES_IN_ADDRESS));
address = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, IMT.copyD2U(), offset);
Call.setAddress(v, address);
} else {
int itableIndex = -1;
if (VM.BuildForITableInterfaceInvocation && methOp.hasTarget()) {
RVMClass I = methOp.getTarget().getDeclaringClass();
// search ITable variant
itableIndex = InterfaceInvocation.getITableIndex(I, methOp.getMemberRef().getName(), methOp.getMemberRef().getDescriptor());
}
if (itableIndex == -1) {
// itable index is not known at compile-time.
// call "invokeinterface" to resolve the object and method id
// into a method address
RegisterOperand realAddrReg = ir.regpool.makeTemp(TypeReference.CodeArray);
RVMMethod target = Entrypoints.invokeInterfaceMethod;
Instruction vp = Call.create2(CALL, realAddrReg, AC(target.getOffset()), MethodOperand.STATIC(target), Call.getParam(v, 0).asRegister().copyU2U(), IC(methOp.getMemberRef().getId()));
vp.setSourcePosition(RUNTIME_SERVICES_BCI, v.position());
v.insertBefore(vp);
callHelper(vp, ir);
Call.setAddress(v, realAddrReg.copyD2U());
return v;
} else {
// itable index is known at compile-time.
// call "findITable" to resolve object + interface id into
// itable address
RegisterOperand iTable = ir.regpool.makeTemp(TypeReference.ITable);
Operand RHStib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
RVMMethod target = Entrypoints.findItableMethod;
Instruction fi = Call.create2(CALL, iTable, AC(target.getOffset()), MethodOperand.STATIC(target), RHStib, IC(methOp.getTarget().getDeclaringClass().getInterfaceId()));
fi.setSourcePosition(RUNTIME_SERVICES_BCI, v.position());
v.insertBefore(fi);
callHelper(fi, ir);
RegisterOperand address = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, iTable.copyD2U(), Offset.fromIntZeroExtend(itableIndex << LOG_BYTES_IN_ADDRESS));
Call.setAddress(v, address);
return v;
}
}
}
return v;
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand 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.BranchOperand in project JikesRVM by JikesRVM.
the class BranchSimplifier method processLookupSwitch.
static boolean processLookupSwitch(IR ir, BasicBlock bb, Instruction s) {
Operand val = LookupSwitch.getValue(s);
int numMatches = LookupSwitch.getNumberOfMatches(s);
if (numMatches == 0) {
// Can only goto default
Goto.mutate(s, GOTO, LookupSwitch.getDefault(s));
} else if (val.isConstant()) {
// lookup value is constant
int value = ((IntConstantOperand) val).value;
BranchOperand target = LookupSwitch.getDefault(s);
for (int i = 0; i < numMatches; i++) {
if (value == LookupSwitch.getMatch(s, i).value) {
target = LookupSwitch.getTarget(s, i);
break;
}
}
Goto.mutate(s, GOTO, target);
} else if (numMatches == 1) {
// only 1 match, simplify to ifcmp
BranchOperand defaultTarget = LookupSwitch.getClearDefault(s);
IfCmp.mutate(s, INT_IFCMP, ir.regpool.makeTempValidation(), val, LookupSwitch.getMatch(s, 0), ConditionOperand.EQUAL(), LookupSwitch.getTarget(s, 0), LookupSwitch.getBranchProfile(s, 0));
s.insertAfter(Goto.create(GOTO, defaultTarget));
} else {
// no optimisation, just continue
return false;
}
return true;
}
Aggregations