Home | History | Annotate | Download | only in quick
      1 /*
      2  * Copyright (C) 2011 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 "dex/dataflow_iterator-inl.h"
     20 #include "dex/quick/dex_file_method_inliner.h"
     21 #include "driver/compiler_driver.h"
     22 #include "primitive.h"
     23 #include "thread-inl.h"
     24 
     25 namespace art {
     26 
     27 class Mir2Lir::SpecialSuspendCheckSlowPath : public Mir2Lir::LIRSlowPath {
     28  public:
     29   SpecialSuspendCheckSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont)
     30       : LIRSlowPath(m2l, branch, cont),
     31         num_used_args_(0u) {
     32   }
     33 
     34   void PreserveArg(int in_position) {
     35     // Avoid duplicates.
     36     for (size_t i = 0; i != num_used_args_; ++i) {
     37       if (used_args_[i] == in_position) {
     38         return;
     39       }
     40     }
     41     DCHECK_LT(num_used_args_, kMaxArgsToPreserve);
     42     used_args_[num_used_args_] = in_position;
     43     ++num_used_args_;
     44   }
     45 
     46   void Compile() OVERRIDE {
     47     m2l_->ResetRegPool();
     48     m2l_->ResetDefTracking();
     49     GenerateTargetLabel(kPseudoSuspendTarget);
     50 
     51     m2l_->LockCallTemps();
     52 
     53     // Generate frame.
     54     m2l_->GenSpecialEntryForSuspend();
     55 
     56     // Spill all args.
     57     for (size_t i = 0, end = m2l_->in_to_reg_storage_mapping_.GetEndMappedIn(); i < end;
     58         i += m2l_->in_to_reg_storage_mapping_.GetShorty(i).IsWide() ? 2u : 1u) {
     59       m2l_->SpillArg(i);
     60     }
     61 
     62     m2l_->FreeCallTemps();
     63 
     64     // Do the actual suspend call to runtime.
     65     m2l_->CallRuntimeHelper(kQuickTestSuspend, true);
     66 
     67     m2l_->LockCallTemps();
     68 
     69     // Unspill used regs. (Don't unspill unused args.)
     70     for (size_t i = 0; i != num_used_args_; ++i) {
     71       m2l_->UnspillArg(used_args_[i]);
     72     }
     73 
     74     // Pop the frame.
     75     m2l_->GenSpecialExitForSuspend();
     76 
     77     // Branch to the continue label.
     78     DCHECK(cont_ != nullptr);
     79     m2l_->OpUnconditionalBranch(cont_);
     80 
     81     m2l_->FreeCallTemps();
     82   }
     83 
     84  private:
     85   static constexpr size_t kMaxArgsToPreserve = 2u;
     86   size_t num_used_args_;
     87   int used_args_[kMaxArgsToPreserve];
     88 };
     89 
     90 RegisterClass Mir2Lir::ShortyToRegClass(char shorty_type) {
     91   RegisterClass res;
     92   switch (shorty_type) {
     93     case 'L':
     94       res = kRefReg;
     95       break;
     96     case 'F':
     97       // Expected fallthrough.
     98     case 'D':
     99       res = kFPReg;
    100       break;
    101     default:
    102       res = kCoreReg;
    103   }
    104   return res;
    105 }
    106 
    107 void Mir2Lir::LockArg(size_t in_position) {
    108   RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
    109 
    110   if (reg_arg.Valid()) {
    111     LockTemp(reg_arg);
    112   }
    113 }
    114 
    115 RegStorage Mir2Lir::LoadArg(size_t in_position, RegisterClass reg_class, bool wide) {
    116   ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    117   int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
    118 
    119   if (cu_->instruction_set == kX86) {
    120     /*
    121      * When doing a call for x86, it moves the stack pointer in order to push return.
    122      * Thus, we add another 4 bytes to figure out the out of caller (in of callee).
    123      */
    124     offset += sizeof(uint32_t);
    125   }
    126 
    127   if (cu_->instruction_set == kX86_64) {
    128     /*
    129      * When doing a call for x86, it moves the stack pointer in order to push return.
    130      * Thus, we add another 8 bytes to figure out the out of caller (in of callee).
    131      */
    132     offset += sizeof(uint64_t);
    133   }
    134 
    135   RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
    136 
    137   // TODO: REVISIT: This adds a spill of low part while we could just copy it.
    138   if (reg_arg.Valid() && wide && (reg_arg.GetWideKind() == kNotWide)) {
    139     // For wide register we've got only half of it.
    140     // Flush it to memory then.
    141     StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, k32, kNotVolatile);
    142     reg_arg = RegStorage::InvalidReg();
    143   }
    144 
    145   if (!reg_arg.Valid()) {
    146     reg_arg = wide ?  AllocTypedTempWide(false, reg_class) : AllocTypedTemp(false, reg_class);
    147     LoadBaseDisp(TargetPtrReg(kSp), offset, reg_arg, wide ? k64 : k32, kNotVolatile);
    148   } else {
    149     // Check if we need to copy the arg to a different reg_class.
    150     if (!RegClassMatches(reg_class, reg_arg)) {
    151       if (wide) {
    152         RegStorage new_reg = AllocTypedTempWide(false, reg_class);
    153         OpRegCopyWide(new_reg, reg_arg);
    154         reg_arg = new_reg;
    155       } else {
    156         RegStorage new_reg = AllocTypedTemp(false, reg_class);
    157         OpRegCopy(new_reg, reg_arg);
    158         reg_arg = new_reg;
    159       }
    160     }
    161   }
    162   return reg_arg;
    163 }
    164 
    165 void Mir2Lir::LoadArgDirect(size_t in_position, RegLocation rl_dest) {
    166   DCHECK_EQ(rl_dest.location, kLocPhysReg);
    167   ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    168   int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
    169   if (cu_->instruction_set == kX86) {
    170     /*
    171      * When doing a call for x86, it moves the stack pointer in order to push return.
    172      * Thus, we add another 4 bytes to figure out the out of caller (in of callee).
    173      */
    174     offset += sizeof(uint32_t);
    175   }
    176 
    177   if (cu_->instruction_set == kX86_64) {
    178     /*
    179      * When doing a call for x86, it moves the stack pointer in order to push return.
    180      * Thus, we add another 8 bytes to figure out the out of caller (in of callee).
    181      */
    182     offset += sizeof(uint64_t);
    183   }
    184 
    185   RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
    186 
    187   // TODO: REVISIT: This adds a spill of low part while we could just copy it.
    188   if (reg_arg.Valid() && rl_dest.wide && (reg_arg.GetWideKind() == kNotWide)) {
    189     // For wide register we've got only half of it.
    190     // Flush it to memory then.
    191     StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, k32, kNotVolatile);
    192     reg_arg = RegStorage::InvalidReg();
    193   }
    194 
    195   if (!reg_arg.Valid()) {
    196     OpSize op_size = rl_dest.wide ? k64 : (rl_dest.ref ? kReference : k32);
    197     LoadBaseDisp(TargetPtrReg(kSp), offset, rl_dest.reg, op_size, kNotVolatile);
    198   } else {
    199     if (rl_dest.wide) {
    200       OpRegCopyWide(rl_dest.reg, reg_arg);
    201     } else {
    202       OpRegCopy(rl_dest.reg, reg_arg);
    203     }
    204   }
    205 }
    206 
    207 void Mir2Lir::SpillArg(size_t in_position) {
    208   RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
    209 
    210   if (reg_arg.Valid()) {
    211     int offset = frame_size_ + StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
    212     ShortyArg arg = in_to_reg_storage_mapping_.GetShorty(in_position);
    213     OpSize size = arg.IsRef() ? kReference :
    214         (arg.IsWide() && reg_arg.GetWideKind() == kWide) ? k64 : k32;
    215     StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, size, kNotVolatile);
    216   }
    217 }
    218 
    219 void Mir2Lir::UnspillArg(size_t in_position) {
    220   RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
    221 
    222   if (reg_arg.Valid()) {
    223     int offset = frame_size_ + StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
    224     ShortyArg arg = in_to_reg_storage_mapping_.GetShorty(in_position);
    225     OpSize size = arg.IsRef() ? kReference :
    226         (arg.IsWide() && reg_arg.GetWideKind() == kWide) ? k64 : k32;
    227     LoadBaseDisp(TargetPtrReg(kSp), offset, reg_arg, size, kNotVolatile);
    228   }
    229 }
    230 
    231 Mir2Lir::SpecialSuspendCheckSlowPath* Mir2Lir::GenSpecialSuspendTest() {
    232   LockCallTemps();
    233   LIR* branch = OpTestSuspend(nullptr);
    234   FreeCallTemps();
    235   LIR* cont = NewLIR0(kPseudoTargetLabel);
    236   SpecialSuspendCheckSlowPath* slow_path =
    237       new (arena_) SpecialSuspendCheckSlowPath(this, branch, cont);
    238   AddSlowPath(slow_path);
    239   return slow_path;
    240 }
    241 
    242 bool Mir2Lir::GenSpecialIGet(MIR* mir, const InlineMethod& special) {
    243   // FastInstance() already checked by DexFileMethodInliner.
    244   const InlineIGetIPutData& data = special.d.ifield_data;
    245   if (data.method_is_static != 0u || data.object_arg != 0u) {
    246     // The object is not "this" and has to be null-checked.
    247     return false;
    248   }
    249 
    250   OpSize size;
    251   switch (data.op_variant) {
    252     case InlineMethodAnalyser::IGetVariant(Instruction::IGET):
    253       size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kSingle : k32;
    254       break;
    255     case InlineMethodAnalyser::IGetVariant(Instruction::IGET_WIDE):
    256       size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kDouble : k64;
    257       break;
    258     case InlineMethodAnalyser::IGetVariant(Instruction::IGET_OBJECT):
    259       size = kReference;
    260       break;
    261     case InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT):
    262       size = kSignedHalf;
    263       break;
    264     case InlineMethodAnalyser::IGetVariant(Instruction::IGET_CHAR):
    265       size = kUnsignedHalf;
    266       break;
    267     case InlineMethodAnalyser::IGetVariant(Instruction::IGET_BYTE):
    268       size = kSignedByte;
    269       break;
    270     case InlineMethodAnalyser::IGetVariant(Instruction::IGET_BOOLEAN):
    271       size = kUnsignedByte;
    272       break;
    273     default:
    274       LOG(FATAL) << "Unknown variant: " << data.op_variant;
    275       UNREACHABLE();
    276   }
    277 
    278   // Point of no return - no aborts after this
    279   if (!kLeafOptimization) {
    280     auto* slow_path = GenSpecialSuspendTest();
    281     slow_path->PreserveArg(data.object_arg);
    282   }
    283   LockArg(data.object_arg);
    284   GenPrintLabel(mir);
    285   RegStorage reg_obj = LoadArg(data.object_arg, kRefReg);
    286   RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile);
    287   RegisterClass ret_reg_class = ShortyToRegClass(cu_->shorty[0]);
    288   RegLocation rl_dest = IsWide(size) ? GetReturnWide(ret_reg_class) : GetReturn(ret_reg_class);
    289   RegStorage r_result = rl_dest.reg;
    290   if (!RegClassMatches(reg_class, r_result)) {
    291     r_result = IsWide(size) ? AllocTypedTempWide(rl_dest.fp, reg_class)
    292                             : AllocTypedTemp(rl_dest.fp, reg_class);
    293   }
    294   if (IsRef(size)) {
    295     LoadRefDisp(reg_obj, data.field_offset, r_result, data.is_volatile ? kVolatile : kNotVolatile);
    296   } else {
    297     LoadBaseDisp(reg_obj, data.field_offset, r_result, size, data.is_volatile ? kVolatile :
    298         kNotVolatile);
    299   }
    300   if (r_result.NotExactlyEquals(rl_dest.reg)) {
    301     if (IsWide(size)) {
    302       OpRegCopyWide(rl_dest.reg, r_result);
    303     } else {
    304       OpRegCopy(rl_dest.reg, r_result);
    305     }
    306   }
    307   return true;
    308 }
    309 
    310 bool Mir2Lir::GenSpecialIPut(MIR* mir, const InlineMethod& special) {
    311   // FastInstance() already checked by DexFileMethodInliner.
    312   const InlineIGetIPutData& data = special.d.ifield_data;
    313   if (data.method_is_static != 0u || data.object_arg != 0u) {
    314     // The object is not "this" and has to be null-checked.
    315     return false;
    316   }
    317   if (data.return_arg_plus1 != 0u) {
    318     // The setter returns a method argument which we don't support here.
    319     return false;
    320   }
    321 
    322   OpSize size;
    323   switch (data.op_variant) {
    324     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT):
    325       size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kSingle : k32;
    326       break;
    327     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_WIDE):
    328       size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kDouble : k64;
    329       break;
    330     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_OBJECT):
    331       size = kReference;
    332       break;
    333     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT):
    334       size = kSignedHalf;
    335       break;
    336     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_CHAR):
    337       size = kUnsignedHalf;
    338       break;
    339     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BYTE):
    340       size = kSignedByte;
    341       break;
    342     case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BOOLEAN):
    343       size = kUnsignedByte;
    344       break;
    345     default:
    346       LOG(FATAL) << "Unknown variant: " << data.op_variant;
    347       UNREACHABLE();
    348   }
    349 
    350   // Point of no return - no aborts after this
    351   if (!kLeafOptimization) {
    352     auto* slow_path = GenSpecialSuspendTest();
    353     slow_path->PreserveArg(data.object_arg);
    354     slow_path->PreserveArg(data.src_arg);
    355   }
    356   LockArg(data.object_arg);
    357   LockArg(data.src_arg);
    358   GenPrintLabel(mir);
    359   RegStorage reg_obj = LoadArg(data.object_arg, kRefReg);
    360   RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile);
    361   RegStorage reg_src = LoadArg(data.src_arg, reg_class, IsWide(size));
    362   if (IsRef(size)) {
    363     StoreRefDisp(reg_obj, data.field_offset, reg_src, data.is_volatile ? kVolatile : kNotVolatile);
    364   } else {
    365     StoreBaseDisp(reg_obj, data.field_offset, reg_src, size, data.is_volatile ? kVolatile :
    366         kNotVolatile);
    367   }
    368   if (IsRef(size)) {
    369     MarkGCCard(0, reg_src, reg_obj);
    370   }
    371   return true;
    372 }
    373 
    374 bool Mir2Lir::GenSpecialIdentity(MIR* mir, const InlineMethod& special) {
    375   const InlineReturnArgData& data = special.d.return_data;
    376   bool wide = (data.is_wide != 0u);
    377 
    378   // Point of no return - no aborts after this
    379   if (!kLeafOptimization) {
    380     auto* slow_path = GenSpecialSuspendTest();
    381     slow_path->PreserveArg(data.arg);
    382   }
    383   LockArg(data.arg);
    384   GenPrintLabel(mir);
    385   RegisterClass reg_class = ShortyToRegClass(cu_->shorty[0]);
    386   RegLocation rl_dest = wide ? GetReturnWide(reg_class) : GetReturn(reg_class);
    387   LoadArgDirect(data.arg, rl_dest);
    388   return true;
    389 }
    390 
    391 /*
    392  * Special-case code generation for simple non-throwing leaf methods.
    393  */
    394 bool Mir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special) {
    395   DCHECK(special.flags & kInlineSpecial);
    396   current_dalvik_offset_ = mir->offset;
    397   DCHECK(current_mir_ == nullptr);  // Safepoints attributed to prologue.
    398   MIR* return_mir = nullptr;
    399   bool successful = false;
    400   EnsureInitializedArgMappingToPhysicalReg();
    401 
    402   switch (special.opcode) {
    403     case kInlineOpNop:
    404       successful = true;
    405       DCHECK_EQ(mir->dalvikInsn.opcode, Instruction::RETURN_VOID);
    406       if (!kLeafOptimization) {
    407         GenSpecialSuspendTest();
    408       }
    409       return_mir = mir;
    410       break;
    411     case kInlineOpNonWideConst: {
    412       successful = true;
    413       if (!kLeafOptimization) {
    414         GenSpecialSuspendTest();
    415       }
    416       RegLocation rl_dest = GetReturn(ShortyToRegClass(cu_->shorty[0]));
    417       GenPrintLabel(mir);
    418       LoadConstant(rl_dest.reg, static_cast<int>(special.d.data));
    419       return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
    420       break;
    421     }
    422     case kInlineOpReturnArg:
    423       successful = GenSpecialIdentity(mir, special);
    424       return_mir = mir;
    425       break;
    426     case kInlineOpIGet:
    427       successful = GenSpecialIGet(mir, special);
    428       return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
    429       break;
    430     case kInlineOpIPut:
    431       successful = GenSpecialIPut(mir, special);
    432       return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
    433       break;
    434     default:
    435       break;
    436   }
    437 
    438   if (successful) {
    439     if (kIsDebugBuild) {
    440       // Clear unreachable catch entries.
    441       mir_graph_->catches_.clear();
    442     }
    443 
    444     // Handle verbosity for return MIR.
    445     if (return_mir != nullptr) {
    446       current_dalvik_offset_ = return_mir->offset;
    447       // Not handling special identity case because it already generated code as part
    448       // of the return. The label should have been added before any code was generated.
    449       if (special.opcode != kInlineOpReturnArg) {
    450         GenPrintLabel(return_mir);
    451       }
    452     }
    453     GenSpecialExitSequence();
    454 
    455     if (!kLeafOptimization) {
    456       HandleSlowPaths();
    457     } else {
    458       core_spill_mask_ = 0;
    459       num_core_spills_ = 0;
    460       fp_spill_mask_ = 0;
    461       num_fp_spills_ = 0;
    462       frame_size_ = 0;
    463       core_vmap_table_.clear();
    464       fp_vmap_table_.clear();
    465     }
    466   }
    467 
    468   return successful;
    469 }
    470 
    471 /*
    472  * Target-independent code generation.  Use only high-level
    473  * load/store utilities here, or target-dependent genXX() handlers
    474  * when necessary.
    475  */
    476 void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list) {
    477   RegLocation rl_src[3];
    478   RegLocation rl_dest = mir_graph_->GetBadLoc();
    479   RegLocation rl_result = mir_graph_->GetBadLoc();
    480   const Instruction::Code opcode = mir->dalvikInsn.opcode;
    481   const int opt_flags = mir->optimization_flags;
    482   const uint32_t vB = mir->dalvikInsn.vB;
    483   const uint32_t vC = mir->dalvikInsn.vC;
    484   DCHECK(CheckCorePoolSanity()) << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " @ 0x:"
    485                                 << std::hex << current_dalvik_offset_;
    486 
    487   // Prep Src and Dest locations.
    488   int next_sreg = 0;
    489   int next_loc = 0;
    490   uint64_t attrs = MIRGraph::GetDataFlowAttributes(opcode);
    491   rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
    492   if (attrs & DF_UA) {
    493     if (attrs & DF_A_WIDE) {
    494       rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
    495       next_sreg+= 2;
    496     } else {
    497       rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
    498       next_sreg++;
    499     }
    500   }
    501   if (attrs & DF_UB) {
    502     if (attrs & DF_B_WIDE) {
    503       rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
    504       next_sreg+= 2;
    505     } else {
    506       rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
    507       next_sreg++;
    508     }
    509   }
    510   if (attrs & DF_UC) {
    511     if (attrs & DF_C_WIDE) {
    512       rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
    513     } else {
    514       rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
    515     }
    516   }
    517   if (attrs & DF_DA) {
    518     if (attrs & DF_A_WIDE) {
    519       rl_dest = mir_graph_->GetDestWide(mir);
    520     } else {
    521       rl_dest = mir_graph_->GetDest(mir);
    522     }
    523   }
    524   switch (opcode) {
    525     case Instruction::NOP:
    526       break;
    527 
    528     case Instruction::MOVE_EXCEPTION:
    529       GenMoveException(rl_dest);
    530       break;
    531 
    532     case Instruction::RETURN_VOID_NO_BARRIER:
    533     case Instruction::RETURN_VOID:
    534       if (((cu_->access_flags & kAccConstructor) != 0) &&
    535           cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file,
    536                                                           cu_->class_def_idx)) {
    537         GenMemBarrier(kStoreStore);
    538       }
    539       if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
    540         GenSuspendTest(opt_flags);
    541       }
    542       break;
    543 
    544     case Instruction::RETURN_OBJECT:
    545       DCHECK(rl_src[0].ref);
    546       FALLTHROUGH_INTENDED;
    547     case Instruction::RETURN:
    548       if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
    549         GenSuspendTest(opt_flags);
    550       }
    551       StoreValue(GetReturn(ShortyToRegClass(cu_->shorty[0])), rl_src[0]);
    552       break;
    553 
    554     case Instruction::RETURN_WIDE:
    555       if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
    556         GenSuspendTest(opt_flags);
    557       }
    558       StoreValueWide(GetReturnWide(ShortyToRegClass(cu_->shorty[0])), rl_src[0]);
    559       break;
    560 
    561     case Instruction::MOVE_RESULT:
    562     case Instruction::MOVE_RESULT_WIDE:
    563     case Instruction::MOVE_RESULT_OBJECT:
    564       // Already processed with invoke or filled-new-array.
    565       break;
    566 
    567     case Instruction::MOVE:
    568     case Instruction::MOVE_OBJECT:
    569     case Instruction::MOVE_16:
    570     case Instruction::MOVE_OBJECT_16:
    571     case Instruction::MOVE_FROM16:
    572     case Instruction::MOVE_OBJECT_FROM16:
    573       StoreValue(rl_dest, rl_src[0]);
    574       break;
    575 
    576     case Instruction::MOVE_WIDE:
    577     case Instruction::MOVE_WIDE_16:
    578     case Instruction::MOVE_WIDE_FROM16:
    579       StoreValueWide(rl_dest, rl_src[0]);
    580       break;
    581 
    582     case Instruction::CONST:
    583     case Instruction::CONST_4:
    584     case Instruction::CONST_16:
    585       GenConst(rl_dest, vB);
    586       break;
    587 
    588     case Instruction::CONST_HIGH16:
    589       GenConst(rl_dest, vB << 16);
    590       break;
    591 
    592     case Instruction::CONST_WIDE_16:
    593     case Instruction::CONST_WIDE_32:
    594       GenConstWide(rl_dest, static_cast<int64_t>(static_cast<int32_t>(vB)));
    595       break;
    596 
    597     case Instruction::CONST_WIDE:
    598       GenConstWide(rl_dest, mir->dalvikInsn.vB_wide);
    599       break;
    600 
    601     case Instruction::CONST_WIDE_HIGH16:
    602       rl_result = EvalLoc(rl_dest, kAnyReg, true);
    603       LoadConstantWide(rl_result.reg, static_cast<int64_t>(vB) << 48);
    604       StoreValueWide(rl_dest, rl_result);
    605       break;
    606 
    607     case Instruction::MONITOR_ENTER:
    608       GenMonitorEnter(opt_flags, rl_src[0]);
    609       break;
    610 
    611     case Instruction::MONITOR_EXIT:
    612       GenMonitorExit(opt_flags, rl_src[0]);
    613       break;
    614 
    615     case Instruction::CHECK_CAST: {
    616       GenCheckCast(opt_flags, mir->offset, vB, rl_src[0]);
    617       break;
    618     }
    619     case Instruction::INSTANCE_OF:
    620       GenInstanceof(vC, rl_dest, rl_src[0]);
    621       break;
    622 
    623     case Instruction::NEW_INSTANCE:
    624       GenNewInstance(vB, rl_dest);
    625       break;
    626 
    627     case Instruction::THROW:
    628       GenThrow(rl_src[0]);
    629       break;
    630 
    631     case Instruction::ARRAY_LENGTH: {
    632       int len_offset;
    633       len_offset = mirror::Array::LengthOffset().Int32Value();
    634       rl_src[0] = LoadValue(rl_src[0], kRefReg);
    635       GenNullCheck(rl_src[0].reg, opt_flags);
    636       rl_result = EvalLoc(rl_dest, kCoreReg, true);
    637       Load32Disp(rl_src[0].reg, len_offset, rl_result.reg);
    638       MarkPossibleNullPointerException(opt_flags);
    639       StoreValue(rl_dest, rl_result);
    640       break;
    641     }
    642     case Instruction::CONST_STRING:
    643     case Instruction::CONST_STRING_JUMBO:
    644       GenConstString(vB, rl_dest);
    645       break;
    646 
    647     case Instruction::CONST_CLASS:
    648       GenConstClass(vB, rl_dest);
    649       break;
    650 
    651     case Instruction::FILL_ARRAY_DATA:
    652       GenFillArrayData(mir, vB, rl_src[0]);
    653       break;
    654 
    655     case Instruction::FILLED_NEW_ARRAY:
    656       GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
    657                         false /* not range */));
    658       break;
    659 
    660     case Instruction::FILLED_NEW_ARRAY_RANGE:
    661       GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
    662                         true /* range */));
    663       break;
    664 
    665     case Instruction::NEW_ARRAY:
    666       GenNewArray(vC, rl_dest, rl_src[0]);
    667       break;
    668 
    669     case Instruction::GOTO:
    670     case Instruction::GOTO_16:
    671     case Instruction::GOTO_32:
    672       if (mir_graph_->IsBackEdge(bb, bb->taken)) {
    673         GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken]);
    674       } else {
    675         OpUnconditionalBranch(&label_list[bb->taken]);
    676       }
    677       break;
    678 
    679     case Instruction::PACKED_SWITCH:
    680       GenPackedSwitch(mir, vB, rl_src[0]);
    681       break;
    682 
    683     case Instruction::SPARSE_SWITCH:
    684       GenSparseSwitch(mir, vB, rl_src[0]);
    685       break;
    686 
    687     case Instruction::CMPL_FLOAT:
    688     case Instruction::CMPG_FLOAT:
    689     case Instruction::CMPL_DOUBLE:
    690     case Instruction::CMPG_DOUBLE:
    691       GenCmpFP(opcode, rl_dest, rl_src[0], rl_src[1]);
    692       break;
    693 
    694     case Instruction::CMP_LONG:
    695       GenCmpLong(rl_dest, rl_src[0], rl_src[1]);
    696       break;
    697 
    698     case Instruction::IF_EQ:
    699     case Instruction::IF_NE:
    700     case Instruction::IF_LT:
    701     case Instruction::IF_GE:
    702     case Instruction::IF_GT:
    703     case Instruction::IF_LE: {
    704       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
    705         GenSuspendTest(opt_flags);
    706       }
    707       LIR* taken = &label_list[bb->taken];
    708       GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken);
    709       break;
    710     }
    711     case Instruction::IF_EQZ:
    712     case Instruction::IF_NEZ:
    713     case Instruction::IF_LTZ:
    714     case Instruction::IF_GEZ:
    715     case Instruction::IF_GTZ:
    716     case Instruction::IF_LEZ: {
    717       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
    718         GenSuspendTest(opt_flags);
    719       }
    720       LIR* taken = &label_list[bb->taken];
    721       GenCompareZeroAndBranch(opcode, rl_src[0], taken);
    722       break;
    723     }
    724 
    725     case Instruction::AGET_WIDE:
    726       GenArrayGet(opt_flags, rl_dest.fp ? kDouble : k64, rl_src[0], rl_src[1], rl_dest, 3);
    727       break;
    728     case Instruction::AGET_OBJECT:
    729       GenArrayGet(opt_flags, kReference, rl_src[0], rl_src[1], rl_dest, 2);
    730       break;
    731     case Instruction::AGET:
    732       GenArrayGet(opt_flags, rl_dest.fp ? kSingle : k32, rl_src[0], rl_src[1], rl_dest, 2);
    733       break;
    734     case Instruction::AGET_BOOLEAN:
    735       GenArrayGet(opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0);
    736       break;
    737     case Instruction::AGET_BYTE:
    738       GenArrayGet(opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0);
    739       break;
    740     case Instruction::AGET_CHAR:
    741       GenArrayGet(opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
    742       break;
    743     case Instruction::AGET_SHORT:
    744       GenArrayGet(opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
    745       break;
    746     case Instruction::APUT_WIDE:
    747       GenArrayPut(opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[1], rl_src[2], rl_src[0], 3, false);
    748       break;
    749     case Instruction::APUT:
    750       GenArrayPut(opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[1], rl_src[2], rl_src[0], 2, false);
    751       break;
    752     case Instruction::APUT_OBJECT: {
    753       bool is_null = mir_graph_->IsConstantNullRef(rl_src[0]);
    754       bool is_safe = is_null;  // Always safe to store null.
    755       if (!is_safe) {
    756         // Check safety from verifier type information.
    757         const DexCompilationUnit* unit = mir_graph_->GetCurrentDexCompilationUnit();
    758         is_safe = cu_->compiler_driver->IsSafeCast(unit, mir->offset);
    759       }
    760       if (is_null || is_safe) {
    761         // Store of constant null doesn't require an assignability test and can be generated inline
    762         // without fixed register usage or a card mark.
    763         GenArrayPut(opt_flags, kReference, rl_src[1], rl_src[2], rl_src[0], 2, !is_null);
    764       } else {
    765         GenArrayObjPut(opt_flags, rl_src[1], rl_src[2], rl_src[0]);
    766       }
    767       break;
    768     }
    769     case Instruction::APUT_SHORT:
    770     case Instruction::APUT_CHAR:
    771       GenArrayPut(opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1, false);
    772       break;
    773     case Instruction::APUT_BYTE:
    774     case Instruction::APUT_BOOLEAN:
    775       GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0, false);
    776       break;
    777 
    778     case Instruction::IGET_OBJECT_QUICK:
    779     case Instruction::IGET_OBJECT:
    780       GenIGet(mir, opt_flags, kReference, Primitive::kPrimNot, rl_dest, rl_src[0]);
    781       break;
    782 
    783     case Instruction::IGET_WIDE_QUICK:
    784     case Instruction::IGET_WIDE:
    785       // kPrimLong and kPrimDouble share the same entrypoints.
    786       if (rl_dest.fp) {
    787         GenIGet(mir, opt_flags, kDouble, Primitive::kPrimDouble, rl_dest, rl_src[0]);
    788       } else {
    789         GenIGet(mir, opt_flags, k64, Primitive::kPrimLong, rl_dest, rl_src[0]);
    790       }
    791       break;
    792 
    793     case Instruction::IGET_QUICK:
    794     case Instruction::IGET:
    795       if (rl_dest.fp) {
    796         GenIGet(mir, opt_flags, kSingle, Primitive::kPrimFloat, rl_dest, rl_src[0]);
    797       } else {
    798         GenIGet(mir, opt_flags, k32, Primitive::kPrimInt, rl_dest, rl_src[0]);
    799       }
    800       break;
    801 
    802     case Instruction::IGET_CHAR_QUICK:
    803     case Instruction::IGET_CHAR:
    804       GenIGet(mir, opt_flags, kUnsignedHalf, Primitive::kPrimChar, rl_dest, rl_src[0]);
    805       break;
    806 
    807     case Instruction::IGET_SHORT_QUICK:
    808     case Instruction::IGET_SHORT:
    809       GenIGet(mir, opt_flags, kSignedHalf, Primitive::kPrimShort, rl_dest, rl_src[0]);
    810       break;
    811 
    812     case Instruction::IGET_BOOLEAN_QUICK:
    813     case Instruction::IGET_BOOLEAN:
    814       GenIGet(mir, opt_flags, kUnsignedByte, Primitive::kPrimBoolean, rl_dest, rl_src[0]);
    815       break;
    816 
    817     case Instruction::IGET_BYTE_QUICK:
    818     case Instruction::IGET_BYTE:
    819       GenIGet(mir, opt_flags, kSignedByte, Primitive::kPrimByte, rl_dest, rl_src[0]);
    820       break;
    821 
    822     case Instruction::IPUT_WIDE_QUICK:
    823     case Instruction::IPUT_WIDE:
    824       GenIPut(mir, opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[0], rl_src[1]);
    825       break;
    826 
    827     case Instruction::IPUT_OBJECT_QUICK:
    828     case Instruction::IPUT_OBJECT:
    829       GenIPut(mir, opt_flags, kReference, rl_src[0], rl_src[1]);
    830       break;
    831 
    832     case Instruction::IPUT_QUICK:
    833     case Instruction::IPUT:
    834       GenIPut(mir, opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[0], rl_src[1]);
    835       break;
    836 
    837     case Instruction::IPUT_BYTE_QUICK:
    838     case Instruction::IPUT_BOOLEAN_QUICK:
    839     case Instruction::IPUT_BYTE:
    840     case Instruction::IPUT_BOOLEAN:
    841       GenIPut(mir, opt_flags, kUnsignedByte, rl_src[0], rl_src[1]);
    842       break;
    843 
    844     case Instruction::IPUT_CHAR_QUICK:
    845     case Instruction::IPUT_CHAR:
    846       GenIPut(mir, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1]);
    847       break;
    848 
    849     case Instruction::IPUT_SHORT_QUICK:
    850     case Instruction::IPUT_SHORT:
    851       GenIPut(mir, opt_flags, kSignedHalf, rl_src[0], rl_src[1]);
    852       break;
    853 
    854     case Instruction::SGET_OBJECT:
    855       GenSget(mir, rl_dest, kReference, Primitive::kPrimNot);
    856       break;
    857 
    858     case Instruction::SGET:
    859       GenSget(mir, rl_dest, rl_dest.fp ? kSingle : k32, Primitive::kPrimInt);
    860       break;
    861 
    862     case Instruction::SGET_CHAR:
    863       GenSget(mir, rl_dest, kUnsignedHalf, Primitive::kPrimChar);
    864       break;
    865 
    866     case Instruction::SGET_SHORT:
    867       GenSget(mir, rl_dest, kSignedHalf, Primitive::kPrimShort);
    868       break;
    869 
    870     case Instruction::SGET_BOOLEAN:
    871       GenSget(mir, rl_dest, kUnsignedByte, Primitive::kPrimBoolean);
    872       break;
    873 
    874     case Instruction::SGET_BYTE:
    875       GenSget(mir, rl_dest, kSignedByte, Primitive::kPrimByte);
    876       break;
    877 
    878     case Instruction::SGET_WIDE:
    879       // kPrimLong and kPrimDouble share the same entrypoints.
    880       GenSget(mir, rl_dest, rl_dest.fp ? kDouble : k64, Primitive::kPrimDouble);
    881       break;
    882 
    883     case Instruction::SPUT_OBJECT:
    884       GenSput(mir, rl_src[0], kReference);
    885       break;
    886 
    887     case Instruction::SPUT:
    888       GenSput(mir, rl_src[0], rl_src[0].fp ? kSingle : k32);
    889       break;
    890 
    891     case Instruction::SPUT_BYTE:
    892     case Instruction::SPUT_BOOLEAN:
    893       GenSput(mir, rl_src[0], kUnsignedByte);
    894       break;
    895 
    896     case Instruction::SPUT_CHAR:
    897       GenSput(mir, rl_src[0], kUnsignedHalf);
    898       break;
    899 
    900     case Instruction::SPUT_SHORT:
    901       GenSput(mir, rl_src[0], kSignedHalf);
    902       break;
    903 
    904 
    905     case Instruction::SPUT_WIDE:
    906       GenSput(mir, rl_src[0], rl_src[0].fp ? kDouble : k64);
    907       break;
    908 
    909     case Instruction::INVOKE_STATIC_RANGE:
    910       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true));
    911       break;
    912     case Instruction::INVOKE_STATIC:
    913       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false));
    914       break;
    915 
    916     case Instruction::INVOKE_DIRECT:
    917       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false));
    918       break;
    919     case Instruction::INVOKE_DIRECT_RANGE:
    920       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true));
    921       break;
    922 
    923     case Instruction::INVOKE_VIRTUAL_QUICK:
    924     case Instruction::INVOKE_VIRTUAL:
    925       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false));
    926       break;
    927 
    928     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
    929     case Instruction::INVOKE_VIRTUAL_RANGE:
    930       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true));
    931       break;
    932 
    933     case Instruction::INVOKE_SUPER:
    934       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false));
    935       break;
    936     case Instruction::INVOKE_SUPER_RANGE:
    937       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true));
    938       break;
    939 
    940     case Instruction::INVOKE_INTERFACE:
    941       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false));
    942       break;
    943     case Instruction::INVOKE_INTERFACE_RANGE:
    944       GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true));
    945       break;
    946 
    947     case Instruction::NEG_INT:
    948     case Instruction::NOT_INT:
    949       GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags);
    950       break;
    951 
    952     case Instruction::NEG_LONG:
    953     case Instruction::NOT_LONG:
    954       GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags);
    955       break;
    956 
    957     case Instruction::NEG_FLOAT:
    958       GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[0]);
    959       break;
    960 
    961     case Instruction::NEG_DOUBLE:
    962       GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[0]);
    963       break;
    964 
    965     case Instruction::INT_TO_LONG:
    966       GenIntToLong(rl_dest, rl_src[0]);
    967       break;
    968 
    969     case Instruction::LONG_TO_INT:
    970       GenLongToInt(rl_dest, rl_src[0]);
    971       break;
    972 
    973     case Instruction::INT_TO_BYTE:
    974     case Instruction::INT_TO_SHORT:
    975     case Instruction::INT_TO_CHAR:
    976       GenIntNarrowing(opcode, rl_dest, rl_src[0]);
    977       break;
    978 
    979     case Instruction::INT_TO_FLOAT:
    980     case Instruction::INT_TO_DOUBLE:
    981     case Instruction::LONG_TO_FLOAT:
    982     case Instruction::LONG_TO_DOUBLE:
    983     case Instruction::FLOAT_TO_INT:
    984     case Instruction::FLOAT_TO_LONG:
    985     case Instruction::FLOAT_TO_DOUBLE:
    986     case Instruction::DOUBLE_TO_INT:
    987     case Instruction::DOUBLE_TO_LONG:
    988     case Instruction::DOUBLE_TO_FLOAT:
    989       GenConversion(opcode, rl_dest, rl_src[0]);
    990       break;
    991 
    992 
    993     case Instruction::ADD_INT:
    994     case Instruction::ADD_INT_2ADDR:
    995     case Instruction::MUL_INT:
    996     case Instruction::MUL_INT_2ADDR:
    997     case Instruction::AND_INT:
    998     case Instruction::AND_INT_2ADDR:
    999     case Instruction::OR_INT:
   1000     case Instruction::OR_INT_2ADDR:
   1001     case Instruction::XOR_INT:
   1002     case Instruction::XOR_INT_2ADDR:
   1003       if (rl_src[0].is_const &&
   1004           InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[0]), opcode)) {
   1005         GenArithOpIntLit(opcode, rl_dest, rl_src[1],
   1006                              mir_graph_->ConstantValue(rl_src[0].orig_sreg));
   1007       } else if (rl_src[1].is_const &&
   1008                  InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) {
   1009         GenArithOpIntLit(opcode, rl_dest, rl_src[0],
   1010                              mir_graph_->ConstantValue(rl_src[1].orig_sreg));
   1011       } else {
   1012         GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
   1013       }
   1014       break;
   1015 
   1016     case Instruction::SUB_INT:
   1017     case Instruction::SUB_INT_2ADDR:
   1018     case Instruction::DIV_INT:
   1019     case Instruction::DIV_INT_2ADDR:
   1020     case Instruction::REM_INT:
   1021     case Instruction::REM_INT_2ADDR:
   1022     case Instruction::SHL_INT:
   1023     case Instruction::SHL_INT_2ADDR:
   1024     case Instruction::SHR_INT:
   1025     case Instruction::SHR_INT_2ADDR:
   1026     case Instruction::USHR_INT:
   1027     case Instruction::USHR_INT_2ADDR:
   1028       if (rl_src[1].is_const &&
   1029           InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) {
   1030         GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1]));
   1031       } else {
   1032         GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
   1033       }
   1034       break;
   1035 
   1036     case Instruction::ADD_LONG:
   1037     case Instruction::SUB_LONG:
   1038     case Instruction::AND_LONG:
   1039     case Instruction::OR_LONG:
   1040     case Instruction::XOR_LONG:
   1041     case Instruction::ADD_LONG_2ADDR:
   1042     case Instruction::SUB_LONG_2ADDR:
   1043     case Instruction::AND_LONG_2ADDR:
   1044     case Instruction::OR_LONG_2ADDR:
   1045     case Instruction::XOR_LONG_2ADDR:
   1046       if (rl_src[0].is_const || rl_src[1].is_const) {
   1047         GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
   1048         break;
   1049       }
   1050       FALLTHROUGH_INTENDED;
   1051     case Instruction::MUL_LONG:
   1052     case Instruction::DIV_LONG:
   1053     case Instruction::REM_LONG:
   1054     case Instruction::MUL_LONG_2ADDR:
   1055     case Instruction::DIV_LONG_2ADDR:
   1056     case Instruction::REM_LONG_2ADDR:
   1057       GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
   1058       break;
   1059 
   1060     case Instruction::SHL_LONG:
   1061     case Instruction::SHR_LONG:
   1062     case Instruction::USHR_LONG:
   1063     case Instruction::SHL_LONG_2ADDR:
   1064     case Instruction::SHR_LONG_2ADDR:
   1065     case Instruction::USHR_LONG_2ADDR:
   1066       if (rl_src[1].is_const) {
   1067         GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
   1068       } else {
   1069         GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
   1070       }
   1071       break;
   1072 
   1073     case Instruction::DIV_FLOAT:
   1074     case Instruction::DIV_FLOAT_2ADDR:
   1075       if (HandleEasyFloatingPointDiv(rl_dest, rl_src[0], rl_src[1])) {
   1076         break;
   1077       }
   1078       FALLTHROUGH_INTENDED;
   1079     case Instruction::ADD_FLOAT:
   1080     case Instruction::SUB_FLOAT:
   1081     case Instruction::MUL_FLOAT:
   1082     case Instruction::REM_FLOAT:
   1083     case Instruction::ADD_FLOAT_2ADDR:
   1084     case Instruction::SUB_FLOAT_2ADDR:
   1085     case Instruction::MUL_FLOAT_2ADDR:
   1086     case Instruction::REM_FLOAT_2ADDR:
   1087       GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[1]);
   1088       break;
   1089 
   1090     case Instruction::DIV_DOUBLE:
   1091     case Instruction::DIV_DOUBLE_2ADDR:
   1092       if (HandleEasyFloatingPointDiv(rl_dest, rl_src[0], rl_src[1])) {
   1093         break;
   1094       }
   1095       FALLTHROUGH_INTENDED;
   1096     case Instruction::ADD_DOUBLE:
   1097     case Instruction::SUB_DOUBLE:
   1098     case Instruction::MUL_DOUBLE:
   1099     case Instruction::REM_DOUBLE:
   1100     case Instruction::ADD_DOUBLE_2ADDR:
   1101     case Instruction::SUB_DOUBLE_2ADDR:
   1102     case Instruction::MUL_DOUBLE_2ADDR:
   1103     case Instruction::REM_DOUBLE_2ADDR:
   1104       GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[1]);
   1105       break;
   1106 
   1107     case Instruction::RSUB_INT:
   1108     case Instruction::ADD_INT_LIT16:
   1109     case Instruction::MUL_INT_LIT16:
   1110     case Instruction::DIV_INT_LIT16:
   1111     case Instruction::REM_INT_LIT16:
   1112     case Instruction::AND_INT_LIT16:
   1113     case Instruction::OR_INT_LIT16:
   1114     case Instruction::XOR_INT_LIT16:
   1115     case Instruction::ADD_INT_LIT8:
   1116     case Instruction::RSUB_INT_LIT8:
   1117     case Instruction::MUL_INT_LIT8:
   1118     case Instruction::DIV_INT_LIT8:
   1119     case Instruction::REM_INT_LIT8:
   1120     case Instruction::AND_INT_LIT8:
   1121     case Instruction::OR_INT_LIT8:
   1122     case Instruction::XOR_INT_LIT8:
   1123     case Instruction::SHL_INT_LIT8:
   1124     case Instruction::SHR_INT_LIT8:
   1125     case Instruction::USHR_INT_LIT8:
   1126       GenArithOpIntLit(opcode, rl_dest, rl_src[0], vC);
   1127       break;
   1128 
   1129     default:
   1130       LOG(FATAL) << "Unexpected opcode: " << opcode;
   1131   }
   1132   DCHECK(CheckCorePoolSanity());
   1133 }  // NOLINT(readability/fn_size)
   1134 
   1135 // Process extended MIR instructions
   1136 void Mir2Lir::HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
   1137   switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
   1138     case kMirOpCopy: {
   1139       RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
   1140       RegLocation rl_dest = mir_graph_->GetDest(mir);
   1141       StoreValue(rl_dest, rl_src);
   1142       break;
   1143     }
   1144     case kMirOpFusedCmplFloat:
   1145       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
   1146         GenSuspendTest(mir->optimization_flags);
   1147       }
   1148       GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, false /*double*/);
   1149       break;
   1150     case kMirOpFusedCmpgFloat:
   1151       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
   1152         GenSuspendTest(mir->optimization_flags);
   1153       }
   1154       GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, false /*double*/);
   1155       break;
   1156     case kMirOpFusedCmplDouble:
   1157       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
   1158         GenSuspendTest(mir->optimization_flags);
   1159       }
   1160       GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, true /*double*/);
   1161       break;
   1162     case kMirOpFusedCmpgDouble:
   1163       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
   1164         GenSuspendTest(mir->optimization_flags);
   1165       }
   1166       GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, true /*double*/);
   1167       break;
   1168     case kMirOpFusedCmpLong:
   1169       if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
   1170         GenSuspendTest(mir->optimization_flags);
   1171       }
   1172       GenFusedLongCmpBranch(bb, mir);
   1173       break;
   1174     case kMirOpSelect:
   1175       GenSelect(bb, mir);
   1176       break;
   1177     case kMirOpNullCheck: {
   1178       RegLocation rl_obj = mir_graph_->GetSrc(mir, 0);
   1179       rl_obj = LoadValue(rl_obj, kRefReg);
   1180       // An explicit check is done because it is not expected that when this is used,
   1181       // that it will actually trip up the implicit checks (since an invalid access
   1182       // is needed on the null object).
   1183       GenExplicitNullCheck(rl_obj.reg, mir->optimization_flags);
   1184       break;
   1185     }
   1186     case kMirOpPhi:
   1187     case kMirOpNop:
   1188     case kMirOpRangeCheck:
   1189     case kMirOpDivZeroCheck:
   1190     case kMirOpCheck:
   1191       // Ignore these known opcodes
   1192       break;
   1193     default:
   1194       // Give the backends a chance to handle unknown extended MIR opcodes.
   1195       GenMachineSpecificExtendedMethodMIR(bb, mir);
   1196       break;
   1197   }
   1198 }
   1199 
   1200 void Mir2Lir::GenPrintLabel(MIR* mir) {
   1201   // Mark the beginning of a Dalvik instruction for line tracking.
   1202   if (cu_->verbose) {
   1203      char* inst_str = mir_graph_->GetDalvikDisassembly(mir);
   1204      MarkBoundary(mir->offset, inst_str);
   1205   }
   1206 }
   1207 
   1208 // Handle the content in each basic block.
   1209 bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) {
   1210   if (bb->block_type == kDead) return false;
   1211   current_dalvik_offset_ = bb->start_offset;
   1212   MIR* mir;
   1213   int block_id = bb->id;
   1214 
   1215   block_label_list_[block_id].operands[0] = bb->start_offset;
   1216 
   1217   // Insert the block label.
   1218   block_label_list_[block_id].opcode = kPseudoNormalBlockLabel;
   1219   block_label_list_[block_id].flags.fixup = kFixupLabel;
   1220   AppendLIR(&block_label_list_[block_id]);
   1221 
   1222   LIR* head_lir = nullptr;
   1223 
   1224   // If this is a catch block, export the start address.
   1225   if (bb->catch_entry) {
   1226     head_lir = NewLIR0(kPseudoExportedPC);
   1227   }
   1228 
   1229   // Free temp registers and reset redundant store tracking.
   1230   ClobberAllTemps();
   1231 
   1232   if (bb->block_type == kEntryBlock) {
   1233     ResetRegPool();
   1234     int start_vreg = mir_graph_->GetFirstInVR();
   1235     AppendLIR(NewLIR0(kPseudoPrologueBegin));
   1236     DCHECK_EQ(cu_->target64, Is64BitInstructionSet(cu_->instruction_set));
   1237     if (cu_->target64) {
   1238       DCHECK(mir_graph_->GetMethodLoc().wide);
   1239     }
   1240     GenEntrySequence(&mir_graph_->reg_location_[start_vreg], mir_graph_->GetMethodLoc());
   1241     AppendLIR(NewLIR0(kPseudoPrologueEnd));
   1242     DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
   1243   } else if (bb->block_type == kExitBlock) {
   1244     ResetRegPool();
   1245     DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
   1246     AppendLIR(NewLIR0(kPseudoEpilogueBegin));
   1247     GenExitSequence();
   1248     AppendLIR(NewLIR0(kPseudoEpilogueEnd));
   1249     DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
   1250   }
   1251 
   1252   for (mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
   1253     ResetRegPool();
   1254     if (cu_->disable_opt & (1 << kTrackLiveTemps)) {
   1255       ClobberAllTemps();
   1256       // Reset temp allocation to minimize differences when A/B testing.
   1257       reg_pool_->ResetNextTemp();
   1258     }
   1259 
   1260     if (cu_->disable_opt & (1 << kSuppressLoads)) {
   1261       ResetDefTracking();
   1262     }
   1263 
   1264     // Reset temp tracking sanity check.
   1265     if (kIsDebugBuild) {
   1266       live_sreg_ = INVALID_SREG;
   1267     }
   1268 
   1269     current_dalvik_offset_ = mir->offset;
   1270     current_mir_ = mir;
   1271     int opcode = mir->dalvikInsn.opcode;
   1272 
   1273     GenPrintLabel(mir);
   1274 
   1275     // Remember the first LIR for this block.
   1276     if (head_lir == nullptr) {
   1277       head_lir = &block_label_list_[bb->id];
   1278       // Set the first label as a scheduling barrier.
   1279       DCHECK(!head_lir->flags.use_def_invalid);
   1280       head_lir->u.m.def_mask = &kEncodeAll;
   1281     }
   1282 
   1283     if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
   1284       HandleExtendedMethodMIR(bb, mir);
   1285       continue;
   1286     }
   1287 
   1288     CompileDalvikInstruction(mir, bb, block_label_list_);
   1289   }
   1290 
   1291   if (head_lir) {
   1292     // Eliminate redundant loads/stores and delay stores into later slots.
   1293     ApplyLocalOptimizations(head_lir, last_lir_insn_);
   1294   }
   1295   return false;
   1296 }
   1297 
   1298 bool Mir2Lir::SpecialMIR2LIR(const InlineMethod& special) {
   1299   cu_->NewTimingSplit("SpecialMIR2LIR");
   1300   // Find the first DalvikByteCode block.
   1301   DCHECK_EQ(mir_graph_->GetNumReachableBlocks(), mir_graph_->GetDfsOrder().size());
   1302   BasicBlock*bb = nullptr;
   1303   for (BasicBlockId dfs_id : mir_graph_->GetDfsOrder()) {
   1304     BasicBlock* candidate = mir_graph_->GetBasicBlock(dfs_id);
   1305     if (candidate->block_type == kDalvikByteCode) {
   1306       bb = candidate;
   1307       break;
   1308     }
   1309   }
   1310   if (bb == nullptr) {
   1311     return false;
   1312   }
   1313   DCHECK_EQ(bb->start_offset, 0);
   1314   DCHECK(bb->first_mir_insn != nullptr);
   1315 
   1316   // Get the first instruction.
   1317   MIR* mir = bb->first_mir_insn;
   1318 
   1319   // Free temp registers and reset redundant store tracking.
   1320   ResetRegPool();
   1321   ResetDefTracking();
   1322   ClobberAllTemps();
   1323 
   1324   return GenSpecialCase(bb, mir, special);
   1325 }
   1326 
   1327 void Mir2Lir::MethodMIR2LIR() {
   1328   cu_->NewTimingSplit("MIR2LIR");
   1329 
   1330   // Hold the labels of each block.
   1331   block_label_list_ = arena_->AllocArray<LIR>(mir_graph_->GetNumBlocks(), kArenaAllocLIR);
   1332 
   1333   PreOrderDfsIterator iter(mir_graph_);
   1334   BasicBlock* curr_bb = iter.Next();
   1335   BasicBlock* next_bb = iter.Next();
   1336   while (curr_bb != nullptr) {
   1337     MethodBlockCodeGen(curr_bb);
   1338     // If the fall_through block is no longer laid out consecutively, drop in a branch.
   1339     BasicBlock* curr_bb_fall_through = mir_graph_->GetBasicBlock(curr_bb->fall_through);
   1340     if ((curr_bb_fall_through != nullptr) && (curr_bb_fall_through != next_bb)) {
   1341       OpUnconditionalBranch(&block_label_list_[curr_bb->fall_through]);
   1342     }
   1343     curr_bb = next_bb;
   1344     do {
   1345       next_bb = iter.Next();
   1346     } while ((next_bb != nullptr) && (next_bb->block_type == kDead));
   1347   }
   1348   HandleSlowPaths();
   1349 }
   1350 
   1351 //
   1352 // LIR Slow Path
   1353 //
   1354 
   1355 LIR* Mir2Lir::LIRSlowPath::GenerateTargetLabel(int opcode) {
   1356   m2l_->SetCurrentDexPc(current_dex_pc_);
   1357   m2l_->current_mir_ = current_mir_;
   1358   LIR* target = m2l_->NewLIR0(opcode);
   1359   fromfast_->target = target;
   1360   return target;
   1361 }
   1362 
   1363 
   1364 void Mir2Lir::CheckRegStorageImpl(RegStorage rs, WidenessCheck wide, RefCheck ref, FPCheck fp,
   1365                                   bool fail, bool report)
   1366     const  {
   1367   if (rs.Valid()) {
   1368     if (ref == RefCheck::kCheckRef) {
   1369       if (cu_->target64 && !rs.Is64Bit()) {
   1370         if (fail) {
   1371           CHECK(false) << "Reg storage not 64b for ref.";
   1372         } else if (report) {
   1373           LOG(WARNING) << "Reg storage not 64b for ref.";
   1374         }
   1375       }
   1376     }
   1377     if (wide == WidenessCheck::kCheckWide) {
   1378       if (!rs.Is64Bit()) {
   1379         if (fail) {
   1380           CHECK(false) << "Reg storage not 64b for wide.";
   1381         } else if (report) {
   1382           LOG(WARNING) << "Reg storage not 64b for wide.";
   1383         }
   1384       }
   1385     }
   1386     // A tighter check would be nice, but for now soft-float will not check float at all.
   1387     if (fp == FPCheck::kCheckFP && cu_->instruction_set != kArm) {
   1388       if (!rs.IsFloat()) {
   1389         if (fail) {
   1390           CHECK(false) << "Reg storage not float for fp.";
   1391         } else if (report) {
   1392           LOG(WARNING) << "Reg storage not float for fp.";
   1393         }
   1394       }
   1395     } else if (fp == FPCheck::kCheckNotFP) {
   1396       if (rs.IsFloat()) {
   1397         if (fail) {
   1398           CHECK(false) << "Reg storage float for not-fp.";
   1399         } else if (report) {
   1400           LOG(WARNING) << "Reg storage float for not-fp.";
   1401         }
   1402       }
   1403     }
   1404   }
   1405 }
   1406 
   1407 void Mir2Lir::CheckRegLocationImpl(RegLocation rl, bool fail, bool report) const {
   1408   // Regrettably can't use the fp part of rl, as that is not really indicative of where a value
   1409   // will be stored.
   1410   CheckRegStorageImpl(rl.reg, rl.wide ? WidenessCheck::kCheckWide : WidenessCheck::kCheckNotWide,
   1411       rl.ref ? RefCheck::kCheckRef : RefCheck::kCheckNotRef, FPCheck::kIgnoreFP, fail, report);
   1412 }
   1413 
   1414 size_t Mir2Lir::GetInstructionOffset(LIR* lir) {
   1415   UNUSED(lir);
   1416   UNIMPLEMENTED(FATAL) << "Unsupported GetInstructionOffset()";
   1417   UNREACHABLE();
   1418 }
   1419 
   1420 void Mir2Lir::InToRegStorageMapping::Initialize(ShortyIterator* shorty,
   1421                                                 InToRegStorageMapper* mapper) {
   1422   DCHECK(mapper != nullptr);
   1423   DCHECK(shorty != nullptr);
   1424   DCHECK(!IsInitialized());
   1425   DCHECK_EQ(end_mapped_in_, 0u);
   1426   DCHECK(!has_arguments_on_stack_);
   1427   while (shorty->Next()) {
   1428      ShortyArg arg = shorty->GetArg();
   1429      RegStorage reg = mapper->GetNextReg(arg);
   1430      mapping_.emplace_back(arg, reg);
   1431      if (arg.IsWide()) {
   1432        mapping_.emplace_back(ShortyArg(kInvalidShorty), RegStorage::InvalidReg());
   1433      }
   1434      if (reg.Valid()) {
   1435        end_mapped_in_ = mapping_.size();
   1436        // If the VR is wide but wasn't mapped as wide then account for it.
   1437        if (arg.IsWide() && !reg.Is64Bit()) {
   1438          --end_mapped_in_;
   1439        }
   1440      } else {
   1441        has_arguments_on_stack_ = true;
   1442      }
   1443   }
   1444   initialized_ = true;
   1445 }
   1446 
   1447 RegStorage Mir2Lir::InToRegStorageMapping::GetReg(size_t in_position) {
   1448   DCHECK(IsInitialized());
   1449   DCHECK_LT(in_position, mapping_.size());
   1450   DCHECK_NE(mapping_[in_position].first.GetType(), kInvalidShorty);
   1451   return mapping_[in_position].second;
   1452 }
   1453 
   1454 Mir2Lir::ShortyArg Mir2Lir::InToRegStorageMapping::GetShorty(size_t in_position) {
   1455   DCHECK(IsInitialized());
   1456   DCHECK_LT(static_cast<size_t>(in_position), mapping_.size());
   1457   DCHECK_NE(mapping_[in_position].first.GetType(), kInvalidShorty);
   1458   return mapping_[in_position].first;
   1459 }
   1460 
   1461 }  // namespace art
   1462