use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class SCCP method replaceConstants.
/**
* Replaces TypeBearers in source register specs with constant type
* bearers if possible. These are then referenced in later optimization
* steps.
*/
private void 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;
}
SsaInsn defn = ssaMeth.getDefinitionForRegister(reg);
TypeBearer typeBearer = defn.getResult().getTypeBearer();
if (typeBearer.isConstant()) {
/*
* The definition was a constant already.
* The uses should be as well.
*/
continue;
}
// Update the destination RegisterSpec with the constant value
RegisterSpec dest = defn.getResult();
RegisterSpec newDest = dest.withType((TypedConstant) latticeConstants[reg]);
defn.setResult(newDest);
/*
* Update the sources RegisterSpec's of all non-move uses.
* These will be used in later steps.
*/
for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
if (insn.isPhiOrMove()) {
continue;
}
NormalSsaInsn nInsn = (NormalSsaInsn) insn;
RegisterSpecList sources = insn.getSources();
int index = sources.indexOfRegister(reg);
RegisterSpec spec = sources.get(index);
RegisterSpec newSpec = spec.withType((TypedConstant) latticeConstants[reg]);
nInsn.changeOneSource(index, newSpec);
}
}
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class SsaBasicBlock method scheduleMovesFromPhis.
/**
* Sorts move instructions added via {@code addMoveToEnd} during
* phi removal so that results don't overwrite sources that are used.
* For use after all phis have been removed and all calls to
* addMoveToEnd() have been made.<p>
*
* This is necessary because copy-propogation may have left us in a state
* where the same basic block has the same register as a phi operand
* and a result. In this case, the register in the phi operand always
* refers value before any other phis have executed.
*/
public void scheduleMovesFromPhis() {
if (movesFromPhisAtBeginning > 1) {
List<SsaInsn> toSchedule;
toSchedule = insns.subList(0, movesFromPhisAtBeginning);
scheduleUseBeforeAssigned(toSchedule);
SsaInsn firstNonPhiMoveInsn = insns.get(movesFromPhisAtBeginning);
/*
* TODO: It's actually possible that this case never happens,
* because a move-exception block, having only one predecessor
* in SSA form, perhaps is never on a dominance frontier.
*/
if (firstNonPhiMoveInsn.isMoveException()) {
if (true) {
/*
* We've yet to observe this case, and if it can
* occur the code written to handle it probably
* does not work.
*/
throw new RuntimeException("Unexpected: moves from " + "phis before move-exception");
} else {
/*
* A move-exception insn must be placed first in this block
* We need to move it there, and deal with possible
* interference.
*/
boolean moveExceptionInterferes = false;
int moveExceptionResult = firstNonPhiMoveInsn.getResult().getReg();
/*
* Does the move-exception result reg interfere with the
* phi moves?
*/
for (SsaInsn insn : toSchedule) {
if (insn.isResultReg(moveExceptionResult) || insn.isRegASource(moveExceptionResult)) {
moveExceptionInterferes = true;
break;
}
}
if (!moveExceptionInterferes) {
// This is the easy case.
insns.remove(movesFromPhisAtBeginning);
insns.add(0, firstNonPhiMoveInsn);
} else {
/*
* We need to move the result to a spare reg
* and move it back.
*/
RegisterSpec originalResultSpec = firstNonPhiMoveInsn.getResult();
int spareRegister = parent.borrowSpareRegister(originalResultSpec.getCategory());
// We now move it to a spare register.
firstNonPhiMoveInsn.changeResultReg(spareRegister);
RegisterSpec tempSpec = firstNonPhiMoveInsn.getResult();
insns.add(0, firstNonPhiMoveInsn);
// And here we move it back.
NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(tempSpec.getType()), SourcePosition.NO_INFO, originalResultSpec, RegisterSpecList.make(tempSpec)), this);
/*
* Place it immediately after the phi-moves,
* overwriting the move-exception that was there.
*/
insns.set(movesFromPhisAtBeginning + 1, toAdd);
}
}
}
}
if (movesFromPhisAtEnd > 1) {
scheduleUseBeforeAssigned(insns.subList(insns.size() - movesFromPhisAtEnd - 1, insns.size() - 1));
}
// Return registers borrowed here and in scheduleUseBeforeAssigned().
parent.returnSpareRegisters();
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class SsaConverter method placePhiFunctions.
/**
* See Appel algorithm 19.6:
*
* Place Phi functions in appropriate locations.
*
* @param ssaMeth {@code non-null;} method to process.
* Modifications are made in-place.
* @param localInfo {@code non-null;} local variable info, used
* when placing phis
* @param threshold registers below this number are ignored
*/
private static void placePhiFunctions(SsaMethod ssaMeth, LocalVariableInfo localInfo, int threshold) {
ArrayList<SsaBasicBlock> ssaBlocks;
int regCount;
int blockCount;
ssaBlocks = ssaMeth.getBlocks();
blockCount = ssaBlocks.size();
regCount = ssaMeth.getRegCount() - threshold;
DomFront df = new DomFront(ssaMeth);
DomFront.DomInfo[] domInfos = df.run();
// Bit set of registers vs block index "definition sites"
BitSet[] defsites = new BitSet[regCount];
// Bit set of registers vs block index "phi placement sites"
BitSet[] phisites = new BitSet[regCount];
for (int i = 0; i < regCount; i++) {
defsites[i] = new BitSet(blockCount);
phisites[i] = new BitSet(blockCount);
}
/*
* For each register, build a set of all basic blocks where
* containing an assignment to that register.
*/
for (int bi = 0, s = ssaBlocks.size(); bi < s; bi++) {
SsaBasicBlock b = ssaBlocks.get(bi);
for (SsaInsn insn : b.getInsns()) {
RegisterSpec rs = insn.getResult();
if (rs != null && rs.getReg() - threshold >= 0) {
defsites[rs.getReg() - threshold].set(bi);
}
}
}
if (DEBUG) {
System.out.println("defsites");
for (int i = 0; i < regCount; i++) {
StringBuilder sb = new StringBuilder();
sb.append('v').append(i).append(": ");
sb.append(defsites[i].toString());
System.out.println(sb);
}
}
BitSet worklist;
/*
* For each register, compute all locations for phi placement
* based on dominance-frontier algorithm.
*/
for (int reg = 0, s = regCount; reg < s; reg++) {
int workBlockIndex;
/* Worklist set starts out with each node where reg is assigned. */
worklist = (BitSet) (defsites[reg].clone());
while (0 <= (workBlockIndex = worklist.nextSetBit(0))) {
worklist.clear(workBlockIndex);
IntIterator dfIterator = domInfos[workBlockIndex].dominanceFrontiers.iterator();
while (dfIterator.hasNext()) {
int dfBlockIndex = dfIterator.next();
if (!phisites[reg].get(dfBlockIndex)) {
phisites[reg].set(dfBlockIndex);
int tReg = reg + threshold;
RegisterSpec rs = localInfo.getStarts(dfBlockIndex).get(tReg);
if (rs == null) {
ssaBlocks.get(dfBlockIndex).addPhiInsnForReg(tReg);
} else {
ssaBlocks.get(dfBlockIndex).addPhiInsnForReg(rs);
}
if (!defsites[reg].get(dfBlockIndex)) {
worklist.set(dfBlockIndex);
}
}
}
}
}
if (DEBUG) {
System.out.println("phisites");
for (int i = 0; i < regCount; i++) {
StringBuilder sb = new StringBuilder();
sb.append('v').append(i).append(": ");
sb.append(phisites[i].toString());
System.out.println(sb);
}
}
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class SsaInsn method mapRegisters.
/**
* Map registers after register allocation.
*
* @param mapper {@code non-null;} mapping from old to new registers
*/
public final void mapRegisters(RegisterMapper mapper) {
RegisterSpec oldResult = result;
result = mapper.map(result);
block.getParent().updateOneDefinition(this, oldResult);
mapSourceRegisters(mapper);
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class LivenessAnalyzer method liveOutAtStatement.
/**
* "v is live-out at s."
*/
private void liveOutAtStatement() {
SsaInsn statement = blockN.getInsns().get(statementIndex);
RegisterSpec rs = statement.getResult();
if (!statement.isResultReg(regV)) {
if (rs != null) {
interference.add(regV, rs.getReg());
}
nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
}
}
Aggregations