use of com.taobao.android.dx.util.IntSet in project atlas by alibaba.
the class FirstFitLocalCombiningAllocator method fitPlanForRange.
/**
* Attempts to build a plan for fitting a range of sources into rop
* registers.
*
* @param ropReg {@code >= 0;} rop reg that begins range
* @param insn {@code non-null;} insn to plan range for
* @param categoriesForIndex {@code non-null;} indexed by source index;
* the category for each source
* @param outMovesRequired {@code non-null;} an output parameter indexed by
* source index that will contain the set of sources which need
* moves inserted
* @return the width of the fit that that does not involve added moves or
* {@code -1} if "no fit possible"
*/
private int fitPlanForRange(int ropReg, NormalSsaInsn insn, int[] categoriesForIndex, BitSet outMovesRequired) {
RegisterSpecList sources = insn.getSources();
int szSources = sources.size();
int fitWidth = 0;
IntSet liveOut = insn.getBlock().getLiveOutRegs();
RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);
// An SSA reg may only be mapped into a range once.
BitSet seen = new BitSet(ssaMeth.getRegCount());
for (int i = 0; i < szSources; i++) {
RegisterSpec ssaSpec = sources.get(i);
int ssaReg = ssaSpec.getReg();
int category = categoriesForIndex[i];
if (i != 0) {
ropReg += categoriesForIndex[i - 1];
}
if (ssaRegsMapped.get(ssaReg) && mapper.oldToNew(ssaReg) == ropReg) {
// This is a register that is already mapped appropriately.
fitWidth += category;
} else if (rangeContainsReserved(ropReg, category)) {
fitWidth = -1;
break;
} else if (!ssaRegsMapped.get(ssaReg) && canMapReg(ssaSpec, ropReg) && !seen.get(ssaReg)) {
// This is a register that can be mapped appropriately.
fitWidth += category;
} else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category) && !mapper.areAnyPinned(sources, ropReg, category)) {
/*
* This is a source that can be moved. We can insert a
* move as long as:
*
* * no SSA register pinned to the desired rop reg
* is live out on the block
*
* * no SSA register pinned to desired rop reg is
* a source of this insn (since this may require
* overlapping moves, which we can't presently handle)
*/
outMovesRequired.set(i);
} else {
fitWidth = -1;
break;
}
seen.set(ssaReg);
}
return fitWidth;
}
use of com.taobao.android.dx.util.IntSet in project atlas by alibaba.
the class FirstFitAllocator method allocateRegisters.
/**
* {@inheritDoc}
*/
@Override
public RegisterMapper allocateRegisters() {
int oldRegCount = ssaMeth.getRegCount();
BasicRegisterMapper mapper = new BasicRegisterMapper(oldRegCount);
int nextNewRegister = 0;
if (PRESLOT_PARAMS) {
/*
* Reserve space for the params at the bottom of the register
* space. Later, we'll flip the params to the end of the register
* space.
*/
nextNewRegister = ssaMeth.getParamWidth();
}
for (int i = 0; i < oldRegCount; i++) {
if (mapped.get(i)) {
// we already got this one
continue;
}
int maxCategory = getCategoryForSsaReg(i);
IntSet current = new BitIntSet(oldRegCount);
interference.mergeInterferenceSet(i, current);
boolean isPreslotted = false;
int newReg = 0;
if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
// Any move-param definition must be a NormalSsaInsn
NormalSsaInsn defInsn = (NormalSsaInsn) ssaMeth.getDefinitionForRegister(i);
newReg = paramNumberFromMoveParam(defInsn);
mapper.addMapping(i, newReg, maxCategory);
isPreslotted = true;
} else {
mapper.addMapping(i, nextNewRegister, maxCategory);
newReg = nextNewRegister;
}
for (int j = i + 1; j < oldRegCount; j++) {
if (mapped.get(j) || isDefinitionMoveParam(j)) {
continue;
}
/*
* If reg j doesn't interfere with the current mapping.
* Also, if this is a pre-slotted method parameter, we
* can't use more than the original param width.
*/
if (!current.has(j) && !(isPreslotted && (maxCategory < getCategoryForSsaReg(j)))) {
interference.mergeInterferenceSet(j, current);
maxCategory = Math.max(maxCategory, getCategoryForSsaReg(j));
mapper.addMapping(j, newReg, maxCategory);
mapped.set(j);
}
}
mapped.set(i);
if (!isPreslotted) {
nextNewRegister += maxCategory;
}
}
return mapper;
}
use of com.taobao.android.dx.util.IntSet 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