use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class LoopVersioning method createOptimizedLoop.
/**
* Create a clone of the loop replacing definitions in the cloned
* loop with those found in the register map and eliminate
* unnecessary bound checks
* @param loop - loop to clone
* @param regMap - mapping of original definition to new
* definition
* @param instrToEliminate - instructions to eliminate
* @param regToBlockMap - mapping of a register to its defining BB
* @return a mapping from original BBs to created BBs
*/
private HashMap<BasicBlock, BasicBlock> createOptimizedLoop(AnnotatedLSTNode loop, HashMap<Register, Register> regMap, ArrayList<Instruction> instrToEliminate, HashMap<Register, BasicBlock> regToBlockMap) {
HashMap<BasicBlock, BasicBlock> originalToCloneBBMap = new HashMap<BasicBlock, BasicBlock>();
// After the newly created loop goto the old loop header
originalToCloneBBMap.put(loop.successor, loop.header);
// Create an empty block to be the loop predecessor
BasicBlock new_pred = loop.header.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
ir.cfg.linkInCodeOrder(ir.cfg.lastInCodeOrder(), new_pred);
originalToCloneBBMap.put(loop.predecessor, new_pred);
// Create copy blocks
Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
// N.B. fall through will have been killed by unoptimized loop
// Create copy and register mapping
BasicBlock copy = block.copyWithoutLinks(ir);
originalToCloneBBMap.put(block, copy);
// Link into code order
ir.cfg.linkInCodeOrder(ir.cfg.lastInCodeOrder(), copy);
// Alter register definitions in copy
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, copy);
loop_over_created_instructions: while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
if (BoundsCheck.conforms(instruction)) {
for (Instruction anInstrToEliminate : instrToEliminate) {
if (instruction.similar(anInstrToEliminate)) {
instruction.remove();
continue loop_over_created_instructions;
}
}
} else if (NullCheck.conforms(instruction)) {
for (Instruction anInstrToEliminate : instrToEliminate) {
if (instruction.similar(anInstrToEliminate)) {
instruction.remove();
continue loop_over_created_instructions;
}
}
}
Enumeration<Operand> operands = instruction.getDefs();
while (operands.hasMoreElements()) {
Operand operand = operands.nextElement();
if (operand instanceof RegisterOperand) {
Register register = operand.asRegister().getRegister();
if (regMap.containsKey(register)) {
instruction.replaceRegister(register, regMap.get(register));
regToBlockMap.put(regMap.get(register), copy);
}
}
}
operands = instruction.getUses();
while (operands.hasMoreElements()) {
Operand operand = operands.nextElement();
if (operand.isRegister()) {
Register register = operand.asRegister().getRegister();
if (regMap.containsKey(register)) {
instruction.replaceRegister(register, regMap.get(register));
}
}
}
}
}
// Fix up outs
// loop predecessor
new_pred.redirectOuts(loop.header, originalToCloneBBMap.get(loop.header), ir);
blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
BasicBlock copy = originalToCloneBBMap.get(block);
Enumeration<BasicBlock> outs = block.getOutNodes();
while (outs.hasMoreElements()) {
BasicBlock out = outs.nextElement();
if (originalToCloneBBMap.containsKey(out)) {
copy.redirectOuts(out, originalToCloneBBMap.get(out), ir);
}
}
}
// Fix up phis
blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
BasicBlock copy = originalToCloneBBMap.get(block);
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, copy);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
if (Phi.conforms(instruction)) {
for (int i = 0; i < Phi.getNumberOfValues(instruction); i++) {
BasicBlock phi_predecessor = Phi.getPred(instruction, i).block;
if (originalToCloneBBMap.containsKey(phi_predecessor)) {
Phi.setPred(instruction, i, new BasicBlockOperand(originalToCloneBBMap.get(phi_predecessor)));
} else {
throw new Error("There's > 1 route to this phi node from outside the loop: " + phi_predecessor);
}
}
}
}
}
return originalToCloneBBMap;
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class LoopVersioning method generateNullCheckBranchBlocks.
/**
* Generate null check branch blocks
*
* @param loop the current loop where checks are being eliminated
* @param checksToEliminate all of the checks that are being eliminated in the pass
* @param optimalRegMap a map from original register to the register used in the optimal loop
* @param block the block to generate code into
* @param unoptimizedLoopEntry entry to the unoptimized loop for if the check fails
* @return the new block to generate code into
*/
private BasicBlock generateNullCheckBranchBlocks(AnnotatedLSTNode loop, ArrayList<Instruction> checksToEliminate, HashMap<Register, Register> optimalRegMap, BasicBlock block, BasicBlock unoptimizedLoopEntry) {
// Map of already generated null check references to their
// corresponding guard result
HashMap<Register, Operand> refToGuardMap = new HashMap<Register, Operand>();
// Iterate over checks
for (Instruction instr : checksToEliminate) {
// Is this a null check
if (NullCheck.conforms(instr)) {
// the generated branch instruction
Instruction branch;
// the reference to compare
Operand ref = AnnotatedLSTNode.follow(NullCheck.getRef(instr));
// the guard result to define
RegisterOperand guardResult = NullCheck.getGuardResult(instr).copyRO();
guardResult.setRegister(optimalRegMap.get(guardResult.getRegister()));
// check if we've generated this test already
if (ref.isRegister() && refToGuardMap.containsKey(ref.asRegister().getRegister())) {
// yes - generate just a guard move
branch = Move.create(GUARD_MOVE, guardResult, refToGuardMap.get(ref.asRegister().getRegister()).copy());
branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(branch);
} else {
// check if we can just move a guard from the loop predecessors
RegisterOperand guard = nullCheckPerformedInLoopPredecessors(loop.header, instr);
if (guard != null) {
// yes - generate just a guard move
branch = Move.create(GUARD_MOVE, guardResult, guard.copyRO());
branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(branch);
} else {
// generate explicit null test
branch = IfCmp.create(REF_IFCMP, guardResult, ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), unoptimizedLoopEntry.makeJumpTarget(), BranchProfileOperand.unlikely());
if (ref.isRegister()) {
refToGuardMap.put(ref.asRegister().getRegister(), guardResult);
}
branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
block.appendInstruction(branch);
// Adjust block
block.insertOut(unoptimizedLoopEntry);
BasicBlock new_block = block.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
BasicBlock temp = (BasicBlock) block.next;
ir.cfg.breakCodeOrder(block, temp);
ir.cfg.linkInCodeOrder(block, new_block);
ir.cfg.linkInCodeOrder(new_block, temp);
block.insertOut(new_block);
block = new_block;
}
}
}
}
return block;
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class LoopVersioning method modifyOriginalLoop.
/*
* TODO Convert to JavaDoc and add missing tags.
* <p>
* Remove loop and replace register definitions in the original loop
* with phi instructions
*/
private void modifyOriginalLoop(AnnotatedLSTNode loop, ArrayList<Instruction> phiInstructions, ArrayList<Instruction> definingInstrInOriginalLoop, HashMap<Register, Register> subOptimalRegMap, HashMap<Register, Register> optimalRegMap) {
// Remove instructions from loop header and exit, remove other
// loop body blocks
Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
if ((block == loop.header) || (block == loop.exit)) {
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, block);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
if (!BBend.conforms(instruction) && !Label.conforms(instruction)) {
instruction.remove();
}
}
} else {
ir.cfg.removeFromCFGAndCodeOrder(block);
}
}
// Place phi instructions in loop header
for (int i = 0; i < phiInstructions.size(); i++) {
Instruction origInstr = definingInstrInOriginalLoop.get(i);
// Did the original instructions value escape the loop?
if (origInstr != null) {
// Was this a phi of a phi?
if (Phi.conforms(origInstr)) {
Instruction phi = phiInstructions.get(i);
boolean phiHasUnoptimizedArg = Phi.getNumberOfValues(phi) == 2;
// Phi of a phi - so make sure that we get the value to escape the loop, not the value at the loop header
boolean fixed = false;
for (int index = 0; index < Phi.getNumberOfPreds(origInstr); index++) {
BasicBlockOperand predOp = Phi.getPred(origInstr, index);
// Only worry about values who are on the backward branch
if (predOp.block == loop.exit) {
if (fixed) {
// We've tried to do 2 replaces => something wrong
SSA.printInstructions(ir);
OptimizingCompilerException.UNREACHABLE("LoopVersioning", "Phi node in loop header with multiple in loop predecessors");
}
Operand rval = Phi.getValue(origInstr, index);
if (rval.isRegister()) {
// Sort out registers
Register origRegPhiRval = rval.asRegister().getRegister();
Register subOptRegPhiRval;
Register optRegPhiRval;
if (!subOptimalRegMap.containsKey(origRegPhiRval)) {
// Register comes from loop exit but it wasn't defined in the loop
subOptRegPhiRval = origRegPhiRval;
optRegPhiRval = origRegPhiRval;
} else {
subOptRegPhiRval = subOptimalRegMap.get(origRegPhiRval);
optRegPhiRval = optimalRegMap.get(origRegPhiRval);
}
if (phiHasUnoptimizedArg) {
Phi.getValue(phi, UNOPTIMIZED_LOOP_OPERAND).asRegister().setRegister(subOptRegPhiRval);
}
Phi.getValue(phi, OPTIMIZED_LOOP_OPERAND).asRegister().setRegister(optRegPhiRval);
} else if (rval.isConstant()) {
// Sort out constants
if (phiHasUnoptimizedArg) {
Phi.setValue(phi, UNOPTIMIZED_LOOP_OPERAND, rval.copy());
}
Phi.setValue(phi, OPTIMIZED_LOOP_OPERAND, rval.copy());
} else if (rval instanceof HeapOperand) {
// Sort out heap variables
// Cast to generic type
@SuppressWarnings("unchecked") HeapVariable<Object> origPhiRval = ((HeapOperand) rval).value;
HeapVariable<Object> subOptPhiRval;
HeapVariable<Object> optPhiRval;
if (true) /*subOptimalRegMap.containsKey(origPhiRval) == false*/
{
// currently we only expect to optimise scalar SSA
// form
subOptPhiRval = origPhiRval;
optPhiRval = origPhiRval;
} else {
/*
subOptPhiRval = (HeapVariable)subOptimalRegMap.get(origPhiRval);
optPhiRval = (HeapVariable)optimalRegMap.get(origPhiRval);
*/
}
if (phiHasUnoptimizedArg) {
Phi.setValue(phi, UNOPTIMIZED_LOOP_OPERAND, new HeapOperand<Object>(subOptPhiRval));
}
Phi.setValue(phi, OPTIMIZED_LOOP_OPERAND, new HeapOperand<Object>(optPhiRval));
} else {
OptimizingCompilerException.UNREACHABLE("LoopVersioning", "Unknown operand type", rval.toString());
}
fixed = true;
}
}
}
// Add back to loop
loop.header.appendInstruction(phiInstructions.get(i));
}
}
// Remove original loop and branch to loop successor
Instruction tempInstr;
if (loop.header != loop.exit) {
tempInstr = Goto.create(GOTO, loop.exit.makeJumpTarget());
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
loop.header.appendInstruction(tempInstr);
loop.header.deleteNormalOut();
loop.header.insertOut(loop.exit);
}
tempInstr = Goto.create(GOTO, loop.successor.makeJumpTarget());
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
loop.exit.appendInstruction(tempInstr);
loop.exit.deleteNormalOut();
loop.exit.insertOut(loop.successor);
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class LoopVersioning method createCloneLoop.
/**
* Create a clone of the loop replacing definitions in the cloned
* loop with those found in the register map
* @param loop - loop to clone
* @param regMap - mapping of original definition to new
* definition
* @param regToBlockMap mapping of registers to new, unoptimized blocks. This starts
* empty and will be filled during execution of the method.
* @return a mapping from original BBs to created BBs
*/
private HashMap<BasicBlock, BasicBlock> createCloneLoop(AnnotatedLSTNode loop, HashMap<Register, Register> regMap, HashMap<Register, BasicBlock> regToBlockMap) {
HashMap<BasicBlock, BasicBlock> originalToCloneBBMap = new HashMap<BasicBlock, BasicBlock>();
// After the newly created loop goto the old loop header
originalToCloneBBMap.put(loop.successor, loop.header);
// Create an empty block to be the loop predecessor
BasicBlock new_pred = loop.header.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
ir.cfg.linkInCodeOrder(ir.cfg.lastInCodeOrder(), new_pred);
originalToCloneBBMap.put(loop.predecessor, new_pred);
// Create copy blocks
Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
// get rid of fall through edges to aid recomputeNormalOuts
block.killFallThrough();
// Create copy and register mapping
BasicBlock copy = block.copyWithoutLinks(ir);
originalToCloneBBMap.put(block, copy);
// Link into code order
ir.cfg.linkInCodeOrder(ir.cfg.lastInCodeOrder(), copy);
// Alter register definitions and uses in copy
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, copy);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
Enumeration<Operand> operands = instruction.getDefs();
while (operands.hasMoreElements()) {
Operand operand = operands.nextElement();
if (operand.isRegister()) {
Register register = operand.asRegister().getRegister();
if (regMap.containsKey(register)) {
instruction.replaceRegister(register, regMap.get(register));
regToBlockMap.put(regMap.get(register), copy);
}
}
}
operands = instruction.getUses();
while (operands.hasMoreElements()) {
Operand operand = operands.nextElement();
if (operand instanceof RegisterOperand) {
Register register = operand.asRegister().getRegister();
if (regMap.containsKey(register)) {
instruction.replaceRegister(register, regMap.get(register));
}
}
}
}
}
// Fix up outs
// loop predecessor
new_pred.redirectOuts(loop.header, originalToCloneBBMap.get(loop.header), ir);
// loop blocks
blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
BasicBlock copy = originalToCloneBBMap.get(block);
Enumeration<BasicBlock> outs = block.getOutNodes();
while (outs.hasMoreElements()) {
BasicBlock out = outs.nextElement();
if (originalToCloneBBMap.containsKey(out)) {
copy.redirectOuts(out, originalToCloneBBMap.get(out), ir);
}
}
}
// Fix up phis
blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
BasicBlock copy = originalToCloneBBMap.get(block);
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, copy);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
if (Phi.conforms(instruction)) {
for (int i = 0; i < Phi.getNumberOfValues(instruction); i++) {
BasicBlock phi_predecessor = Phi.getPred(instruction, i).block;
if (originalToCloneBBMap.containsKey(phi_predecessor)) {
Phi.setPred(instruction, i, new BasicBlockOperand(originalToCloneBBMap.get(phi_predecessor)));
} else {
dumpIR(ir, "Error when optimising" + ir.getMethod());
throw new Error("There's > 1 route to this phi node " + instruction + " from outside the loop: " + phi_predecessor);
}
}
}
}
}
return originalToCloneBBMap;
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class SpillLocationManager method findOrCreateSpillLocation.
/**
* @param ci a compound interval that we want to spill
* @return a spill location that is valid to hold the contents of
* the compound interval
*/
SpillLocationInterval findOrCreateSpillLocation(CompoundInterval ci) {
SpillLocationInterval result = null;
Register r = ci.getRegister();
int type = GenericPhysicalRegisterSet.getPhysicalRegisterType(r);
int spillSize = ir.stackManager.getSpillSize(type);
// reuse. First look for the preferred interval.
if (ir.options.REGALLOC_COALESCE_SPILLS) {
result = getSpillPreference(ci, spillSize, type);
if (result != null) {
if (LinearScan.DEBUG_COALESCE) {
System.out.println("SPILL PREFERENCE " + ci + " " + result);
}
freeIntervals.remove(result);
}
}
// Now search for any free interval.
if (result == null) {
Iterator<SpillLocationInterval> iter = freeIntervals.iterator();
while (iter.hasNext()) {
SpillLocationInterval s = iter.next();
if (s.getSize() == spillSize && !s.intersects(ci) && s.getType() == type) {
result = s;
iter.remove();
break;
}
}
}
if (result == null) {
// Could not find an interval to reuse. Create a new interval.
int location = ir.stackManager.allocateNewSpillLocation(type);
result = new SpillLocationInterval(location, spillSize, type);
}
// Update the spill location interval to hold the new spill
result.addAll(ci);
return result;
}
Aggregations