use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class LiveAnalysis method collectOsrInfo.
/* collect osr info according to live information */
private void collectOsrInfo(Instruction inst, LiveSet lives) {
// create an entry to the OSRIRMap, order: callee => caller
LinkedList<MethodVariables> mvarList = new LinkedList<MethodVariables>();
// get the type info for locals and stacks
InlinedOsrTypeInfoOperand typeInfo = OsrPoint.getInlinedTypeInfo(inst);
/* iterator over type info and create LocalRegTuple
* for each variable.
* NOTE: we do not process LONG type register operand here,
* which was splitted in BURS.
*/
byte[][] ltypes = typeInfo.localTypeCodes;
byte[][] stypes = typeInfo.stackTypeCodes;
int nummeth = typeInfo.methodids.length;
int elm_idx = 0;
int snd_long_idx = typeInfo.validOps;
for (int midx = 0; midx < nummeth; midx++) {
LinkedList<LocalRegPair> tupleList = new LinkedList<LocalRegPair>();
byte[] ls = ltypes[midx];
byte[] ss = stypes[midx];
/* record maps for local variables, skip dead ones */
for (int i = 0, n = ls.length; i < n; i++) {
if (ls[i] != VoidTypeCode) {
// check liveness
Operand op = OsrPoint.getElement(inst, elm_idx++);
LocalRegPair tuple = new LocalRegPair(LOCAL, i, ls[i], op);
// put it in the list
tupleList.add(tuple);
// get another half of a long type operand
if (VM.BuildFor32Addr && (ls[i] == LongTypeCode)) {
Operand other_op = OsrPoint.getElement(inst, snd_long_idx++);
tuple._otherHalf = new LocalRegPair(LOCAL, i, ls[i], other_op);
}
}
}
/* record maps for stack slots */
for (int i = 0, n = ss.length; i < n; i++) {
if (ss[i] != VoidTypeCode) {
LocalRegPair tuple = new LocalRegPair(STACK, i, ss[i], OsrPoint.getElement(inst, elm_idx++));
tupleList.add(tuple);
if (VM.BuildFor32Addr && (ss[i] == LongTypeCode)) {
tuple._otherHalf = new LocalRegPair(STACK, i, ss[i], OsrPoint.getElement(inst, snd_long_idx++));
}
}
}
// create MethodVariables
MethodVariables mvar = new MethodVariables(typeInfo.methodids[midx], typeInfo.bcindexes[midx], tupleList);
mvarList.add(mvar);
}
// put the method variables for this OSR in the osrMap, encoding later.
osrMap.insertFirst(inst, mvarList);
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class LiveAnalysis method computeBlockGenAndKill.
/**
* Compute summary (local) live variable analysis for a basic block, which
* is basically Gen and Kill information.<p>
*
* For more details, see the paper "Efficient and Precise Modeling of
* Exceptions for the Analysis of Java Programs" by Choi, Grove, Hind
* and Sarkar in ACM PASTE99 workshop.
*
* @param bblock the basic block
* @param ir the governing IR
*/
private void computeBlockGenAndKill(BasicBlock bblock, IR ir) {
if (VERBOSE) {
System.out.println(" --> Computing Gen/Kill for block " + bblock);
}
// Tells whether we've seen the first PEI
boolean seenFirstPEI = false;
// Because control flow may emanate from a potentially excepting
// instruction (PEI) out of the basic block, care must be taken
// when computing what can be killed by a basic block.
//
// S1: y =
// S2: <exception-raising inst>
// S3: x =
// For example in the block above, live variables coming from
// the normal exit of the block (i.e., after S3) can be killed
// by S1 or S3 (depending on the variable). However, live variables
// coming from the PEI edge (at S2) can only be killed by S1.
// Thus, when a block contains PEIs, we need to distinguish the
// kill sets. Namely, we need
// Kill_tot - what can be killed anywhere in the block
// Kill_n - what can be killed from PEI_n on up
// Kill_n-1 - what can be killed from PEI_n-1 on up
// ...
// Kill_1 - what can be killed from PEI_1 on up
// We would then compute In as follows
//
// In = Out_norm - Kill_tot (all vars entering from bottom are eligible
// to be killed)
// U Out_n - Kill_n
// U Out_n-1 - Kill_n-1
// ...
// U Out_1 - Kill_1
// U Gen
// where Out_n is the out information at PEI i, i.e., the IN information
// for whatever handlers may catch PEI i
// ...
// PEI 1
// ...
// PEI n-1
// ...
// PEI n
// ...
// If we conservatively assume all handlers for the block of interest
// can be reached by all PEIs in this block then the equation becomes
// In = (Out_norm - Kill_tot)
// U (Out_hand - Kill_n)
// U (Out_hand - Kill_n-1)
// ...
// U (Out_hand - Kill_1)
// U Gen
// where "Out_hand" is the union of the in sets for all handlers.
// Since Kill_i is a subset of Kill_j, for i < j, we can simplify to
// In = (Out_norm - Kill_tot)
// U (Out_hand - Kill_1) (1)
// U Gen
// Since kill_1 is a subset of kill_tot, we don't need the
// the parenthesis (and the intermediate set)
// If there are no handlers than (1) is empty and we don't need
// to compute Kill_1. We will take this approach for now.
// So for each block we will have at most 2 kill sets: Kill_tot and Kill_1
// This code finds the first PEI in the block
Instruction firstPEI = null;
if (bblock.canThrowExceptions()) {
for (Instruction inst = bblock.firstInstruction(); inst != bblock.lastInstruction(); inst = inst.nextInstructionInCodeOrder()) {
if (inst.isPEI() && bblock.getApplicableExceptionalOut(inst).hasMoreElements()) {
firstPEI = inst;
// remember that this block has a PEI with a handler for use
// later in "processBlock"
bbLiveInfo[bblock.getNumber()].setContainsPEIWithHandler(true);
break;
}
}
}
// Get any uses from PHIs, which are in the successor blocks
getUsesFromPhis(bblock);
// Traverse instructions in reverse order within the basic block.
for (Instruction inst = bblock.lastInstruction(); inst != bblock.firstInstruction(); inst = inst.prevInstructionInCodeOrder()) {
// traverse from defs to uses becauses uses happen after
// (in a backward sense) defs
Enumeration<Operand> defs = inst.getPureDefs();
while (defs.hasMoreElements()) {
Operand def = defs.nextElement();
if (def instanceof RegisterOperand) {
RegisterOperand regOp = (RegisterOperand) def;
// Do we care about this reg?
if (isSkippableReg(regOp, ir)) {
continue;
}
TypeReference regType = regOp.getType();
// include it. It will be picked up later by local propagation phase.
if (regOp.getRegister().spansBasicBlock() && regType != null) {
// if it is a DEF we place it is the BBKillSet and remove it from
// the GEN set, (GEN should only contain upward-exposed uses,
// i.e., uses that are NOT dominated by a DEF).
// We don't need to worry about PEIs here because
// later instructions (traversing backwards like we are)
// will always dominate earlier instructions *of this block*
bbLiveInfo[bblock.getNumber()].BBKillSet().add(regOp);
bbLiveInfo[bblock.getNumber()].getGen().remove(regOp);
// If there are no PEIs in this block we don't bother to add
if (seenFirstPEI) {
bbLiveInfo[bblock.getNumber()].firstPEIKillSet().add(regOp);
}
}
}
}
// Now process the uses, unless this is a PHI operator
if (inst.operator() != PHI) {
for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements(); ) {
Operand use = uses.nextElement();
if (use instanceof RegisterOperand) {
RegisterOperand regOp = (RegisterOperand) use;
// Do we care about this reg?
if (isSkippableReg(regOp, ir)) {
continue;
}
TypeReference regType = regOp.getType();
// later by local propagation phase.
if (regOp.getRegister().spansBasicBlock() && regType != null) {
bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
}
}
// is RegOp
}
// foreach use
}
// If so, set the flag so we can start killing.
if (firstPEI == inst) {
seenFirstPEI = true;
}
}
// foreach instruction in block
if (VERBOSE) {
System.out.println(" Gen: " + bbLiveInfo[bblock.getNumber()].getGen());
System.out.println(" Kill: " + bbLiveInfo[bblock.getNumber()].BBKillSet());
System.out.println(" 1st PEI Kill: " + bbLiveInfo[bblock.getNumber()].firstPEIKillSet());
System.out.println(" ---> Done computing Gen/Kill for block");
}
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand 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.operand.Operand 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.operand.Operand in project JikesRVM by JikesRVM.
the class LoopVersioning method getConstantAdjustedArrayLengthDistance.
/**
* Get the distance from an array length by addding up instructions
* that adjust the array length result by a constant amount
*
* @param op operand to chase arraylength opcode to
* @return the array length as defined above
*/
private int getConstantAdjustedArrayLengthDistance(Operand op) {
Instruction opInstr = AnnotatedLSTNode.definingInstruction(op);
if (opInstr.getOpcode() == ARRAYLENGTH_opcode) {
return 0;
} else if (opInstr.getOpcode() == INT_ADD_opcode) {
Operand val1 = Binary.getVal1(opInstr);
Operand val2 = Binary.getVal2(opInstr);
if (val1.isConstant()) {
return val1.asIntConstant().value + getConstantAdjustedArrayLengthDistance(val2);
} else {
if (VM.VerifyAssertions)
VM._assert(val2.isConstant());
return getConstantAdjustedArrayLengthDistance(val1) + val2.asIntConstant().value;
}
} else if (opInstr.getOpcode() == INT_SUB_opcode) {
Operand val1 = Binary.getVal1(opInstr);
Operand val2 = Binary.getVal2(opInstr);
if (val1.isConstant()) {
return val1.asIntConstant().value - getConstantAdjustedArrayLengthDistance(val2);
} else {
if (VM.VerifyAssertions)
VM._assert(val2.isConstant());
return getConstantAdjustedArrayLengthDistance(val1) - val2.asIntConstant().value;
}
} else {
throw new Error("Unexpected opcode when computing distance " + op);
}
}
Aggregations