/** *AsmallvariantofWegmanandZadeck'sSparseConditionalConstant *Propagationalgorithm.
*/ publicclass SCCP { /** Lattice values */ privatestaticfinalint TOP = 0; privatestaticfinalint CONSTANT = 1; privatestaticfinalint VARYING = 2; /** method we're processing */ privatefinal SsaMethod ssaMeth; /** ssaMeth.getRegCount() */ privatefinalint regCount; /** Lattice values for each SSA register */ privatefinalint[] latticeValues; /** For those registers that are constant, this is the constant value */ privatefinal Constant[] latticeConstants; /** Worklist of basic blocks to be processed */ privatefinal ArrayList<SsaBasicBlock> cfgWorklist; /** Worklist of executed basic blocks with phis to be processed */ privatefinal ArrayList<SsaBasicBlock> cfgPhiWorklist; /** Bitset containing bits for each block that has been found executable */ privatefinal BitSet executableBlocks; /** Worklist for SSA edges. This is a list of registers to process */ privatefinal ArrayList<SsaInsn> ssaWorklist; /** *WorklistforSSAedgesthatrepresentvaryingvalues.Itmakesthe *algorithmmuchfasterifyoumoveallvaluestoVARYINGasfastas *possible.
*/ privatefinal ArrayList<SsaInsn> varyingWorklist; /** Worklist of potential branches to convert to gotos */ privatefinal ArrayList<SsaInsn> branchWorklist;
private SCCP(SsaMethod ssaMeth) { this.ssaMeth = ssaMeth; this.regCount = ssaMeth.getRegCount(); this.latticeValues = newint[this.regCount]; this.latticeConstants = new Constant[this.regCount]; this.cfgWorklist = new ArrayList<SsaBasicBlock>(); this.cfgPhiWorklist = new ArrayList<SsaBasicBlock>(); this.executableBlocks = new BitSet(ssaMeth.getBlocks().size()); this.ssaWorklist = new ArrayList<SsaInsn>(); this.varyingWorklist = new ArrayList<SsaInsn>(); this.branchWorklist = new ArrayList<SsaInsn>(); for (int i = 0; i < this.regCount; i++) {
latticeValues[i] = TOP;
latticeConstants[i] = null;
}
}
/** *Performssparseconditionalconstantpropagationonamethod. *@paramssaMethodMethodtoprocess
*/ publicstaticvoid process (SsaMethod ssaMethod) { new SCCP(ssaMethod).run();
}
if (latticeValues[phiResultReg] == VARYING) { return;
}
RegisterSpecList sources = insn.getSources(); int phiResultValue = TOP;
Constant phiConstant = null; int sourceSize = sources.size();
for (int i = 0; i < sourceSize; i++) { int predBlockIndex = insn.predBlockIndexForSourcesIndex(i); int sourceReg = sources.get(i).getReg(); int sourceRegValue = latticeValues[sourceReg];
if (!executableBlocks.get(predBlockIndex)) { continue;
}
if (cA == null || cB == null) { //TODO handle a constant of 0 with MUL or AND returnnull;
}
switch (resultType) { case Type.BT_INT: int vR; boolean skip=false;
int vA = ((CstInteger) cA).getValue(); int vB = ((CstInteger) cB).getValue();
switch (opcode) { case RegOps.ADD:
vR = vA + vB; break; case RegOps.SUB: // 1 source for reverse sub, 2 sources for regular sub if (sources.size() == 1) {
vR = vB - vA;
} else {
vR = vA - vB;
} break; case RegOps.MUL:
vR = vA * vB; break; case RegOps.DIV: if (vB == 0) {
skip = true;
vR = 0; // just to hide a warning
} else {
vR = vA / vB;
} break; case RegOps.AND:
vR = vA & vB; break; case RegOps.OR:
vR = vA | vB; break; case RegOps.XOR:
vR = vA ^ vB; break; case RegOps.SHL:
vR = vA << vB; break; case RegOps.SHR:
vR = vA >> vB; break; case RegOps.USHR:
vR = vA >>> vB; break; case RegOps.REM: if (vB == 0) {
skip = true;
vR = 0; // just to hide a warning
} else {
vR = vA % vB;
} break; default: thrownew RuntimeException("Unexpected op");
}
int opcode = insn.getOpcode().getOpcode();
RegisterSpec result = insn.getResult();
if (result == null) { // Find move-result-pseudo result for int div and int rem if (opcode == RegOps.DIV || opcode == RegOps.REM) {
SsaBasicBlock succ = insn.getBlock().getPrimarySuccessor();
result = succ.getInsns().get(0).getResult();
} else { return;
}
}
int resultReg = result.getReg(); int resultValue = VARYING;
Constant resultConstant = null;
switch (opcode) { case RegOps.CONST: {
CstInsn cstInsn = (CstInsn)ropInsn;
resultValue = CONSTANT;
resultConstant = cstInsn.getConstant(); break;
} case RegOps.MOVE: { if (insn.getSources().size() == 1) { int sourceReg = insn.getSources().get(0).getReg();
resultValue = latticeValues[sourceReg];
resultConstant = latticeConstants[sourceReg];
} break;
} case RegOps.ADD: case RegOps.SUB: case RegOps.MUL: case RegOps.DIV: case RegOps.AND: case RegOps.OR: case RegOps.XOR: case RegOps.SHL: case RegOps.SHR: case RegOps.USHR: case RegOps.REM: {
resultConstant = simulateMath(insn, result.getBasicType()); if (resultConstant != null) {
resultValue = CONSTANT;
} break;
} case RegOps.MOVE_RESULT_PSEUDO: { if (latticeValues[resultReg] == CONSTANT) {
resultValue = latticeValues[resultReg];
resultConstant = latticeConstants[resultReg];
} break;
} // TODO: Handle non-int arithmetic. // TODO: Eliminate check casts that we can prove the type of. default: {}
} if (setLatticeValueTo(resultReg, resultValue, resultConstant)) {
addUsersToWorklist(resultReg, resultValue);
}
}
/** *ReplacesTypeBearersinsourceregisterspecswithconstanttype *bearersifpossible.Thesearethenreferencedinlateroptimization *steps.
*/ privatevoid replaceConstants() { for (int reg = 0; reg < regCount; reg++) { if (latticeValues[reg] != CONSTANT) { continue;
} if (!(latticeConstants[reg] instanceof TypedConstant)) { // We can't do much with these continue;
}
if (typeBearer.isConstant()) { /* *Thedefinitionwasaconstantalready. *Theusesshouldbeaswell.
*/ continue;
}
// Update the destination RegisterSpec with the constant value
RegisterSpec dest = defn.getResult();
RegisterSpec newDest
= dest.withType((TypedConstant)latticeConstants[reg]);
defn.setResult(newDest);
/* *UpdatethesourcesRegisterSpec'sofallnon-moveuses. *Thesewillbeusedinlatersteps.
*/ for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) { if (insn.isPhiOrMove()) { continue;
}
/** *Replacesbranchesthathaveconstantconditionswithgotos
*/ privatevoid replaceBranches() { for (SsaInsn insn : branchWorklist) { // Find if a successor block is never executed int oldSuccessor = -1;
SsaBasicBlock block = insn.getBlock(); int successorSize = block.getSuccessorList().size(); for (int i = 0; i < successorSize; i++) { int successorBlock = block.getSuccessorList().get(i); if (!executableBlocks.get(successorBlock)) {
oldSuccessor = successorBlock;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.