use of org.jikesrvm.compilers.opt.ir.BasicBlock in project JikesRVM by JikesRVM.
the class LiveAnalysis method printFinalLiveIntervals.
/**
* Prints the Final Live Intervals
* @param ir the IR
*/
private void printFinalLiveIntervals(IR ir) {
ir.printInstructions();
System.out.println();
System.out.println(" *+*+*+*+*+ Final Live Intervals for " + ir.method.getDeclaringClass() + "." + ir.method.getName());
for (BasicBlock block = ir.firstBasicBlockInCodeOrder(); block != null; block = block.nextBasicBlockInCodeOrder()) {
liveIntervals.printLiveIntervalList(block);
}
System.out.println(" *+*+*+*+*+ End Final Live Intervals");
System.out.println();
}
use of org.jikesrvm.compilers.opt.ir.BasicBlock 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.BasicBlock in project JikesRVM by JikesRVM.
the class LoopVersioning method getRegistersDefinedInLoop.
/**
* Get registers defined in the given loop. As we're in SSA form
* all register definitions must be unique.
* @param loop - the loop to examine
* @param registers - vector to which defined registers are added
* @param types list to which the register's types are added
* @param definingInstructions list to which the defining instructions for
* the registers are added
*/
private void getRegistersDefinedInLoop(AnnotatedLSTNode loop, ArrayList<Register> registers, ArrayList<TypeReference> types, ArrayList<Instruction> definingInstructions) {
Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
// can value escape
final boolean escapes = (block == loop.exit) || (ir.HIRInfo.dominatorTree.dominates(block, loop.exit));
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, block);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
Enumeration<Operand> operands = instruction.getDefs();
while (operands.hasMoreElements()) {
Operand operand = operands.nextElement();
if (operand.isRegister()) {
registers.add(operand.asRegister().getRegister());
types.add(operand.asRegister().getType());
if (escapes) {
definingInstructions.add(instruction);
} else {
definingInstructions.add(null);
}
}
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.BasicBlock 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.BasicBlock in project JikesRVM by JikesRVM.
the class LoopVersioning method getListOfChecksToEliminate.
/**
* Create a list of instructions to be eliminated
* @param loop the loop to examine
* @param instrToEliminate the instructions to remove
*/
private void getListOfChecksToEliminate(AnnotatedLSTNode loop, ArrayList<Instruction> instrToEliminate) {
ArrayList<Instruction> nullChecks = new ArrayList<Instruction>();
ArrayList<Instruction> oddBoundChecks = new ArrayList<Instruction>();
Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, block);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
if (NullCheck.conforms(instruction)) {
if (loop.isInvariant(NullCheck.getRef(instruction))) {
instrToEliminate.add(instruction);
nullChecks.add(instruction);
}
} else if (loop.isMonotonic() && BoundsCheck.conforms(instruction)) {
if (loop.isInvariant(BoundsCheck.getRef(instruction))) {
if (loop.isRelatedToIterator(BoundsCheck.getIndex(instruction))) {
if (loop.isInvariant(BoundsCheck.getGuard(instruction))) {
instrToEliminate.add(instruction);
} else {
// Null check isn't invariant but reference was, check
// null check will be eliminated at end of loop
oddBoundChecks.add(instruction);
}
}
}
}
}
}
// it will be in the optimized loop as we'll have eliminated it
for (Instruction oddBoundCheck : oddBoundChecks) {
Operand guard = BoundsCheck.getGuard(oddBoundCheck);
for (Instruction nullCheck : nullChecks) {
if (guard.similar(NullCheck.getGuardResult(nullCheck))) {
instrToEliminate.add(oddBoundCheck);
break;
}
}
}
}
Aggregations