LiteralOpUpgraderpublic class LiteralOpUpgrader extends Object Upgrades insn to their literal (constant-immediate) equivilent if possible.
Also switches IF instructions that compare with a constant zero or null
to be their IF_*Z equivalents. |
Fields Summary |
---|
private final SsaMethod | ssaMethmethod we're processing |
Constructors Summary |
---|
private LiteralOpUpgrader(SsaMethod ssaMethod)
this.ssaMeth = ssaMethod;
|
Methods Summary |
---|
private static boolean | isConstIntZeroOrKnownNull(com.android.dx.rop.code.RegisterSpec spec)Returns true if the register contains an integer 0 or a known-null
object reference
TypeBearer tb = spec.getTypeBearer();
if (tb instanceof CstLiteralBits) {
CstLiteralBits clb = (CstLiteralBits) tb;
return (clb.getLongBits() == 0);
}
return false;
| public static void | process(SsaMethod ssaMethod)Process a method.
LiteralOpUpgrader dc;
dc = new LiteralOpUpgrader(ssaMethod);
dc.run();
| private void | replacePlainInsn(NormalSsaInsn insn, com.android.dx.rop.code.RegisterSpecList newSources, int newOpcode)Replaces an SsaInsn containing a PlainInsn with a new PlainInsn. The
new PlainInsn is contructed with a new RegOp and new sources.
TODO move this somewhere else.
Insn originalRopInsn = insn.getOriginalRopInsn();
Rop newRop = Rops.ropFor(newOpcode,
insn.getResult(), newSources, null);
Insn newRopInsn = new PlainInsn(newRop,
originalRopInsn.getPosition(), insn.getResult(),
newSources);
NormalSsaInsn newInsn
= new NormalSsaInsn(newRopInsn, insn.getBlock());
List<SsaInsn> insns = insn.getBlock().getInsns();
ssaMeth.onInsnRemoved(insn);
insns.set(insns.lastIndexOf(insn), newInsn);
ssaMeth.onInsnAdded(newInsn);
| private void | run()Run the literal op upgrader
final TranslationAdvice advice = Optimizer.getAdvice();
ssaMeth.forEachInsn(new SsaInsn.Visitor() {
public void visitMoveInsn(NormalSsaInsn insn) {
// do nothing
}
public void visitPhiInsn(PhiInsn insn) {
// do nothing
}
public void visitNonMoveInsn(NormalSsaInsn insn) {
Insn originalRopInsn = insn.getOriginalRopInsn();
Rop opcode = originalRopInsn.getOpcode();
RegisterSpecList sources = insn.getSources();
if (sources.size() != 2 ) {
// We're only dealing with two-source insns here.
return;
}
if (opcode.getBranchingness() == Rop.BRANCH_IF) {
/*
* An if instruction can become an if-*z instruction.
*/
if (isConstIntZeroOrKnownNull(sources.get(0))) {
replacePlainInsn(insn, sources.withoutFirst(),
RegOps.flippedIfOpcode(opcode.getOpcode()));
} else if (isConstIntZeroOrKnownNull(sources.get(1))) {
replacePlainInsn(insn, sources.withoutLast(),
opcode.getOpcode());
}
} else if (advice.hasConstantOperation(
opcode, sources.get(0), sources.get(1))) {
insn.upgradeToLiteral();
} else if (opcode.isCommutative()
&& advice.hasConstantOperation(
opcode, sources.get(1), sources.get(0))) {
/*
* An instruction can be commuted to a literal operation
*/
insn.setNewSources(
RegisterSpecList.make(
sources.get(1), sources.get(0)));
insn.upgradeToLiteral();
}
}
});
|
|