use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class LiteralOpUpgrader method tryReplacingWithConstant.
/**
* Tries to replace an instruction with a const instruction. The given
* instruction must have a constant result for it to be replaced.
*
* @param insn {@code non-null;} instruction to try to replace
* @return true if the instruction was replaced
*/
private boolean tryReplacingWithConstant(NormalSsaInsn insn) {
Insn originalRopInsn = insn.getOriginalRopInsn();
Rop opcode = originalRopInsn.getOpcode();
RegisterSpec result = insn.getResult();
if (result != null && !ssaMeth.isRegALocal(result) && opcode.getOpcode() != RegOps.CONST) {
TypeBearer type = insn.getResult().getTypeBearer();
if (type.isConstant() && type.getBasicType() == Type.BT_INT) {
// Replace the instruction with a constant
replacePlainInsn(insn, RegisterSpecList.EMPTY, RegOps.CONST, (Constant) type);
// Remove the source as well if this is a move-result-pseudo
if (opcode.getOpcode() == RegOps.MOVE_RESULT_PSEUDO) {
int pred = insn.getBlock().getPredecessors().nextSetBit(0);
ArrayList<SsaInsn> predInsns = ssaMeth.getBlocks().get(pred).getInsns();
NormalSsaInsn sourceInsn = (NormalSsaInsn) predInsns.get(predInsns.size() - 1);
replacePlainInsn(sourceInsn, RegisterSpecList.EMPTY, RegOps.GOTO, null);
}
return true;
}
}
return false;
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class SsaBasicBlock method scheduleUseBeforeAssigned.
/**
* Ensures that all move operations in this block occur such that
* reads of any register happen before writes to that register.
* NOTE: caller is expected to returnSpareRegisters()!
*
* TODO: See Briggs, et al "Practical Improvements to the Construction and
* Destruction of Static Single Assignment Form" section 5. a) This can
* be done in three passes.
*
* @param toSchedule List of instructions. Must consist only of moves.
*/
private void scheduleUseBeforeAssigned(List<SsaInsn> toSchedule) {
BitSet regsUsedAsSources = new BitSet(parent.getRegCount());
// TODO: Get rid of this.
BitSet regsUsedAsResults = new BitSet(parent.getRegCount());
int sz = toSchedule.size();
int insertPlace = 0;
while (insertPlace < sz) {
int oldInsertPlace = insertPlace;
// Record all registers used as sources in this block.
for (int i = insertPlace; i < sz; i++) {
setRegsUsed(regsUsedAsSources, toSchedule.get(i).getSources().get(0));
setRegsUsed(regsUsedAsResults, toSchedule.get(i).getResult());
}
/*
* If there are no circular dependencies, then there exists
* n instructions where n > 1 whose result is not used as a source.
*/
for (int i = insertPlace; i < sz; i++) {
SsaInsn insn = toSchedule.get(i);
/*
* Move these n registers to the front, since they overwrite
* nothing.
*/
if (!checkRegUsed(regsUsedAsSources, insn.getResult())) {
Collections.swap(toSchedule, i, insertPlace++);
}
}
/*
* If we've made no progress in this iteration, there's a
* circular dependency. Split it using the temp reg.
*/
if (oldInsertPlace == insertPlace) {
SsaInsn insnToSplit = null;
// Find an insn whose result is used as a source.
for (int i = insertPlace; i < sz; i++) {
SsaInsn insn = toSchedule.get(i);
if (checkRegUsed(regsUsedAsSources, insn.getResult()) && checkRegUsed(regsUsedAsResults, insn.getSources().get(0))) {
insnToSplit = insn;
/*
* We're going to split this insn; move it to the
* front.
*/
Collections.swap(toSchedule, insertPlace, i);
break;
}
}
// At least one insn will be set above.
RegisterSpec result = insnToSplit.getResult();
RegisterSpec tempSpec = result.withReg(parent.borrowSpareRegister(result.getCategory()));
NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, tempSpec, insnToSplit.getSources()), this);
toSchedule.add(insertPlace++, toAdd);
RegisterSpecList newSources = RegisterSpecList.make(tempSpec);
NormalSsaInsn toReplace = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, newSources), this);
toSchedule.set(insertPlace, toReplace);
// The size changed.
sz = toSchedule.size();
}
regsUsedAsSources.clear();
regsUsedAsResults.clear();
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class NormalSsaInsn method getLocalAssignment.
/** {@inheritDoc} */
@Override
public RegisterSpec getLocalAssignment() {
RegisterSpec assignment;
if (insn.getOpcode().getOpcode() == RegOps.MARK_LOCAL) {
assignment = insn.getSources().get(0);
} else {
assignment = getResult();
}
if (assignment == null) {
return null;
}
LocalItem local = assignment.getLocalItem();
if (local == null) {
return null;
}
return assignment;
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class PhiTypeResolver method resolveResultType.
/**
* Resolves the result of a phi insn based on its operands. The "void"
* type, which is a nonsensical type for a register, is used for
* registers defined by as-of-yet-unresolved phi operations.
*
* @return true if the result type changed, false if no change
*/
boolean resolveResultType(PhiInsn insn) {
insn.updateSourcesToDefinitions(ssaMeth);
RegisterSpecList sources = insn.getSources();
// Start by finding the first non-void operand
RegisterSpec first = null;
int firstIndex = -1;
int szSources = sources.size();
for (int i = 0; i < szSources; i++) {
RegisterSpec rs = sources.get(i);
if (rs.getBasicType() != Type.BT_VOID) {
first = rs;
firstIndex = i;
}
}
if (first == null) {
// All operands are void -- we're not ready to resolve yet
return false;
}
LocalItem firstLocal = first.getLocalItem();
TypeBearer mergedType = first.getType();
boolean sameLocals = true;
for (int i = 0; i < szSources; i++) {
if (i == firstIndex) {
continue;
}
RegisterSpec rs = sources.get(i);
// Just skip void (unresolved phi results) for now
if (rs.getBasicType() == Type.BT_VOID) {
continue;
}
sameLocals = sameLocals && equalsHandlesNulls(firstLocal, rs.getLocalItem());
mergedType = Merger.mergeType(mergedType, rs.getType());
}
TypeBearer newResultType;
if (mergedType != null) {
newResultType = mergedType;
} else {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < szSources; i++) {
sb.append(sources.get(i).toString());
sb.append(' ');
}
throw new RuntimeException("Couldn't map types in phi insn:" + sb);
}
LocalItem newLocal = sameLocals ? firstLocal : null;
RegisterSpec result = insn.getResult();
if ((result.getTypeBearer() == newResultType) && equalsHandlesNulls(newLocal, result.getLocalItem())) {
return false;
}
insn.changeResultType(newResultType, newLocal);
return true;
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class HighRegisterPrefix method calculateInsnsIfNecessary.
/**
* Helper for {@link #codeSize} and {@link #writeTo} which sets up
* {@link #insns} if not already done.
*/
private void calculateInsnsIfNecessary() {
if (insns != null) {
return;
}
RegisterSpecList registers = getRegisters();
int sz = registers.size();
insns = new SimpleInsn[sz];
for (int i = 0, outAt = 0; i < sz; i++) {
RegisterSpec src = registers.get(i);
insns[i] = moveInsnFor(src, outAt);
outAt += src.getCategory();
}
}
Aggregations