use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class LoopVersioning method createBranchBlocks.
/*
* TODO better JavaDoc comment.
* <p>
* Create the block containing explict branches to either the
* optimized or unoptimized loops
* @param optimalRegMap - mapping used to map eliminated bound and
* null check guards to
*/
private boolean createBranchBlocks(AnnotatedLSTNode loop, BasicBlock block, ArrayList<Instruction> checksToEliminate, BasicBlock unoptimizedLoopEntry, BasicBlock optimizedLoopEntry, HashMap<Register, Register> optimalRegMap) {
BasicBlock blockOnEntry = block;
// 1) generate null check guards
block = generateNullCheckBranchBlocks(loop, checksToEliminate, optimalRegMap, block, unoptimizedLoopEntry);
// 2) generate bound check guards
if (loop.isMonotonic()) {
// create new operands for values beyond initial and terminal iterator values
Operand terminal;
Operand terminalLessStrideOnce;
Operand terminalPlusStrideOnce;
// it does create dead code though
if (loop.terminalIteratorValue.isIntConstant()) {
terminal = loop.terminalIteratorValue;
int terminalAsInt = terminal.asIntConstant().value;
int stride = loop.strideValue.asIntConstant().value;
terminalLessStrideOnce = new IntConstantOperand(terminalAsInt - stride);
terminalPlusStrideOnce = new IntConstantOperand(terminalAsInt + stride);
} else {
Instruction tempInstr;
terminal = loop.generateLoopInvariantOperand(block, loop.terminalIteratorValue);
terminalLessStrideOnce = ir.regpool.makeTempInt();
terminalPlusStrideOnce = ir.regpool.makeTempInt();
tempInstr = Binary.create(INT_SUB, terminalLessStrideOnce.asRegister(), terminal.copy(), loop.strideValue.copy());
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(tempInstr);
DefUse.updateDUForNewInstruction(tempInstr);
tempInstr = Binary.create(INT_ADD, terminalPlusStrideOnce.asRegister(), terminal.copy(), loop.strideValue.copy());
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(tempInstr);
DefUse.updateDUForNewInstruction(tempInstr);
}
// Determine maximum and minimum index values for different loop types
Operand phiMinIndexValue;
Operand phiMaxIndexValue;
if (loop.isMonotonicIncreasing()) {
phiMinIndexValue = loop.initialIteratorValue;
if ((loop.condition.isLESS() || loop.condition.isLOWER() || loop.condition.isNOT_EQUAL())) {
phiMaxIndexValue = terminal;
} else if ((loop.condition.isLESS_EQUAL() || loop.condition.isLOWER_EQUAL() || loop.condition.isEQUAL())) {
phiMaxIndexValue = terminalPlusStrideOnce;
} else {
throw new Error("Unrecognised loop for fission " + loop);
}
} else if (loop.isMonotonicDecreasing()) {
phiMaxIndexValue = loop.initialIteratorValue;
if ((loop.condition.isGREATER() || loop.condition.isHIGHER() || loop.condition.isNOT_EQUAL())) {
phiMinIndexValue = terminalPlusStrideOnce;
} else if ((loop.condition.isGREATER_EQUAL() || loop.condition.isHIGHER_EQUAL() || loop.condition.isEQUAL())) {
phiMinIndexValue = terminalLessStrideOnce;
} else {
throw new Error("Unrecognised loop for fission " + loop);
}
} else {
throw new Error("Unrecognised loop for fission " + loop);
}
// Generate tests
for (int i = 0; i < checksToEliminate.size(); i++) {
Instruction instr = checksToEliminate.get(i);
if (BoundsCheck.conforms(instr)) {
// Have we already generated these tests?
boolean alreadyChecked = false;
for (int j = 0; j < i; j++) {
Instruction old_instr = checksToEliminate.get(j);
if (BoundsCheck.conforms(old_instr) && (BoundsCheck.getRef(old_instr).similar(BoundsCheck.getRef(instr))) && (BoundsCheck.getIndex(old_instr).similar(BoundsCheck.getIndex(instr)))) {
// yes - just create a guard move
alreadyChecked = true;
RegisterOperand guardResult = BoundsCheck.getGuardResult(instr).copyRO();
guardResult.setRegister(optimalRegMap.get(guardResult.getRegister()));
RegisterOperand guardSource = BoundsCheck.getGuardResult(old_instr).copyRO();
guardSource.setRegister(optimalRegMap.get(guardSource.getRegister()));
Instruction tempInstr = Move.create(GUARD_MOVE, guardResult, guardSource);
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(tempInstr);
break;
}
}
if (!alreadyChecked) {
// no - generate tests
Operand index = BoundsCheck.getIndex(instr);
int distance = loop.getFixedDistanceFromPhiIterator(index);
if (distance == 0) {
block = generateExplicitBoundCheck(instr, phiMinIndexValue, phiMaxIndexValue, optimalRegMap, block, unoptimizedLoopEntry);
} else {
Instruction tempInstr;
RegisterOperand minIndex = ir.regpool.makeTempInt();
RegisterOperand maxIndex = ir.regpool.makeTempInt();
tempInstr = Binary.create(INT_ADD, minIndex, phiMinIndexValue.copy(), new IntConstantOperand(distance));
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(tempInstr);
DefUse.updateDUForNewInstruction(tempInstr);
tempInstr = Binary.create(INT_ADD, maxIndex, phiMaxIndexValue.copy(), new IntConstantOperand(distance));
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(tempInstr);
DefUse.updateDUForNewInstruction(tempInstr);
block = generateExplicitBoundCheck(instr, minIndex, maxIndex, optimalRegMap, block, unoptimizedLoopEntry);
}
}
}
}
}
// Have we had to create a new basic block since entry => we
// generated a branch to the unoptimized loop
boolean isUnoptimizedLoopReachable = (blockOnEntry != block);
// 3) Finish up with goto and generate true guard value
{
// the generated branch instruction
Instruction branch;
branch = Goto.create(GOTO, optimizedLoopEntry.makeJumpTarget());
branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(branch);
block.deleteNormalOut();
block.insertOut(optimizedLoopEntry);
}
return isUnoptimizedLoopReachable;
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class PiNodes method insertPiNullCheckNodes.
/**
* Insert Pi nodes for null check operations.
*
* <p>Each checkcast obj will be followed by
* <pre> PI obj, obj </pre>
*
* @param ir the governing IR
*/
private void insertPiNullCheckNodes(IR ir) {
if (!CHECK_REF_PI)
return;
Instruction nextInst = null;
// for each instruction in the IR
for (Instruction instr = ir.firstInstructionInCodeOrder(); instr != null; instr = nextInst) {
// can't use iterator, since we modify instruction stream
nextInst = instr.nextInstructionInCodeOrder();
if (NullCheck.conforms(instr)) {
// get compared variables
Operand obj = NullCheck.getRef(instr);
// create the instruction and insert it
if (obj.isRegister()) {
RegisterOperand lval = (RegisterOperand) obj.copy();
Instruction s = GuardedUnary.create(PI, lval, obj.copy(), null);
RegisterOperand sGuard = (RegisterOperand) NullCheck.getGuardResult(instr).copy();
sGuard.setNullCheck();
GuardedUnary.setGuard(s, sGuard);
instr.insertAfter(s);
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class PiNodes method insertPiCheckCastNodes.
/**
* Insert Pi nodes for checkcast operations.
*
* <p>Each checkcast obj will be followed by
* <pre> ref_move obj, obj </pre>
*
* @param ir the governing IR
*/
private void insertPiCheckCastNodes(IR ir) {
Instruction nextInst = null;
// for each instruction in the IR
for (Instruction instr = ir.firstInstructionInCodeOrder(); instr != null; instr = nextInst) {
// can't use iterator, since we modify instruction stream
nextInst = instr.nextInstructionInCodeOrder();
if (TypeCheck.conforms(instr)) {
// get compared variables
Operand obj = TypeCheck.getRef(instr);
// create the instruction and insert it
if (obj.isRegister()) {
RegisterOperand lval = (RegisterOperand) obj.copy();
lval.clearDeclaredType();
if (lval.getType().isLoaded() && lval.getType().isClassType() && lval.getType().peekType().asClass().isFinal()) {
lval.setPreciseType(TypeCheck.getType(instr).getTypeRef());
} else {
lval.clearPreciseType();
lval.setType(TypeCheck.getType(instr).getTypeRef());
}
Instruction s = GuardedUnary.create(PI, lval, obj.copy(), null);
s.copyPosition(instr);
Operand iGuard = TypeCheck.getGuard(instr);
if (iGuard != null) {
Operand sGuard = iGuard.copy();
GuardedUnary.setGuard(s, sGuard);
}
instr.insertAfter(s);
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class PiNodes method cleanUp.
/**
* Change all PI nodes to INT_MOVE instructions
* <p> Side effect: invalidates SSA state
*
* @param ir the governing IR
*/
static void cleanUp(IR ir) {
for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (s.operator() == PI) {
RegisterOperand result = GuardedUnary.getResult(s);
Operator mv = IRTools.getMoveOp(result.getType());
Operand val = GuardedUnary.getVal(s);
Move.mutate(s, mv, result, val);
}
}
// invalidate SSA state
ir.actualSSAOptions = null;
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class PiNodes method insertPiIfNodes.
/**
* Insert PI nodes corresponding to compare operations.
* Pi-nodes are represented as dummy assignments with a single
* argument inserted along each outedge of the conditional.
*
* @param ir the governing IR
*/
private void insertPiIfNodes(IR ir) {
Enumeration<Instruction> e = ir.forwardInstrEnumerator();
while (e.hasMoreElements()) {
Instruction instr = e.nextElement();
// TODO: what other compareops generate useful assertions?
if (IfCmp.conforms(instr) || InlineGuard.conforms(instr)) {
BasicBlock thisbb = instr.getBasicBlock();
// only handle the "normal" case
if (thisbb.getNumberOfNormalOut() != 2) {
continue;
}
// insert new basic blocks on each edge out of thisbb
Enumeration<BasicBlock> outBB = thisbb.getNormalOut();
BasicBlock out1 = outBB.nextElement();
BasicBlock new1 = IRTools.makeBlockOnEdge(thisbb, out1, ir);
BasicBlock out2 = outBB.nextElement();
BasicBlock new2 = IRTools.makeBlockOnEdge(thisbb, out2, ir);
// blocks made on the outgoing edges.
if (InlineGuard.conforms(instr))
continue;
RegisterOperand ifGuard = IfCmp.getGuardResult(instr);
if (VM.VerifyAssertions) {
VM._assert(ifGuard != null);
}
// get compared variables
Operand a = IfCmp.getVal1(instr);
Operand b = IfCmp.getVal2(instr);
// determine which block is "taken" on the branch
BasicBlock takenBlock = IfCmp.getTarget(instr).target.getBasicBlock();
boolean new1IsTaken = false;
if (takenBlock == new1) {
new1IsTaken = true;
}
// insert the PI-node instructions for a and b
if (a.isRegister() && !a.asRegister().getRegister().isPhysical() && (a.asRegister().getRegister().isInteger() || a.asRegister().getRegister().isAddress())) {
// insert pi-nodes only for variables, not constants
Instruction s = GuardedUnary.create(PI, (RegisterOperand) a.copy(), a.copy(), null);
RegisterOperand sGuard = (RegisterOperand) ifGuard.copy();
if (new1IsTaken) {
sGuard.setTaken();
} else {
sGuard.setNotTaken();
}
GuardedUnary.setGuard(s, sGuard);
new1.prependInstruction(s);
s = s.copyWithoutLinks();
sGuard = (RegisterOperand) ifGuard.copy();
if (new1IsTaken) {
sGuard.setNotTaken();
} else {
sGuard.setTaken();
}
GuardedUnary.setGuard(s, sGuard);
new2.prependInstruction(s);
}
if (b.isRegister() && !b.asRegister().getRegister().isPhysical() && (b.asRegister().getRegister().isInteger() || b.asRegister().getRegister().isAddress())) {
Instruction s = GuardedUnary.create(PI, (RegisterOperand) b.copy(), b.copy(), null);
RegisterOperand sGuard = (RegisterOperand) ifGuard.copy();
if (new1IsTaken) {
sGuard.setTaken();
} else {
sGuard.setNotTaken();
}
GuardedUnary.setGuard(s, sGuard);
new1.prependInstruction(s);
s = s.copyWithoutLinks();
sGuard = (RegisterOperand) ifGuard.copy();
if (new1IsTaken) {
sGuard.setNotTaken();
} else {
sGuard.setTaken();
}
GuardedUnary.setGuard(s, sGuard);
new2.prependInstruction(s);
}
}
}
}
Aggregations