Runs this optimization step.
// This will contain the definition specs for each parameter
final RegisterSpec[] paramSpecs
= new RegisterSpec[ssaMeth.getParamWidth()];
// Insns to delete when all done
final HashSet<SsaInsn> deletedInsns = new HashSet();
ssaMeth.forEachInsn(new SsaInsn.Visitor() {
public void visitMoveInsn (NormalSsaInsn insn) {
}
public void visitPhiInsn (PhiInsn phi) {
}
public void visitNonMoveInsn (NormalSsaInsn insn) {
if (insn.getOpcode().getOpcode() != RegOps.MOVE_PARAM) {
return;
}
int param = getParamIndex(insn);
if (paramSpecs[param] == null) {
paramSpecs[param] = insn.getResult();
} else {
final RegisterSpec specA = paramSpecs[param];
final RegisterSpec specB = insn.getResult();
LocalItem localA = specA.getLocalItem();
LocalItem localB = specB.getLocalItem();
LocalItem newLocal;
/*
* Is there local information to preserve?
*/
if (localA == null) {
newLocal = localB;
} else if (localB == null) {
newLocal = localA;
} else if (localA.equals(localB)) {
newLocal = localA;
} else {
/*
* Oddly, these two identical move-params have distinct
* debug info. We'll just keep them distinct.
*/
return;
}
ssaMeth.getDefinitionForRegister(specA.getReg())
.setResultLocal(newLocal);
/*
* Map all uses of specB to specA
*/
RegisterMapper mapper = new RegisterMapper() {
/** @inheritDoc */
public int getNewRegisterCount() {
return ssaMeth.getRegCount();
}
/** @inheritDoc */
public RegisterSpec map(RegisterSpec registerSpec) {
if (registerSpec.getReg() == specB.getReg()) {
return specA;
}
return registerSpec;
}
};
List<SsaInsn> uses
= ssaMeth.getUseListForRegister(specB.getReg());
// Use list is modified by mapSourceRegisters
for (int i = uses.size() - 1; i >= 0; i--) {
SsaInsn use = uses.get(i);
use.mapSourceRegisters(mapper);
}
deletedInsns.add(insn);
}
}
});
ssaMeth.deleteInsns(deletedInsns);