use of com.taobao.android.dx.ssa.SsaBasicBlock in project atlas by alibaba.
the class SsaDumper method endParsingMember.
/** {@inheritDoc} */
@Override
public void endParsingMember(ByteArray bytes, int offset, String name, String descriptor, Member member) {
if (!(member instanceof Method)) {
return;
}
if (!shouldDumpMethod(name)) {
return;
}
if ((member.getAccessFlags() & (AccessFlags.ACC_ABSTRACT | AccessFlags.ACC_NATIVE)) != 0) {
return;
}
ConcreteMethod meth = new ConcreteMethod((Method) member, classFile, true, true);
TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
RopMethod rmeth = Ropper.convert(meth, advice, classFile.getMethods());
SsaMethod ssaMeth = null;
boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
int paramWidth = computeParamWidth(meth, isStatic);
if (args.ssaStep == null) {
ssaMeth = new Optimizer().debugNoRegisterAllocation(rmeth, paramWidth, isStatic, true, advice, EnumSet.allOf(Optimizer.OptionalStep.class));
} else if ("edge-split".equals(args.ssaStep)) {
ssaMeth = new Optimizer().debugEdgeSplit(rmeth, paramWidth, isStatic, true, advice);
} else if ("phi-placement".equals(args.ssaStep)) {
ssaMeth = new Optimizer().debugPhiPlacement(rmeth, paramWidth, isStatic, true, advice);
} else if ("renaming".equals(args.ssaStep)) {
ssaMeth = new Optimizer().debugRenaming(rmeth, paramWidth, isStatic, true, advice);
} else if ("dead-code".equals(args.ssaStep)) {
ssaMeth = new Optimizer().debugDeadCodeRemover(rmeth, paramWidth, isStatic, true, advice);
}
StringBuffer sb = new StringBuffer(2000);
sb.append("first ");
sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex())));
sb.append('\n');
ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
ArrayList<SsaBasicBlock> sortedBlocks = (ArrayList<SsaBasicBlock>) blocks.clone();
Collections.sort(sortedBlocks, SsaBasicBlock.LABEL_COMPARATOR);
for (SsaBasicBlock block : sortedBlocks) {
sb.append("block ").append(Hex.u2(block.getRopLabel())).append('\n');
BitSet preds = block.getPredecessors();
for (int i = preds.nextSetBit(0); i >= 0; i = preds.nextSetBit(i + 1)) {
sb.append(" pred ");
sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(i)));
sb.append('\n');
}
sb.append(" live in:" + block.getLiveInRegs());
sb.append("\n");
for (SsaInsn insn : block.getInsns()) {
sb.append(" ");
sb.append(insn.toHuman());
sb.append('\n');
}
if (block.getSuccessors().cardinality() == 0) {
sb.append(" returns\n");
} else {
int primary = block.getPrimarySuccessorRopLabel();
IntList succLabelList = block.getRopLabelSuccessorList();
int szSuccLabels = succLabelList.size();
for (int i = 0; i < szSuccLabels; i++) {
sb.append(" next ");
sb.append(Hex.u2(succLabelList.get(i)));
if (szSuccLabels != 1 && primary == succLabelList.get(i)) {
sb.append(" *");
}
sb.append('\n');
}
}
sb.append(" live out:" + block.getLiveOutRegs());
sb.append("\n");
}
suppressDump = false;
setAt(bytes, 0);
parsed(bytes, 0, bytes.size(), sb.toString());
suppressDump = true;
}
use of com.taobao.android.dx.ssa.SsaBasicBlock in project atlas by alibaba.
the class LivenessAnalyzer method coInterferePhis.
/**
* Ensures that all the phi result registers for all the phis in the
* same basic block interfere with each other. This is needed since
* the dead code remover has allowed through "dead-end phis" whose
* results are not used except as local assignments. Without this step,
* a the result of a dead-end phi might be assigned the same register
* as the result of another phi, and the phi removal move scheduler may
* generate moves that over-write the live result.
*
* @param ssaMeth {@code non-null;} method to pricess
* @param interference {@code non-null;} interference graph
*/
private static void coInterferePhis(SsaMethod ssaMeth, InterferenceGraph interference) {
for (SsaBasicBlock b : ssaMeth.getBlocks()) {
List<SsaInsn> phis = b.getPhiInsns();
int szPhis = phis.size();
for (int i = 0; i < szPhis; i++) {
for (int j = 0; j < szPhis; j++) {
if (i == j) {
continue;
}
interference.add(phis.get(i).getResult().getReg(), phis.get(j).getResult().getReg());
}
}
}
}
use of com.taobao.android.dx.ssa.SsaBasicBlock in project atlas by alibaba.
the class LivenessAnalyzer method run.
/**
* From Appel algorithm 19.17.
*/
public void run() {
List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);
for (SsaInsn insn : useList) {
nextFunction = NextFunction.DONE;
if (insn instanceof PhiInsn) {
// If s is a phi-function with V as it's ith argument.
PhiInsn phi = (PhiInsn) insn;
for (SsaBasicBlock pred : phi.predBlocksForReg(regV, ssaMeth)) {
blockN = pred;
nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
handleTailRecursion();
}
} else {
blockN = insn.getBlock();
statementIndex = blockN.getInsns().indexOf(insn);
if (statementIndex < 0) {
throw new RuntimeException("insn not found in it's own block");
}
nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
handleTailRecursion();
}
}
int nextLiveOutBlock;
while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
liveOutBlocks.clear(nextLiveOutBlock);
nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
handleTailRecursion();
}
}
use of com.taobao.android.dx.ssa.SsaBasicBlock in project atlas by alibaba.
the class SsaToRop method convertBasicBlocks.
/**
* @return rop-form basic block list
*/
private BasicBlockList convertBasicBlocks() {
ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
// Exit block may be null.
SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
ssaMeth.computeReachability();
int ropBlockCount = ssaMeth.getCountReachableBlocks();
// Don't count the exit block, if it exists and is reachable.
ropBlockCount -= (exitBlock != null && exitBlock.isReachable()) ? 1 : 0;
BasicBlockList result = new BasicBlockList(ropBlockCount);
// Convert all the reachable blocks except the exit block.
int ropBlockIndex = 0;
for (SsaBasicBlock b : blocks) {
if (b.isReachable() && b != exitBlock) {
result.set(ropBlockIndex++, convertBasicBlock(b));
}
}
// The exit block, which is discarded, must do nothing.
if (exitBlock != null && exitBlock.getInsns().size() != 0) {
throw new RuntimeException("Exit block must have no insns when leaving SSA form");
}
return result;
}
use of com.taobao.android.dx.ssa.SsaBasicBlock in project atlas by alibaba.
the class RegisterAllocator method insertMoveBefore.
/**
* Inserts a move instruction for a specified SSA register before a
* specified instruction, creating a new SSA register and adjusting the
* interference graph in the process. The insn currently must be the
* last insn in a block.
*
* @param insn {@code non-null;} insn to insert move before, must
* be last insn in block
* @param reg {@code non-null;} SSA register to duplicate
* @return {@code non-null;} spec of new SSA register created by move
*/
protected final RegisterSpec insertMoveBefore(SsaInsn insn, RegisterSpec reg) {
SsaBasicBlock block = insn.getBlock();
ArrayList<SsaInsn> insns = block.getInsns();
int insnIndex = insns.indexOf(insn);
if (insnIndex < 0) {
throw new IllegalArgumentException("specified insn is not in this block");
}
if (insnIndex != insns.size() - 1) {
/*
* Presently, the interference updater only works when
* adding before the last insn, and the last insn must have no
* result
*/
throw new IllegalArgumentException("Adding move here not supported:" + insn.toHuman());
}
/*
* Get new register and make new move instruction.
*/
// The new result must not have an associated local variable.
RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(), reg.getTypeBearer());
SsaInsn toAdd = SsaInsn.makeFromRop(new PlainInsn(Rops.opMove(newRegSpec.getType()), SourcePosition.NO_INFO, newRegSpec, RegisterSpecList.make(reg)), block);
insns.add(insnIndex, toAdd);
int newReg = newRegSpec.getReg();
/*
* Adjust interference graph based on what's live out of the current
* block and what's used by the final instruction.
*/
IntSet liveOut = block.getLiveOutRegs();
IntIterator liveOutIter = liveOut.iterator();
while (liveOutIter.hasNext()) {
interference.add(newReg, liveOutIter.next());
}
// Everything that's a source in the last insn interferes.
RegisterSpecList sources = insn.getSources();
int szSources = sources.size();
for (int i = 0; i < szSources; i++) {
interference.add(newReg, sources.get(i).getReg());
}
ssaMeth.onInsnsChanged();
return newRegSpec;
}
Aggregations