use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class SsaBasicBlock method addMoveToEnd.
/**
* Adds a move instruction to the end of this basic block, just
* before the last instruction. If the result of the final instruction
* is the source in question, then the move is placed at the beginning of
* the primary successor block. This is for unversioned registers.
*
* @param result move destination
* @param source move source
*/
public void addMoveToEnd(RegisterSpec result, RegisterSpec source) {
if (result.getReg() == source.getReg()) {
// Sometimes we end up with no-op moves. Ignore them here.
return;
}
/*
* The last Insn has to be a normal SSA insn: a phi can't branch
* or return or cause an exception, etc.
*/
NormalSsaInsn lastInsn;
lastInsn = (NormalSsaInsn) insns.get(insns.size() - 1);
if (lastInsn.getResult() != null || lastInsn.getSources().size() > 0) {
for (int i = successors.nextSetBit(0); i >= 0; i = successors.nextSetBit(i + 1)) {
SsaBasicBlock succ;
succ = parent.getBlocks().get(i);
succ.addMoveToBeginning(result, source);
}
} else {
/*
* We can safely add a move to the end of the block just
* before the last instruction, because the final insn does
* not assign to anything.
*/
RegisterSpecList sources = RegisterSpecList.make(source);
NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, sources), this);
insns.add(insns.size() - 1, toAdd);
movesFromPhisAtEnd++;
}
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class SsaMethod method onSourcesChanged.
/**
* Updates the use list for a source list change.
*
* @param insn {@code insn non-null;} insn being changed.
* {@code insn.getSources()} must return the new source list.
* @param oldSources {@code null-ok;} list of sources that were
* previously used
*/
/*package*/
void onSourcesChanged(SsaInsn insn, RegisterSpecList oldSources) {
if (useList == null)
return;
if (oldSources != null) {
removeFromUseList(insn, oldSources);
}
RegisterSpecList sources = insn.getSources();
int szNew = sources.size();
for (int i = 0; i < szNew; i++) {
int reg = sources.get(i).getReg();
useList[reg].add(insn);
}
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class FirstFitLocalCombiningAllocator method findRangeAndAdjust.
/**
* Find a contiguous rop register range that fits the specified
* instruction's sources. First, try to center the range around
* sources that have already been mapped to rop registers. If that fails,
* just find a new contiguous range that doesn't interfere.
*
* @param insn {@code non-null;} the insn whose sources need to
* fit. Must be last insn in basic block.
* @return {@code >= 0;} rop register of start of range
*/
private int findRangeAndAdjust(NormalSsaInsn insn) {
RegisterSpecList sources = insn.getSources();
int szSources = sources.size();
// the category for each source index
int[] categoriesForIndex = new int[szSources];
int rangeLength = 0;
// Compute rangeLength and categoriesForIndex
for (int i = 0; i < szSources; i++) {
int category = sources.get(i).getCategory();
categoriesForIndex[i] = category;
rangeLength += categoriesForIndex[i];
}
// the highest score of fits tried so far
int maxScore = Integer.MIN_VALUE;
// the high scoring range's start
int resultRangeStart = -1;
// by source index: set of sources needing moves in high scoring plan
BitSet resultMovesRequired = null;
/*
* First, go through each source that's already been mapped. Try
* to center the range around the rop register this source is mapped
* to.
*/
int rangeStartOffset = 0;
for (int i = 0; i < szSources; i++) {
int ssaCenterReg = sources.get(i).getReg();
if (i != 0) {
rangeStartOffset -= categoriesForIndex[i - 1];
}
if (!ssaRegsMapped.get(ssaCenterReg)) {
continue;
}
int rangeStart = mapper.oldToNew(ssaCenterReg) + rangeStartOffset;
if (rangeStart < 0 || spansParamRange(rangeStart, rangeLength)) {
continue;
}
BitSet curMovesRequired = new BitSet(szSources);
int fitWidth = fitPlanForRange(rangeStart, insn, categoriesForIndex, curMovesRequired);
if (fitWidth < 0) {
continue;
}
int score = fitWidth - curMovesRequired.cardinality();
if (score > maxScore) {
maxScore = score;
resultRangeStart = rangeStart;
resultMovesRequired = curMovesRequired;
}
if (fitWidth == rangeLength) {
// We can't do any better than this, so stop here
break;
}
}
if (resultRangeStart == -1) {
resultMovesRequired = new BitSet(szSources);
resultRangeStart = findAnyFittingRange(insn, rangeLength, categoriesForIndex, resultMovesRequired);
}
for (int i = resultMovesRequired.nextSetBit(0); i >= 0; i = resultMovesRequired.nextSetBit(i + 1)) {
insn.changeOneSource(i, insertMoveBefore(insn, sources.get(i)));
}
return resultRangeStart;
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
the class FirstFitLocalCombiningAllocator method processPhiInsn.
/**
* Attempts to map the sources and result of a phi to a common register.
* Will try existing mappings first, from most to least common. If none
* of the registers have mappings yet, a new mapping is created.
*/
private void processPhiInsn(PhiInsn insn) {
RegisterSpec result = insn.getResult();
int resultReg = result.getReg();
int category = result.getCategory();
RegisterSpecList sources = insn.getSources();
int sourcesSize = sources.size();
// List of phi sources / result that need mapping
ArrayList<RegisterSpec> ssaRegs = new ArrayList<RegisterSpec>();
// Track how many times a particular mapping is found
Multiset mapSet = new Multiset(sourcesSize + 1);
/*
* If the result of the phi has an existing mapping, get it.
* Otherwise, add it to the list of regs that need mapping.
*/
if (ssaRegsMapped.get(resultReg)) {
mapSet.add(mapper.oldToNew(resultReg));
} else {
ssaRegs.add(result);
}
for (int i = 0; i < sourcesSize; i++) {
RegisterSpec source = sources.get(i);
SsaInsn def = ssaMeth.getDefinitionForRegister(source.getReg());
RegisterSpec sourceDef = def.getResult();
int sourceReg = sourceDef.getReg();
/*
* If a source of the phi has an existing mapping, get it.
* Otherwise, add it to the list of regs that need mapping.
*/
if (ssaRegsMapped.get(sourceReg)) {
mapSet.add(mapper.oldToNew(sourceReg));
} else {
ssaRegs.add(sourceDef);
}
}
// Try all existing mappings, with the most common ones first
for (int i = 0; i < mapSet.getSize(); i++) {
int maxReg = mapSet.getAndRemoveHighestCount();
tryMapRegs(ssaRegs, maxReg, category, false);
}
// Map any remaining unmapped regs with whatever fits
int mapReg = findNextUnreservedRopReg(paramRangeEnd, category);
while (!tryMapRegs(ssaRegs, mapReg, category, false)) {
mapReg = findNextUnreservedRopReg(mapReg + 1, category);
}
}
use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.
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;
}
Aggregations