use of com.android.dx.rop.type.TypeBearer in project buck by facebook.
the class EscapeAnalysis method scalarReplacement.
/**
* Performs scalar replacement on all eligible arrays.
*/
private void scalarReplacement() {
// Iterate through lattice, looking for non-escaping replaceable arrays
for (EscapeSet escSet : latticeValues) {
if (!escSet.replaceableArray || escSet.escape != EscapeState.NONE) {
continue;
}
// Get the instructions for the definition and move of the array
int e = escSet.regSet.nextSetBit(0);
SsaInsn def = ssaMeth.getDefinitionForRegister(e);
SsaInsn prev = getInsnForMove(def);
// Create a map for the new registers that will be created
TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
int length = ((CstLiteralBits) lengthReg).getIntBits();
ArrayList<RegisterSpec> newRegs = new ArrayList<RegisterSpec>(length);
HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
// Replace the definition of the array with registers
replaceDef(def, prev, length, newRegs);
// Mark definition instructions for deletion
deletedInsns.add(prev);
deletedInsns.add(def);
// Go through all uses of the array
List<SsaInsn> useList = ssaMeth.getUseListForRegister(e);
for (SsaInsn use : useList) {
// Replace the use with scalars and then mark it for deletion
replaceUse(use, prev, newRegs, deletedInsns);
deletedInsns.add(use);
}
// Delete all marked instructions
ssaMeth.deleteInsns(deletedInsns);
ssaMeth.onInsnsChanged();
// Convert the method back to SSA form
SsaConverter.updateSsaMethod(ssaMeth, regCount);
// Propagate and remove extra moves added by scalar replacement
movePropagate();
}
}
use of com.android.dx.rop.type.TypeBearer in project buck by facebook.
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.android.dx.rop.type.TypeBearer in project buck by facebook.
the class ConstCollector method getConstsSortedByCountUse.
/**
* Gets all of the collectable constant values used in this method,
* sorted by most used first. Skips non-collectable consts, such as
* non-string object constants
*
* @return {@code non-null;} list of constants in most-to-least used order
*/
private ArrayList<TypedConstant> getConstsSortedByCountUse() {
int regSz = ssaMeth.getRegCount();
final HashMap<TypedConstant, Integer> countUses = new HashMap<TypedConstant, Integer>();
/*
* Each collected constant can be used by just one local
* (used only if COLLECT_ONE_LOCAL is true).
*/
final HashSet<TypedConstant> usedByLocal = new HashSet<TypedConstant>();
// Count how many times each const value is used.
for (int i = 0; i < regSz; i++) {
SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
if (insn == null || insn.getOpcode() == null)
continue;
RegisterSpec result = insn.getResult();
TypeBearer typeBearer = result.getTypeBearer();
if (!typeBearer.isConstant())
continue;
TypedConstant cst = (TypedConstant) typeBearer;
// Find defining instruction for move-result-pseudo instructions
if (insn.getOpcode().getOpcode() == RegOps.MOVE_RESULT_PSEUDO) {
int pred = insn.getBlock().getPredecessors().nextSetBit(0);
ArrayList<SsaInsn> predInsns;
predInsns = ssaMeth.getBlocks().get(pred).getInsns();
insn = predInsns.get(predInsns.size() - 1);
}
if (insn.canThrow()) {
/*
* Don't move anything other than strings -- the risk
* of changing where an exception is thrown is too high.
*/
if (!(cst instanceof CstString) || !COLLECT_STRINGS) {
continue;
}
/*
* We can't move any throwable const whose throw will be
* caught, so don't count them.
*/
if (insn.getBlock().getSuccessors().cardinality() > 1) {
continue;
}
}
/*
* TODO: Might be nice to try and figure out which local
* wins most when collected.
*/
if (ssaMeth.isRegALocal(result)) {
if (!COLLECT_ONE_LOCAL) {
continue;
} else {
if (usedByLocal.contains(cst)) {
// Count one local usage only.
continue;
} else {
usedByLocal.add(cst);
}
}
}
Integer has = countUses.get(cst);
if (has == null) {
countUses.put(cst, 1);
} else {
countUses.put(cst, has + 1);
}
}
// Collect constants that have been reused.
ArrayList<TypedConstant> constantList = new ArrayList<TypedConstant>();
for (Map.Entry<TypedConstant, Integer> entry : countUses.entrySet()) {
if (entry.getValue() > 1) {
constantList.add(entry.getKey());
}
}
// Sort by use, with most used at the beginning of the list.
Collections.sort(constantList, new Comparator<Constant>() {
public int compare(Constant a, Constant b) {
int ret;
ret = countUses.get(b) - countUses.get(a);
if (ret == 0) {
/*
* Provide sorting determinisim for constants with same
* usage count.
*/
ret = a.compareTo(b);
}
return ret;
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
});
return constantList;
}
use of com.android.dx.rop.type.TypeBearer in project buck by facebook.
the class ConstCollector method updateConstUses.
/**
* Updates all uses of various consts to use the values in the newly
* assigned registers.
*
* @param newRegs {@code non-null;} mapping between constant and new reg
* @param origRegCount {@code >=0;} original SSA reg count, not including
* newly added constant regs
*/
private void updateConstUses(HashMap<TypedConstant, RegisterSpec> newRegs, int origRegCount) {
/*
* set of constants associated with a local variable; used
* only if COLLECT_ONE_LOCAL is true.
*/
final HashSet<TypedConstant> usedByLocal = new HashSet<TypedConstant>();
final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
for (int i = 0; i < origRegCount; i++) {
SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
if (insn == null) {
continue;
}
final RegisterSpec origReg = insn.getResult();
TypeBearer typeBearer = insn.getResult().getTypeBearer();
if (!typeBearer.isConstant())
continue;
TypedConstant cst = (TypedConstant) typeBearer;
final RegisterSpec newReg = newRegs.get(cst);
if (newReg == null) {
continue;
}
if (ssaMeth.isRegALocal(origReg)) {
if (!COLLECT_ONE_LOCAL) {
continue;
} else {
/*
* TODO: If the same local gets the same cst
* multiple times, it would be nice to reuse the
* register.
*/
if (usedByLocal.contains(cst)) {
continue;
} else {
usedByLocal.add(cst);
fixLocalAssignment(origReg, newRegs.get(cst));
}
}
}
// maps an original const register to the new collected register
RegisterMapper mapper = new RegisterMapper() {
@Override
public int getNewRegisterCount() {
return ssaMeth.getRegCount();
}
@Override
public RegisterSpec map(RegisterSpec registerSpec) {
if (registerSpec.getReg() == origReg.getReg()) {
return newReg.withLocalItem(registerSpec.getLocalItem());
}
return registerSpec;
}
};
for (SsaInsn use : useList[origReg.getReg()]) {
if (use.canThrow() && use.getBlock().getSuccessors().cardinality() > 1) {
continue;
}
use.mapSourceRegisters(mapper);
}
}
}
use of com.android.dx.rop.type.TypeBearer in project buck by facebook.
the class RegisterSpec method withSimpleType.
/**
* Returns an instance that is identical to this one, except that
* the type bearer is replaced by the actual underlying type
* (thereby stripping off non-type information) with any
* initialization information stripped away as well.
*
* @return {@code non-null;} an appropriately-constructed instance
*/
public RegisterSpec withSimpleType() {
TypeBearer orig = type;
Type newType;
if (orig instanceof Type) {
newType = (Type) orig;
} else {
newType = orig.getType();
}
if (newType.isUninitialized()) {
newType = newType.getInitializedType();
}
if (newType == orig) {
return this;
}
return makeLocalOptional(reg, newType, local);
}
Aggregations