diff options
| author | jeffhao <jeffhao@google.com> | 2011-02-09 18:29:00 -0800 |
|---|---|---|
| committer | jeffhao <jeffhao@google.com> | 2011-02-09 18:29:00 -0800 |
| commit | e1c3a8e2203881759efec3538cc654937de1d817 (patch) | |
| tree | 228c160a06f9826b902701243b639066d75aafda /dx | |
| parent | 1e7c544617b8625719d224730141e4a8da89e25b (diff) | |
| download | android_dalvik-e1c3a8e2203881759efec3538cc654937de1d817.tar.gz android_dalvik-e1c3a8e2203881759efec3538cc654937de1d817.tar.bz2 android_dalvik-e1c3a8e2203881759efec3538cc654937de1d817.zip | |
Added support for integer division to SCCP.
Division generates a result that must be fetched with a
move-result-pseudo instruction. SCCP originally had no way of tying the
division with the result it generates. This change should allow proper
constant propagation when division of integers is involved.
Change-Id: Ib7c5d2dd26eea3ab6545b613a540f0161a8e1642
Diffstat (limited to 'dx')
| -rw-r--r-- | dx/src/com/android/dx/ssa/LiteralOpUpgrader.java | 46 | ||||
| -rw-r--r-- | dx/src/com/android/dx/ssa/SCCP.java | 27 |
2 files changed, 57 insertions, 16 deletions
diff --git a/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java b/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java index bac1d2c08..e36c6ffc1 100644 --- a/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java +++ b/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java @@ -30,6 +30,7 @@ import com.android.dx.rop.cst.CstLiteralBits; import com.android.dx.rop.type.Type; import com.android.dx.rop.type.TypeBearer; +import java.util.ArrayList; import java.util.List; /** @@ -97,16 +98,7 @@ public class LiteralOpUpgrader { RegisterSpecList sources = insn.getSources(); // Replace insns with constant results with const insns - if (insn.getResult() != null && - opcode.getOpcode() != RegOps.CONST) { - TypeBearer type = insn.getResult().getTypeBearer(); - if (type.isConstant() && - type.getBasicType() == Type.BT_INT) { - replacePlainInsn(insn, RegisterSpecList.EMPTY, - RegOps.CONST, (Constant) type); - return; - } - } + if (tryReplacingWithConstant(insn)) return; if (sources.size() != 2 ) { // We're only dealing with two-source insns here. @@ -145,6 +137,40 @@ public class LiteralOpUpgrader { } /** + * Tries to replace an instruction with a const instruction. The given + * instruction must have a constant result for it to be replaced. + * + * @param insn {@code non-null;} instruction to try to replace + * @return true if the instruction was replaced + */ + private boolean tryReplacingWithConstant(NormalSsaInsn insn) { + Insn originalRopInsn = insn.getOriginalRopInsn(); + Rop opcode = originalRopInsn.getOpcode(); + + if (insn.getResult() != null && opcode.getOpcode() != RegOps.CONST) { + TypeBearer type = insn.getResult().getTypeBearer(); + if (type.isConstant() && type.getBasicType() == Type.BT_INT) { + // Replace the instruction with a constant + replacePlainInsn(insn, RegisterSpecList.EMPTY, + RegOps.CONST, (Constant) type); + + // Remove the source as well if this is a move-result-pseudo + if (opcode.getOpcode() == RegOps.MOVE_RESULT_PSEUDO) { + int pred = insn.getBlock().getPredecessors().nextSetBit(0); + ArrayList<SsaInsn> predInsns = + ssaMeth.getBlocks().get(pred).getInsns(); + NormalSsaInsn sourceInsn = + (NormalSsaInsn) predInsns.get(predInsns.size()-1); + replacePlainInsn(sourceInsn, RegisterSpecList.EMPTY, + RegOps.GOTO, null); + } + return true; + } + } + return false; + } + + /** * Replaces an SsaInsn containing a PlainInsn with a new PlainInsn. The * new PlainInsn is constructed with a new RegOp and new sources. * diff --git a/dx/src/com/android/dx/ssa/SCCP.java b/dx/src/com/android/dx/ssa/SCCP.java index d15803017..edc192314 100644 --- a/dx/src/com/android/dx/ssa/SCCP.java +++ b/dx/src/com/android/dx/ssa/SCCP.java @@ -358,9 +358,10 @@ public class SCCP { * Simulates math insns, if possible. * * @param insn non-null insn to simulate + * @param resultType basic type of the result * @return constant result or null if not simulatable. */ - private Constant simulateMath(SsaInsn insn) { + private Constant simulateMath(SsaInsn insn, int resultType) { Insn ropInsn = insn.getOriginalRopInsn(); int opcode = insn.getOpcode().getOpcode(); RegisterSpecList sources = insn.getSources(); @@ -391,7 +392,7 @@ public class SCCP { return null; } - switch (insn.getResult().getBasicType()) { + switch (resultType) { case Type.BT_INT: int vR; boolean skip=false; @@ -470,11 +471,26 @@ public class SCCP { return; } - /* TODO: Simplify statements when possible using the constants. */ int resultReg = insn.getResult().getReg(); + int resultType = insn.getResult().getBasicType(); int resultValue = VARYING; Constant resultConstant = null; int opcode = insn.getOpcode().getOpcode(); + + // TODO: Handle non-int arithmetic. + if (resultType != Type.BT_INT) { + return; + } + + // Find defining instruction for move-result-pseudo instructions + if (opcode == RegOps.MOVE_RESULT_PSEUDO) { + int pred = insn.getBlock().getPredecessors().nextSetBit(0); + ArrayList<SsaInsn> predInsns; + predInsns = ssaMeth.getBlocks().get(pred).getInsns(); + insn = predInsns.get(predInsns.size()-1); + opcode = insn.getOpcode().getOpcode(); + } + switch (opcode) { case RegOps.CONST: { CstInsn cstInsn = (CstInsn)ropInsn; @@ -503,7 +519,7 @@ public class SCCP { case RegOps.USHR: case RegOps.REM: - resultConstant = simulateMath(insn); + resultConstant = simulateMath(insn, resultType); if (resultConstant == null) { resultValue = VARYING; @@ -511,8 +527,7 @@ public class SCCP { resultValue = CONSTANT; } break; - /* TODO: Handle non-int arithmetic. - TODO: Eliminate check casts that we can prove the type of. */ + // TODO: Eliminate check casts that we can prove the type of. default: {} } if (setLatticeValueTo(resultReg, resultValue, resultConstant)) { |
