Home | History | Annotate | Download | only in quick
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "mir_to_lir-inl.h"
     18 
     19 #include <functional>
     20 
     21 #include "arch/arm/instruction_set_features_arm.h"
     22 #include "base/bit_utils.h"
     23 #include "base/macros.h"
     24 #include "dex/compiler_ir.h"
     25 #include "dex/mir_graph.h"
     26 #include "dex/quick/arm/arm_lir.h"
     27 #include "driver/compiler_driver.h"
     28 #include "driver/compiler_options.h"
     29 #include "entrypoints/quick/quick_entrypoints.h"
     30 #include "mirror/array.h"
     31 #include "mirror/object_array-inl.h"
     32 #include "mirror/object-inl.h"
     33 #include "mirror/object_reference.h"
     34 #include "utils/dex_cache_arrays_layout-inl.h"
     35 #include "verifier/method_verifier.h"
     36 
     37 namespace art {
     38 
     39 // Shortcuts to repeatedly used long types.
     40 typedef mirror::ObjectArray<mirror::Object> ObjArray;
     41 typedef mirror::ObjectArray<mirror::Class> ClassArray;
     42 
     43 /*
     44  * This source files contains "gen" codegen routines that should
     45  * be applicable to most targets.  Only mid-level support utilities
     46  * and "op" calls may be used here.
     47  */
     48 
     49 ALWAYS_INLINE static inline bool ForceSlowFieldPath(CompilationUnit* cu) {
     50   return (cu->enable_debug & (1 << kDebugSlowFieldPath)) != 0;
     51 }
     52 
     53 ALWAYS_INLINE static inline bool ForceSlowStringPath(CompilationUnit* cu) {
     54   return (cu->enable_debug & (1 << kDebugSlowStringPath)) != 0;
     55 }
     56 
     57 ALWAYS_INLINE static inline bool ForceSlowTypePath(CompilationUnit* cu) {
     58   return (cu->enable_debug & (1 << kDebugSlowTypePath)) != 0;
     59 }
     60 
     61 void Mir2Lir::GenIfNullUseHelperImm(RegStorage r_result, QuickEntrypointEnum trampoline, int imm) {
     62   class CallHelperImmMethodSlowPath : public LIRSlowPath {
     63    public:
     64     CallHelperImmMethodSlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont,
     65                                 QuickEntrypointEnum trampoline_in, int imm_in,
     66                                 RegStorage r_result_in)
     67         : LIRSlowPath(m2l, fromfast, cont), trampoline_(trampoline_in),
     68           imm_(imm_in), r_result_(r_result_in) {
     69     }
     70 
     71     void Compile() {
     72       GenerateTargetLabel();
     73       m2l_->CallRuntimeHelperImm(trampoline_, imm_, true);
     74       m2l_->OpRegCopy(r_result_,  m2l_->TargetReg(kRet0, kRef));
     75       m2l_->OpUnconditionalBranch(cont_);
     76     }
     77 
     78    private:
     79     QuickEntrypointEnum trampoline_;
     80     const int imm_;
     81     const RegStorage r_result_;
     82   };
     83 
     84   LIR* branch = OpCmpImmBranch(kCondEq, r_result, 0, nullptr);
     85   LIR* cont = NewLIR0(kPseudoTargetLabel);
     86 
     87   AddSlowPath(new (arena_) CallHelperImmMethodSlowPath(this, branch, cont, trampoline, imm,
     88                                                        r_result));
     89 }
     90 
     91 RegStorage Mir2Lir::GenGetOtherTypeForSgetSput(const MirSFieldLoweringInfo& field_info,
     92                                                int opt_flags) {
     93   DCHECK_NE(field_info.StorageIndex(), DexFile::kDexNoIndex);
     94   // May do runtime call so everything to home locations.
     95   FlushAllRegs();
     96   RegStorage r_base = TargetReg(kArg0, kRef);
     97   LockTemp(r_base);
     98   if (CanUseOpPcRelDexCacheArrayLoad()) {
     99     uint32_t offset = dex_cache_arrays_layout_.TypeOffset(field_info.StorageIndex());
    100     OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, r_base, false);
    101   } else {
    102     // Using fixed register to sync with possible call to runtime support.
    103     RegStorage r_method = LoadCurrMethodWithHint(r_base);
    104     LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
    105                 kNotVolatile);
    106     int32_t offset_of_field = ObjArray::OffsetOfElement(field_info.StorageIndex()).Int32Value();
    107     LoadRefDisp(r_base, offset_of_field, r_base, kNotVolatile);
    108   }
    109   // r_base now points at static storage (Class*) or null if the type is not yet resolved.
    110   LIR* unresolved_branch = nullptr;
    111   if (!field_info.IsClassInDexCache() && (opt_flags & MIR_CLASS_IS_IN_DEX_CACHE) == 0) {
    112     // Check if r_base is null.
    113     unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, nullptr);
    114   }
    115   LIR* uninit_branch = nullptr;
    116   if (!field_info.IsClassInitialized() && (opt_flags & MIR_CLASS_IS_INITIALIZED) == 0) {
    117     // Check if r_base is not yet initialized class.
    118     RegStorage r_tmp = TargetReg(kArg2, kNotWide);
    119     LockTemp(r_tmp);
    120     uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
    121                                       mirror::Class::StatusOffset().Int32Value(),
    122                                       mirror::Class::kStatusInitialized, nullptr, nullptr);
    123     FreeTemp(r_tmp);
    124   }
    125   if (unresolved_branch != nullptr || uninit_branch != nullptr) {
    126     //
    127     // Slow path to ensure a class is initialized for sget/sput.
    128     //
    129     class StaticFieldSlowPath : public Mir2Lir::LIRSlowPath {
    130      public:
    131       // There are up to two branches to the static field slow path, the "unresolved" when the type
    132       // entry in the dex cache is null, and the "uninit" when the class is not yet initialized.
    133       // At least one will be non-null here, otherwise we wouldn't generate the slow path.
    134       StaticFieldSlowPath(Mir2Lir* m2l, LIR* unresolved, LIR* uninit, LIR* cont, int storage_index,
    135                           RegStorage r_base_in)
    136           : LIRSlowPath(m2l, unresolved != nullptr ? unresolved : uninit, cont),
    137             second_branch_(unresolved != nullptr ? uninit : nullptr),
    138             storage_index_(storage_index), r_base_(r_base_in) {
    139       }
    140 
    141       void Compile() {
    142         LIR* target = GenerateTargetLabel();
    143         if (second_branch_ != nullptr) {
    144           second_branch_->target = target;
    145         }
    146         m2l_->CallRuntimeHelperImm(kQuickInitializeStaticStorage, storage_index_, true);
    147         // Copy helper's result into r_base, a no-op on all but MIPS.
    148         m2l_->OpRegCopy(r_base_,  m2l_->TargetReg(kRet0, kRef));
    149 
    150         m2l_->OpUnconditionalBranch(cont_);
    151       }
    152 
    153      private:
    154       // Second branch to the slow path, or null if there's only one branch.
    155       LIR* const second_branch_;
    156 
    157       const int storage_index_;
    158       const RegStorage r_base_;
    159     };
    160 
    161     // The slow path is invoked if the r_base is null or the class pointed
    162     // to by it is not initialized.
    163     LIR* cont = NewLIR0(kPseudoTargetLabel);
    164     AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont,
    165                                                  field_info.StorageIndex(), r_base));
    166   }
    167   return r_base;
    168 }
    169 
    170 /*
    171  * Generate a kPseudoBarrier marker to indicate the boundary of special
    172  * blocks.
    173  */
    174 void Mir2Lir::GenBarrier() {
    175   LIR* barrier = NewLIR0(kPseudoBarrier);
    176   /* Mark all resources as being clobbered */
    177   DCHECK(!barrier->flags.use_def_invalid);
    178   barrier->u.m.def_mask = &kEncodeAll;
    179 }
    180 
    181 void Mir2Lir::GenDivZeroException() {
    182   LIR* branch = OpUnconditionalBranch(nullptr);
    183   AddDivZeroCheckSlowPath(branch);
    184 }
    185 
    186 void Mir2Lir::GenDivZeroCheck(ConditionCode c_code) {
    187   LIR* branch = OpCondBranch(c_code, nullptr);
    188   AddDivZeroCheckSlowPath(branch);
    189 }
    190 
    191 void Mir2Lir::GenDivZeroCheck(RegStorage reg) {
    192   LIR* branch = OpCmpImmBranch(kCondEq, reg, 0, nullptr);
    193   AddDivZeroCheckSlowPath(branch);
    194 }
    195 
    196 void Mir2Lir::AddDivZeroCheckSlowPath(LIR* branch) {
    197   class DivZeroCheckSlowPath : public Mir2Lir::LIRSlowPath {
    198    public:
    199     DivZeroCheckSlowPath(Mir2Lir* m2l, LIR* branch_in)
    200         : LIRSlowPath(m2l, branch_in) {
    201     }
    202 
    203     void Compile() OVERRIDE {
    204       m2l_->ResetRegPool();
    205       m2l_->ResetDefTracking();
    206       GenerateTargetLabel(kPseudoThrowTarget);
    207       m2l_->CallRuntimeHelper(kQuickThrowDivZero, true);
    208     }
    209   };
    210 
    211   AddSlowPath(new (arena_) DivZeroCheckSlowPath(this, branch));
    212 }
    213 
    214 void Mir2Lir::GenArrayBoundsCheck(RegStorage index, RegStorage length) {
    215   class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
    216    public:
    217     ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch_in, RegStorage index_in,
    218                              RegStorage length_in)
    219         : LIRSlowPath(m2l, branch_in),
    220           index_(index_in), length_(length_in) {
    221     }
    222 
    223     void Compile() OVERRIDE {
    224       m2l_->ResetRegPool();
    225       m2l_->ResetDefTracking();
    226       GenerateTargetLabel(kPseudoThrowTarget);
    227       m2l_->CallRuntimeHelperRegReg(kQuickThrowArrayBounds, index_, length_, true);
    228     }
    229 
    230    private:
    231     const RegStorage index_;
    232     const RegStorage length_;
    233   };
    234 
    235   LIR* branch = OpCmpBranch(kCondUge, index, length, nullptr);
    236   AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length));
    237 }
    238 
    239 void Mir2Lir::GenArrayBoundsCheck(int index, RegStorage length) {
    240   class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
    241    public:
    242     ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch_in, int index_in, RegStorage length_in)
    243         : LIRSlowPath(m2l, branch_in),
    244           index_(index_in), length_(length_in) {
    245     }
    246 
    247     void Compile() OVERRIDE {
    248       m2l_->ResetRegPool();
    249       m2l_->ResetDefTracking();
    250       GenerateTargetLabel(kPseudoThrowTarget);
    251 
    252       RegStorage arg1_32 = m2l_->TargetReg(kArg1, kNotWide);
    253       RegStorage arg0_32 = m2l_->TargetReg(kArg0, kNotWide);
    254 
    255       m2l_->OpRegCopy(arg1_32, length_);
    256       m2l_->LoadConstant(arg0_32, index_);
    257       m2l_->CallRuntimeHelperRegReg(kQuickThrowArrayBounds, arg0_32, arg1_32, true);
    258     }
    259 
    260    private:
    261     const int32_t index_;
    262     const RegStorage length_;
    263   };
    264 
    265   LIR* branch = OpCmpImmBranch(kCondLs, length, index, nullptr);
    266   AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length));
    267 }
    268 
    269 LIR* Mir2Lir::GenNullCheck(RegStorage reg) {
    270   class NullCheckSlowPath : public Mir2Lir::LIRSlowPath {
    271    public:
    272     NullCheckSlowPath(Mir2Lir* m2l, LIR* branch)
    273         : LIRSlowPath(m2l, branch) {
    274     }
    275 
    276     void Compile() OVERRIDE {
    277       m2l_->ResetRegPool();
    278       m2l_->ResetDefTracking();
    279       GenerateTargetLabel(kPseudoThrowTarget);
    280       m2l_->CallRuntimeHelper(kQuickThrowNullPointer, true);
    281     }
    282   };
    283 
    284   LIR* branch = OpCmpImmBranch(kCondEq, reg, 0, nullptr);
    285   AddSlowPath(new (arena_) NullCheckSlowPath(this, branch));
    286   return branch;
    287 }
    288 
    289 /* Perform null-check on a register.  */
    290 LIR* Mir2Lir::GenNullCheck(RegStorage m_reg, int opt_flags) {
    291   if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
    292     return GenExplicitNullCheck(m_reg, opt_flags);
    293   }
    294   // If null check has not been eliminated, reset redundant store tracking.
    295   if ((opt_flags & MIR_IGNORE_NULL_CHECK) == 0) {
    296     ResetDefTracking();
    297   }
    298   return nullptr;
    299 }
    300 
    301 /* Perform an explicit null-check on a register.  */
    302 LIR* Mir2Lir::GenExplicitNullCheck(RegStorage m_reg, int opt_flags) {
    303   if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
    304     return nullptr;
    305   }
    306   return GenNullCheck(m_reg);
    307 }
    308 
    309 void Mir2Lir::MarkPossibleNullPointerException(int opt_flags) {
    310   if (cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
    311     if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
    312       return;
    313     }
    314     // Insert after last instruction.
    315     MarkSafepointPC(last_lir_insn_);
    316   }
    317 }
    318 
    319 void Mir2Lir::MarkPossibleNullPointerExceptionAfter(int opt_flags, LIR* after) {
    320   if (cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
    321     if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
    322       return;
    323     }
    324     MarkSafepointPCAfter(after);
    325   }
    326 }
    327 
    328 void Mir2Lir::MarkPossibleStackOverflowException() {
    329   if (cu_->compiler_driver->GetCompilerOptions().GetImplicitStackOverflowChecks()) {
    330     MarkSafepointPC(last_lir_insn_);
    331   }
    332 }
    333 
    334 void Mir2Lir::ForceImplicitNullCheck(RegStorage reg, int opt_flags) {
    335   if (cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
    336     if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
    337       return;
    338     }
    339     // Force an implicit null check by performing a memory operation (load) from the given
    340     // register with offset 0.  This will cause a signal if the register contains 0 (null).
    341     RegStorage tmp = AllocTemp();
    342     // TODO: for Mips, would be best to use rZERO as the bogus register target.
    343     LIR* load = Load32Disp(reg, 0, tmp);
    344     FreeTemp(tmp);
    345     MarkSafepointPC(load);
    346   }
    347 }
    348 
    349 void Mir2Lir::GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1,
    350                                   RegLocation rl_src2, LIR* taken) {
    351   ConditionCode cond;
    352   RegisterClass reg_class = (rl_src1.ref || rl_src2.ref) ? kRefReg : kCoreReg;
    353   switch (opcode) {
    354     case Instruction::IF_EQ:
    355       cond = kCondEq;
    356       break;
    357     case Instruction::IF_NE:
    358       cond = kCondNe;
    359       break;
    360     case Instruction::IF_LT:
    361       cond = kCondLt;
    362       break;
    363     case Instruction::IF_GE:
    364       cond = kCondGe;
    365       break;
    366     case Instruction::IF_GT:
    367       cond = kCondGt;
    368       break;
    369     case Instruction::IF_LE:
    370       cond = kCondLe;
    371       break;
    372     default:
    373       cond = static_cast<ConditionCode>(0);
    374       LOG(FATAL) << "Unexpected opcode " << opcode;
    375   }
    376 
    377   // Normalize such that if either operand is constant, src2 will be constant
    378   if (rl_src1.is_const) {
    379     RegLocation rl_temp = rl_src1;
    380     rl_src1 = rl_src2;
    381     rl_src2 = rl_temp;
    382     cond = FlipComparisonOrder(cond);
    383   }
    384 
    385   rl_src1 = LoadValue(rl_src1, reg_class);
    386   // Is this really an immediate comparison?
    387   if (rl_src2.is_const) {
    388     // If it's already live in a register or not easily materialized, just keep going
    389     RegLocation rl_temp = UpdateLoc(rl_src2);
    390     int32_t constant_value = mir_graph_->ConstantValue(rl_src2);
    391     if ((rl_temp.location == kLocDalvikFrame) &&
    392         InexpensiveConstantInt(constant_value, opcode)) {
    393       // OK - convert this to a compare immediate and branch
    394       OpCmpImmBranch(cond, rl_src1.reg, mir_graph_->ConstantValue(rl_src2), taken);
    395       return;
    396     }
    397 
    398     // It's also commonly more efficient to have a test against zero with Eq/Ne. This is not worse
    399     // for x86, and allows a cbz/cbnz for Arm and Mips. At the same time, it works around a register
    400     // mismatch for 64b systems, where a reference is compared against null, as dex bytecode uses
    401     // the 32b literal 0 for null.
    402     if (constant_value == 0 && (cond == kCondEq || cond == kCondNe)) {
    403       // Use the OpCmpImmBranch and ignore the value in the register.
    404       OpCmpImmBranch(cond, rl_src1.reg, 0, taken);
    405       return;
    406     }
    407   }
    408 
    409   rl_src2 = LoadValue(rl_src2, reg_class);
    410   OpCmpBranch(cond, rl_src1.reg, rl_src2.reg, taken);
    411 }
    412 
    413 void Mir2Lir::GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, LIR* taken) {
    414   ConditionCode cond;
    415   RegisterClass reg_class = rl_src.ref ? kRefReg : kCoreReg;
    416   rl_src = LoadValue(rl_src, reg_class);
    417   switch (opcode) {
    418     case Instruction::IF_EQZ:
    419       cond = kCondEq;
    420       break;
    421     case Instruction::IF_NEZ:
    422       cond = kCondNe;
    423       break;
    424     case Instruction::IF_LTZ:
    425       cond = kCondLt;
    426       break;
    427     case Instruction::IF_GEZ:
    428       cond = kCondGe;
    429       break;
    430     case Instruction::IF_GTZ:
    431       cond = kCondGt;
    432       break;
    433     case Instruction::IF_LEZ:
    434       cond = kCondLe;
    435       break;
    436     default:
    437       cond = static_cast<ConditionCode>(0);
    438       LOG(FATAL) << "Unexpected opcode " << opcode;
    439   }
    440   OpCmpImmBranch(cond, rl_src.reg, 0, taken);
    441 }
    442 
    443 void Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) {
    444   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
    445   if (rl_src.location == kLocPhysReg) {
    446     OpRegCopy(rl_result.reg, rl_src.reg);
    447   } else {
    448     LoadValueDirect(rl_src, rl_result.reg.GetLow());
    449   }
    450   OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_result.reg.GetLow(), 31);
    451   StoreValueWide(rl_dest, rl_result);
    452 }
    453 
    454 void Mir2Lir::GenLongToInt(RegLocation rl_dest, RegLocation rl_src) {
    455   rl_src = UpdateLocWide(rl_src);
    456   rl_src = NarrowRegLoc(rl_src);
    457   StoreValue(rl_dest, rl_src);
    458 }
    459 
    460 void Mir2Lir::GenIntNarrowing(Instruction::Code opcode, RegLocation rl_dest,
    461                               RegLocation rl_src) {
    462   rl_src = LoadValue(rl_src, kCoreReg);
    463   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
    464   OpKind op = kOpInvalid;
    465   switch (opcode) {
    466     case Instruction::INT_TO_BYTE:
    467       op = kOp2Byte;
    468       break;
    469     case Instruction::INT_TO_SHORT:
    470        op = kOp2Short;
    471        break;
    472     case Instruction::INT_TO_CHAR:
    473        op = kOp2Char;
    474        break;
    475     default:
    476       LOG(ERROR) << "Bad int conversion type";
    477   }
    478   OpRegReg(op, rl_result.reg, rl_src.reg);
    479   StoreValue(rl_dest, rl_result);
    480 }
    481 
    482 /*
    483  * Let helper function take care of everything.  Will call
    484  * Array::AllocFromCode(type_idx, method, count);
    485  * Note: AllocFromCode will handle checks for errNegativeArraySize.
    486  */
    487 void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest,
    488                           RegLocation rl_src) {
    489   FlushAllRegs();  /* Everything to home location */
    490   const DexFile* dex_file = cu_->dex_file;
    491   CompilerDriver* driver = cu_->compiler_driver;
    492   if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *dex_file, type_idx)) {
    493     bool is_type_initialized;  // Ignored as an array does not have an initializer.
    494     bool use_direct_type_ptr;
    495     uintptr_t direct_type_ptr;
    496     bool is_finalizable;
    497     if (kEmbedClassInCode &&
    498         driver->CanEmbedTypeInCode(*dex_file, type_idx, &is_type_initialized, &use_direct_type_ptr,
    499                                    &direct_type_ptr, &is_finalizable)) {
    500       // The fast path.
    501       if (!use_direct_type_ptr) {
    502         LoadClassType(*dex_file, type_idx, kArg0);
    503         CallRuntimeHelperRegRegLocationMethod(kQuickAllocArrayResolved, TargetReg(kArg0, kNotWide),
    504                                               rl_src, true);
    505       } else {
    506         // Use the direct pointer.
    507         CallRuntimeHelperImmRegLocationMethod(kQuickAllocArrayResolved, direct_type_ptr, rl_src,
    508                                               true);
    509       }
    510     } else {
    511       // The slow path.
    512       CallRuntimeHelperImmRegLocationMethod(kQuickAllocArray, type_idx, rl_src, true);
    513     }
    514   } else {
    515     CallRuntimeHelperImmRegLocationMethod(kQuickAllocArrayWithAccessCheck, type_idx, rl_src, true);
    516   }
    517   StoreValue(rl_dest, GetReturn(kRefReg));
    518 }
    519 
    520 /*
    521  * Similar to GenNewArray, but with post-allocation initialization.
    522  * Verifier guarantees we're dealing with an array class.  Current
    523  * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
    524  * Current code also throws internal unimp if not 'L', '[' or 'I'.
    525  */
    526 void Mir2Lir::GenFilledNewArray(CallInfo* info) {
    527   size_t elems = info->num_arg_words;
    528   int type_idx = info->index;
    529   FlushAllRegs();  /* Everything to home location */
    530   QuickEntrypointEnum target;
    531   if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file,
    532                                                        type_idx)) {
    533     target = kQuickCheckAndAllocArray;
    534   } else {
    535     target = kQuickCheckAndAllocArrayWithAccessCheck;
    536   }
    537   CallRuntimeHelperImmImmMethod(target, type_idx, elems, true);
    538   FreeTemp(TargetReg(kArg2, kNotWide));
    539   FreeTemp(TargetReg(kArg1, kNotWide));
    540   /*
    541    * NOTE: the implicit target for Instruction::FILLED_NEW_ARRAY is the
    542    * return region.  Because AllocFromCode placed the new array
    543    * in kRet0, we'll just lock it into place.  When debugger support is
    544    * added, it may be necessary to additionally copy all return
    545    * values to a home location in thread-local storage
    546    */
    547   RegStorage ref_reg = TargetReg(kRet0, kRef);
    548   LockTemp(ref_reg);
    549 
    550   // TODO: use the correct component size, currently all supported types
    551   // share array alignment with ints (see comment at head of function)
    552   size_t component_size = sizeof(int32_t);
    553 
    554   if (elems > 5) {
    555     DCHECK(info->is_range);  // Non-range insn can't encode more than 5 elems.
    556     /*
    557      * Bit of ugliness here.  We're going generate a mem copy loop
    558      * on the register range, but it is possible that some regs
    559      * in the range have been promoted.  This is unlikely, but
    560      * before generating the copy, we'll just force a flush
    561      * of any regs in the source range that have been promoted to
    562      * home location.
    563      */
    564     for (size_t i = 0; i < elems; i++) {
    565       RegLocation loc = UpdateLoc(info->args[i]);
    566       if (loc.location == kLocPhysReg) {
    567         ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    568         if (loc.ref) {
    569           StoreRefDisp(TargetPtrReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, kNotVolatile);
    570         } else {
    571           Store32Disp(TargetPtrReg(kSp), SRegOffset(loc.s_reg_low), loc.reg);
    572         }
    573       }
    574     }
    575     /*
    576      * TUNING note: generated code here could be much improved, but
    577      * this is an uncommon operation and isn't especially performance
    578      * critical.
    579      */
    580     // This is addressing the stack, which may be out of the 4G area.
    581     RegStorage r_src = AllocTempRef();
    582     RegStorage r_dst = AllocTempRef();
    583     RegStorage r_idx = AllocTempRef();  // Not really a reference, but match src/dst.
    584     RegStorage r_val;
    585     switch (cu_->instruction_set) {
    586       case kThumb2:
    587       case kArm64:
    588         r_val = TargetReg(kLr, kNotWide);
    589         break;
    590       case kX86:
    591       case kX86_64:
    592         FreeTemp(ref_reg);
    593         r_val = AllocTemp();
    594         break;
    595       case kMips:
    596       case kMips64:
    597         r_val = AllocTemp();
    598         break;
    599       default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
    600     }
    601     // Set up source pointer
    602     RegLocation rl_first = info->args[0];
    603     OpRegRegImm(kOpAdd, r_src, TargetPtrReg(kSp), SRegOffset(rl_first.s_reg_low));
    604     // Set up the target pointer
    605     OpRegRegImm(kOpAdd, r_dst, ref_reg,
    606                 mirror::Array::DataOffset(component_size).Int32Value());
    607     // Set up the loop counter (known to be > 0)
    608     LoadConstant(r_idx, static_cast<int>(elems - 1));
    609     // Generate the copy loop.  Going backwards for convenience
    610     LIR* loop_head_target = NewLIR0(kPseudoTargetLabel);
    611     // Copy next element
    612     {
    613       ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    614       LoadBaseIndexed(r_src, r_idx, r_val, 2, k32);
    615       // NOTE: No dalvik register annotation, local optimizations will be stopped
    616       // by the loop boundaries.
    617     }
    618     StoreBaseIndexed(r_dst, r_idx, r_val, 2, k32);
    619     FreeTemp(r_val);
    620     OpDecAndBranch(kCondGe, r_idx, loop_head_target);
    621     if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
    622       // Restore the target pointer
    623       OpRegRegImm(kOpAdd, ref_reg, r_dst,
    624                   -mirror::Array::DataOffset(component_size).Int32Value());
    625     }
    626     FreeTemp(r_idx);
    627     FreeTemp(r_dst);
    628     FreeTemp(r_src);
    629   } else {
    630     DCHECK_LE(elems, 5u);  // Usually but not necessarily non-range.
    631     // TUNING: interleave
    632     for (size_t i = 0; i < elems; i++) {
    633       RegLocation rl_arg;
    634       if (info->args[i].ref) {
    635         rl_arg = LoadValue(info->args[i], kRefReg);
    636         StoreRefDisp(ref_reg,
    637                     mirror::Array::DataOffset(component_size).Int32Value() + i * 4, rl_arg.reg,
    638                     kNotVolatile);
    639       } else {
    640         rl_arg = LoadValue(info->args[i], kCoreReg);
    641         Store32Disp(ref_reg,
    642                     mirror::Array::DataOffset(component_size).Int32Value() + i * 4, rl_arg.reg);
    643       }
    644       // If the LoadValue caused a temp to be allocated, free it
    645       if (IsTemp(rl_arg.reg)) {
    646         FreeTemp(rl_arg.reg);
    647       }
    648     }
    649   }
    650   if (elems != 0 && info->args[0].ref) {
    651     // If there is at least one potentially non-null value, unconditionally mark the GC card.
    652     for (size_t i = 0; i < elems; i++) {
    653       if (!mir_graph_->IsConstantNullRef(info->args[i])) {
    654         UnconditionallyMarkGCCard(ref_reg);
    655         break;
    656       }
    657     }
    658   }
    659   if (info->result.location != kLocInvalid) {
    660     StoreValue(info->result, GetReturn(kRefReg));
    661   }
    662 }
    663 
    664 /*
    665  * Array data table format:
    666  *  ushort ident = 0x0300   magic value
    667  *  ushort width            width of each element in the table
    668  *  uint   size             number of elements in the table
    669  *  ubyte  data[size*width] table of data values (may contain a single-byte
    670  *                          padding at the end)
    671  *
    672  * Total size is 4+(width * size + 1)/2 16-bit code units.
    673  */
    674 void Mir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
    675   if (kIsDebugBuild) {
    676     const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
    677     const Instruction::ArrayDataPayload* payload =
    678         reinterpret_cast<const Instruction::ArrayDataPayload*>(table);
    679     CHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
    680   }
    681   uint32_t table_offset_from_start = mir->offset + static_cast<int32_t>(table_offset);
    682   CallRuntimeHelperImmRegLocation(kQuickHandleFillArrayData, table_offset_from_start, rl_src, true);
    683 }
    684 
    685 void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, OpSize size) {
    686   const MirSFieldLoweringInfo& field_info = mir_graph_->GetSFieldLoweringInfo(mir);
    687   DCHECK_EQ(SPutMemAccessType(mir->dalvikInsn.opcode), field_info.MemAccessType());
    688   cu_->compiler_driver->ProcessedStaticField(field_info.FastPut(), field_info.IsReferrersClass());
    689   if (!ForceSlowFieldPath(cu_) && field_info.FastPut()) {
    690     DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
    691     RegStorage r_base;
    692     if (field_info.IsReferrersClass()) {
    693       // Fast path, static storage base is this method's class
    694       r_base = AllocTempRef();
    695       RegStorage r_method = LoadCurrMethodWithHint(r_base);
    696       LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
    697                   kNotVolatile);
    698     } else {
    699       // Medium path, static storage base in a different class which requires checks that the other
    700       // class is initialized.
    701       r_base = GenGetOtherTypeForSgetSput(field_info, mir->optimization_flags);
    702       if (!field_info.IsClassInitialized() &&
    703           (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0) {
    704         // Ensure load of status and store of value don't re-order.
    705         // TODO: Presumably the actual value store is control-dependent on the status load,
    706         // and will thus not be reordered in any case, since stores are never speculated.
    707         // Does later code "know" that the class is now initialized?  If so, we still
    708         // need the barrier to guard later static loads.
    709         GenMemBarrier(kLoadAny);
    710       }
    711     }
    712     // rBase now holds static storage base
    713     RegisterClass reg_class = RegClassForFieldLoadStore(size, field_info.IsVolatile());
    714     if (IsWide(size)) {
    715       rl_src = LoadValueWide(rl_src, reg_class);
    716     } else {
    717       rl_src = LoadValue(rl_src, reg_class);
    718     }
    719     if (IsRef(size)) {
    720       StoreRefDisp(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg,
    721                    field_info.IsVolatile() ? kVolatile : kNotVolatile);
    722     } else {
    723       StoreBaseDisp(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg, size,
    724                     field_info.IsVolatile() ? kVolatile : kNotVolatile);
    725     }
    726     if (IsRef(size) && !mir_graph_->IsConstantNullRef(rl_src)) {
    727       MarkGCCard(mir->optimization_flags, rl_src.reg, r_base);
    728     }
    729     FreeTemp(r_base);
    730   } else {
    731     FlushAllRegs();  // Everything to home locations
    732     QuickEntrypointEnum target;
    733     switch (size) {
    734       case kReference:
    735         target = kQuickSetObjStatic;
    736         break;
    737       case k64:
    738       case kDouble:
    739         target = kQuickSet64Static;
    740         break;
    741       case k32:
    742       case kSingle:
    743         target = kQuickSet32Static;
    744         break;
    745       case kSignedHalf:
    746       case kUnsignedHalf:
    747         target = kQuickSet16Static;
    748         break;
    749       case kSignedByte:
    750       case kUnsignedByte:
    751         target = kQuickSet8Static;
    752         break;
    753       case kWord:  // Intentional fallthrough.
    754       default:
    755         LOG(FATAL) << "Can't determine entrypoint for: " << size;
    756         target = kQuickSet32Static;
    757     }
    758     CallRuntimeHelperImmRegLocation(target, field_info.FieldIndex(), rl_src, true);
    759   }
    760 }
    761 
    762 void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, OpSize size, Primitive::Type type) {
    763   const MirSFieldLoweringInfo& field_info = mir_graph_->GetSFieldLoweringInfo(mir);
    764   DCHECK_EQ(SGetMemAccessType(mir->dalvikInsn.opcode), field_info.MemAccessType());
    765   cu_->compiler_driver->ProcessedStaticField(field_info.FastGet(), field_info.IsReferrersClass());
    766 
    767   if (!ForceSlowFieldPath(cu_) && field_info.FastGet()) {
    768     DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
    769     RegStorage r_base;
    770     if (field_info.IsReferrersClass()) {
    771       // Fast path, static storage base is this method's class
    772       r_base = AllocTempRef();
    773       RegStorage r_method = LoadCurrMethodWithHint(r_base);
    774       LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
    775                   kNotVolatile);
    776     } else {
    777       // Medium path, static storage base in a different class which requires checks that the other
    778       // class is initialized
    779       r_base = GenGetOtherTypeForSgetSput(field_info, mir->optimization_flags);
    780       if (!field_info.IsClassInitialized() &&
    781           (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0) {
    782         // Ensure load of status and load of value don't re-order.
    783         GenMemBarrier(kLoadAny);
    784       }
    785     }
    786     // r_base now holds static storage base
    787     RegisterClass reg_class = RegClassForFieldLoadStore(size, field_info.IsVolatile());
    788     RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
    789 
    790     int field_offset = field_info.FieldOffset().Int32Value();
    791     if (IsRef(size)) {
    792       // TODO: DCHECK?
    793       LoadRefDisp(r_base, field_offset, rl_result.reg, field_info.IsVolatile() ? kVolatile :
    794           kNotVolatile);
    795     } else {
    796       LoadBaseDisp(r_base, field_offset, rl_result.reg, size, field_info.IsVolatile() ?
    797           kVolatile : kNotVolatile);
    798     }
    799     FreeTemp(r_base);
    800 
    801     if (IsWide(size)) {
    802       StoreValueWide(rl_dest, rl_result);
    803     } else {
    804       StoreValue(rl_dest, rl_result);
    805     }
    806   } else {
    807     DCHECK(SizeMatchesTypeForEntrypoint(size, type));
    808     FlushAllRegs();  // Everything to home locations
    809     QuickEntrypointEnum target;
    810     switch (type) {
    811       case Primitive::kPrimNot:
    812         target = kQuickGetObjStatic;
    813         break;
    814       case Primitive::kPrimLong:
    815       case Primitive::kPrimDouble:
    816         target = kQuickGet64Static;
    817         break;
    818       case Primitive::kPrimInt:
    819       case Primitive::kPrimFloat:
    820         target = kQuickGet32Static;
    821         break;
    822       case Primitive::kPrimShort:
    823         target = kQuickGetShortStatic;
    824         break;
    825       case Primitive::kPrimChar:
    826         target = kQuickGetCharStatic;
    827         break;
    828       case Primitive::kPrimByte:
    829         target = kQuickGetByteStatic;
    830         break;
    831       case Primitive::kPrimBoolean:
    832         target = kQuickGetBooleanStatic;
    833         break;
    834       case Primitive::kPrimVoid:  // Intentional fallthrough.
    835       default:
    836         LOG(FATAL) << "Can't determine entrypoint for: " << type;
    837         target = kQuickGet32Static;
    838     }
    839     CallRuntimeHelperImm(target, field_info.FieldIndex(), true);
    840 
    841     // FIXME: pGetXXStatic always return an int or int64 regardless of rl_dest.fp.
    842     if (IsWide(size)) {
    843       RegLocation rl_result = GetReturnWide(kCoreReg);
    844       StoreValueWide(rl_dest, rl_result);
    845     } else {
    846       RegLocation rl_result = GetReturn(rl_dest.ref ? kRefReg : kCoreReg);
    847       StoreValue(rl_dest, rl_result);
    848     }
    849   }
    850 }
    851 
    852 // Generate code for all slow paths.
    853 void Mir2Lir::HandleSlowPaths() {
    854   // We should check slow_paths_.Size() every time, because a new slow path
    855   // may be created during slowpath->Compile().
    856   for (LIRSlowPath* slowpath : slow_paths_) {
    857     slowpath->Compile();
    858   }
    859   slow_paths_.clear();
    860 }
    861 
    862 void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, Primitive::Type type,
    863                       RegLocation rl_dest, RegLocation rl_obj) {
    864   const MirIFieldLoweringInfo& field_info = mir_graph_->GetIFieldLoweringInfo(mir);
    865   if (kIsDebugBuild) {
    866     auto mem_access_type = IsInstructionIGetQuickOrIPutQuick(mir->dalvikInsn.opcode) ?
    867         IGetQuickOrIPutQuickMemAccessType(mir->dalvikInsn.opcode) :
    868         IGetMemAccessType(mir->dalvikInsn.opcode);
    869     DCHECK_EQ(mem_access_type, field_info.MemAccessType()) << mir->dalvikInsn.opcode;
    870   }
    871   cu_->compiler_driver->ProcessedInstanceField(field_info.FastGet());
    872   if (!ForceSlowFieldPath(cu_) && field_info.FastGet()) {
    873     RegisterClass reg_class = RegClassForFieldLoadStore(size, field_info.IsVolatile());
    874     // A load of the class will lead to an iget with offset 0.
    875     DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
    876     rl_obj = LoadValue(rl_obj, kRefReg);
    877     GenNullCheck(rl_obj.reg, opt_flags);
    878     RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
    879     int field_offset = field_info.FieldOffset().Int32Value();
    880     LIR* load_lir;
    881     if (IsRef(size)) {
    882       load_lir = LoadRefDisp(rl_obj.reg, field_offset, rl_result.reg, field_info.IsVolatile() ?
    883           kVolatile : kNotVolatile);
    884     } else {
    885       load_lir = LoadBaseDisp(rl_obj.reg, field_offset, rl_result.reg, size,
    886                               field_info.IsVolatile() ? kVolatile : kNotVolatile);
    887     }
    888     MarkPossibleNullPointerExceptionAfter(opt_flags, load_lir);
    889     if (IsWide(size)) {
    890       StoreValueWide(rl_dest, rl_result);
    891     } else {
    892       StoreValue(rl_dest, rl_result);
    893     }
    894   } else {
    895     DCHECK(SizeMatchesTypeForEntrypoint(size, type));
    896     QuickEntrypointEnum target;
    897     switch (type) {
    898       case Primitive::kPrimNot:
    899         target = kQuickGetObjInstance;
    900         break;
    901       case Primitive::kPrimLong:
    902       case Primitive::kPrimDouble:
    903         target = kQuickGet64Instance;
    904         break;
    905       case Primitive::kPrimFloat:
    906       case Primitive::kPrimInt:
    907         target = kQuickGet32Instance;
    908         break;
    909       case Primitive::kPrimShort:
    910         target = kQuickGetShortInstance;
    911         break;
    912       case Primitive::kPrimChar:
    913         target = kQuickGetCharInstance;
    914         break;
    915       case Primitive::kPrimByte:
    916         target = kQuickGetByteInstance;
    917         break;
    918       case Primitive::kPrimBoolean:
    919         target = kQuickGetBooleanInstance;
    920         break;
    921       case Primitive::kPrimVoid:  // Intentional fallthrough.
    922       default:
    923         LOG(FATAL) << "Can't determine entrypoint for: " << type;
    924         target = kQuickGet32Instance;
    925     }
    926     // Second argument of pGetXXInstance is always a reference.
    927     DCHECK_EQ(static_cast<unsigned int>(rl_obj.wide), 0U);
    928     CallRuntimeHelperImmRegLocation(target, field_info.FieldIndex(), rl_obj, true);
    929 
    930     // FIXME: pGetXXInstance always return an int or int64 regardless of rl_dest.fp.
    931     if (IsWide(size)) {
    932       RegLocation rl_result = GetReturnWide(kCoreReg);
    933       StoreValueWide(rl_dest, rl_result);
    934     } else {
    935       RegLocation rl_result = GetReturn(rl_dest.ref ? kRefReg : kCoreReg);
    936       StoreValue(rl_dest, rl_result);
    937     }
    938   }
    939 }
    940 
    941 void Mir2Lir::GenIPut(MIR* mir, int opt_flags, OpSize size,
    942                       RegLocation rl_src, RegLocation rl_obj) {
    943   const MirIFieldLoweringInfo& field_info = mir_graph_->GetIFieldLoweringInfo(mir);
    944   if (kIsDebugBuild) {
    945     auto mem_access_type = IsInstructionIGetQuickOrIPutQuick(mir->dalvikInsn.opcode) ?
    946         IGetQuickOrIPutQuickMemAccessType(mir->dalvikInsn.opcode) :
    947         IPutMemAccessType(mir->dalvikInsn.opcode);
    948     DCHECK_EQ(mem_access_type, field_info.MemAccessType());
    949   }
    950   cu_->compiler_driver->ProcessedInstanceField(field_info.FastPut());
    951   if (!ForceSlowFieldPath(cu_) && field_info.FastPut()) {
    952     RegisterClass reg_class = RegClassForFieldLoadStore(size, field_info.IsVolatile());
    953     // Dex code never writes to the class field.
    954     DCHECK_GE(static_cast<uint32_t>(field_info.FieldOffset().Int32Value()),
    955               sizeof(mirror::HeapReference<mirror::Class>));
    956     rl_obj = LoadValue(rl_obj, kRefReg);
    957     if (IsWide(size)) {
    958       rl_src = LoadValueWide(rl_src, reg_class);
    959     } else {
    960       rl_src = LoadValue(rl_src, reg_class);
    961     }
    962     GenNullCheck(rl_obj.reg, opt_flags);
    963     int field_offset = field_info.FieldOffset().Int32Value();
    964     LIR* null_ck_insn;
    965     if (IsRef(size)) {
    966       null_ck_insn = StoreRefDisp(rl_obj.reg, field_offset, rl_src.reg, field_info.IsVolatile() ?
    967           kVolatile : kNotVolatile);
    968     } else {
    969       null_ck_insn = StoreBaseDisp(rl_obj.reg, field_offset, rl_src.reg, size,
    970                                    field_info.IsVolatile() ? kVolatile : kNotVolatile);
    971     }
    972     MarkPossibleNullPointerExceptionAfter(opt_flags, null_ck_insn);
    973     if (IsRef(size) && !mir_graph_->IsConstantNullRef(rl_src)) {
    974       MarkGCCard(opt_flags, rl_src.reg, rl_obj.reg);
    975     }
    976   } else {
    977     QuickEntrypointEnum target;
    978     switch (size) {
    979       case kReference:
    980         target = kQuickSetObjInstance;
    981         break;
    982       case k64:
    983       case kDouble:
    984         target = kQuickSet64Instance;
    985         break;
    986       case k32:
    987       case kSingle:
    988         target = kQuickSet32Instance;
    989         break;
    990       case kSignedHalf:
    991       case kUnsignedHalf:
    992         target = kQuickSet16Instance;
    993         break;
    994       case kSignedByte:
    995       case kUnsignedByte:
    996         target = kQuickSet8Instance;
    997         break;
    998       case kWord:  // Intentional fallthrough.
    999       default:
   1000         LOG(FATAL) << "Can't determine entrypoint for: " << size;
   1001         target = kQuickSet32Instance;
   1002     }
   1003     CallRuntimeHelperImmRegLocationRegLocation(target, field_info.FieldIndex(), rl_obj, rl_src,
   1004                                                true);
   1005   }
   1006 }
   1007 
   1008 void Mir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index,
   1009                              RegLocation rl_src) {
   1010   bool needs_range_check = !(opt_flags & MIR_IGNORE_RANGE_CHECK);
   1011   bool needs_null_check = !((cu_->disable_opt & (1 << kNullCheckElimination)) &&
   1012       (opt_flags & MIR_IGNORE_NULL_CHECK));
   1013   QuickEntrypointEnum target = needs_range_check
   1014         ? (needs_null_check ? kQuickAputObjectWithNullAndBoundCheck
   1015                             : kQuickAputObjectWithBoundCheck)
   1016         : kQuickAputObject;
   1017   CallRuntimeHelperRegLocationRegLocationRegLocation(target, rl_array, rl_index, rl_src, true);
   1018 }
   1019 
   1020 void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
   1021   RegLocation rl_result;
   1022   if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
   1023                                                         *cu_->dex_file,
   1024                                                         type_idx)) {
   1025     // Call out to helper which resolves type and verifies access.
   1026     // Resolved type returned in kRet0.
   1027     CallRuntimeHelperImm(kQuickInitializeTypeAndVerifyAccess, type_idx, true);
   1028     rl_result = GetReturn(kRefReg);
   1029   } else {
   1030     rl_result = EvalLoc(rl_dest, kRefReg, true);
   1031     // We don't need access checks, load type from dex cache
   1032     if (CanUseOpPcRelDexCacheArrayLoad()) {
   1033       size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
   1034       OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg, false);
   1035     } else {
   1036       int32_t dex_cache_offset =
   1037           ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
   1038       RegStorage res_reg = AllocTempRef();
   1039       RegStorage r_method = LoadCurrMethodWithHint(res_reg);
   1040       LoadRefDisp(r_method, dex_cache_offset, res_reg, kNotVolatile);
   1041       int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
   1042       LoadRefDisp(res_reg, offset_of_type, rl_result.reg, kNotVolatile);
   1043       FreeTemp(res_reg);
   1044     }
   1045     if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file,
   1046         type_idx) || ForceSlowTypePath(cu_)) {
   1047       // Slow path, at runtime test if type is null and if so initialize
   1048       FlushAllRegs();
   1049       GenIfNullUseHelperImm(rl_result.reg, kQuickInitializeType, type_idx);
   1050     }
   1051   }
   1052   StoreValue(rl_dest, rl_result);
   1053 }
   1054 
   1055 void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
   1056   /* NOTE: Most strings should be available at compile time */
   1057   int32_t offset_of_string = mirror::ObjectArray<mirror::String>::OffsetOfElement(string_idx).
   1058                                                                                       Int32Value();
   1059   if (!cu_->compiler_driver->CanAssumeStringIsPresentInDexCache(
   1060       *cu_->dex_file, string_idx) || ForceSlowStringPath(cu_)) {
   1061     // slow path, resolve string if not in dex cache
   1062     FlushAllRegs();
   1063     LockCallTemps();  // Using explicit registers
   1064 
   1065     // Might call out to helper, which will return resolved string in kRet0
   1066     RegStorage ret0 = TargetReg(kRet0, kRef);
   1067     if (CanUseOpPcRelDexCacheArrayLoad()) {
   1068       size_t offset = dex_cache_arrays_layout_.StringOffset(string_idx);
   1069       OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, ret0, false);
   1070     } else {
   1071       // Method to declaring class.
   1072       RegStorage arg0 = TargetReg(kArg0, kRef);
   1073       RegStorage r_method = LoadCurrMethodWithHint(arg0);
   1074       LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), arg0, kNotVolatile);
   1075       // Declaring class to dex cache strings.
   1076       LoadRefDisp(arg0, mirror::Class::DexCacheStringsOffset().Int32Value(), arg0, kNotVolatile);
   1077 
   1078       LoadRefDisp(arg0, offset_of_string, ret0, kNotVolatile);
   1079     }
   1080     GenIfNullUseHelperImm(ret0, kQuickResolveString, string_idx);
   1081 
   1082     GenBarrier();
   1083     StoreValue(rl_dest, GetReturn(kRefReg));
   1084   } else {
   1085     RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
   1086     if (CanUseOpPcRelDexCacheArrayLoad()) {
   1087       size_t offset = dex_cache_arrays_layout_.StringOffset(string_idx);
   1088       OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg, false);
   1089     } else {
   1090       RegLocation rl_method = LoadCurrMethod();
   1091       RegStorage res_reg = AllocTempRef();
   1092       LoadRefDisp(rl_method.reg, ArtMethod::DeclaringClassOffset().Int32Value(), res_reg,
   1093                   kNotVolatile);
   1094       LoadRefDisp(res_reg, mirror::Class::DexCacheStringsOffset().Int32Value(), res_reg,
   1095                   kNotVolatile);
   1096       LoadRefDisp(res_reg, offset_of_string, rl_result.reg, kNotVolatile);
   1097       FreeTemp(res_reg);
   1098     }
   1099     StoreValue(rl_dest, rl_result);
   1100   }
   1101 }
   1102 
   1103 /*
   1104  * Let helper function take care of everything.  Will
   1105  * call Class::NewInstanceFromCode(type_idx, method);
   1106  */
   1107 void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) {
   1108   FlushAllRegs();  /* Everything to home location */
   1109   // alloc will always check for resolution, do we also need to verify
   1110   // access because the verifier was unable to?
   1111   const DexFile* dex_file = cu_->dex_file;
   1112   CompilerDriver* driver = cu_->compiler_driver;
   1113   if (driver->CanAccessInstantiableTypeWithoutChecks(cu_->method_idx, *dex_file, type_idx)) {
   1114     bool is_type_initialized;
   1115     bool use_direct_type_ptr;
   1116     uintptr_t direct_type_ptr;
   1117     bool is_finalizable;
   1118     if (kEmbedClassInCode &&
   1119         driver->CanEmbedTypeInCode(*dex_file, type_idx, &is_type_initialized, &use_direct_type_ptr,
   1120                                    &direct_type_ptr, &is_finalizable) &&
   1121                                    !is_finalizable) {
   1122       // The fast path.
   1123       if (!use_direct_type_ptr) {
   1124         LoadClassType(*dex_file, type_idx, kArg0);
   1125         if (!is_type_initialized) {
   1126           CallRuntimeHelperRegMethod(kQuickAllocObjectResolved, TargetReg(kArg0, kRef), true);
   1127         } else {
   1128           CallRuntimeHelperRegMethod(kQuickAllocObjectInitialized, TargetReg(kArg0, kRef), true);
   1129         }
   1130       } else {
   1131         // Use the direct pointer.
   1132         if (!is_type_initialized) {
   1133           CallRuntimeHelperImmMethod(kQuickAllocObjectResolved, direct_type_ptr, true);
   1134         } else {
   1135           CallRuntimeHelperImmMethod(kQuickAllocObjectInitialized, direct_type_ptr, true);
   1136         }
   1137       }
   1138     } else {
   1139       // The slow path.
   1140       CallRuntimeHelperImmMethod(kQuickAllocObject, type_idx, true);
   1141     }
   1142   } else {
   1143     CallRuntimeHelperImmMethod(kQuickAllocObjectWithAccessCheck, type_idx, true);
   1144   }
   1145   StoreValue(rl_dest, GetReturn(kRefReg));
   1146 }
   1147 
   1148 void Mir2Lir::GenThrow(RegLocation rl_src) {
   1149   FlushAllRegs();
   1150   CallRuntimeHelperRegLocation(kQuickDeliverException, rl_src, true);
   1151 }
   1152 
   1153 // For final classes there are no sub-classes to check and so we can answer the instance-of
   1154 // question with simple comparisons.
   1155 void Mir2Lir::GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, RegLocation rl_dest,
   1156                                  RegLocation rl_src) {
   1157   // X86 has its own implementation.
   1158   DCHECK(cu_->instruction_set != kX86 && cu_->instruction_set != kX86_64);
   1159 
   1160   RegLocation object = LoadValue(rl_src, kRefReg);
   1161   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1162   RegStorage result_reg = rl_result.reg;
   1163   if (IsSameReg(result_reg, object.reg)) {
   1164     result_reg = AllocTypedTemp(false, kCoreReg);
   1165     DCHECK(!IsSameReg(result_reg, object.reg));
   1166   }
   1167   LoadConstant(result_reg, 0);     // assume false
   1168   LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg, 0, nullptr);
   1169 
   1170   RegStorage check_class = AllocTypedTemp(false, kRefReg);
   1171   RegStorage object_class = AllocTypedTemp(false, kRefReg);
   1172 
   1173   if (use_declaring_class) {
   1174     RegStorage r_method = LoadCurrMethodWithHint(check_class);
   1175     LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), check_class,
   1176                 kNotVolatile);
   1177     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
   1178                 kNotVolatile);
   1179   } else if (CanUseOpPcRelDexCacheArrayLoad()) {
   1180     size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
   1181     OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, check_class, false);
   1182     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
   1183                 kNotVolatile);
   1184   } else {
   1185     RegStorage r_method = LoadCurrMethodWithHint(check_class);
   1186     LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
   1187                 check_class, kNotVolatile);
   1188     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
   1189                 kNotVolatile);
   1190     int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
   1191     LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
   1192   }
   1193 
   1194   // FIXME: what should we be comparing here? compressed or decompressed references?
   1195   if (cu_->instruction_set == kThumb2) {
   1196     OpRegReg(kOpCmp, check_class, object_class);  // Same?
   1197     LIR* it = OpIT(kCondEq, "");   // if-convert the test
   1198     LoadConstant(result_reg, 1);     // .eq case - load true
   1199     OpEndIT(it);
   1200   } else {
   1201     GenSelectConst32(check_class, object_class, kCondEq, 1, 0, result_reg, kCoreReg);
   1202   }
   1203   LIR* target = NewLIR0(kPseudoTargetLabel);
   1204   null_branchover->target = target;
   1205   FreeTemp(object_class);
   1206   FreeTemp(check_class);
   1207   if (IsTemp(result_reg)) {
   1208     OpRegCopy(rl_result.reg, result_reg);
   1209     FreeTemp(result_reg);
   1210   }
   1211   StoreValue(rl_dest, rl_result);
   1212 }
   1213 
   1214 void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_known_final,
   1215                                          bool type_known_abstract, bool use_declaring_class,
   1216                                          bool can_assume_type_is_in_dex_cache,
   1217                                          uint32_t type_idx, RegLocation rl_dest,
   1218                                          RegLocation rl_src) {
   1219   FlushAllRegs();
   1220   // May generate a call - use explicit registers
   1221   LockCallTemps();
   1222   RegStorage class_reg = TargetReg(kArg2, kRef);  // kArg2 will hold the Class*
   1223   RegStorage ref_reg = TargetReg(kArg0, kRef);  // kArg0 will hold the ref.
   1224   RegStorage ret_reg = GetReturn(kRefReg).reg;
   1225   if (needs_access_check) {
   1226     // Check we have access to type_idx and if not throw IllegalAccessError,
   1227     // returns Class* in kArg0
   1228     CallRuntimeHelperImmMethod(kQuickInitializeTypeAndVerifyAccess, type_idx, true);
   1229     OpRegCopy(class_reg, ret_reg);  // Align usage with fast path
   1230     LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
   1231   } else if (use_declaring_class) {
   1232     RegStorage r_method = LoadCurrMethodWithHint(TargetReg(kArg1, kRef));
   1233     LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
   1234     LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(),
   1235                 class_reg, kNotVolatile);
   1236   } else {
   1237     if (can_assume_type_is_in_dex_cache) {
   1238       // Conditionally, as in the other case we will also load it.
   1239       LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
   1240     }
   1241 
   1242     if (CanUseOpPcRelDexCacheArrayLoad()) {
   1243       size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
   1244       OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
   1245     } else {
   1246       RegStorage r_method = LoadCurrMethodWithHint(class_reg);
   1247       // Load dex cache entry into class_reg (kArg2)
   1248       LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
   1249                   class_reg, kNotVolatile);
   1250       int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
   1251       LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
   1252     }
   1253     if (!can_assume_type_is_in_dex_cache) {
   1254       GenIfNullUseHelperImm(class_reg, kQuickInitializeType, type_idx);
   1255 
   1256       // Should load value here.
   1257       LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
   1258     }
   1259   }
   1260   /* kArg0 is ref, kArg2 is class. If ref==null, use directly as bool result */
   1261   RegLocation rl_result = GetReturn(kCoreReg);
   1262   if (!IsSameReg(rl_result.reg, ref_reg)) {
   1263     // On MIPS and x86_64 rArg0 != rl_result, place false in result if branch is taken.
   1264     LoadConstant(rl_result.reg, 0);
   1265   }
   1266   LIR* branch1 = OpCmpImmBranch(kCondEq, ref_reg, 0, nullptr);
   1267 
   1268   /* load object->klass_ */
   1269   RegStorage ref_class_reg = TargetReg(kArg1, kRef);  // kArg1 will hold the Class* of ref.
   1270   DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
   1271   LoadRefDisp(ref_reg, mirror::Object::ClassOffset().Int32Value(),
   1272               ref_class_reg, kNotVolatile);
   1273   /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */
   1274   LIR* branchover = nullptr;
   1275   if (type_known_final) {
   1276     // rl_result == ref == class.
   1277     GenSelectConst32(ref_class_reg, class_reg, kCondEq, 1, 0, rl_result.reg,
   1278                      kCoreReg);
   1279   } else {
   1280     if (cu_->instruction_set == kThumb2) {
   1281       RegStorage r_tgt = LoadHelper(kQuickInstanceofNonTrivial);
   1282       LIR* it = nullptr;
   1283       if (!type_known_abstract) {
   1284       /* Uses conditional nullification */
   1285         OpRegReg(kOpCmp, ref_class_reg, class_reg);  // Same?
   1286         it = OpIT(kCondEq, "EE");   // if-convert the test
   1287         LoadConstant(rl_result.reg, 1);     // .eq case - load true
   1288       }
   1289       OpRegCopy(ref_reg, class_reg);    // .ne case - arg0 <= class
   1290       OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
   1291       if (it != nullptr) {
   1292         OpEndIT(it);
   1293       }
   1294       FreeTemp(r_tgt);
   1295     } else {
   1296       if (!type_known_abstract) {
   1297         /* Uses branchovers */
   1298         LoadConstant(rl_result.reg, 1);     // assume true
   1299         branchover = OpCmpBranch(kCondEq, TargetReg(kArg1, kRef), TargetReg(kArg2, kRef), nullptr);
   1300       }
   1301 
   1302       OpRegCopy(TargetReg(kArg0, kRef), class_reg);    // .ne case - arg0 <= class
   1303       CallRuntimeHelper(kQuickInstanceofNonTrivial, false);
   1304     }
   1305   }
   1306   // TODO: only clobber when type isn't final?
   1307   ClobberCallerSave();
   1308   /* branch targets here */
   1309   LIR* target = NewLIR0(kPseudoTargetLabel);
   1310   StoreValue(rl_dest, rl_result);
   1311   branch1->target = target;
   1312   if (branchover != nullptr) {
   1313     branchover->target = target;
   1314   }
   1315 }
   1316 
   1317 void Mir2Lir::GenInstanceof(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) {
   1318   bool type_known_final, type_known_abstract, use_declaring_class;
   1319   bool needs_access_check = !cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
   1320                                                                               *cu_->dex_file,
   1321                                                                               type_idx,
   1322                                                                               &type_known_final,
   1323                                                                               &type_known_abstract,
   1324                                                                               &use_declaring_class);
   1325   bool can_assume_type_is_in_dex_cache = !needs_access_check &&
   1326       cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx);
   1327 
   1328   if ((use_declaring_class || can_assume_type_is_in_dex_cache) && type_known_final) {
   1329     GenInstanceofFinal(use_declaring_class, type_idx, rl_dest, rl_src);
   1330   } else {
   1331     GenInstanceofCallingHelper(needs_access_check, type_known_final, type_known_abstract,
   1332                                use_declaring_class, can_assume_type_is_in_dex_cache,
   1333                                type_idx, rl_dest, rl_src);
   1334   }
   1335 }
   1336 
   1337 void Mir2Lir::GenCheckCast(int opt_flags, uint32_t insn_idx, uint32_t type_idx,
   1338                            RegLocation rl_src) {
   1339   if ((opt_flags & MIR_IGNORE_CHECK_CAST) != 0) {
   1340     // Compiler analysis proved that this check-cast would never cause an exception.
   1341     return;
   1342   }
   1343   bool type_known_final, type_known_abstract, use_declaring_class;
   1344   bool needs_access_check = !cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
   1345                                                                               *cu_->dex_file,
   1346                                                                               type_idx,
   1347                                                                               &type_known_final,
   1348                                                                               &type_known_abstract,
   1349                                                                               &use_declaring_class);
   1350   // Note: currently type_known_final is unused, as optimizing will only improve the performance
   1351   // of the exception throw path.
   1352   DexCompilationUnit* cu = mir_graph_->GetCurrentDexCompilationUnit();
   1353   if (!needs_access_check && cu_->compiler_driver->IsSafeCast(cu, insn_idx)) {
   1354     // Verifier type analysis proved this check cast would never cause an exception.
   1355     return;
   1356   }
   1357   FlushAllRegs();
   1358   // May generate a call - use explicit registers
   1359   LockCallTemps();
   1360   RegStorage class_reg = TargetReg(kArg2, kRef);  // kArg2 will hold the Class*
   1361   if (needs_access_check) {
   1362     // Check we have access to type_idx and if not throw IllegalAccessError,
   1363     // returns Class* in kRet0
   1364     // InitializeTypeAndVerifyAccess(idx, method)
   1365     CallRuntimeHelperImmMethod(kQuickInitializeTypeAndVerifyAccess, type_idx, true);
   1366     OpRegCopy(class_reg, TargetReg(kRet0, kRef));  // Align usage with fast path
   1367   } else if (use_declaring_class) {
   1368     RegStorage method_reg = LoadCurrMethodWithHint(TargetReg(kArg1, kRef));
   1369     LoadRefDisp(method_reg, ArtMethod::DeclaringClassOffset().Int32Value(),
   1370                 class_reg, kNotVolatile);
   1371   } else {
   1372     // Load dex cache entry into class_reg (kArg2)
   1373     if (CanUseOpPcRelDexCacheArrayLoad()) {
   1374       size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
   1375       OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
   1376     } else {
   1377       RegStorage r_method = LoadCurrMethodWithHint(class_reg);
   1378 
   1379       LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
   1380                   class_reg, kNotVolatile);
   1381       int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
   1382       LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
   1383     }
   1384     if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx)) {
   1385       // Need to test presence of type in dex cache at runtime
   1386       GenIfNullUseHelperImm(class_reg, kQuickInitializeType, type_idx);
   1387     }
   1388   }
   1389   // At this point, class_reg (kArg2) has class
   1390   LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  // kArg0 <= ref
   1391 
   1392   // Slow path for the case where the classes are not equal.  In this case we need
   1393   // to call a helper function to do the check.
   1394   class SlowPath : public LIRSlowPath {
   1395    public:
   1396     SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, bool load)
   1397         : LIRSlowPath(m2l, fromfast, cont), load_(load) {
   1398     }
   1399 
   1400     void Compile() {
   1401       GenerateTargetLabel();
   1402 
   1403       if (load_) {
   1404         m2l_->LoadRefDisp(m2l_->TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
   1405                           m2l_->TargetReg(kArg1, kRef), kNotVolatile);
   1406       }
   1407       m2l_->CallRuntimeHelperRegReg(kQuickCheckCast, m2l_->TargetReg(kArg2, kRef),
   1408                                     m2l_->TargetReg(kArg1, kRef), true);
   1409       m2l_->OpUnconditionalBranch(cont_);
   1410     }
   1411 
   1412    private:
   1413     const bool load_;
   1414   };
   1415 
   1416   if (type_known_abstract) {
   1417     // Easier case, run slow path if target is non-null (slow path will load from target)
   1418     LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kArg0, kRef), 0, nullptr);
   1419     LIR* cont = NewLIR0(kPseudoTargetLabel);
   1420     AddSlowPath(new (arena_) SlowPath(this, branch, cont, true));
   1421   } else {
   1422     // Harder, more common case.  We need to generate a forward branch over the load
   1423     // if the target is null.  If it's non-null we perform the load and branch to the
   1424     // slow path if the classes are not equal.
   1425 
   1426     /* Null is OK - continue */
   1427     LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0, kRef), 0, nullptr);
   1428     /* load object->klass_ */
   1429     DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
   1430     LoadRefDisp(TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
   1431                 TargetReg(kArg1, kRef), kNotVolatile);
   1432 
   1433     LIR* branch2 = OpCmpBranch(kCondNe, TargetReg(kArg1, kRef), class_reg, nullptr);
   1434     LIR* cont = NewLIR0(kPseudoTargetLabel);
   1435 
   1436     // Add the slow path that will not perform load since this is already done.
   1437     AddSlowPath(new (arena_) SlowPath(this, branch2, cont, false));
   1438 
   1439     // Set the null check to branch to the continuation.
   1440     branch1->target = cont;
   1441   }
   1442 }
   1443 
   1444 void Mir2Lir::GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_dest,
   1445                            RegLocation rl_src1, RegLocation rl_src2) {
   1446   RegLocation rl_result;
   1447   if (cu_->instruction_set == kThumb2) {
   1448     /*
   1449      * NOTE:  This is the one place in the code in which we might have
   1450      * as many as six live temporary registers.  There are 5 in the normal
   1451      * set for Arm.  Until we have spill capabilities, temporarily add
   1452      * lr to the temp set.  It is safe to do this locally, but note that
   1453      * lr is used explicitly elsewhere in the code generator and cannot
   1454      * normally be used as a general temp register.
   1455      */
   1456     MarkTemp(TargetReg(kLr, kNotWide));   // Add lr to the temp pool
   1457     FreeTemp(TargetReg(kLr, kNotWide));   // and make it available
   1458   }
   1459   rl_src1 = LoadValueWide(rl_src1, kCoreReg);
   1460   rl_src2 = LoadValueWide(rl_src2, kCoreReg);
   1461   rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1462   // The longs may overlap - use intermediate temp if so
   1463   if ((rl_result.reg.GetLowReg() == rl_src1.reg.GetHighReg()) || (rl_result.reg.GetLowReg() == rl_src2.reg.GetHighReg())) {
   1464     RegStorage t_reg = AllocTemp();
   1465     OpRegRegReg(first_op, t_reg, rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
   1466     OpRegRegReg(second_op, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
   1467     OpRegCopy(rl_result.reg.GetLow(), t_reg);
   1468     FreeTemp(t_reg);
   1469   } else {
   1470     OpRegRegReg(first_op, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
   1471     OpRegRegReg(second_op, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
   1472   }
   1473   /*
   1474    * NOTE: If rl_dest refers to a frame variable in a large frame, the
   1475    * following StoreValueWide might need to allocate a temp register.
   1476    * To further work around the lack of a spill capability, explicitly
   1477    * free any temps from rl_src1 & rl_src2 that aren't still live in rl_result.
   1478    * Remove when spill is functional.
   1479    */
   1480   FreeRegLocTemps(rl_result, rl_src1);
   1481   FreeRegLocTemps(rl_result, rl_src2);
   1482   StoreValueWide(rl_dest, rl_result);
   1483   if (cu_->instruction_set == kThumb2) {
   1484     Clobber(TargetReg(kLr, kNotWide));
   1485     UnmarkTemp(TargetReg(kLr, kNotWide));  // Remove lr from the temp pool
   1486   }
   1487 }
   1488 
   1489 void Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
   1490                              RegLocation rl_src1, RegLocation rl_shift) {
   1491   QuickEntrypointEnum target;
   1492   switch (opcode) {
   1493     case Instruction::SHL_LONG:
   1494     case Instruction::SHL_LONG_2ADDR:
   1495       target = kQuickShlLong;
   1496       break;
   1497     case Instruction::SHR_LONG:
   1498     case Instruction::SHR_LONG_2ADDR:
   1499       target = kQuickShrLong;
   1500       break;
   1501     case Instruction::USHR_LONG:
   1502     case Instruction::USHR_LONG_2ADDR:
   1503       target = kQuickUshrLong;
   1504       break;
   1505     default:
   1506       LOG(FATAL) << "Unexpected case";
   1507       target = kQuickShlLong;
   1508   }
   1509   FlushAllRegs();   /* Send everything to home location */
   1510   CallRuntimeHelperRegLocationRegLocation(target, rl_src1, rl_shift, false);
   1511   RegLocation rl_result = GetReturnWide(kCoreReg);
   1512   StoreValueWide(rl_dest, rl_result);
   1513 }
   1514 
   1515 
   1516 void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
   1517                             RegLocation rl_src1, RegLocation rl_src2, int flags) {
   1518   DCHECK(cu_->instruction_set != kX86 && cu_->instruction_set != kX86_64);
   1519   OpKind op = kOpBkpt;
   1520   bool is_div_rem = false;
   1521   bool check_zero = false;
   1522   bool unary = false;
   1523   RegLocation rl_result;
   1524   bool shift_op = false;
   1525   switch (opcode) {
   1526     case Instruction::NEG_INT:
   1527       op = kOpNeg;
   1528       unary = true;
   1529       break;
   1530     case Instruction::NOT_INT:
   1531       op = kOpMvn;
   1532       unary = true;
   1533       break;
   1534     case Instruction::ADD_INT:
   1535     case Instruction::ADD_INT_2ADDR:
   1536       op = kOpAdd;
   1537       break;
   1538     case Instruction::SUB_INT:
   1539     case Instruction::SUB_INT_2ADDR:
   1540       op = kOpSub;
   1541       break;
   1542     case Instruction::MUL_INT:
   1543     case Instruction::MUL_INT_2ADDR:
   1544       op = kOpMul;
   1545       break;
   1546     case Instruction::DIV_INT:
   1547     case Instruction::DIV_INT_2ADDR:
   1548       check_zero = true;
   1549       op = kOpDiv;
   1550       is_div_rem = true;
   1551       break;
   1552     /* NOTE: returns in kArg1 */
   1553     case Instruction::REM_INT:
   1554     case Instruction::REM_INT_2ADDR:
   1555       check_zero = true;
   1556       op = kOpRem;
   1557       is_div_rem = true;
   1558       break;
   1559     case Instruction::AND_INT:
   1560     case Instruction::AND_INT_2ADDR:
   1561       op = kOpAnd;
   1562       break;
   1563     case Instruction::OR_INT:
   1564     case Instruction::OR_INT_2ADDR:
   1565       op = kOpOr;
   1566       break;
   1567     case Instruction::XOR_INT:
   1568     case Instruction::XOR_INT_2ADDR:
   1569       op = kOpXor;
   1570       break;
   1571     case Instruction::SHL_INT:
   1572     case Instruction::SHL_INT_2ADDR:
   1573       shift_op = true;
   1574       op = kOpLsl;
   1575       break;
   1576     case Instruction::SHR_INT:
   1577     case Instruction::SHR_INT_2ADDR:
   1578       shift_op = true;
   1579       op = kOpAsr;
   1580       break;
   1581     case Instruction::USHR_INT:
   1582     case Instruction::USHR_INT_2ADDR:
   1583       shift_op = true;
   1584       op = kOpLsr;
   1585       break;
   1586     default:
   1587       LOG(FATAL) << "Invalid word arith op: " << opcode;
   1588   }
   1589   if (!is_div_rem) {
   1590     if (unary) {
   1591       rl_src1 = LoadValue(rl_src1, kCoreReg);
   1592       rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1593       OpRegReg(op, rl_result.reg, rl_src1.reg);
   1594     } else {
   1595       if ((shift_op) && (cu_->instruction_set != kArm64)) {
   1596         rl_src2 = LoadValue(rl_src2, kCoreReg);
   1597         RegStorage t_reg = AllocTemp();
   1598         OpRegRegImm(kOpAnd, t_reg, rl_src2.reg, 31);
   1599         rl_src1 = LoadValue(rl_src1, kCoreReg);
   1600         rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1601         OpRegRegReg(op, rl_result.reg, rl_src1.reg, t_reg);
   1602         FreeTemp(t_reg);
   1603       } else {
   1604         rl_src1 = LoadValue(rl_src1, kCoreReg);
   1605         rl_src2 = LoadValue(rl_src2, kCoreReg);
   1606         rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1607         OpRegRegReg(op, rl_result.reg, rl_src1.reg, rl_src2.reg);
   1608       }
   1609     }
   1610     StoreValue(rl_dest, rl_result);
   1611   } else {
   1612     bool done = false;      // Set to true if we happen to find a way to use a real instruction.
   1613     if (cu_->instruction_set == kMips || cu_->instruction_set == kMips64 ||
   1614         cu_->instruction_set == kArm64) {
   1615       rl_src1 = LoadValue(rl_src1, kCoreReg);
   1616       rl_src2 = LoadValue(rl_src2, kCoreReg);
   1617       if (check_zero && (flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) {
   1618         GenDivZeroCheck(rl_src2.reg);
   1619       }
   1620       rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
   1621       done = true;
   1622     } else if (cu_->instruction_set == kThumb2) {
   1623       if (cu_->compiler_driver->GetInstructionSetFeatures()->AsArmInstructionSetFeatures()->
   1624               HasDivideInstruction()) {
   1625         // Use ARM SDIV instruction for division.  For remainder we also need to
   1626         // calculate using a MUL and subtract.
   1627         rl_src1 = LoadValue(rl_src1, kCoreReg);
   1628         rl_src2 = LoadValue(rl_src2, kCoreReg);
   1629         if (check_zero && (flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) {
   1630           GenDivZeroCheck(rl_src2.reg);
   1631         }
   1632         rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
   1633         done = true;
   1634       }
   1635     }
   1636 
   1637     // If we haven't already generated the code use the callout function.
   1638     if (!done) {
   1639       FlushAllRegs();   /* Send everything to home location */
   1640       LoadValueDirectFixed(rl_src2, TargetReg(kArg1, kNotWide));
   1641       RegStorage r_tgt = CallHelperSetup(kQuickIdivmod);
   1642       LoadValueDirectFixed(rl_src1, TargetReg(kArg0, kNotWide));
   1643       if (check_zero && (flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) {
   1644         GenDivZeroCheck(TargetReg(kArg1, kNotWide));
   1645       }
   1646       // NOTE: callout here is not a safepoint.
   1647       CallHelper(r_tgt, kQuickIdivmod, false /* not a safepoint */);
   1648       if (op == kOpDiv)
   1649         rl_result = GetReturn(kCoreReg);
   1650       else
   1651         rl_result = GetReturnAlt();
   1652     }
   1653     StoreValue(rl_dest, rl_result);
   1654   }
   1655 }
   1656 
   1657 /*
   1658  * The following are the first-level codegen routines that analyze the format
   1659  * of each bytecode then either dispatch special purpose codegen routines
   1660  * or produce corresponding Thumb instructions directly.
   1661  */
   1662 
   1663 // Returns true if no more than two bits are set in 'x'.
   1664 static bool IsPopCountLE2(unsigned int x) {
   1665   x &= x - 1;
   1666   return (x & (x - 1)) == 0;
   1667 }
   1668 
   1669 // Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit'
   1670 // and store the result in 'rl_dest'.
   1671 bool Mir2Lir::HandleEasyDivRem(Instruction::Code dalvik_opcode ATTRIBUTE_UNUSED, bool is_div,
   1672                                RegLocation rl_src, RegLocation rl_dest, int lit) {
   1673   if ((lit < 2) || (!IsPowerOfTwo(lit))) {
   1674     return false;
   1675   }
   1676   int k = CTZ(lit);
   1677   if (k >= 30) {
   1678     // Avoid special cases.
   1679     return false;
   1680   }
   1681   rl_src = LoadValue(rl_src, kCoreReg);
   1682   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1683   if (is_div) {
   1684     RegStorage t_reg = AllocTemp();
   1685     if (lit == 2) {
   1686       // Division by 2 is by far the most common division by constant.
   1687       OpRegRegImm(kOpLsr, t_reg, rl_src.reg, 32 - k);
   1688       OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg);
   1689       OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
   1690     } else {
   1691       OpRegRegImm(kOpAsr, t_reg, rl_src.reg, 31);
   1692       OpRegRegImm(kOpLsr, t_reg, t_reg, 32 - k);
   1693       OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg);
   1694       OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
   1695     }
   1696   } else {
   1697     RegStorage t_reg1 = AllocTemp();
   1698     RegStorage t_reg2 = AllocTemp();
   1699     if (lit == 2) {
   1700       OpRegRegImm(kOpLsr, t_reg1, rl_src.reg, 32 - k);
   1701       OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg);
   1702       OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit -1);
   1703       OpRegRegReg(kOpSub, rl_result.reg, t_reg2, t_reg1);
   1704     } else {
   1705       OpRegRegImm(kOpAsr, t_reg1, rl_src.reg, 31);
   1706       OpRegRegImm(kOpLsr, t_reg1, t_reg1, 32 - k);
   1707       OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg);
   1708       OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit - 1);
   1709       OpRegRegReg(kOpSub, rl_result.reg, t_reg2, t_reg1);
   1710     }
   1711   }
   1712   StoreValue(rl_dest, rl_result);
   1713   return true;
   1714 }
   1715 
   1716 // Returns true if it added instructions to 'cu' to multiply 'rl_src' by 'lit'
   1717 // and store the result in 'rl_dest'.
   1718 bool Mir2Lir::HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) {
   1719   if (lit < 0) {
   1720     return false;
   1721   }
   1722   if (lit == 0) {
   1723     RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1724     LoadConstant(rl_result.reg, 0);
   1725     StoreValue(rl_dest, rl_result);
   1726     return true;
   1727   }
   1728   if (lit == 1) {
   1729     rl_src = LoadValue(rl_src, kCoreReg);
   1730     RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1731     OpRegCopy(rl_result.reg, rl_src.reg);
   1732     StoreValue(rl_dest, rl_result);
   1733     return true;
   1734   }
   1735   // There is RegRegRegShift on Arm, so check for more special cases
   1736   if (cu_->instruction_set == kThumb2) {
   1737     return EasyMultiply(rl_src, rl_dest, lit);
   1738   }
   1739   // Can we simplify this multiplication?
   1740   bool power_of_two = false;
   1741   bool pop_count_le2 = false;
   1742   bool power_of_two_minus_one = false;
   1743   if (IsPowerOfTwo(lit)) {
   1744     power_of_two = true;
   1745   } else if (IsPopCountLE2(lit)) {
   1746     pop_count_le2 = true;
   1747   } else if (IsPowerOfTwo(lit + 1)) {
   1748     power_of_two_minus_one = true;
   1749   } else {
   1750     return false;
   1751   }
   1752   rl_src = LoadValue(rl_src, kCoreReg);
   1753   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1754   if (power_of_two) {
   1755     // Shift.
   1756     OpRegRegImm(kOpLsl, rl_result.reg, rl_src.reg, CTZ(lit));
   1757   } else if (pop_count_le2) {
   1758     // Shift and add and shift.
   1759     int first_bit = CTZ(lit);
   1760     int second_bit = CTZ(lit ^ (1 << first_bit));
   1761     GenMultiplyByTwoBitMultiplier(rl_src, rl_result, lit, first_bit, second_bit);
   1762   } else {
   1763     // Reverse subtract: (src << (shift + 1)) - src.
   1764     DCHECK(power_of_two_minus_one);
   1765     // TUNING: rsb dst, src, src lsl#CTZ(lit + 1)
   1766     RegStorage t_reg = AllocTemp();
   1767     OpRegRegImm(kOpLsl, t_reg, rl_src.reg, CTZ(lit + 1));
   1768     OpRegRegReg(kOpSub, rl_result.reg, t_reg, rl_src.reg);
   1769   }
   1770   StoreValue(rl_dest, rl_result);
   1771   return true;
   1772 }
   1773 
   1774 // Returns true if it generates instructions.
   1775 bool Mir2Lir::HandleEasyFloatingPointDiv(RegLocation rl_dest, RegLocation rl_src1,
   1776                                          RegLocation rl_src2) {
   1777   if (!rl_src2.is_const ||
   1778       ((cu_->instruction_set != kThumb2) && (cu_->instruction_set != kArm64))) {
   1779     return false;
   1780   }
   1781 
   1782   if (!rl_src2.wide) {
   1783     int32_t divisor = mir_graph_->ConstantValue(rl_src2);
   1784     if (CanDivideByReciprocalMultiplyFloat(divisor)) {
   1785       // Generate multiply by reciprocal instead of div.
   1786       float recip = 1.0f/bit_cast<float, int32_t>(divisor);
   1787       GenMultiplyByConstantFloat(rl_dest, rl_src1, bit_cast<int32_t, float>(recip));
   1788       return true;
   1789     }
   1790   } else {
   1791     int64_t divisor = mir_graph_->ConstantValueWide(rl_src2);
   1792     if (CanDivideByReciprocalMultiplyDouble(divisor)) {
   1793       // Generate multiply by reciprocal instead of div.
   1794       double recip = 1.0/bit_cast<double, int64_t>(divisor);
   1795       GenMultiplyByConstantDouble(rl_dest, rl_src1, bit_cast<int64_t, double>(recip));
   1796       return true;
   1797     }
   1798   }
   1799   return false;
   1800 }
   1801 
   1802 void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src,
   1803                                int lit) {
   1804   RegLocation rl_result;
   1805   OpKind op = static_cast<OpKind>(0);    /* Make gcc happy */
   1806   int shift_op = false;
   1807   bool is_div = false;
   1808 
   1809   switch (opcode) {
   1810     case Instruction::RSUB_INT_LIT8:
   1811     case Instruction::RSUB_INT: {
   1812       rl_src = LoadValue(rl_src, kCoreReg);
   1813       rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1814       if (cu_->instruction_set == kThumb2) {
   1815         OpRegRegImm(kOpRsub, rl_result.reg, rl_src.reg, lit);
   1816       } else {
   1817         OpRegReg(kOpNeg, rl_result.reg, rl_src.reg);
   1818         OpRegImm(kOpAdd, rl_result.reg, lit);
   1819       }
   1820       StoreValue(rl_dest, rl_result);
   1821       return;
   1822     }
   1823 
   1824     case Instruction::SUB_INT:
   1825     case Instruction::SUB_INT_2ADDR:
   1826       lit = -lit;
   1827       FALLTHROUGH_INTENDED;
   1828     case Instruction::ADD_INT:
   1829     case Instruction::ADD_INT_2ADDR:
   1830     case Instruction::ADD_INT_LIT8:
   1831     case Instruction::ADD_INT_LIT16:
   1832       op = kOpAdd;
   1833       break;
   1834     case Instruction::MUL_INT:
   1835     case Instruction::MUL_INT_2ADDR:
   1836     case Instruction::MUL_INT_LIT8:
   1837     case Instruction::MUL_INT_LIT16: {
   1838       if (HandleEasyMultiply(rl_src, rl_dest, lit)) {
   1839         return;
   1840       }
   1841       op = kOpMul;
   1842       break;
   1843     }
   1844     case Instruction::AND_INT:
   1845     case Instruction::AND_INT_2ADDR:
   1846     case Instruction::AND_INT_LIT8:
   1847     case Instruction::AND_INT_LIT16:
   1848       op = kOpAnd;
   1849       break;
   1850     case Instruction::OR_INT:
   1851     case Instruction::OR_INT_2ADDR:
   1852     case Instruction::OR_INT_LIT8:
   1853     case Instruction::OR_INT_LIT16:
   1854       op = kOpOr;
   1855       break;
   1856     case Instruction::XOR_INT:
   1857     case Instruction::XOR_INT_2ADDR:
   1858     case Instruction::XOR_INT_LIT8:
   1859     case Instruction::XOR_INT_LIT16:
   1860       op = kOpXor;
   1861       break;
   1862     case Instruction::SHL_INT_LIT8:
   1863     case Instruction::SHL_INT:
   1864     case Instruction::SHL_INT_2ADDR:
   1865       lit &= 31;
   1866       shift_op = true;
   1867       op = kOpLsl;
   1868       break;
   1869     case Instruction::SHR_INT_LIT8:
   1870     case Instruction::SHR_INT:
   1871     case Instruction::SHR_INT_2ADDR:
   1872       lit &= 31;
   1873       shift_op = true;
   1874       op = kOpAsr;
   1875       break;
   1876     case Instruction::USHR_INT_LIT8:
   1877     case Instruction::USHR_INT:
   1878     case Instruction::USHR_INT_2ADDR:
   1879       lit &= 31;
   1880       shift_op = true;
   1881       op = kOpLsr;
   1882       break;
   1883 
   1884     case Instruction::DIV_INT:
   1885     case Instruction::DIV_INT_2ADDR:
   1886     case Instruction::DIV_INT_LIT8:
   1887     case Instruction::DIV_INT_LIT16:
   1888     case Instruction::REM_INT:
   1889     case Instruction::REM_INT_2ADDR:
   1890     case Instruction::REM_INT_LIT8:
   1891     case Instruction::REM_INT_LIT16: {
   1892       if (lit == 0) {
   1893         GenDivZeroException();
   1894         return;
   1895       }
   1896       if ((opcode == Instruction::DIV_INT) ||
   1897           (opcode == Instruction::DIV_INT_2ADDR) ||
   1898           (opcode == Instruction::DIV_INT_LIT8) ||
   1899           (opcode == Instruction::DIV_INT_LIT16)) {
   1900         is_div = true;
   1901       } else {
   1902         is_div = false;
   1903       }
   1904       if (HandleEasyDivRem(opcode, is_div, rl_src, rl_dest, lit)) {
   1905         return;
   1906       }
   1907 
   1908       bool done = false;
   1909       if (cu_->instruction_set == kMips || cu_->instruction_set == kMips64 ||
   1910           cu_->instruction_set == kArm64) {
   1911         rl_src = LoadValue(rl_src, kCoreReg);
   1912         rl_result = GenDivRemLit(rl_dest, rl_src.reg, lit, is_div);
   1913         done = true;
   1914       } else if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
   1915         rl_result = GenDivRemLit(rl_dest, rl_src, lit, is_div);
   1916         done = true;
   1917       } else if (cu_->instruction_set == kThumb2) {
   1918         if (cu_->compiler_driver->GetInstructionSetFeatures()->AsArmInstructionSetFeatures()->
   1919                 HasDivideInstruction()) {
   1920           // Use ARM SDIV instruction for division.  For remainder we also need to
   1921           // calculate using a MUL and subtract.
   1922           rl_src = LoadValue(rl_src, kCoreReg);
   1923           rl_result = GenDivRemLit(rl_dest, rl_src.reg, lit, is_div);
   1924           done = true;
   1925         }
   1926       }
   1927 
   1928       if (!done) {
   1929         FlushAllRegs();   /* Everything to home location. */
   1930         LoadValueDirectFixed(rl_src, TargetReg(kArg0, kNotWide));
   1931         Clobber(TargetReg(kArg0, kNotWide));
   1932         CallRuntimeHelperRegImm(kQuickIdivmod, TargetReg(kArg0, kNotWide), lit, false);
   1933         if (is_div)
   1934           rl_result = GetReturn(kCoreReg);
   1935         else
   1936           rl_result = GetReturnAlt();
   1937       }
   1938       StoreValue(rl_dest, rl_result);
   1939       return;
   1940     }
   1941     default:
   1942       LOG(FATAL) << "Unexpected opcode " << opcode;
   1943   }
   1944   rl_src = LoadValue(rl_src, kCoreReg);
   1945   rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1946   // Avoid shifts by literal 0 - no support in Thumb.  Change to copy.
   1947   if (shift_op && (lit == 0)) {
   1948     OpRegCopy(rl_result.reg, rl_src.reg);
   1949   } else {
   1950     OpRegRegImm(op, rl_result.reg, rl_src.reg, lit);
   1951   }
   1952   StoreValue(rl_dest, rl_result);
   1953 }
   1954 
   1955 void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
   1956                              RegLocation rl_src1, RegLocation rl_src2, int flags) {
   1957   RegLocation rl_result;
   1958   OpKind first_op = kOpBkpt;
   1959   OpKind second_op = kOpBkpt;
   1960   bool call_out = false;
   1961   bool check_zero = false;
   1962   int ret_reg = TargetReg(kRet0, kNotWide).GetReg();
   1963   QuickEntrypointEnum target;
   1964 
   1965   switch (opcode) {
   1966     case Instruction::NOT_LONG:
   1967       rl_src2 = LoadValueWide(rl_src2, kCoreReg);
   1968       rl_result = EvalLoc(rl_dest, kCoreReg, true);
   1969       // Check for destructive overlap
   1970       if (rl_result.reg.GetLowReg() == rl_src2.reg.GetHighReg()) {
   1971         RegStorage t_reg = AllocTemp();
   1972         OpRegCopy(t_reg, rl_src2.reg.GetHigh());
   1973         OpRegReg(kOpMvn, rl_result.reg.GetLow(), rl_src2.reg.GetLow());
   1974         OpRegReg(kOpMvn, rl_result.reg.GetHigh(), t_reg);
   1975         FreeTemp(t_reg);
   1976       } else {
   1977         OpRegReg(kOpMvn, rl_result.reg.GetLow(), rl_src2.reg.GetLow());
   1978         OpRegReg(kOpMvn, rl_result.reg.GetHigh(), rl_src2.reg.GetHigh());
   1979       }
   1980       StoreValueWide(rl_dest, rl_result);
   1981       return;
   1982     case Instruction::ADD_LONG:
   1983     case Instruction::ADD_LONG_2ADDR:
   1984       first_op = kOpAdd;
   1985       second_op = kOpAdc;
   1986       break;
   1987     case Instruction::SUB_LONG:
   1988     case Instruction::SUB_LONG_2ADDR:
   1989       first_op = kOpSub;
   1990       second_op = kOpSbc;
   1991       break;
   1992     case Instruction::MUL_LONG:
   1993     case Instruction::MUL_LONG_2ADDR:
   1994       call_out = true;
   1995       ret_reg = TargetReg(kRet0, kNotWide).GetReg();
   1996       target = kQuickLmul;
   1997       break;
   1998     case Instruction::DIV_LONG:
   1999     case Instruction::DIV_LONG_2ADDR:
   2000       call_out = true;
   2001       check_zero = true;
   2002       ret_reg = TargetReg(kRet0, kNotWide).GetReg();
   2003       target = kQuickLdiv;
   2004       break;
   2005     case Instruction::REM_LONG:
   2006     case Instruction::REM_LONG_2ADDR:
   2007       call_out = true;
   2008       check_zero = true;
   2009       target = kQuickLmod;
   2010       /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */
   2011       ret_reg = (cu_->instruction_set == kThumb2) ? TargetReg(kArg2, kNotWide).GetReg() :
   2012           TargetReg(kRet0, kNotWide).GetReg();
   2013       break;
   2014     case Instruction::AND_LONG_2ADDR:
   2015     case Instruction::AND_LONG:
   2016       first_op = kOpAnd;
   2017       second_op = kOpAnd;
   2018       break;
   2019     case Instruction::OR_LONG:
   2020     case Instruction::OR_LONG_2ADDR:
   2021       first_op = kOpOr;
   2022       second_op = kOpOr;
   2023       break;
   2024     case Instruction::XOR_LONG:
   2025     case Instruction::XOR_LONG_2ADDR:
   2026       first_op = kOpXor;
   2027       second_op = kOpXor;
   2028       break;
   2029     default:
   2030       LOG(FATAL) << "Invalid long arith op";
   2031   }
   2032   if (!call_out) {
   2033     GenLong3Addr(first_op, second_op, rl_dest, rl_src1, rl_src2);
   2034   } else {
   2035     FlushAllRegs();   /* Send everything to home location */
   2036     if (check_zero) {
   2037       RegStorage r_tmp1 = TargetReg(kArg0, kWide);
   2038       RegStorage r_tmp2 = TargetReg(kArg2, kWide);
   2039       LoadValueDirectWideFixed(rl_src2, r_tmp2);
   2040       RegStorage r_tgt = CallHelperSetup(target);
   2041       if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) {
   2042         GenDivZeroCheckWide(r_tmp2);
   2043       }
   2044       LoadValueDirectWideFixed(rl_src1, r_tmp1);
   2045       // NOTE: callout here is not a safepoint
   2046       CallHelper(r_tgt, target, false /* not safepoint */);
   2047     } else {
   2048       CallRuntimeHelperRegLocationRegLocation(target, rl_src1, rl_src2, false);
   2049     }
   2050     // Adjust return regs in to handle case of rem returning kArg2/kArg3
   2051     if (ret_reg == TargetReg(kRet0, kNotWide).GetReg())
   2052       rl_result = GetReturnWide(kCoreReg);
   2053     else
   2054       rl_result = GetReturnWideAlt();
   2055     StoreValueWide(rl_dest, rl_result);
   2056   }
   2057 }
   2058 
   2059 void Mir2Lir::GenConst(RegLocation rl_dest, int value) {
   2060   RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
   2061   LoadConstantNoClobber(rl_result.reg, value);
   2062   StoreValue(rl_dest, rl_result);
   2063 }
   2064 
   2065 void Mir2Lir::GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest,
   2066                                 RegLocation rl_src, RegisterClass return_reg_class) {
   2067   /*
   2068    * Don't optimize the register usage since it calls out to support
   2069    * functions
   2070    */
   2071 
   2072   FlushAllRegs();   /* Send everything to home location */
   2073   CallRuntimeHelperRegLocation(trampoline, rl_src, false);
   2074   if (rl_dest.wide) {
   2075     RegLocation rl_result = GetReturnWide(return_reg_class);
   2076     StoreValueWide(rl_dest, rl_result);
   2077   } else {
   2078     RegLocation rl_result = GetReturn(return_reg_class);
   2079     StoreValue(rl_dest, rl_result);
   2080   }
   2081 }
   2082 
   2083 class Mir2Lir::SuspendCheckSlowPath : public Mir2Lir::LIRSlowPath {
   2084  public:
   2085   SuspendCheckSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont)
   2086       : LIRSlowPath(m2l, branch, cont) {
   2087   }
   2088 
   2089   void Compile() OVERRIDE {
   2090     m2l_->ResetRegPool();
   2091     m2l_->ResetDefTracking();
   2092     GenerateTargetLabel(kPseudoSuspendTarget);
   2093     m2l_->CallRuntimeHelper(kQuickTestSuspend, true);
   2094     if (cont_ != nullptr) {
   2095       m2l_->OpUnconditionalBranch(cont_);
   2096     }
   2097   }
   2098 };
   2099 
   2100 /* Check if we need to check for pending suspend request */
   2101 void Mir2Lir::GenSuspendTest(int opt_flags) {
   2102   if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK) != 0) {
   2103     return;
   2104   }
   2105   if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitSuspendChecks()) {
   2106     FlushAllRegs();
   2107     LIR* branch = OpTestSuspend(nullptr);
   2108     LIR* cont = NewLIR0(kPseudoTargetLabel);
   2109     AddSlowPath(new (arena_) SuspendCheckSlowPath(this, branch, cont));
   2110   } else {
   2111     FlushAllRegs();     // TODO: needed?
   2112     LIR* inst = CheckSuspendUsingLoad();
   2113     MarkSafepointPC(inst);
   2114   }
   2115 }
   2116 
   2117 /* Check if we need to check for pending suspend request */
   2118 void Mir2Lir::GenSuspendTestAndBranch(int opt_flags, LIR* target) {
   2119   if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK) != 0) {
   2120     OpUnconditionalBranch(target);
   2121     return;
   2122   }
   2123   if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitSuspendChecks()) {
   2124     OpTestSuspend(target);
   2125     FlushAllRegs();
   2126     LIR* branch = OpUnconditionalBranch(nullptr);
   2127     AddSlowPath(new (arena_) SuspendCheckSlowPath(this, branch, target));
   2128   } else {
   2129     // For the implicit suspend check, just perform the trigger
   2130     // load and branch to the target.
   2131     FlushAllRegs();
   2132     LIR* inst = CheckSuspendUsingLoad();
   2133     MarkSafepointPC(inst);
   2134     OpUnconditionalBranch(target);
   2135   }
   2136 }
   2137 
   2138 /* Call out to helper assembly routine that will null check obj and then lock it. */
   2139 void Mir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
   2140   UNUSED(opt_flags);  // TODO: avoid null check with specialized non-null helper.
   2141   FlushAllRegs();
   2142   CallRuntimeHelperRegLocation(kQuickLockObject, rl_src, true);
   2143 }
   2144 
   2145 /* Call out to helper assembly routine that will null check obj and then unlock it. */
   2146 void Mir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
   2147   UNUSED(opt_flags);  // TODO: avoid null check with specialized non-null helper.
   2148   FlushAllRegs();
   2149   CallRuntimeHelperRegLocation(kQuickUnlockObject, rl_src, true);
   2150 }
   2151 
   2152 /* Generic code for generating a wide constant into a VR. */
   2153 void Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
   2154   RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
   2155   LoadConstantWide(rl_result.reg, value);
   2156   StoreValueWide(rl_dest, rl_result);
   2157 }
   2158 
   2159 void Mir2Lir::GenSmallPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
   2160   BasicBlock* bb = mir_graph_->GetBasicBlock(mir->bb);
   2161   DCHECK(bb != nullptr);
   2162   ArenaVector<SuccessorBlockInfo*>::const_iterator succ_bb_iter = bb->successor_blocks.cbegin();
   2163   const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
   2164   const uint16_t entries = table[1];
   2165   // Chained cmp-and-branch.
   2166   const int32_t* as_int32 = reinterpret_cast<const int32_t*>(&table[2]);
   2167   int32_t starting_key = as_int32[0];
   2168   rl_src = LoadValue(rl_src, kCoreReg);
   2169   int i = 0;
   2170   for (; i < entries; ++i, ++succ_bb_iter) {
   2171     if (!InexpensiveConstantInt(starting_key + i, Instruction::Code::IF_EQ)) {
   2172       // Switch to using a temp and add.
   2173       break;
   2174     }
   2175     SuccessorBlockInfo* successor_block_info = *succ_bb_iter;
   2176     DCHECK(successor_block_info != nullptr);
   2177     int case_block_id = successor_block_info->block;
   2178     DCHECK_EQ(starting_key + i, successor_block_info->key);
   2179     OpCmpImmBranch(kCondEq, rl_src.reg, starting_key + i, &block_label_list_[case_block_id]);
   2180   }
   2181   if (i < entries) {
   2182     // The rest do not seem to be inexpensive. Try to allocate a temp and use add.
   2183     RegStorage key_temp = AllocTypedTemp(false, kCoreReg, false);
   2184     if (key_temp.Valid()) {
   2185       LoadConstantNoClobber(key_temp, starting_key + i);
   2186       for (; i < entries - 1; ++i, ++succ_bb_iter) {
   2187         SuccessorBlockInfo* successor_block_info = *succ_bb_iter;
   2188         DCHECK(successor_block_info != nullptr);
   2189         int case_block_id = successor_block_info->block;
   2190         DCHECK_EQ(starting_key + i, successor_block_info->key);
   2191         OpCmpBranch(kCondEq, rl_src.reg, key_temp, &block_label_list_[case_block_id]);
   2192         OpRegImm(kOpAdd, key_temp, 1);  // Increment key.
   2193       }
   2194       SuccessorBlockInfo* successor_block_info = *succ_bb_iter;
   2195       DCHECK(successor_block_info != nullptr);
   2196       int case_block_id = successor_block_info->block;
   2197       DCHECK_EQ(starting_key + i, successor_block_info->key);
   2198       OpCmpBranch(kCondEq, rl_src.reg, key_temp, &block_label_list_[case_block_id]);
   2199     } else {
   2200       // No free temp, just finish the old loop.
   2201       for (; i < entries; ++i, ++succ_bb_iter) {
   2202         SuccessorBlockInfo* successor_block_info = *succ_bb_iter;
   2203         DCHECK(successor_block_info != nullptr);
   2204         int case_block_id = successor_block_info->block;
   2205         DCHECK_EQ(starting_key + i, successor_block_info->key);
   2206         OpCmpImmBranch(kCondEq, rl_src.reg, starting_key + i, &block_label_list_[case_block_id]);
   2207       }
   2208     }
   2209   }
   2210 }
   2211 
   2212 void Mir2Lir::GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
   2213   const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
   2214   if (cu_->verbose) {
   2215     DumpPackedSwitchTable(table);
   2216   }
   2217 
   2218   const uint16_t entries = table[1];
   2219   if (entries <= kSmallSwitchThreshold) {
   2220     GenSmallPackedSwitch(mir, table_offset, rl_src);
   2221   } else {
   2222     // Use the backend-specific implementation.
   2223     GenLargePackedSwitch(mir, table_offset, rl_src);
   2224   }
   2225 }
   2226 
   2227 void Mir2Lir::GenSmallSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
   2228   BasicBlock* bb = mir_graph_->GetBasicBlock(mir->bb);
   2229   DCHECK(bb != nullptr);
   2230   const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
   2231   const uint16_t entries = table[1];
   2232   // Chained cmp-and-branch.
   2233   rl_src = LoadValue(rl_src, kCoreReg);
   2234   int i = 0;
   2235   for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
   2236     int case_block_id = successor_block_info->block;
   2237     int key = successor_block_info->key;
   2238     OpCmpImmBranch(kCondEq, rl_src.reg, key, &block_label_list_[case_block_id]);
   2239     i++;
   2240   }
   2241   DCHECK_EQ(i, entries);
   2242 }
   2243 
   2244 void Mir2Lir::GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
   2245   const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
   2246   if (cu_->verbose) {
   2247     DumpSparseSwitchTable(table);
   2248   }
   2249 
   2250   const uint16_t entries = table[1];
   2251   if (entries <= kSmallSwitchThreshold) {
   2252     GenSmallSparseSwitch(mir, table_offset, rl_src);
   2253   } else {
   2254     // Use the backend-specific implementation.
   2255     GenLargeSparseSwitch(mir, table_offset, rl_src);
   2256   }
   2257 }
   2258 
   2259 bool Mir2Lir::SizeMatchesTypeForEntrypoint(OpSize size, Primitive::Type type) {
   2260   switch (size) {
   2261     case kReference:
   2262       return type == Primitive::kPrimNot;
   2263     case k64:
   2264     case kDouble:
   2265       return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
   2266     case k32:
   2267     case kSingle:
   2268       return type == Primitive::kPrimInt || type == Primitive::kPrimFloat;
   2269     case kSignedHalf:
   2270       return type == Primitive::kPrimShort;
   2271     case kUnsignedHalf:
   2272       return type == Primitive::kPrimChar;
   2273     case kSignedByte:
   2274       return type == Primitive::kPrimByte;
   2275     case kUnsignedByte:
   2276       return type == Primitive::kPrimBoolean;
   2277     case kWord:  // Intentional fallthrough.
   2278     default:
   2279       return false;  // There are no sane types with this op size.
   2280   }
   2281 }
   2282 
   2283 }  // namespace art
   2284