Allow X86 QBE to be extended

Enhancements and updates to allow X86Mir2LIR Backend to be subclassed
for experimentation.  Add virtual in a whole bunch of places, and make
some other changes to get this to work.

Change-Id: I0980a19bc5d5725f91660f98c95f1f51c17ee9b6
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 778a92d..11d2fbe 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -902,7 +902,11 @@
   static const char* extended_mir_op_names_[kMirOpLast - kMirOpFirst];
   static const uint32_t analysis_attributes_[kMirOpLast];
 
- private:
+  void HandleSSADef(int* defs, int dalvik_reg, int reg_index);
+  bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed);
+  void ComputeDFSOrders();
+
+ protected:
   int FindCommonParent(int block1, int block2);
   void ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src1,
                          const ArenaBitVector* src2);
@@ -928,17 +932,14 @@
                               const uint16_t* code_end);
   int AddNewSReg(int v_reg);
   void HandleSSAUse(int* uses, int dalvik_reg, int reg_index);
-  void HandleSSADef(int* defs, int dalvik_reg, int reg_index);
   void DataFlowSSAFormat35C(MIR* mir);
   void DataFlowSSAFormat3RC(MIR* mir);
   bool FindLocalLiveIn(BasicBlock* bb);
-  bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed);
   bool VerifyPredInfo(BasicBlock* bb);
   BasicBlock* NeedsVisit(BasicBlock* bb);
   BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb);
   void MarkPreOrder(BasicBlock* bb);
   void RecordDFSOrders(BasicBlock* bb);
-  void ComputeDFSOrders();
   void ComputeDefBlockMatrix();
   void ComputeDomPostOrderTraversal(BasicBlock* bb);
   void ComputeDominators();
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 350823d..de55a05 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -2082,6 +2082,15 @@
   }
 }
 
+void Mir2Lir::GenConst(RegLocation rl_dest, int value) {
+  RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
+  LoadConstantNoClobber(rl_result.reg, value);
+  StoreValue(rl_dest, rl_result);
+  if (value == 0) {
+    Workaround7250540(rl_dest, rl_result.reg);
+  }
+}
+
 template <size_t pointer_size>
 void Mir2Lir::GenConversionCall(ThreadOffset<pointer_size> func_offset,
                                 RegLocation rl_dest, RegLocation rl_src) {
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 3662592..721b345 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1030,9 +1030,9 @@
         bytes_to_move = sizeof(uint32_t) * 4;
 
         // Allocate a free xmm temp. Since we are working through the calling sequence,
-        // we expect to have an xmm temporary available.
+        // we expect to have an xmm temporary available.  AllocTempDouble will abort if
+        // there are no free registers.
         RegStorage temp = AllocTempDouble();
-        DCHECK(temp.Valid());
 
         LIR* ld1 = nullptr;
         LIR* ld2 = nullptr;
@@ -1702,6 +1702,7 @@
 
   const MirMethodLoweringInfo& method_info = mir_graph_->GetMethodLoweringInfo(info->mir);
   cu_->compiler_driver->ProcessedInvoke(method_info.GetInvokeType(), method_info.StatsFlags());
+  BeginInvoke(info);
   InvokeType original_type = static_cast<InvokeType>(method_info.GetInvokeType());
   info->type = static_cast<InvokeType>(method_info.GetSharpType());
   bool fast_path = method_info.FastPath();
@@ -1766,6 +1767,7 @@
       }
     }
   }
+  EndInvoke(info);
   MarkSafepointPC(call_inst);
 
   ClobberCallerSave();
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index ba6865d..2f37520 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -149,7 +149,7 @@
 /*
  * Set up the proper fields in the resource mask
  */
-inline void Mir2Lir::SetupResourceMasks(LIR* lir) {
+inline void Mir2Lir::SetupResourceMasks(LIR* lir, bool leave_mem_ref) {
   int opcode = lir->opcode;
 
   if (IsPseudoLirOp(opcode)) {
@@ -170,7 +170,7 @@
   lir->flags.size = GetInsnSize(lir);
   estimated_native_code_size_ += lir->flags.size;
   /* Set up the mask for resources that are updated */
-  if (flags & (IS_LOAD | IS_STORE)) {
+  if (!leave_mem_ref && (flags & (IS_LOAD | IS_STORE))) {
     /* Default to heap - will catch specialized classes later */
     SetMemRefType(lir, flags & IS_LOAD, kHeapRef);
   }
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index ea8071d..9fc93d0 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -425,21 +425,11 @@
     case Instruction::CONST:
     case Instruction::CONST_4:
     case Instruction::CONST_16:
-      rl_result = EvalLoc(rl_dest, kAnyReg, true);
-      LoadConstantNoClobber(rl_result.reg, vB);
-      StoreValue(rl_dest, rl_result);
-      if (vB == 0) {
-        Workaround7250540(rl_dest, rl_result.reg);
-      }
+      GenConst(rl_dest, vB);
       break;
 
     case Instruction::CONST_HIGH16:
-      rl_result = EvalLoc(rl_dest, kAnyReg, true);
-      LoadConstantNoClobber(rl_result.reg, vB << 16);
-      StoreValue(rl_dest, rl_result);
-      if (vB == 0) {
-        Workaround7250540(rl_dest, rl_result.reg);
-      }
+      GenConst(rl_dest, vB << 16);
       break;
 
     case Instruction::CONST_WIDE_16:
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 687c41d..7f0bf30 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -485,6 +485,7 @@
       LIRSlowPath(Mir2Lir* m2l, const DexOffset dexpc, LIR* fromfast,
                   LIR* cont = nullptr) :
         m2l_(m2l), cu_(m2l->cu_), current_dex_pc_(dexpc), fromfast_(fromfast), cont_(cont) {
+          m2l->StartSlowPath(cont);
       }
       virtual ~LIRSlowPath() {}
       virtual void Compile() = 0;
@@ -493,6 +494,14 @@
         return arena->Alloc(size, kArenaAllocData);
       }
 
+      LIR *GetContinuationLabel() {
+        return cont_;
+      }
+
+      LIR *GetFromFast() {
+        return fromfast_;
+      }
+
      protected:
       LIR* GenerateTargetLabel(int opcode = kPseudoTargetLabel);
 
@@ -583,7 +592,7 @@
     virtual void Materialize();
     virtual CompiledMethod* GetCompiledMethod();
     void MarkSafepointPC(LIR* inst);
-    void SetupResourceMasks(LIR* lir);
+    void SetupResourceMasks(LIR* lir, bool leave_mem_ref = false);
     void SetMemRefType(LIR* lir, bool is_load, int mem_type);
     void AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load, bool is64bit);
     void SetupRegMask(uint64_t* mask, int reg);
@@ -625,6 +634,12 @@
     LIR* InsertCaseLabel(DexOffset vaddr, int keyVal);
     void MarkPackedCaseLabels(Mir2Lir::SwitchTable* tab_rec);
     void MarkSparseCaseLabels(Mir2Lir::SwitchTable* tab_rec);
+
+    virtual void StartSlowPath(LIR *label) {}
+    virtual void BeginInvoke(CallInfo* info) {}
+    virtual void EndInvoke(CallInfo* info) {}
+
+
     // Handle bookkeeping to convert a wide RegLocation to a narow RegLocation.  No code generated.
     RegLocation NarrowRegLoc(RegLocation loc);
 
@@ -632,7 +647,7 @@
     void ConvertMemOpIntoMove(LIR* orig_lir, RegStorage dest, RegStorage src);
     void ApplyLoadStoreElimination(LIR* head_lir, LIR* tail_lir);
     void ApplyLoadHoisting(LIR* head_lir, LIR* tail_lir);
-    void ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir);
+    virtual void ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir);
 
     // Shared by all targets - implemented in ralloc_util.cc
     int GetSRegHi(int lowSreg);
@@ -656,18 +671,18 @@
     RegStorage AllocPreservedSingle(int s_reg);
     virtual RegStorage AllocPreservedDouble(int s_reg);
     RegStorage AllocTempBody(GrowableArray<RegisterInfo*> &regs, int* next_temp, bool required);
-    RegStorage AllocFreeTemp();
-    RegStorage AllocTemp();
-    RegStorage AllocTempSingle();
-    RegStorage AllocTempDouble();
+    virtual RegStorage AllocFreeTemp();
+    virtual RegStorage AllocTemp();
+    virtual RegStorage AllocTempSingle();
+    virtual RegStorage AllocTempDouble();
     void FlushReg(RegStorage reg);
     void FlushRegWide(RegStorage reg);
     RegStorage AllocLiveReg(int s_reg, int reg_class, bool wide);
     RegStorage FindLiveReg(GrowableArray<RegisterInfo*> &regs, int s_reg);
-    void FreeTemp(RegStorage reg);
-    void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
-    bool IsLive(RegStorage reg);
-    bool IsTemp(RegStorage reg);
+    virtual void FreeTemp(RegStorage reg);
+    virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
+    virtual bool IsLive(RegStorage reg);
+    virtual bool IsTemp(RegStorage reg);
     bool IsPromoted(RegStorage reg);
     bool IsDirty(RegStorage reg);
     void LockTemp(RegStorage reg);
@@ -675,7 +690,7 @@
     void NullifyRange(RegStorage reg, int s_reg);
     void MarkDef(RegLocation rl, LIR *start, LIR *finish);
     void MarkDefWide(RegLocation rl, LIR *start, LIR *finish);
-    RegLocation WideToNarrow(RegLocation rl);
+    virtual RegLocation WideToNarrow(RegLocation rl);
     void ResetDefLoc(RegLocation rl);
     void ResetDefLocWide(RegLocation rl);
     void ResetDefTracking();
@@ -692,8 +707,8 @@
     void MarkDirty(RegLocation loc);
     void MarkInUse(RegStorage reg);
     bool CheckCorePoolSanity();
-    RegLocation UpdateLoc(RegLocation loc);
-    RegLocation UpdateLocWide(RegLocation loc);
+    virtual RegLocation UpdateLoc(RegLocation loc);
+    virtual RegLocation UpdateLocWide(RegLocation loc);
     RegLocation UpdateRawLoc(RegLocation loc);
 
     /**
@@ -704,7 +719,7 @@
      * @param update Whether the liveness information should be updated.
      * @return Returns the properly typed temporary in physical register pairs.
      */
-    RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update);
+    virtual RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update);
 
     /**
      * @brief Used to prepare a register location to receive a value.
@@ -713,7 +728,7 @@
      * @param update Whether the liveness information should be updated.
      * @return Returns the properly typed temporary in physical register.
      */
-    RegLocation EvalLoc(RegLocation loc, int reg_class, bool update);
+    virtual RegLocation EvalLoc(RegLocation loc, int reg_class, bool update);
 
     void CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs);
     void DumpCounts(const RefCounts* arr, int size, const char* msg);
@@ -729,7 +744,7 @@
     bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
                           RegLocation rl_src, RegLocation rl_dest, int lit);
     bool HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit);
-    void HandleSlowPaths();
+    virtual void HandleSlowPaths();
     void GenBarrier();
     void GenDivZeroException();
     // c_code holds condition code that's generated from testing divisor against 0.
@@ -783,8 +798,8 @@
     template <size_t pointer_size>
     void GenConversionCall(ThreadOffset<pointer_size> func_offset, RegLocation rl_dest,
                            RegLocation rl_src);
-    void GenSuspendTest(int opt_flags);
-    void GenSuspendTestAndBranch(int opt_flags, LIR* target);
+    virtual void GenSuspendTest(int opt_flags);
+    virtual void GenSuspendTestAndBranch(int opt_flags, LIR* target);
 
     // This will be overridden by x86 implementation.
     virtual void GenConstWide(RegLocation rl_dest, int64_t value);
@@ -914,41 +929,41 @@
     // Shared by all targets - implemented in gen_loadstore.cc.
     RegLocation LoadCurrMethod();
     void LoadCurrMethodDirect(RegStorage r_tgt);
-    LIR* LoadConstant(RegStorage r_dest, int value);
+    virtual LIR* LoadConstant(RegStorage r_dest, int value);
     // Natural word size.
-    LIR* LoadWordDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
+    virtual LIR* LoadWordDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
       return LoadBaseDisp(r_base, displacement, r_dest, kWord);
     }
     // Load 32 bits, regardless of target.
-    LIR* Load32Disp(RegStorage r_base, int displacement, RegStorage r_dest)  {
+    virtual LIR* Load32Disp(RegStorage r_base, int displacement, RegStorage r_dest)  {
       return LoadBaseDisp(r_base, displacement, r_dest, k32);
     }
     // Load a reference at base + displacement and decompress into register.
-    LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
+    virtual LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
       return LoadBaseDisp(r_base, displacement, r_dest, kReference);
     }
     // Load Dalvik value with 32-bit memory storage.  If compressed object reference, decompress.
-    RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind);
+    virtual RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind);
     // Load Dalvik value with 64-bit memory storage.
-    RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind);
+    virtual RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind);
     // Load Dalvik value with 32-bit memory storage.  If compressed object reference, decompress.
-    void LoadValueDirect(RegLocation rl_src, RegStorage r_dest);
+    virtual void LoadValueDirect(RegLocation rl_src, RegStorage r_dest);
     // Load Dalvik value with 32-bit memory storage.  If compressed object reference, decompress.
-    void LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest);
+    virtual void LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest);
     // Load Dalvik value with 64-bit memory storage.
-    void LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest);
+    virtual void LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest);
     // Load Dalvik value with 64-bit memory storage.
-    void LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest);
+    virtual void LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest);
     // Store an item of natural word size.
-    LIR* StoreWordDisp(RegStorage r_base, int displacement, RegStorage r_src) {
+    virtual LIR* StoreWordDisp(RegStorage r_base, int displacement, RegStorage r_src) {
       return StoreBaseDisp(r_base, displacement, r_src, kWord);
     }
     // Store an uncompressed reference into a compressed 32-bit container.
-    LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src) {
+    virtual LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src) {
       return StoreBaseDisp(r_base, displacement, r_src, kReference);
     }
     // Store 32 bits, regardless of target.
-    LIR* Store32Disp(RegStorage r_base, int displacement, RegStorage r_src) {
+    virtual LIR* Store32Disp(RegStorage r_base, int displacement, RegStorage r_src) {
       return StoreBaseDisp(r_base, displacement, r_src, k32);
     }
 
@@ -957,7 +972,7 @@
      * @param rl_dest The destination dalvik register location.
      * @param rl_src The source register location. Can be either physical register or dalvik register.
      */
-    void StoreValue(RegLocation rl_dest, RegLocation rl_src);
+    virtual void StoreValue(RegLocation rl_dest, RegLocation rl_src);
 
     /**
      * @brief Used to do the final store in a wide destination as per bytecode semantics.
@@ -966,7 +981,7 @@
      * @param rl_src The source register location. Can be either physical register or dalvik
      *  register.
      */
-    void StoreValueWide(RegLocation rl_dest, RegLocation rl_src);
+    virtual void StoreValueWide(RegLocation rl_dest, RegLocation rl_src);
 
     /**
      * @brief Used to do the final store to a destination as per bytecode semantics.
@@ -978,7 +993,7 @@
      * register value that now needs to be properly registered.  This is used to avoid an
      * extra register copy that would result if StoreValue was called.
      */
-    void StoreFinalValue(RegLocation rl_dest, RegLocation rl_src);
+    virtual void StoreFinalValue(RegLocation rl_dest, RegLocation rl_src);
 
     /**
      * @brief Used to do the final store in a wide destination as per bytecode semantics.
@@ -990,14 +1005,14 @@
      * register values that now need to be properly registered.  This is used to avoid an
      * extra pair of register copies that would result if StoreValueWide was called.
      */
-    void StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src);
+    virtual void StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src);
 
     // Shared by all targets - implemented in mir_to_lir.cc.
     void CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list);
-    void HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir);
+    virtual void HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir);
     bool MethodBlockCodeGen(BasicBlock* bb);
     bool SpecialMIR2LIR(const InlineMethod& special);
-    void MethodMIR2LIR();
+    virtual void MethodMIR2LIR();
     // Update LIR for verbose listings.
     void UpdateLIROffsets();
 
@@ -1345,14 +1360,14 @@
      * @param loc location of result
      * @returns update location
      */
-    RegLocation ForceTemp(RegLocation loc);
+    virtual RegLocation ForceTemp(RegLocation loc);
 
     /*
      * @brief Force a wide location (in registers) into temporary registers
      * @param loc location of result
      * @returns update location
      */
-    RegLocation ForceTempWide(RegLocation loc);
+    virtual RegLocation ForceTempWide(RegLocation loc);
 
     static constexpr OpSize LoadStoreOpSize(bool wide, bool ref) {
       return wide ? k64 : ref ? kReference : k32;
@@ -1398,7 +1413,7 @@
      */
     virtual bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
 
-  private:
+  protected:
     void ClobberBody(RegisterInfo* p);
     void SetCurrentDexPc(DexOffset dexpc) {
       current_dalvik_offset_ = dexpc;
@@ -1457,7 +1472,14 @@
 
     // Copy arg0 and arg1 to kArg0 and kArg1 safely, possibly using
     // kArg2 as temp.
-    void CopyToArgumentRegs(RegStorage arg0, RegStorage arg1);
+    virtual void CopyToArgumentRegs(RegStorage arg0, RegStorage arg1);
+
+    /**
+     * @brief Load Constant into RegLocation
+     * @param rl_dest Destination RegLocation
+     * @param value Constant value
+     */
+    virtual void GenConst(RegLocation rl_dest, int value);
 
   public:
     // TODO: add accessors for these.
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 52c870b..e717638 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -22,7 +22,7 @@
 
 namespace art {
 
-class X86Mir2Lir FINAL : public Mir2Lir {
+class X86Mir2Lir : public Mir2Lir {
   public:
     X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena, bool gen64bit);
 
@@ -175,8 +175,8 @@
       * @param op The DEX opcode for the operation.
       * @param is_commutative The sources can be swapped if needed.
       */
-    void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
-                      Instruction::Code op, bool is_commutative);
+    virtual void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
+                              Instruction::Code op, bool is_commutative);
 
     /**
       * @brief Generate a two operand long arithmetic operation.
@@ -192,7 +192,7 @@
       * @param rl_src The other operand.  May be in a register or in memory.
       * @param op The DEX opcode for the operation.
       */
-    void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
+    virtual void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
 
     /**
      * @brief Implement instanceof a final class with x86 specific code.
@@ -265,6 +265,12 @@
     bool InexpensiveConstantDouble(int64_t value);
 
     /*
+     * @brief Should try to optimize for two address instructions?
+     * @return true if we try to avoid generating three operand instructions.
+     */
+    virtual bool GenerateTwoOperandInstructions() const { return true; }
+
+    /*
      * @brief x86 specific codegen for int operations.
      * @param opcode Operation to perform.
      * @param rl_dest Destination for the result.
@@ -304,7 +310,7 @@
      * @param type How the method will be invoked.
      * @returns Call instruction
      */
-    LIR * CallWithLinkerFixup(const MethodReference& target_method, InvokeType type);
+    virtual LIR * CallWithLinkerFixup(const MethodReference& target_method, InvokeType type);
 
     /*
      * @brief Handle x86 specific literals
@@ -323,7 +329,7 @@
      */
     std::vector<uint8_t>* ReturnCallFrameInformation();
 
-  private:
+  protected:
     size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib);
     void EmitPrefix(const X86EncodingMap* entry);
     void EmitOpcode(const X86EncodingMap* entry);
@@ -398,6 +404,12 @@
     static bool ProvidesFullMemoryBarrier(X86OpCode opcode);
 
     /*
+     * @brief Ensure that a temporary register is byte addressable.
+     * @returns a temporary guarenteed to be byte addressable.
+     */
+    virtual RegStorage AllocateByteRegister();
+
+    /*
      * @brief generate inline code for fast case of Strng.indexOf.
      * @param info Call parameters
      * @param zero_based 'true' if the index into the string is 0.
@@ -533,7 +545,7 @@
      * @param rl_src The source of the long.
      * @param is_double 'true' if dealing with double, 'false' for float.
      */
-    void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double);
+    virtual void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double);
 
     /*
      * @brief Perform MIR analysis before compiling method.
@@ -579,7 +591,7 @@
      * @param bb Basic block containing instruction.
      * @param mir Instruction to analyze.
      */
-    void AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir);
+    virtual void AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir);
 
     /*
      * @brief Analyze one MIR float/double instruction
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 71a3962..a6ccc99 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1292,8 +1292,12 @@
     case Instruction::AND_LONG_2ADDR:
     case Instruction::OR_LONG_2ADDR:
     case Instruction::XOR_LONG_2ADDR:
-      GenLongArith(rl_dest, rl_src2, op);
-      return;
+      if (GenerateTwoOperandInstructions()) {
+        GenLongArith(rl_dest, rl_src2, op);
+        return;
+      }
+      break;
+
     default:
       break;
   }
@@ -1532,7 +1536,7 @@
 
 RegLocation X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
                                           RegLocation rl_src, int shift_amount) {
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+  RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
   switch (opcode) {
     case Instruction::SHL_LONG:
     case Instruction::SHL_LONG_2ADDR:
@@ -1641,7 +1645,11 @@
     case Instruction::XOR_LONG_2ADDR:
     case Instruction::AND_LONG_2ADDR:
       if (rl_src2.is_const) {
-        GenLongImm(rl_dest, rl_src2, opcode);
+        if (GenerateTwoOperandInstructions()) {
+          GenLongImm(rl_dest, rl_src2, opcode);
+        } else {
+          GenLongLongImm(rl_dest, rl_src1, rl_src2, opcode);
+        }
       } else {
         DCHECK(rl_src1.is_const);
         GenLongLongImm(rl_dest, rl_src2, rl_src1, opcode);
@@ -1869,7 +1877,7 @@
 
   // SETcc only works with EAX..EDX.
   if (result_reg == object.reg || result_reg.GetRegNum() >= rs_rX86_SP.GetRegNum()) {
-    result_reg = AllocTypedTemp(false, kCoreReg);
+    result_reg = AllocateByteRegister();
     DCHECK_LT(result_reg.GetRegNum(), rs_rX86_SP.GetRegNum());
   }
 
@@ -2110,12 +2118,16 @@
       LOG(FATAL) << "Invalid word arith op: " << opcode;
   }
 
-    // Can we convert to a two address instruction?
+  // Can we convert to a two address instruction?
   if (!is_two_addr &&
         (mir_graph_->SRegToVReg(rl_dest.s_reg_low) ==
          mir_graph_->SRegToVReg(rl_lhs.s_reg_low))) {
-      is_two_addr = true;
-    }
+    is_two_addr = true;
+  }
+
+  if (!GenerateTwoOperandInstructions()) {
+    is_two_addr = false;
+  }
 
   // Get the div/rem stuff out of the way.
   if (is_div_rem) {
@@ -2212,6 +2224,8 @@
             if (mir_graph_->SRegToVReg(rl_dest.s_reg_low) == mir_graph_->SRegToVReg(rl_lhs.s_reg_low)) {
               rl_lhs = LoadValue(rl_lhs, kCoreReg);
               rl_result = EvalLoc(rl_dest, kCoreReg, true);
+              // No-op if these are the same.
+              OpRegCopy(rl_result.reg, rl_lhs.reg);
             } else {
               rl_result = EvalLoc(rl_dest, kCoreReg, true);
               LoadValueDirect(rl_lhs, rl_result.reg);
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 8f06791..9ddeb68 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -423,6 +423,10 @@
   UNIMPLEMENTED(FATAL) << "MarkPreservedDouble";
 }
 
+RegStorage X86Mir2Lir::AllocateByteRegister() {
+  return AllocTypedTemp(false, kCoreReg);
+}
+
 /* Clobber all regs that might be used by an external C call */
 void X86Mir2Lir::ClobberCallerSave() {
   Clobber(rs_rAX);
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index e9592a6..fed31c1 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -161,6 +161,22 @@
       case kOpMul:
         opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
         return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value);
+      case kOp2Byte:
+        opcode = kX86Mov32RI;
+        value = static_cast<int8_t>(value);
+        break;
+      case kOp2Short:
+        opcode = kX86Mov32RI;
+        value = static_cast<int16_t>(value);
+        break;
+      case kOp2Char:
+        opcode = kX86Mov32RI;
+        value = static_cast<uint16_t>(value);
+        break;
+      case kOpNeg:
+        opcode = kX86Mov32RI;
+        value = -value;
+        break;
       default:
         LOG(FATAL) << "Bad case in OpRegImm " << op;
     }
@@ -523,7 +539,7 @@
     int32_t val_hi = High32Bits(value);
     int32_t low_reg_val = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
     LIR *res;
-    bool is_fp = RegStorage::IsFloat(low_reg_val);
+    bool is_fp = r_dest.IsFloat();
     // TODO: clean this up once we fully recognize 64-bit storage containers.
     if (is_fp) {
       if (value == 0) {