OSDN Git Service

Optimized dx instruction expansion to only generate necessary moves.
authorjeffhao <jeffhao@google.com>
Mon, 17 Jan 2011 19:37:21 +0000 (11:37 -0800)
committerjeffhao <jeffhao@google.com>
Tue, 18 Jan 2011 21:13:10 +0000 (13:13 -0800)
When an instruction's fields do not fit into an instruction format, dx
expands the instruction. Before, this would always use new registers for
sources and destination, generating moves for each. However, some of
these moves would be unnecessary if an original register already fit
into the instruction format. This change checks to see if the original
register fits before using a new register and generating a new move.

Change-Id: I17c6722cf4053573bf913a28d631386f2c3a733d

31 files changed:
dx/src/com/android/dx/dex/code/DalvInsn.java
dx/src/com/android/dx/dex/code/InsnFormat.java
dx/src/com/android/dx/dex/code/OutputFinisher.java
dx/src/com/android/dx/dex/code/RopTranslator.java
dx/src/com/android/dx/dex/code/form/Form11n.java
dx/src/com/android/dx/dex/code/form/Form11x.java
dx/src/com/android/dx/dex/code/form/Form12x.java
dx/src/com/android/dx/dex/code/form/Form21c.java
dx/src/com/android/dx/dex/code/form/Form21h.java
dx/src/com/android/dx/dex/code/form/Form21s.java
dx/src/com/android/dx/dex/code/form/Form21t.java
dx/src/com/android/dx/dex/code/form/Form22b.java
dx/src/com/android/dx/dex/code/form/Form22c.java
dx/src/com/android/dx/dex/code/form/Form22s.java
dx/src/com/android/dx/dex/code/form/Form22t.java
dx/src/com/android/dx/dex/code/form/Form22x.java
dx/src/com/android/dx/dex/code/form/Form23x.java
dx/src/com/android/dx/dex/code/form/Form31c.java
dx/src/com/android/dx/dex/code/form/Form31i.java
dx/src/com/android/dx/dex/code/form/Form31t.java
dx/src/com/android/dx/dex/code/form/Form32s.java
dx/src/com/android/dx/dex/code/form/Form32x.java
dx/src/com/android/dx/dex/code/form/Form33x.java
dx/src/com/android/dx/dex/code/form/Form35c.java
dx/src/com/android/dx/dex/code/form/Form3rc.java
dx/src/com/android/dx/dex/code/form/Form41c.java
dx/src/com/android/dx/dex/code/form/Form51l.java
dx/src/com/android/dx/dex/code/form/Form52c.java
dx/src/com/android/dx/dex/code/form/Form5rc.java
dx/src/com/android/dx/rop/code/RegisterSpecList.java
dx/src/com/android/dx/ssa/back/SsaToRop.java

index f203817..d0cf395 100644 (file)
@@ -23,6 +23,8 @@ import com.android.dx.util.AnnotatedOutput;
 import com.android.dx.util.Hex;
 import com.android.dx.util.TwoColumnOutput;
 
+import java.util.BitSet;
+
 /**
  * Base class for Dalvik instructions.
  */
@@ -205,60 +207,85 @@ public abstract class DalvInsn {
 
     /**
      * Gets the minimum distinct registers required for this instruction.
+     * Uses the given BitSet to determine which registers require
+     * replacement, and ignores registers that are already compatible.
      * This assumes that the result (if any) can share registers with the
      * sources (if any), that each source register is unique, and that
      * (to be explicit here) category-2 values take up two consecutive
      * registers.
      *
+     * @param compatRegs {@code non-null;} set of compatible registers
      * @return {@code >= 0;} the minimum distinct register requirement
      */
-    public final int getMinimumRegisterRequirement() {
+    public final int getMinimumRegisterRequirement(BitSet compatRegs) {
         boolean hasResult = hasResult();
         int regSz = registers.size();
-        int resultRequirement = hasResult ? registers.get(0).getCategory() : 0;
+        int resultRequirement = 0;
         int sourceRequirement = 0;
 
+        if (hasResult && !compatRegs.get(0)) {
+            resultRequirement = registers.get(0).getCategory();
+        }
+
         for (int i = hasResult ? 1 : 0; i < regSz; i++) {
-            sourceRequirement += registers.get(i).getCategory();
+            if (!compatRegs.get(i)) {
+                sourceRequirement += registers.get(i).getCategory();
+            }
         }
 
         return Math.max(sourceRequirement, resultRequirement);
     }
 
     /**
-     * Gets the instruction prefix required, if any, to use in a high
-     * register transformed version of this instance.
+     * Gets the instruction that is equivalent to this one, except that
+     * it uses sequential registers starting at {@code 0} (storing
+     * the result, if any, in register {@code 0} as well).
      *
-     * @see #hrVersion
+     * @return {@code non-null;} the replacement
+     */
+    public DalvInsn getLowRegVersion() {
+        RegisterSpecList regs =
+            registers.withExpandedRegisters(0, hasResult(), null);
+        return withRegisters(regs);
+    }
+
+    /**
+     * Gets the instruction prefix required, if any, to use in an expanded
+     * version of this instance. Will not generate moves for registers
+     * marked compatible to the format by the given BitSet.
+     *
+     * @see #expandedVersion
      *
+     * @param compatRegs {@code non-null;} set of compatible registers
      * @return {@code null-ok;} the prefix, if any
      */
-    public DalvInsn hrPrefix() {
+    public DalvInsn expandedPrefix(BitSet compatRegs) {
         RegisterSpecList regs = registers;
-        int sz = regs.size();
+        boolean firstBit = compatRegs.get(0);
 
-        if (hasResult()) {
-            if (sz == 1) {
-                return null;
-            }
-            regs = regs.withoutFirst();
-        } else if (sz == 0) {
-            return null;
-        }
+        if (hasResult()) compatRegs.set(0);
+
+        regs = regs.subset(compatRegs);
+
+        if (hasResult()) compatRegs.set(0, firstBit);
+
+        if (regs.size() == 0) return null;
 
         return new HighRegisterPrefix(position, regs);
     }
 
     /**
-     * Gets the instruction suffix required, if any, to use in a high
-     * register transformed version of this instance.
+     * Gets the instruction suffix required, if any, to use in an expanded
+     * version of this instance. Will not generate a move for a register
+     * marked compatible to the format by the given BitSet.
      *
-     * @see #hrVersion
+     * @see #expandedVersion
      *
+     * @param compatRegs {@code non-null;} set of compatible registers
      * @return {@code null-ok;} the suffix, if any
      */
-    public DalvInsn hrSuffix() {
-        if (hasResult()) {
+    public DalvInsn expandedSuffix(BitSet compatRegs) {
+        if (hasResult() && !compatRegs.get(0)) {
             RegisterSpec r = registers.get(0);
             return makeMove(position, r, r.withReg(0));
         } else {
@@ -268,20 +295,21 @@ public abstract class DalvInsn {
 
     /**
      * Gets the instruction that is equivalent to this one, except that
-     * uses sequential registers starting at {@code 0} (storing
-     * the result, if any, in register {@code 0} as well). The
-     * sequence of instructions from {@link #hrPrefix} and {@link
-     * #hrSuffix} (if non-null) surrounding the result of a call to
-     * this method are the high register transformation of this
-     * instance, and it is guaranteed that the number of low registers
-     * used will be the number returned by {@link
-     * #getMinimumRegisterRequirement}.
+     * it replaces incompatible registers with sequential registers
+     * starting at {@code 0} (storing the result, if any, in register
+     * {@code 0} as well). The sequence of instructions from
+     * {@link #expandedPrefix} and {@link #expandedSuffix} (if non-null)
+     * surrounding the result of a call to this method are the expanded
+     * transformation of this instance, and it is guaranteed that the
+     * number of low registers used will be the number returned by
+     * {@link #getMinimumRegisterRequirement}.
      *
+     * @param compatRegs {@code non-null;} set of compatible registers
      * @return {@code non-null;} the replacement
      */
-    public DalvInsn hrVersion() {
+    public DalvInsn expandedVersion(BitSet compatRegs) {
         RegisterSpecList regs =
-            registers.withSequentialRegisters(0, hasResult());
+            registers.withExpandedRegisters(0, hasResult(), compatRegs);
         return withRegisters(regs);
     }
 
index 97f5cd3..fc63797 100644 (file)
@@ -26,6 +26,8 @@ import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 import com.android.dx.util.Hex;
 
+import java.util.BitSet;
+
 /**
  * Base class for all instruction format handlers. Instruction format
  * handlers know how to translate {@link DalvInsn} instances into
@@ -127,6 +129,22 @@ public abstract class InsnFormat {
     public abstract boolean isCompatible(DalvInsn insn);
 
     /**
+     * Returns which of a given instruction's registers will fit in
+     * this instance's format.
+     *
+     * <p>The default implementation of this method always returns
+     * an empty BitSet. Subclasses must override this method if they
+     * have registers.</p>
+     *
+     * @param insn {@code non-null;} the instruction to check
+     * @return {@code non-null;} a BitSet flagging registers in the
+     * register list that are compatible to this format
+     */
+    public BitSet compatibleRegs(DalvInsn insn) {
+        return new BitSet();
+    }
+
+    /**
      * Returns whether or not the given instruction's branch offset will
      * fit in this instance's format. This always returns {@code false}
      * for formats that don't include a branch offset.
index 9d6fec7..e526817 100644 (file)
@@ -28,6 +28,7 @@ import com.android.dx.rop.cst.CstUtf8;
 import com.android.dx.rop.type.Type;
 
 import java.util.ArrayList;
+import java.util.BitSet;
 import java.util.HashSet;
 
 /**
@@ -450,19 +451,19 @@ public final class OutputFinisher {
             Dop originalOpcode = opcodes[i];
             Dop newOpcode = findOpcodeForInsn(insn, originalOpcode);
 
-            if (originalOpcode == newOpcode) {
-                continue;
-            }
-
             if (newOpcode == null) {
                 /*
-                 * The instruction will need to be expanded, so reserve
-                 * registers for it.
+                 * The instruction will need to be expanded, so find the
+                 * expanded opcode and reserve registers for it.
                  */
-                int reserve = insn.getMinimumRegisterRequirement();
+                Dop expandedOp = findExpandedOpcodeForInsn(insn);
+                BitSet compatRegs = expandedOp.getFormat().compatibleRegs(insn);
+                int reserve = insn.getMinimumRegisterRequirement(compatRegs);
                 if (reserve > newReservedCount) {
                     newReservedCount = reserve;
                 }
+            } else if (originalOpcode == newOpcode) {
+                continue;
             }
 
             opcodes[i] = newOpcode;
@@ -505,6 +506,17 @@ public final class OutputFinisher {
     }
 
     /**
+     * Finds the proper opcode for the given instruction, ignoring
+     * register constraints.
+     *
+     * @param insn {@code non-null;} the instruction in question
+     * @return {@code non-null;} the opcode that fits
+     */
+    private Dop findExpandedOpcodeForInsn(DalvInsn insn) {
+        return findOpcodeForInsn(insn.getLowRegVersion(), insn.getOpcode());
+    }
+
+    /**
      * Helper for {@link #finishProcessingAndGetList}, which goes
      * through each instruction in the output, making sure its opcode
      * can accomodate its arguments. In cases where the opcode is
@@ -583,16 +595,14 @@ public final class OutputFinisher {
                 suffix = null;
             } else {
                 // Expansion is required.
-                prefix = insn.hrPrefix();
-                suffix = insn.hrSuffix();
-
-                /*
-                 * Get the initial guess as to the hr version, but then
-                 * let findOpcodeForInsn() pick a better format, if any.
-                 */
-                insn = insn.hrVersion();
-                originalOpcode = insn.getOpcode();
-                currentOpcode = findOpcodeForInsn(insn, originalOpcode);
+                currentOpcode = findExpandedOpcodeForInsn(insn);
+                BitSet compatRegs =
+                    currentOpcode.getFormat().compatibleRegs(insn);
+                prefix = insn.expandedPrefix(compatRegs);
+                suffix = insn.expandedSuffix(compatRegs);
+
+                // Expand necessary registers to fit the new format
+                insn = insn.expandedVersion(compatRegs);
             }
 
             if (prefix != null) {
index a38ea11..2eb6454 100644 (file)
@@ -181,6 +181,7 @@ public final class RopTranslator {
          * subsequent block in the case of synchronized methods.
          */
         method.getBlocks().forEachInsn(new Insn.BaseVisitor() {
+            @Override
             public void visitPlainCstInsn(PlainCstInsn insn) {
                 if (insn.getOpcode().getOpcode()== RegOps.MOVE_PARAM) {
                     int param =
index 904aa6b..479af6e 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 11n}. See the instruction format spec
  * for details.
@@ -87,6 +89,16 @@ public final class Form11n extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int value =
index 739e7d3..82dda65 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.SimpleInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 11x}. See the instruction format spec
  * for details.
@@ -69,6 +71,16 @@ public final class Form11x extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         write(out, opcodeUnit(insn, regs.get(0).getReg()));
index 28c926c..aabab8a 100644 (file)
 package com.android.dx.dex.code.form;
 
 import com.android.dx.dex.code.DalvInsn;
-import com.android.dx.dex.code.HighRegisterPrefix;
 import com.android.dx.dex.code.InsnFormat;
 import com.android.dx.dex.code.SimpleInsn;
 import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 12x}. See the instruction format spec
  * for details.
@@ -109,6 +110,17 @@ public final class Form12x extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int sz = regs.size();
index 5a7ee45..0335dc7 100644 (file)
@@ -27,6 +27,8 @@ import com.android.dx.rop.cst.CstString;
 import com.android.dx.rop.cst.CstType;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 21c}. See the instruction format spec
  * for details.
@@ -116,6 +118,26 @@ public final class Form21c extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        int sz = regs.size();
+        BitSet bits = new BitSet(sz);
+        boolean compat = unsignedFitsInByte(regs.get(0).getReg());
+
+        if (sz == 1) {
+            bits.set(0, compat);
+        } else {
+            if (regs.get(0).getReg() == regs.get(1).getReg()) {
+                bits.set(0, compat);
+                bits.set(1, compat);
+            }
+        }
+
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int cpi = ((CstInsn) insn).getIndex();
index 03ebc29..02cc0fd 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 21h}. See the instruction format spec
  * for details.
@@ -97,6 +99,16 @@ public final class Form21h extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         CstLiteralBits cb = (CstLiteralBits) ((CstInsn) insn).getConstant();
index b7a3f72..9264ec0 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 21s}. See the instruction format spec
  * for details.
@@ -86,6 +88,16 @@ public final class Form21s extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int value =
index d269097..8adb668 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.TargetInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 21t}. See the instruction format spec
  * for details.
@@ -74,6 +76,16 @@ public final class Form21t extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public boolean branchFits(TargetInsn insn) {
         int offset = insn.getTargetOffset();
 
index eb3b884..e5a8b5d 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 22b}. See the instruction format spec
  * for details.
@@ -88,6 +90,17 @@ public final class Form22b extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int value =
index f2a3555..5ffdb86 100644 (file)
@@ -22,10 +22,11 @@ import com.android.dx.dex.code.InsnFormat;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
 import com.android.dx.rop.cst.CstType;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 22c}. See the instruction format spec
  * for details.
@@ -91,6 +92,17 @@ public final class Form22c extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int cpi = ((CstInsn) insn).getIndex();
index 4b67071..03d180a 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 22s}. See the instruction format spec
  * for details.
@@ -88,6 +90,17 @@ public final class Form22s extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int value =
index d216ccc..15ce0f8 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.TargetInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 22t}. See the instruction format spec
  * for details.
@@ -76,6 +78,17 @@ public final class Form22t extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public boolean branchFits(TargetInsn insn) {
         int offset = insn.getTargetOffset();
 
index daf1da2..01eec0b 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.SimpleInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 22x}. See the instruction format spec
  * for details.
@@ -71,6 +73,17 @@ public final class Form22x extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInShort(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         write(out,
index 849e8be..9164482 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.SimpleInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 23x}. See the instruction format spec
  * for details.
@@ -73,6 +75,18 @@ public final class Form23x extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(3);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+        bits.set(2, unsignedFitsInByte(regs.get(2).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         write(out,
index 7383651..3295fda 100644 (file)
@@ -27,6 +27,8 @@ import com.android.dx.rop.cst.CstString;
 import com.android.dx.rop.cst.CstType;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 31c}. See the instruction format spec
  * for details.
@@ -111,6 +113,26 @@ public final class Form31c extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        int sz = regs.size();
+        BitSet bits = new BitSet(sz);
+        boolean compat = unsignedFitsInByte(regs.get(0).getReg());
+
+        if (sz == 1) {
+            bits.set(0, compat);
+        } else {
+            if (regs.get(0).getReg() == regs.get(1).getReg()) {
+                bits.set(0, compat);
+                bits.set(1, compat);
+            }
+        }
+
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int cpi = ((CstInsn) insn).getIndex();
index 7e2583d..b52341d 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 31i}. See the instruction format spec
  * for details.
@@ -84,6 +86,16 @@ public final class Form31i extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int value =
index c7ead27..1999bba 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.TargetInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 31t}. See the instruction format spec
  * for details.
@@ -73,6 +75,16 @@ public final class Form31t extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public boolean branchFits(TargetInsn insn) {
         return true;
     }
index d9118a3..e081470 100644 (file)
@@ -24,6 +24,8 @@ import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 32s}. See the instruction format spec
  * for details.
@@ -92,6 +94,17 @@ public final class Form32s extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int value =
index 87ed6ba..abed0e9 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.SimpleInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 32x}. See the instruction format spec
  * for details.
@@ -70,6 +72,17 @@ public final class Form32x extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInShort(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInShort(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
 
index fb143a4..9a569a0 100644 (file)
@@ -22,6 +22,8 @@ import com.android.dx.dex.code.SimpleInsn;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 33x}. See the instruction format spec
  * for details.
@@ -77,6 +79,18 @@ public final class Form33x extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(3);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+        bits.set(2, unsignedFitsInShort(regs.get(2).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         write(out,
index a8b6f44..b9c12c6 100644 (file)
@@ -27,6 +27,8 @@ import com.android.dx.rop.cst.CstType;
 import com.android.dx.rop.type.Type;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 35c}. See the instruction format spec
  * for details.
@@ -95,6 +97,28 @@ public final class Form35c extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        int sz = regs.size();
+        BitSet bits = new BitSet(sz);
+
+        for (int i = 0; i < sz; i++) {
+            RegisterSpec reg = regs.get(i);
+            /*
+             * The check below adds (category - 1) to the register, to
+             * account for the fact that the second half of a
+             * category-2 register has to be represented explicitly in
+             * the result.
+             */
+            bits.set(i, unsignedFitsInNibble(reg.getReg() +
+                                             reg.getCategory() - 1));
+        }
+
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         int cpi = ((CstInsn) insn).getIndex();
         RegisterSpecList regs = explicitize(insn.getRegisters());
index fde7744..1727af5 100644 (file)
@@ -19,7 +19,6 @@ package com.android.dx.dex.code.form;
 import com.android.dx.dex.code.CstInsn;
 import com.android.dx.dex.code.DalvInsn;
 import com.android.dx.dex.code.InsnFormat;
-import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstMethodRef;
index 65b4bec..24067bc 100644 (file)
@@ -23,10 +23,11 @@ import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
 import com.android.dx.rop.cst.CstType;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 41c}. See the instruction format spec
  * for details.
@@ -114,6 +115,26 @@ public final class Form41c extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        int sz = regs.size();
+        BitSet bits = new BitSet(sz);
+        boolean compat = unsignedFitsInByte(regs.get(0).getReg());
+
+        if (sz == 1) {
+            bits.set(0, compat);
+        } else {
+            if (regs.get(0).getReg() == regs.get(1).getReg()) {
+                bits.set(0, compat);
+                bits.set(1, compat);
+            }
+        }
+
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int cpi = ((CstInsn) insn).getIndex();
index 447351d..4dc7bcd 100644 (file)
@@ -25,6 +25,8 @@ import com.android.dx.rop.cst.CstLiteral64;
 import com.android.dx.rop.cst.CstLiteralBits;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 51l}. See the instruction format spec
  * for details.
@@ -81,6 +83,16 @@ public final class Form51l extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(1);
+
+        bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         long value =
index 7ebeb85..acd2124 100644 (file)
@@ -22,10 +22,11 @@ import com.android.dx.dex.code.InsnFormat;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
 import com.android.dx.rop.cst.CstType;
 import com.android.dx.util.AnnotatedOutput;
 
+import java.util.BitSet;
+
 /**
  * Instruction format {@code 52c}. See the instruction format spec
  * for details.
@@ -90,6 +91,17 @@ public final class Form52c extends InsnFormat {
 
     /** {@inheritDoc} */
     @Override
+    public BitSet compatibleRegs(DalvInsn insn) {
+        RegisterSpecList regs = insn.getRegisters();
+        BitSet bits = new BitSet(2);
+
+        bits.set(0, unsignedFitsInShort(regs.get(0).getReg()));
+        bits.set(1, unsignedFitsInShort(regs.get(1).getReg()));
+        return bits;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
         RegisterSpecList regs = insn.getRegisters();
         int cpi = ((CstInsn) insn).getIndex();
index 4efb98e..0c54702 100644 (file)
@@ -19,7 +19,6 @@ package com.android.dx.dex.code.form;
 import com.android.dx.dex.code.CstInsn;
 import com.android.dx.dex.code.DalvInsn;
 import com.android.dx.dex.code.InsnFormat;
-import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.cst.Constant;
 import com.android.dx.rop.cst.CstMethodRef;
index e900787..3d891fd 100644 (file)
@@ -20,6 +20,8 @@ import com.android.dx.rop.type.Type;
 import com.android.dx.rop.type.TypeList;
 import com.android.dx.util.FixedSizeList;
 
+import java.util.BitSet;
+
 /**
  * List of {@link RegisterSpec} instances.
  */
@@ -291,6 +293,39 @@ public final class RegisterSpecList
     }
 
     /**
+     * Returns a new instance, which contains a subset of the elements
+     * specified by the given BitSet. Indexes in the BitSet with a zero
+     * are included, while indexes with a one are excluded. Mutability
+     * of the result is inherited from the original.
+     *
+     * @param exclusionSet {@code non-null;} set of registers to exclude
+     * @return {@code non-null;} an appropriately-constructed instance
+     */
+    public RegisterSpecList subset(BitSet exclusionSet) {
+        int newSize = size() - exclusionSet.cardinality();
+
+        if (newSize == 0) {
+            return EMPTY;
+        }
+
+        RegisterSpecList result = new RegisterSpecList(newSize);
+
+        int newIndex = 0;
+        for (int oldIndex = 0; oldIndex < size(); oldIndex++) {
+            if (!exclusionSet.get(oldIndex)) {
+                result.set0(newIndex, get0(oldIndex));
+                newIndex++;
+            }
+        }
+
+        if (isImmutable()) {
+            result.setImmutable();
+        }
+
+        return result;
+    }
+
+    /**
      * Returns an instance that is identical to this one, except that
      * all register numbers are offset by the given amount. Mutability
      * of the result is inherited from the original.
@@ -324,15 +359,20 @@ public final class RegisterSpecList
 
     /**
      * Returns an instance that is identical to this one, except that
-     * all register numbers are renumbered sequentially from the given
-     * base, with the first number duplicated if indicated.
+     * all incompatible register numbers are renumbered sequentially from
+     * the given base, with the first number duplicated if indicated. If
+     * a null BitSet is given, it indicates all registers are compatible.
      *
      * @param base the base register number
      * @param duplicateFirst whether to duplicate the first number
+     * @param compatRegs {@code null-ok;} either a {@code non-null} set of
+     * compatible registers, or {@code null} to indicate all registers are
+     * compatible
      * @return {@code non-null;} an appropriately-constructed instance
      */
-    public RegisterSpecList withSequentialRegisters(int base,
-                                                    boolean duplicateFirst) {
+    public RegisterSpecList withExpandedRegisters(int base,
+                                                  boolean duplicateFirst,
+                                                  BitSet compatRegs) {
         int sz = size();
 
         if (sz == 0) {
@@ -344,11 +384,19 @@ public final class RegisterSpecList
 
         for (int i = 0; i < sz; i++) {
             RegisterSpec one = (RegisterSpec) get0(i);
-            result.set0(i, one.withReg(base));
+            boolean replace = (compatRegs == null) ? true : !compatRegs.get(i);
+
+            if (replace) {
+                result.set0(i, one.withReg(base));
+                if (!duplicateFirst) {
+                    base += one.getCategory();
+                }
+            } else {
+                result.set0(i, one);
+            }
+
             if (duplicateFirst) {
                 duplicateFirst = false;
-            } else {
-                base += one.getCategory();
             }
         }
 
@@ -358,5 +406,4 @@ public final class RegisterSpecList
 
         return result;
     }
-
 }
index d9d2c45..afbb285 100644 (file)
@@ -18,31 +18,25 @@ package com.android.dx.ssa.back;
 
 import com.android.dx.rop.code.BasicBlock;
 import com.android.dx.rop.code.BasicBlockList;
-import com.android.dx.rop.code.CstInsn;
 import com.android.dx.rop.code.InsnList;
-import com.android.dx.rop.code.RegOps;
 import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
+import com.android.dx.rop.code.Rop;
 import com.android.dx.rop.code.RopMethod;
 import com.android.dx.rop.code.Rops;
-import com.android.dx.rop.code.Rop;
-import com.android.dx.rop.cst.CstInteger;
-import com.android.dx.ssa.NormalSsaInsn;
 import com.android.dx.ssa.BasicRegisterMapper;
 import com.android.dx.ssa.PhiInsn;
 import com.android.dx.ssa.RegisterMapper;
 import com.android.dx.ssa.SsaBasicBlock;
 import com.android.dx.ssa.SsaInsn;
 import com.android.dx.ssa.SsaMethod;
-import com.android.dx.util.IntList;
 import com.android.dx.util.Hex;
+import com.android.dx.util.IntList;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
 
 /**
  * Converts a method in SSA form to ROP form.