use of com.android.dx.rop.code.RegisterSpec 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.RegisterSpec in project J2ME-Loader by nikita36078.
the class FirstFitLocalCombiningAllocator method tryMapRegs.
/**
* Tries to map a list of SSA registers into the a rop reg, marking
* used rop space as reserved. SSA registers that don't fit are left
* unmapped.
*
* @param specs {@code non-null;} SSA registers to attempt to map
* @param ropReg {@code >=0;} rop register to map to
* @param maxAllowedCategory {@code 1..2;} maximum category
* allowed in mapping.
* @param markReserved do so if {@code true}
* @return {@code true} if all registers were mapped, {@code false}
* if some remain unmapped
*/
private boolean tryMapRegs(ArrayList<RegisterSpec> specs, int ropReg, int maxAllowedCategory, boolean markReserved) {
boolean remaining = false;
for (RegisterSpec spec : specs) {
if (ssaRegsMapped.get(spec.getReg())) {
continue;
}
boolean succeeded;
succeeded = tryMapReg(spec, ropReg, maxAllowedCategory);
remaining = !succeeded || remaining;
if (succeeded && markReserved) {
// This only needs to be called once really with
// the widest category used, but <shrug>
markReserved(ropReg, spec.getCategory());
}
}
return !remaining;
}
use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.
the class FirstFitLocalCombiningAllocator method handleCheckCastResults.
/**
* Handles check cast results to reuse the same source register.
* Inserts a move if it can't map the same register to both and the
* check cast is not caught.
*/
private void handleCheckCastResults() {
for (NormalSsaInsn insn : moveResultPseudoInsns) {
RegisterSpec moveRegSpec = insn.getResult();
int moveReg = moveRegSpec.getReg();
BitSet predBlocks = insn.getBlock().getPredecessors();
// Expect one predecessor block only
if (predBlocks.cardinality() != 1) {
continue;
}
SsaBasicBlock predBlock = ssaMeth.getBlocks().get(predBlocks.nextSetBit(0));
ArrayList<SsaInsn> insnList = predBlock.getInsns();
/**
* If the predecessor block has a check-cast, it will be the last
* instruction
*/
SsaInsn checkCastInsn = insnList.get(insnList.size() - 1);
if (checkCastInsn.getOpcode().getOpcode() != RegOps.CHECK_CAST) {
continue;
}
RegisterSpec checkRegSpec = checkCastInsn.getSources().get(0);
int checkReg = checkRegSpec.getReg();
/**
* See if either register is already mapped. Most likely the move
* result will be mapped already since the cast result is stored
* in a local variable.
*/
int category = checkRegSpec.getCategory();
boolean moveMapped = ssaRegsMapped.get(moveReg);
boolean checkMapped = ssaRegsMapped.get(checkReg);
if (moveMapped & !checkMapped) {
int moveRopReg = mapper.oldToNew(moveReg);
checkMapped = tryMapReg(checkRegSpec, moveRopReg, category);
}
if (checkMapped & !moveMapped) {
int checkRopReg = mapper.oldToNew(checkReg);
moveMapped = tryMapReg(moveRegSpec, checkRopReg, category);
}
// Map any unmapped registers to anything available
if (!moveMapped || !checkMapped) {
int ropReg = findNextUnreservedRopReg(paramRangeEnd, category);
ArrayList<RegisterSpec> ssaRegs = new ArrayList<RegisterSpec>(2);
ssaRegs.add(moveRegSpec);
ssaRegs.add(checkRegSpec);
while (!tryMapRegs(ssaRegs, ropReg, category, false)) {
ropReg = findNextUnreservedRopReg(ropReg + 1, category);
}
}
/*
* If source and result have a different mapping, insert a move so
* they can have the same mapping. Don't do this if the check cast
* is caught, since it will overwrite a potentially live value.
*/
boolean hasExceptionHandlers = checkCastInsn.getOriginalRopInsn().getCatches().size() != 0;
int moveRopReg = mapper.oldToNew(moveReg);
int checkRopReg = mapper.oldToNew(checkReg);
if (moveRopReg != checkRopReg && !hasExceptionHandlers) {
((NormalSsaInsn) checkCastInsn).changeOneSource(0, insertMoveBefore(checkCastInsn, checkRegSpec));
addMapping(checkCastInsn.getSources().get(0), moveRopReg);
}
}
}
use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.
the class FirstFitLocalCombiningAllocator method handleLocalAssociatedParams.
/**
* Maps all local-associated parameters to rop registers.
*/
private void handleLocalAssociatedParams() {
for (ArrayList<RegisterSpec> ssaRegs : localVariables.values()) {
int sz = ssaRegs.size();
int paramIndex = -1;
int paramCategory = 0;
// First, find out if this local variable is a parameter.
for (int i = 0; i < sz; i++) {
RegisterSpec ssaSpec = ssaRegs.get(i);
int ssaReg = ssaSpec.getReg();
paramIndex = getParameterIndexForReg(ssaReg);
if (paramIndex >= 0) {
paramCategory = ssaSpec.getCategory();
addMapping(ssaSpec, paramIndex);
break;
}
}
if (paramIndex < 0) {
// This local wasn't a parameter.
continue;
}
// Any remaining local-associated registers will be mapped later.
tryMapRegs(ssaRegs, paramIndex, paramCategory, true);
}
}
use of com.android.dx.rop.code.RegisterSpec 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