use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.
the class SCCP method replaceBranches.
/**
* Replaces branches that have constant conditions with gotos
*/
private void 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;
}
}
/*
* Prune branches that have already been handled and ones that no
* longer have constant conditions (no nonexecutable successors)
*/
if (successorSize != 2 || oldSuccessor == -1)
continue;
// Replace branch with goto
Insn originalRopInsn = insn.getOriginalRopInsn();
block.replaceLastInsn(new PlainInsn(Rops.GOTO, originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
block.removeSuccessor(oldSuccessor);
}
}
use of com.taobao.android.dx.rop.code.PlainInsn 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.PlainInsn in project atlas by alibaba.
the class SsaBasicBlock method addMoveToBeginning.
/**
* Adds a move instruction after the phi insn block.
*
* @param result move destination
* @param source move source
*/
public void addMoveToBeginning(RegisterSpec result, RegisterSpec source) {
if (result.getReg() == source.getReg()) {
// Sometimes we end up with no-op moves. Ignore them here.
return;
}
RegisterSpecList sources = RegisterSpecList.make(source);
NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, sources), this);
insns.add(getCountPhiInsns(), toAdd);
movesFromPhisAtBeginning++;
}
use of com.taobao.android.dx.rop.code.PlainInsn 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;
}
use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.
the class Ropper method addSetupBlocks.
/**
* Constructs and adds the blocks that perform setup for the rest of
* the method. This includes a first block which merely contains
* assignments from parameters to the same-numbered registers and
* a possible second block which deals with synchronization.
*/
private void addSetupBlocks() {
LocalVariableList localVariables = method.getLocalVariables();
SourcePosition pos = method.makeSourcePosistion(0);
Prototype desc = method.getEffectiveDescriptor();
StdTypeList params = desc.getParameterTypes();
int sz = params.size();
InsnList insns = new InsnList(sz + 1);
int at = 0;
for (int i = 0; i < sz; i++) {
Type one = params.get(i);
LocalVariableList.Item local = localVariables.pcAndIndexToLocal(0, at);
RegisterSpec result = (local == null) ? RegisterSpec.make(at, one) : RegisterSpec.makeLocalOptional(at, one, local.getLocalItem());
Insn insn = new PlainCstInsn(Rops.opMoveParam(one), pos, result, RegisterSpecList.EMPTY, CstInteger.make(at));
insns.set(i, insn);
at += one.getCategory();
}
insns.set(sz, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
insns.setImmutable();
boolean synch = isSynchronized();
int label = synch ? getSpecialLabel(SYNCH_SETUP_1) : 0;
BasicBlock bb = new BasicBlock(getSpecialLabel(PARAM_ASSIGNMENT), insns, IntList.makeImmutable(label), label);
addBlock(bb, IntList.EMPTY);
if (synch) {
RegisterSpec synchReg = getSynchReg();
Insn insn;
if (isStatic()) {
insn = new ThrowingCstInsn(Rops.CONST_OBJECT, pos, RegisterSpecList.EMPTY, StdTypeList.EMPTY, method.getDefiningClass());
insns = new InsnList(1);
insns.set(0, insn);
} else {
insns = new InsnList(2);
insn = new PlainCstInsn(Rops.MOVE_PARAM_OBJECT, pos, synchReg, RegisterSpecList.EMPTY, CstInteger.VALUE_0);
insns.set(0, insn);
insns.set(1, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
}
int label2 = getSpecialLabel(SYNCH_SETUP_2);
insns.setImmutable();
bb = new BasicBlock(label, insns, IntList.makeImmutable(label2), label2);
addBlock(bb, IntList.EMPTY);
insns = new InsnList(isStatic() ? 2 : 1);
if (isStatic()) {
insns.set(0, new PlainInsn(Rops.opMoveResultPseudo(synchReg), pos, synchReg, RegisterSpecList.EMPTY));
}
insn = new ThrowingInsn(Rops.MONITOR_ENTER, pos, RegisterSpecList.make(synchReg), StdTypeList.EMPTY);
insns.set(isStatic() ? 1 : 0, insn);
insns.setImmutable();
bb = new BasicBlock(label2, insns, IntList.makeImmutable(0), 0);
addBlock(bb, IntList.EMPTY);
}
}
Aggregations