use of org.jikesrvm.compilers.opt.ir.BasicBlock in project JikesRVM by JikesRVM.
the class LocalCastOptimization method perform.
/**
* Main routine: perform the transformation.
* @param ir the IR to transform
*/
@Override
public void perform(IR ir) {
// loop over all basic blocks ...
for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements(); ) {
BasicBlock bb = e.nextElement();
if (bb.isEmpty())
continue;
container.counter2++;
if (bb.getInfrequent()) {
container.counter1++;
if (ir.options.FREQ_FOCUS_EFFORT)
continue;
}
// visit each instruction in the basic block
for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements(); ) {
Instruction s = ie.nextElement();
if (TypeCheck.conforms(s) && (invertNullAndTypeChecks(s) || pushTypeCheckBelowIf(s, ir))) {
// hack: we may have modified the instructions; start over
ie = bb.forwardInstrEnumerator();
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.BasicBlock in project JikesRVM by JikesRVM.
the class LocalCastOptimization method pushTypeCheckBelowIf.
/**
* Where legal, move a type check below an if instruction.
* @param s the potential typecheck instruction
* @param ir the governing IR
* @return {@code true} if and only if a type check was moved
*/
private boolean pushTypeCheckBelowIf(Instruction s, IR ir) {
if (s.operator() == CHECKCAST) {
Register r = TypeCheck.getRef(s).asRegister().getRegister();
Instruction n = s.nextInstructionInCodeOrder();
/* find moves of the checked value, so that we can also
optimize cases where the checked value is moved before
it is used
*/
while (n.operator() == REF_MOVE && Move.getVal(n) instanceof RegisterOperand && Move.getVal(n).asRegister().getRegister() == r) {
r = Move.getResult(n).asRegister().getRegister();
n = n.nextInstructionInCodeOrder();
}
if (n.operator() == REF_IFCMP && IfCmp.getVal2(n) instanceof NullConstantOperand && IfCmp.getVal1(n) instanceof RegisterOperand && r == IfCmp.getVal1(n).asRegister().getRegister()) {
BasicBlock newBlock, patchBlock;
BasicBlock myBlock = n.getBasicBlock();
Instruction after = n.nextInstructionInCodeOrder();
if (IfCmp.getCond(n).isEQUAL()) /* We fall through on non-NULL values, so the
checkcast must be on the not-taken path
from the branch. There are 3 cases:
1. n is the last instruction in its basic block,
in which case control falls through to the next
block in code order. This case is if the
instruction after n is a BBEND
*/
{
if (after.operator() == BBEND) {
patchBlock = myBlock.nextBasicBlockInCodeOrder();
} else if (after.operator() == GOTO) {
/* 2. n is followed by an unconditional goto. In
this case control jumps to the target of the
goto.
*/
patchBlock = after.getBranchTarget();
} else if (after.operator() == REF_IFCMP) {
/* 3. n is followed by another conditional branch. In
this case, we will split the basic block to make
n the last instruction in the block, and then
we have the fall through case again.
*/
patchBlock = myBlock.splitNodeAt(n, ir);
myBlock.insertOut(patchBlock);
ir.cfg.linkInCodeOrder(myBlock, patchBlock);
} else {
/* this is a bad thing */
return false;
}
} else /* We branch on not-NULL values, so the checkcast
must be spliced in before the branch target
*/
{
patchBlock = n.getBranchTarget();
}
/* add block between branch and appropriate successor */
newBlock = IRTools.makeBlockOnEdge(myBlock, patchBlock, ir);
/* put check in new block */
s.remove();
TypeCheck.mutate(s, CHECKCAST_NOTNULL, TypeCheck.getClearResult(s), TypeCheck.getClearRef(s), TypeCheck.getClearType(s), IfCmp.getGuardResult(n).copyRO());
newBlock.prependInstruction(s);
return true;
}
}
return false;
}
use of org.jikesrvm.compilers.opt.ir.BasicBlock 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();
}
}
use of org.jikesrvm.compilers.opt.ir.BasicBlock 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.BasicBlock in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method long_ushr.
private static Instruction long_ushr(Instruction s, IR ir) {
Instruction nextInstr = s.nextInstructionInCodeOrder();
while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) {
nextInstr = nextInstr.nextInstructionInCodeOrder();
}
// we need 4 basic blocks
// 1: the current block that does a test if the shift is > 32
// 2: a block to perform a shift in the range 32 to 63
// 3: a block to perform a shift in the range 0 to 31
// 4: the next basic block
BasicBlock testBB = s.getBasicBlock();
BasicBlock nextBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nextBB);
BasicBlock shift32BB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, shift32BB);
BasicBlock shift64BB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, shift64BB);
// Source registers
Register lhsReg = Binary.getClearResult(s).getRegister();
Register lowlhsReg = ir.regpool.getSecondReg(lhsReg);
Operand val1 = Binary.getClearVal1(s);
Register rhsReg;
Register lowrhsReg;
if (val1.isRegister()) {
rhsReg = val1.asRegister().getRegister();
lowrhsReg = ir.regpool.getSecondReg(rhsReg);
} else {
// shift is of a constant so set up registers
int low = val1.asLongConstant().lower32();
int high = val1.asLongConstant().upper32();
testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(low))));
testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(high))));
rhsReg = lhsReg;
lowrhsReg = lowlhsReg;
}
// ecx = shift amount
Register ecx = phys(ir).getECX();
testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(ecx, TypeReference.Int), Binary.getClearVal2(s))));
// Determine shift of 32 to 63 or 0 to 31
testBB.appendInstruction(CPOS(s, MIR_Test.create(IA32_TEST, new RegisterOperand(ecx, TypeReference.Int), IC(32))));
// if (ecx & 32 == 0) goto shift32BB
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.EQ(), shift32BB.makeJumpTarget(), BranchProfileOperand.likely())));
testBB.insertOut(shift32BB);
// fall-through
testBB.insertOut(shift64BB);
// Perform shift in the range 32 to 63
shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(rhsReg, TypeReference.Int))));
shift64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(ecx, TypeReference.Int))));
shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(0))));
shift64BB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
shift64BB.insertOut(nextBB);
// Perform shift in the range 0 to 31
if (lhsReg != rhsReg) {
shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg, TypeReference.Int))));
shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg, TypeReference.Int))));
}
shift32BB.appendInstruction(CPOS(s, MIR_DoubleShift.create(IA32_SHRD, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(ecx, TypeReference.Int))));
shift32BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(ecx, TypeReference.Int))));
shift32BB.insertOut(nextBB);
s.remove();
return nextInstr;
}
Aggregations