use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class EscapeAnalysis method replaceDef.
/**
* Replaces the instructions that define an array with equivalent registers.
* For each entry in the array, a register is created, initialized to zero.
* A mapping between this register and the corresponding array index is
* added.
*
* @param def {@code non-null;} move result instruction for array
* @param prev {@code non-null;} instruction for instantiating new array
* @param length size of the new array
* @param newRegs {@code non-null;} mapping of array indices to new
* registers to be populated
*/
private void replaceDef(SsaInsn def, SsaInsn prev, int length, ArrayList<RegisterSpec> newRegs) {
Type resultType = def.getResult().getType();
// Create new zeroed out registers for each element in the array
for (int i = 0; i < length; i++) {
Constant newZero = Zeroes.zeroFor(resultType.getComponentType());
TypedConstant typedZero = (TypedConstant) newZero;
RegisterSpec newReg = RegisterSpec.make(ssaMeth.makeNewSsaReg(), typedZero);
newRegs.add(newReg);
insertPlainInsnBefore(def, RegisterSpecList.EMPTY, newReg, RegOps.CONST, newZero);
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class EscapeAnalysis method replaceUse.
/**
* Replaces the use for a scalar replaceable array. Gets and puts become
* move instructions, and array lengths and fills are handled. Can also
* identify ArrayIndexOutOfBounds exceptions and throw them if detected.
*
* @param use {@code non-null;} move result instruction for array
* @param prev {@code non-null;} instruction for instantiating new array
* @param newRegs {@code non-null;} mapping of array indices to new
* registers
* @param deletedInsns {@code non-null;} set of instructions marked for
* deletion
*/
private void replaceUse(SsaInsn use, SsaInsn prev, ArrayList<RegisterSpec> newRegs, HashSet<SsaInsn> deletedInsns) {
int index;
int length = newRegs.size();
SsaInsn next;
RegisterSpecList sources;
RegisterSpec source, result;
CstLiteralBits indexReg;
switch(use.getOpcode().getOpcode()) {
case RegOps.AGET:
// Replace array gets with moves
next = getMoveForInsn(use);
sources = use.getSources();
indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
index = indexReg.getIntBits();
if (index < length) {
source = newRegs.get(index);
result = source.withReg(next.getResult().getReg());
insertPlainInsnBefore(next, RegisterSpecList.make(source), result, RegOps.MOVE, null);
} else {
// Throw an exception if the index is out of bounds
insertExceptionThrow(next, sources.get(1), deletedInsns);
deletedInsns.add(next.getBlock().getInsns().get(2));
}
deletedInsns.add(next);
break;
case RegOps.APUT:
// Replace array puts with moves
sources = use.getSources();
indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
index = indexReg.getIntBits();
if (index < length) {
source = sources.get(0);
result = source.withReg(newRegs.get(index).getReg());
insertPlainInsnBefore(use, RegisterSpecList.make(source), result, RegOps.MOVE, null);
// Update the newReg entry to mark value as unknown now
newRegs.set(index, result.withSimpleType());
} else {
// Throw an exception if the index is out of bounds
insertExceptionThrow(use, sources.get(2), deletedInsns);
}
break;
case RegOps.ARRAY_LENGTH:
// Replace array lengths with const instructions
TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
//CstInteger lengthReg = CstInteger.make(length);
next = getMoveForInsn(use);
insertPlainInsnBefore(next, RegisterSpecList.EMPTY, next.getResult(), RegOps.CONST, (Constant) lengthReg);
deletedInsns.add(next);
break;
case RegOps.MARK_LOCAL:
// Remove mark local instructions
break;
case RegOps.FILL_ARRAY_DATA:
// Create const instructions for each fill value
Insn ropUse = use.getOriginalRopInsn();
FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
ArrayList<Constant> constList = fill.getInitValues();
for (int i = 0; i < length; i++) {
RegisterSpec newFill = RegisterSpec.make(newRegs.get(i).getReg(), (TypeBearer) constList.get(i));
insertPlainInsnBefore(use, RegisterSpecList.EMPTY, newFill, RegOps.CONST, constList.get(i));
// Update the newRegs to hold the new const value
newRegs.set(i, newFill);
}
break;
default:
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class EscapeAnalysis method processRegister.
/**
* Iterate through all the uses of a new object.
*
* @param result {@code non-null;} register where new object is stored
* @param escSet {@code non-null;} EscapeSet for the new object
*/
private void processRegister(RegisterSpec result, EscapeSet escSet) {
ArrayList<RegisterSpec> regWorklist = new ArrayList<RegisterSpec>();
regWorklist.add(result);
// Go through the worklist
while (!regWorklist.isEmpty()) {
int listSize = regWorklist.size() - 1;
RegisterSpec def = regWorklist.remove(listSize);
List<SsaInsn> useList = ssaMeth.getUseListForRegister(def.getReg());
// Handle all the uses of this register
for (SsaInsn use : useList) {
Rop useOpcode = use.getOpcode();
if (useOpcode == null) {
// Handle phis
processPhiUse(use, escSet, regWorklist);
} else {
// Handle other opcodes
processUse(def, use, escSet, regWorklist);
}
}
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class EscapeAnalysis method movePropagate.
/**
* Identifies extra moves added by scalar replacement and propagates the
* source of the move to any users of the result.
*/
private void movePropagate() {
for (int i = 0; i < ssaMeth.getRegCount(); i++) {
SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
// Look for move instructions only
if (insn == null || insn.getOpcode() == null || insn.getOpcode().getOpcode() != RegOps.MOVE) {
continue;
}
final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
final RegisterSpec source = insn.getSources().get(0);
final RegisterSpec result = insn.getResult();
// Ignore moves that weren't added due to scalar replacement
if (source.getReg() < regCount && result.getReg() < regCount) {
continue;
}
// Create a mapping from source to result
RegisterMapper mapper = new RegisterMapper() {
@Override
public int getNewRegisterCount() {
return ssaMeth.getRegCount();
}
@Override
public RegisterSpec map(RegisterSpec registerSpec) {
if (registerSpec.getReg() == result.getReg()) {
return source;
}
return registerSpec;
}
};
// Modify all uses of the move to use the source of the move instead
for (SsaInsn use : useList[result.getReg()]) {
use.mapSourceRegisters(mapper);
}
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class InterferenceRegisterMapper method areAnyPinned.
/**
* Checks to see if any of a set of old-namespace registers are
* pinned to the specified new-namespace reg + category. Takes into
* account the category of the old-namespace registers.
*
* @param oldSpecs {@code non-null;} set of old-namespace regs
* @param newReg {@code >= 0;} new-namespace register
* @param targetCategory {@code 1..2;} the number of adjacent new-namespace
* registers (starting at ropReg) to consider
* @return true if any of the old-namespace register have been mapped
* to the new-namespace register + category
*/
public boolean areAnyPinned(RegisterSpecList oldSpecs, int newReg, int targetCategory) {
int sz = oldSpecs.size();
for (int i = 0; i < sz; i++) {
RegisterSpec oldSpec = oldSpecs.get(i);
int r = oldToNew(oldSpec.getReg());
/*
* If oldSpec is a category-2 register, then check both newReg
* and newReg - 1.
*/
if (r == newReg || (oldSpec.getCategory() == 2 && (r + 1) == newReg) || (targetCategory == 2 && (r == newReg + 1))) {
return true;
}
}
return false;
}
Aggregations