use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class BURS_Helpers method LONG_STORE_addi.
protected final void LONG_STORE_addi(Instruction s, RegisterOperand def, RegisterOperand left, IntConstantOperand right, LocationOperand loc, Operand guard) {
if (VM.VerifyAssertions)
VM._assert(VM.BuildFor32Addr);
Register defHigh = def.getRegister();
Register defLow = regpool.getSecondReg(defHigh);
int imm = right.value;
if (VM.VerifyAssertions) {
VM._assert(imm < (0x8000 - 4));
}
Instruction inst = MIR_Store.create(PPC_STW, I(defHigh), left, IC(imm), loc, guard);
inst.copyPosition(s);
EMIT(inst);
if (loc != null) {
loc = (LocationOperand) loc.copy();
}
if (guard != null) {
guard = guard.copy();
}
inst = MIR_Store.create(PPC_STW, I(defLow), left.copyU2U(), IC(imm + 4), loc, guard);
inst.copyPosition(s);
EMIT(inst);
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class NormalizeConstants method perform.
/**
* Doit.
*
* @param ir IR to normalize
*/
public static void perform(IR ir) {
// This greatly reduces the number of cases we have to worry about below.
if (VM.VerifyAssertions)
VM._assert(ir.options.SIMPLIFY_INTEGER_OPS && ir.options.SIMPLIFY_LONG_OPS && ir.options.SIMPLIFY_REF_OPS);
for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
// STEP ONE: Get 'large' constants into a form that the PPC BURS rules
// are prepared to deal with.
// Constants can't appear as defs, so only scan the uses.
//
int numUses = s.getNumberOfUses();
if (numUses > 0) {
int numDefs = s.getNumberOfDefs();
for (int idx = numDefs; idx < numUses + numDefs; idx++) {
Operand use = s.getOperand(idx);
if (use != null) {
if (use instanceof ObjectConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(use.getType());
RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
ObjectConstantOperand oc = (ObjectConstantOperand) use;
Offset offset = oc.offset;
if (offset.isZero()) {
if (use instanceof StringConstantOperand) {
throw new OptimizingCompilerException("String constant w/o valid JTOC offset");
} else if (use instanceof ClassConstantOperand) {
throw new OptimizingCompilerException("Class constant w/o valid JTOC offset");
}
offset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(oc.value));
}
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof DoubleConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Double);
RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
DoubleConstantOperand dc = (DoubleConstantOperand) use;
Offset offset = dc.offset;
if (offset.isZero()) {
offset = Offset.fromIntSignExtend(Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value)));
}
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(DOUBLE_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof FloatConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Float);
RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
FloatConstantOperand fc = (FloatConstantOperand) use;
Offset offset = fc.offset;
if (offset.isZero()) {
offset = Offset.fromIntSignExtend(Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value)));
}
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(FLOAT_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof LongConstantOperand) {
if (!VM.BuildFor64Addr) {
if (s.getOpcode() != TRAP_IF_opcode) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Long);
s.insertBefore(Move.create(LONG_MOVE, rop, use.copy()));
s.putOperand(idx, rop.copyD2U());
}
}
} else if (use instanceof NullConstantOperand) {
s.putOperand(idx, AC(Address.zero()));
} else if (use instanceof TIBConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.JavaLangObjectArray);
Operand jtoc = ir.regpool.makeJTOCOp();
Offset offset = ((TIBConstantOperand) use).value.getTibOffset();
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof CodeConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.CodeArray);
Operand jtoc = ir.regpool.makeJTOCOp();
Offset offset = ((CodeConstantOperand) use).value.findOrCreateJtocOffset();
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
s.putOperand(idx, rop.copyD2U());
}
}
}
}
// Calling Simplifier.simplify ensures that the instruction is
// in normalized form. This reduces the number of cases we have to
// worry about (and does last minute constant folding on the off chance
// we've missed an opportunity...)
Simplifier.simplify(false, ir.regpool, ir.options, s);
switch(s.getOpcode()) {
// ////////
case REF_STORE_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_STORE : LONG_STORE);
// On PowerPC, the value being stored must be in a register
Store.setValue(s, asRegPolymorphic(Store.getClearValue(s), s, ir));
// Supported addressing modes are quite limited.
Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
break;
case BYTE_STORE_opcode:
case SHORT_STORE_opcode:
case INT_STORE_opcode:
case LONG_STORE_opcode:
// On PowerPC, the value being stored must be in a register
Store.setValue(s, asRegPolymorphic(Store.getClearValue(s), s, ir));
// Supported addressing modes are quite limited.
Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
break;
case FLOAT_STORE_opcode:
case DOUBLE_STORE_opcode:
// Supported addressing modes are quite limited.
Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
break;
case REF_LOAD_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD);
// Supported addressing modes are quite limited.
Load.setAddress(s, asRegAddress(Load.getClearAddress(s), s, ir));
Load.setOffset(s, asImmediateOrRegOffset(Load.getClearOffset(s), s, ir, true));
break;
case BYTE_LOAD_opcode:
case UBYTE_LOAD_opcode:
case SHORT_LOAD_opcode:
case USHORT_LOAD_opcode:
case INT_LOAD_opcode:
case LONG_LOAD_opcode:
case FLOAT_LOAD_opcode:
case DOUBLE_LOAD_opcode:
// Supported addressing modes are quite limited.
Load.setAddress(s, asRegAddress(Load.getClearAddress(s), s, ir));
Load.setOffset(s, asImmediateOrRegOffset(Load.getClearOffset(s), s, ir, true));
break;
case ATTEMPT_INT_opcode:
case ATTEMPT_LONG_opcode:
case ATTEMPT_ADDR_opcode:
// On PowerPC, the value being stored must be in a register
Attempt.setNewValue(s, asRegPolymorphic(Attempt.getClearNewValue(s), s, ir));
// not used on powerpc.
Attempt.setOldValue(s, null);
// Supported addressing modes are quite limited.
Attempt.setAddress(s, asRegAddress(Attempt.getClearAddress(s), s, ir));
Attempt.setOffset(s, asRegOffset(Attempt.getClearOffset(s), s, ir));
break;
case PREPARE_INT_opcode:
case PREPARE_LONG_opcode:
case PREPARE_ADDR_opcode:
// Supported addressing modes are quite limited.
Prepare.setAddress(s, asRegAddress(Prepare.getClearAddress(s), s, ir));
Prepare.setOffset(s, asRegOffset(Prepare.getClearOffset(s), s, ir));
break;
case LONG_MOVE_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_MOVE);
}
break;
case INT_MOVE_opcode:
s.changeOperatorTo(REF_MOVE);
break;
case REF_COND_MOVE_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_COND_MOVE : LONG_COND_MOVE);
break;
case REF_IFCMP_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_IFCMP : LONG_IFCMP);
// val1 can't be a constant, val2 must be small enough.
IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
case LONG_IFCMP_opcode:
if (VM.BuildFor64Addr) {
// val1 can't be a constant, val2 must be small enough.
IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
}
break;
case INT_IFCMP_opcode:
// val1 can't be a constant, val2 must be small enough.
IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
break;
case INT_IFCMP2_opcode:
// val1 can't be a constant, val2 must be small enough.
IfCmp2.setVal1(s, asRegInt(IfCmp2.getClearVal1(s), s, ir));
IfCmp2.setVal2(s, asImmediateOrRegInt(IfCmp2.getClearVal2(s), s, ir, true));
break;
case BOOLEAN_CMP_INT_opcode:
case BOOLEAN_CMP_ADDR_opcode:
// val2 must be small enough.
BooleanCmp.setVal2(s, asImmediateOrRegPolymorphic(BooleanCmp.getClearVal2(s), s, ir, !BooleanCmp.getCond(s).isUNSIGNED()));
break;
case LONG_CMP_opcode:
Binary.setVal1(s, asRegPolymorphic(Binary.getVal1(s), s, ir));
Binary.setVal2(s, asRegPolymorphic(Binary.getVal2(s), s, ir));
break;
case LONG_ADD_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_ADD);
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
}
break;
case INT_ADD_opcode:
s.changeOperatorTo(REF_ADD);
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
break;
case REF_ADD_opcode:
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
break;
case LONG_SUB_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_SUB);
Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
// val2 isn't be constant (if it were, Simplifier would have
// converted this into an ADD of -Val2).
}
break;
case INT_SUB_opcode:
s.changeOperatorTo(REF_SUB);
Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
// converted this into an ADD of -Val2).
break;
case REF_SUB_opcode:
Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
// converted this into an ADD of -Val2).
break;
case INT_MUL_opcode:
Binary.setVal2(s, asImmediateOrRegInt(Binary.getClearVal2(s), s, ir, true));
break;
case LONG_MUL_opcode:
if (VM.BuildFor64Addr) {
Binary.setVal2(s, asImmediateOrRegLong(Binary.getClearVal2(s), s, ir, true));
}
break;
// seem to expect constant operands at all.
case INT_REM_opcode:
case INT_DIV_opcode:
GuardedBinary.setVal1(s, asRegInt(GuardedBinary.getClearVal1(s), s, ir));
GuardedBinary.setVal2(s, asRegInt(GuardedBinary.getClearVal2(s), s, ir));
break;
case LONG_REM_opcode:
case LONG_DIV_opcode:
if (VM.BuildFor64Addr) {
GuardedBinary.setVal1(s, asRegLong(GuardedBinary.getClearVal1(s), s, ir));
GuardedBinary.setVal2(s, asRegLong(GuardedBinary.getClearVal2(s), s, ir));
}
break;
case LONG_NEG_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_NEG);
}
break;
case INT_NEG_opcode:
s.changeOperatorTo(REF_NEG);
break;
case LONG_NOT_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_NOT);
}
break;
case INT_NOT_opcode:
s.changeOperatorTo(REF_NOT);
break;
case LONG_AND_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_AND);
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
}
break;
case INT_AND_opcode:
s.changeOperatorTo(REF_AND);
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
break;
case REF_AND_opcode:
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
break;
case LONG_OR_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_OR);
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
}
break;
case INT_OR_opcode:
s.changeOperatorTo(REF_OR);
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
break;
case REF_OR_opcode:
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
break;
case LONG_XOR_opcode:
if (VM.BuildFor64Addr) {
s.changeOperatorTo(REF_XOR);
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
}
break;
case INT_XOR_opcode:
s.changeOperatorTo(REF_XOR);
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
break;
case REF_XOR_opcode:
// unsigned immediate
Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
break;
case REF_SHL_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHL : LONG_SHL);
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
break;
case LONG_SHL_opcode:
if (VM.BuildFor64Addr) {
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
}
break;
case INT_SHL_opcode:
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
break;
case REF_SHR_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHR : LONG_SHR);
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
break;
case LONG_SHR_opcode:
if (VM.BuildFor64Addr) {
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
}
break;
case INT_SHR_opcode:
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
break;
case REF_USHR_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_USHR : LONG_USHR);
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
break;
case LONG_USHR_opcode:
if (VM.BuildFor64Addr) {
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
}
break;
case INT_USHR_opcode:
// Val2 could be a constant, but Val1 apparently can't be.
Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
break;
// Deal with Simplifier.CF_FLOAT or Simplifier.CF_DOUBLE being false
case INT_2DOUBLE_opcode:
case INT_2FLOAT_opcode:
case INT_BITS_AS_FLOAT_opcode:
Unary.setVal(s, asRegInt(Unary.getVal(s), s, ir));
break;
case ADDR_2INT_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? REF_MOVE : LONG_2INT);
break;
case ADDR_2LONG_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? INT_2LONG : REF_MOVE);
break;
case INT_2ADDRSigExt_opcode:
s.changeOperatorTo(VM.BuildFor32Addr ? REF_MOVE : INT_2LONG);
break;
case INT_2ADDRZerExt_opcode:
if (VM.BuildFor32Addr) {
s.changeOperatorTo(REF_MOVE);
}
break;
case LONG_2ADDR_opcode:
s.changeOperatorTo(VM.BuildFor64Addr ? REF_MOVE : LONG_2INT);
break;
case NULL_CHECK_opcode:
NullCheck.setRef(s, asRegAddress(NullCheck.getClearRef(s), s, ir));
break;
// Force all call parameters to be in registers
case SYSCALL_opcode:
case CALL_opcode:
{
int numArgs = Call.getNumberOfParams(s);
for (int i = 0; i < numArgs; i++) {
Call.setParam(s, i, asRegPolymorphic(Call.getClearParam(s, i), s, ir));
}
}
break;
case RETURN_opcode:
if (Return.hasVal(s)) {
Return.setVal(s, asRegPolymorphic(Return.getClearVal(s), s, ir));
}
break;
}
}
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class LiveAnalysis method getLiveRegistersOnEntry.
/**
* @param bb the basic block we're interested in
* @return the set of registers that are live across a basic block, and who
* are live before the basic block entry.
*/
HashSet<Register> getLiveRegistersOnEntry(BasicBlock bb) {
HashSet<Register> result = new HashSet<Register>(10);
for (Enumeration<LiveIntervalElement> e = liveIntervals.enumerateLiveIntervals(bb); e.hasMoreElements(); ) {
LiveIntervalElement lie = e.nextElement();
Instruction begin = lie.getBegin();
if (begin == null)
result.add(lie.getRegister());
}
return result;
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class LiveAnalysis method getLiveRegistersOnExit.
/**
* @param bb the basic block we're interested in
* @return the set of registers that are live across a basic block, and who
* are live after the basic block exit.
*/
HashSet<Register> getLiveRegistersOnExit(BasicBlock bb) {
HashSet<Register> result = new HashSet<Register>(10);
for (Enumeration<LiveIntervalElement> e = liveIntervals.enumerateLiveIntervals(bb); e.hasMoreElements(); ) {
LiveIntervalElement lie = e.nextElement();
Instruction end = lie.getEnd();
if (end == null)
result.add(lie.getRegister());
}
return result;
}
use of org.jikesrvm.compilers.opt.ir.Instruction 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");
}
}
Aggregations