Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 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 #include "nodes.h"
     17 
     18 #include <cfloat>
     19 
     20 #include "art_method-inl.h"
     21 #include "base/bit_utils.h"
     22 #include "base/bit_vector-inl.h"
     23 #include "base/stl_util.h"
     24 #include "class_linker-inl.h"
     25 #include "code_generator.h"
     26 #include "common_dominator.h"
     27 #include "intrinsics.h"
     28 #include "mirror/class-inl.h"
     29 #include "scoped_thread_state_change-inl.h"
     30 #include "ssa_builder.h"
     31 
     32 namespace art {
     33 
     34 // Enable floating-point static evaluation during constant folding
     35 // only if all floating-point operations and constants evaluate in the
     36 // range and precision of the type used (i.e., 32-bit float, 64-bit
     37 // double).
     38 static constexpr bool kEnableFloatingPointStaticEvaluation = (FLT_EVAL_METHOD == 0);
     39 
     40 void HGraph::InitializeInexactObjectRTI(VariableSizedHandleScope* handles) {
     41   ScopedObjectAccess soa(Thread::Current());
     42   // Create the inexact Object reference type and store it in the HGraph.
     43   ClassLinker* linker = Runtime::Current()->GetClassLinker();
     44   inexact_object_rti_ = ReferenceTypeInfo::Create(
     45       handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)),
     46       /* is_exact */ false);
     47 }
     48 
     49 void HGraph::AddBlock(HBasicBlock* block) {
     50   block->SetBlockId(blocks_.size());
     51   blocks_.push_back(block);
     52 }
     53 
     54 void HGraph::FindBackEdges(ArenaBitVector* visited) {
     55   // "visited" must be empty on entry, it's an output argument for all visited (i.e. live) blocks.
     56   DCHECK_EQ(visited->GetHighestBitSet(), -1);
     57 
     58   // Allocate memory from local ScopedArenaAllocator.
     59   ScopedArenaAllocator allocator(GetArenaStack());
     60   // Nodes that we're currently visiting, indexed by block id.
     61   ArenaBitVector visiting(
     62       &allocator, blocks_.size(), /* expandable */ false, kArenaAllocGraphBuilder);
     63   visiting.ClearAllBits();
     64   // Number of successors visited from a given node, indexed by block id.
     65   ScopedArenaVector<size_t> successors_visited(blocks_.size(),
     66                                                0u,
     67                                                allocator.Adapter(kArenaAllocGraphBuilder));
     68   // Stack of nodes that we're currently visiting (same as marked in "visiting" above).
     69   ScopedArenaVector<HBasicBlock*> worklist(allocator.Adapter(kArenaAllocGraphBuilder));
     70   constexpr size_t kDefaultWorklistSize = 8;
     71   worklist.reserve(kDefaultWorklistSize);
     72   visited->SetBit(entry_block_->GetBlockId());
     73   visiting.SetBit(entry_block_->GetBlockId());
     74   worklist.push_back(entry_block_);
     75 
     76   while (!worklist.empty()) {
     77     HBasicBlock* current = worklist.back();
     78     uint32_t current_id = current->GetBlockId();
     79     if (successors_visited[current_id] == current->GetSuccessors().size()) {
     80       visiting.ClearBit(current_id);
     81       worklist.pop_back();
     82     } else {
     83       HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++];
     84       uint32_t successor_id = successor->GetBlockId();
     85       if (visiting.IsBitSet(successor_id)) {
     86         DCHECK(ContainsElement(worklist, successor));
     87         successor->AddBackEdge(current);
     88       } else if (!visited->IsBitSet(successor_id)) {
     89         visited->SetBit(successor_id);
     90         visiting.SetBit(successor_id);
     91         worklist.push_back(successor);
     92       }
     93     }
     94   }
     95 }
     96 
     97 // Remove the environment use records of the instruction for users.
     98 void RemoveEnvironmentUses(HInstruction* instruction) {
     99   for (HEnvironment* environment = instruction->GetEnvironment();
    100        environment != nullptr;
    101        environment = environment->GetParent()) {
    102     for (size_t i = 0, e = environment->Size(); i < e; ++i) {
    103       if (environment->GetInstructionAt(i) != nullptr) {
    104         environment->RemoveAsUserOfInput(i);
    105       }
    106     }
    107   }
    108 }
    109 
    110 // Return whether the instruction has an environment and it's used by others.
    111 bool HasEnvironmentUsedByOthers(HInstruction* instruction) {
    112   for (HEnvironment* environment = instruction->GetEnvironment();
    113        environment != nullptr;
    114        environment = environment->GetParent()) {
    115     for (size_t i = 0, e = environment->Size(); i < e; ++i) {
    116       HInstruction* user = environment->GetInstructionAt(i);
    117       if (user != nullptr) {
    118         return true;
    119       }
    120     }
    121   }
    122   return false;
    123 }
    124 
    125 // Reset environment records of the instruction itself.
    126 void ResetEnvironmentInputRecords(HInstruction* instruction) {
    127   for (HEnvironment* environment = instruction->GetEnvironment();
    128        environment != nullptr;
    129        environment = environment->GetParent()) {
    130     for (size_t i = 0, e = environment->Size(); i < e; ++i) {
    131       DCHECK(environment->GetHolder() == instruction);
    132       if (environment->GetInstructionAt(i) != nullptr) {
    133         environment->SetRawEnvAt(i, nullptr);
    134       }
    135     }
    136   }
    137 }
    138 
    139 static void RemoveAsUser(HInstruction* instruction) {
    140   instruction->RemoveAsUserOfAllInputs();
    141   RemoveEnvironmentUses(instruction);
    142 }
    143 
    144 void HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const {
    145   for (size_t i = 0; i < blocks_.size(); ++i) {
    146     if (!visited.IsBitSet(i)) {
    147       HBasicBlock* block = blocks_[i];
    148       if (block == nullptr) continue;
    149       DCHECK(block->GetPhis().IsEmpty()) << "Phis are not inserted at this stage";
    150       for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
    151         RemoveAsUser(it.Current());
    152       }
    153     }
    154   }
    155 }
    156 
    157 void HGraph::RemoveDeadBlocks(const ArenaBitVector& visited) {
    158   for (size_t i = 0; i < blocks_.size(); ++i) {
    159     if (!visited.IsBitSet(i)) {
    160       HBasicBlock* block = blocks_[i];
    161       if (block == nullptr) continue;
    162       // We only need to update the successor, which might be live.
    163       for (HBasicBlock* successor : block->GetSuccessors()) {
    164         successor->RemovePredecessor(block);
    165       }
    166       // Remove the block from the list of blocks, so that further analyses
    167       // never see it.
    168       blocks_[i] = nullptr;
    169       if (block->IsExitBlock()) {
    170         SetExitBlock(nullptr);
    171       }
    172       // Mark the block as removed. This is used by the HGraphBuilder to discard
    173       // the block as a branch target.
    174       block->SetGraph(nullptr);
    175     }
    176   }
    177 }
    178 
    179 GraphAnalysisResult HGraph::BuildDominatorTree() {
    180   // Allocate memory from local ScopedArenaAllocator.
    181   ScopedArenaAllocator allocator(GetArenaStack());
    182 
    183   ArenaBitVector visited(&allocator, blocks_.size(), false, kArenaAllocGraphBuilder);
    184   visited.ClearAllBits();
    185 
    186   // (1) Find the back edges in the graph doing a DFS traversal.
    187   FindBackEdges(&visited);
    188 
    189   // (2) Remove instructions and phis from blocks not visited during
    190   //     the initial DFS as users from other instructions, so that
    191   //     users can be safely removed before uses later.
    192   RemoveInstructionsAsUsersFromDeadBlocks(visited);
    193 
    194   // (3) Remove blocks not visited during the initial DFS.
    195   //     Step (5) requires dead blocks to be removed from the
    196   //     predecessors list of live blocks.
    197   RemoveDeadBlocks(visited);
    198 
    199   // (4) Simplify the CFG now, so that we don't need to recompute
    200   //     dominators and the reverse post order.
    201   SimplifyCFG();
    202 
    203   // (5) Compute the dominance information and the reverse post order.
    204   ComputeDominanceInformation();
    205 
    206   // (6) Analyze loops discovered through back edge analysis, and
    207   //     set the loop information on each block.
    208   GraphAnalysisResult result = AnalyzeLoops();
    209   if (result != kAnalysisSuccess) {
    210     return result;
    211   }
    212 
    213   // (7) Precompute per-block try membership before entering the SSA builder,
    214   //     which needs the information to build catch block phis from values of
    215   //     locals at throwing instructions inside try blocks.
    216   ComputeTryBlockInformation();
    217 
    218   return kAnalysisSuccess;
    219 }
    220 
    221 void HGraph::ClearDominanceInformation() {
    222   for (HBasicBlock* block : GetReversePostOrder()) {
    223     block->ClearDominanceInformation();
    224   }
    225   reverse_post_order_.clear();
    226 }
    227 
    228 void HGraph::ClearLoopInformation() {
    229   SetHasIrreducibleLoops(false);
    230   for (HBasicBlock* block : GetReversePostOrder()) {
    231     block->SetLoopInformation(nullptr);
    232   }
    233 }
    234 
    235 void HBasicBlock::ClearDominanceInformation() {
    236   dominated_blocks_.clear();
    237   dominator_ = nullptr;
    238 }
    239 
    240 HInstruction* HBasicBlock::GetFirstInstructionDisregardMoves() const {
    241   HInstruction* instruction = GetFirstInstruction();
    242   while (instruction->IsParallelMove()) {
    243     instruction = instruction->GetNext();
    244   }
    245   return instruction;
    246 }
    247 
    248 static bool UpdateDominatorOfSuccessor(HBasicBlock* block, HBasicBlock* successor) {
    249   DCHECK(ContainsElement(block->GetSuccessors(), successor));
    250 
    251   HBasicBlock* old_dominator = successor->GetDominator();
    252   HBasicBlock* new_dominator =
    253       (old_dominator == nullptr) ? block
    254                                  : CommonDominator::ForPair(old_dominator, block);
    255 
    256   if (old_dominator == new_dominator) {
    257     return false;
    258   } else {
    259     successor->SetDominator(new_dominator);
    260     return true;
    261   }
    262 }
    263 
    264 void HGraph::ComputeDominanceInformation() {
    265   DCHECK(reverse_post_order_.empty());
    266   reverse_post_order_.reserve(blocks_.size());
    267   reverse_post_order_.push_back(entry_block_);
    268 
    269   // Allocate memory from local ScopedArenaAllocator.
    270   ScopedArenaAllocator allocator(GetArenaStack());
    271   // Number of visits of a given node, indexed by block id.
    272   ScopedArenaVector<size_t> visits(blocks_.size(), 0u, allocator.Adapter(kArenaAllocGraphBuilder));
    273   // Number of successors visited from a given node, indexed by block id.
    274   ScopedArenaVector<size_t> successors_visited(blocks_.size(),
    275                                                0u,
    276                                                allocator.Adapter(kArenaAllocGraphBuilder));
    277   // Nodes for which we need to visit successors.
    278   ScopedArenaVector<HBasicBlock*> worklist(allocator.Adapter(kArenaAllocGraphBuilder));
    279   constexpr size_t kDefaultWorklistSize = 8;
    280   worklist.reserve(kDefaultWorklistSize);
    281   worklist.push_back(entry_block_);
    282 
    283   while (!worklist.empty()) {
    284     HBasicBlock* current = worklist.back();
    285     uint32_t current_id = current->GetBlockId();
    286     if (successors_visited[current_id] == current->GetSuccessors().size()) {
    287       worklist.pop_back();
    288     } else {
    289       HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++];
    290       UpdateDominatorOfSuccessor(current, successor);
    291 
    292       // Once all the forward edges have been visited, we know the immediate
    293       // dominator of the block. We can then start visiting its successors.
    294       if (++visits[successor->GetBlockId()] ==
    295           successor->GetPredecessors().size() - successor->NumberOfBackEdges()) {
    296         reverse_post_order_.push_back(successor);
    297         worklist.push_back(successor);
    298       }
    299     }
    300   }
    301 
    302   // Check if the graph has back edges not dominated by their respective headers.
    303   // If so, we need to update the dominators of those headers and recursively of
    304   // their successors. We do that with a fix-point iteration over all blocks.
    305   // The algorithm is guaranteed to terminate because it loops only if the sum
    306   // of all dominator chains has decreased in the current iteration.
    307   bool must_run_fix_point = false;
    308   for (HBasicBlock* block : blocks_) {
    309     if (block != nullptr &&
    310         block->IsLoopHeader() &&
    311         block->GetLoopInformation()->HasBackEdgeNotDominatedByHeader()) {
    312       must_run_fix_point = true;
    313       break;
    314     }
    315   }
    316   if (must_run_fix_point) {
    317     bool update_occurred = true;
    318     while (update_occurred) {
    319       update_occurred = false;
    320       for (HBasicBlock* block : GetReversePostOrder()) {
    321         for (HBasicBlock* successor : block->GetSuccessors()) {
    322           update_occurred |= UpdateDominatorOfSuccessor(block, successor);
    323         }
    324       }
    325     }
    326   }
    327 
    328   // Make sure that there are no remaining blocks whose dominator information
    329   // needs to be updated.
    330   if (kIsDebugBuild) {
    331     for (HBasicBlock* block : GetReversePostOrder()) {
    332       for (HBasicBlock* successor : block->GetSuccessors()) {
    333         DCHECK(!UpdateDominatorOfSuccessor(block, successor));
    334       }
    335     }
    336   }
    337 
    338   // Populate `dominated_blocks_` information after computing all dominators.
    339   // The potential presence of irreducible loops requires to do it after.
    340   for (HBasicBlock* block : GetReversePostOrder()) {
    341     if (!block->IsEntryBlock()) {
    342       block->GetDominator()->AddDominatedBlock(block);
    343     }
    344   }
    345 }
    346 
    347 HBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) {
    348   HBasicBlock* new_block = new (allocator_) HBasicBlock(this, successor->GetDexPc());
    349   AddBlock(new_block);
    350   // Use `InsertBetween` to ensure the predecessor index and successor index of
    351   // `block` and `successor` are preserved.
    352   new_block->InsertBetween(block, successor);
    353   return new_block;
    354 }
    355 
    356 void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) {
    357   // Insert a new node between `block` and `successor` to split the
    358   // critical edge.
    359   HBasicBlock* new_block = SplitEdge(block, successor);
    360   new_block->AddInstruction(new (allocator_) HGoto(successor->GetDexPc()));
    361   if (successor->IsLoopHeader()) {
    362     // If we split at a back edge boundary, make the new block the back edge.
    363     HLoopInformation* info = successor->GetLoopInformation();
    364     if (info->IsBackEdge(*block)) {
    365       info->RemoveBackEdge(block);
    366       info->AddBackEdge(new_block);
    367     }
    368   }
    369 }
    370 
    371 // Reorder phi inputs to match reordering of the block's predecessors.
    372 static void FixPhisAfterPredecessorsReodering(HBasicBlock* block, size_t first, size_t second) {
    373   for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
    374     HPhi* phi = it.Current()->AsPhi();
    375     HInstruction* first_instr = phi->InputAt(first);
    376     HInstruction* second_instr = phi->InputAt(second);
    377     phi->ReplaceInput(first_instr, second);
    378     phi->ReplaceInput(second_instr, first);
    379   }
    380 }
    381 
    382 // Make sure that the first predecessor of a loop header is the incoming block.
    383 void HGraph::OrderLoopHeaderPredecessors(HBasicBlock* header) {
    384   DCHECK(header->IsLoopHeader());
    385   HLoopInformation* info = header->GetLoopInformation();
    386   if (info->IsBackEdge(*header->GetPredecessors()[0])) {
    387     HBasicBlock* to_swap = header->GetPredecessors()[0];
    388     for (size_t pred = 1, e = header->GetPredecessors().size(); pred < e; ++pred) {
    389       HBasicBlock* predecessor = header->GetPredecessors()[pred];
    390       if (!info->IsBackEdge(*predecessor)) {
    391         header->predecessors_[pred] = to_swap;
    392         header->predecessors_[0] = predecessor;
    393         FixPhisAfterPredecessorsReodering(header, 0, pred);
    394         break;
    395       }
    396     }
    397   }
    398 }
    399 
    400 // Transform control flow of the loop to a single preheader format (don't touch the data flow).
    401 // New_preheader can be already among the header predecessors - this situation will be correctly
    402 // processed.
    403 static void FixControlForNewSinglePreheader(HBasicBlock* header, HBasicBlock* new_preheader) {
    404   HLoopInformation* loop_info = header->GetLoopInformation();
    405   for (size_t pred = 0; pred < header->GetPredecessors().size(); ++pred) {
    406     HBasicBlock* predecessor = header->GetPredecessors()[pred];
    407     if (!loop_info->IsBackEdge(*predecessor) && predecessor != new_preheader) {
    408       predecessor->ReplaceSuccessor(header, new_preheader);
    409       pred--;
    410     }
    411   }
    412 }
    413 
    414 //             == Before ==                                               == After ==
    415 //      _________         _________                               _________         _________
    416 //     | B0      |       | B1      |      (old preheaders)       | B0      |       | B1      |
    417 //     |=========|       |=========|                             |=========|       |=========|
    418 //     | i0 = .. |       | i1 = .. |                             | i0 = .. |       | i1 = .. |
    419 //     |_________|       |_________|                             |_________|       |_________|
    420 //           \               /                                         \              /
    421 //            \             /                                        ___v____________v___
    422 //             \           /               (new preheader)          | B20 <- B0, B1      |
    423 //              |         |                                         |====================|
    424 //              |         |                                         | i20 = phi(i0, i1)  |
    425 //              |         |                                         |____________________|
    426 //              |         |                                                   |
    427 //    /\        |         |        /\                           /\            |              /\
    428 //   /  v_______v_________v_______v  \                         /  v___________v_____________v  \
    429 //  |  | B10 <- B0, B1, B2, B3     |  |                       |  | B10 <- B20, B2, B3        |  |
    430 //  |  |===========================|  |       (header)        |  |===========================|  |
    431 //  |  | i10 = phi(i0, i1, i2, i3) |  |                       |  | i10 = phi(i20, i2, i3)    |  |
    432 //  |  |___________________________|  |                       |  |___________________________|  |
    433 //  |        /               \        |                       |        /               \        |
    434 //  |      ...              ...       |                       |      ...              ...       |
    435 //  |   _________         _________   |                       |   _________         _________   |
    436 //  |  | B2      |       | B3      |  |                       |  | B2      |       | B3      |  |
    437 //  |  |=========|       |=========|  |     (back edges)      |  |=========|       |=========|  |
    438 //  |  | i2 = .. |       | i3 = .. |  |                       |  | i2 = .. |       | i3 = .. |  |
    439 //  |  |_________|       |_________|  |                       |  |_________|       |_________|  |
    440 //   \     /                   \     /                         \     /                   \     /
    441 //    \___/                     \___/                           \___/                     \___/
    442 //
    443 void HGraph::TransformLoopToSinglePreheaderFormat(HBasicBlock* header) {
    444   HLoopInformation* loop_info = header->GetLoopInformation();
    445 
    446   HBasicBlock* preheader = new (allocator_) HBasicBlock(this, header->GetDexPc());
    447   AddBlock(preheader);
    448   preheader->AddInstruction(new (allocator_) HGoto(header->GetDexPc()));
    449 
    450   // If the old header has no Phis then we only need to fix the control flow.
    451   if (header->GetPhis().IsEmpty()) {
    452     FixControlForNewSinglePreheader(header, preheader);
    453     preheader->AddSuccessor(header);
    454     return;
    455   }
    456 
    457   // Find the first non-back edge block in the header's predecessors list.
    458   size_t first_nonbackedge_pred_pos = 0;
    459   bool found = false;
    460   for (size_t pred = 0; pred < header->GetPredecessors().size(); ++pred) {
    461     HBasicBlock* predecessor = header->GetPredecessors()[pred];
    462     if (!loop_info->IsBackEdge(*predecessor)) {
    463       first_nonbackedge_pred_pos = pred;
    464       found = true;
    465       break;
    466     }
    467   }
    468 
    469   DCHECK(found);
    470 
    471   // Fix the data-flow.
    472   for (HInstructionIterator it(header->GetPhis()); !it.Done(); it.Advance()) {
    473     HPhi* header_phi = it.Current()->AsPhi();
    474 
    475     HPhi* preheader_phi = new (GetAllocator()) HPhi(GetAllocator(),
    476                                                     header_phi->GetRegNumber(),
    477                                                     0,
    478                                                     header_phi->GetType());
    479     if (header_phi->GetType() == DataType::Type::kReference) {
    480       preheader_phi->SetReferenceTypeInfo(header_phi->GetReferenceTypeInfo());
    481     }
    482     preheader->AddPhi(preheader_phi);
    483 
    484     HInstruction* orig_input = header_phi->InputAt(first_nonbackedge_pred_pos);
    485     header_phi->ReplaceInput(preheader_phi, first_nonbackedge_pred_pos);
    486     preheader_phi->AddInput(orig_input);
    487 
    488     for (size_t input_pos = first_nonbackedge_pred_pos + 1;
    489          input_pos < header_phi->InputCount();
    490          input_pos++) {
    491       HInstruction* input = header_phi->InputAt(input_pos);
    492       HBasicBlock* pred_block = header->GetPredecessors()[input_pos];
    493 
    494       if (loop_info->Contains(*pred_block)) {
    495         DCHECK(loop_info->IsBackEdge(*pred_block));
    496       } else {
    497         preheader_phi->AddInput(input);
    498         header_phi->RemoveInputAt(input_pos);
    499         input_pos--;
    500       }
    501     }
    502   }
    503 
    504   // Fix the control-flow.
    505   HBasicBlock* first_pred = header->GetPredecessors()[first_nonbackedge_pred_pos];
    506   preheader->InsertBetween(first_pred, header);
    507 
    508   FixControlForNewSinglePreheader(header, preheader);
    509 }
    510 
    511 void HGraph::SimplifyLoop(HBasicBlock* header) {
    512   HLoopInformation* info = header->GetLoopInformation();
    513 
    514   // Make sure the loop has only one pre header. This simplifies SSA building by having
    515   // to just look at the pre header to know which locals are initialized at entry of the
    516   // loop. Also, don't allow the entry block to be a pre header: this simplifies inlining
    517   // this graph.
    518   size_t number_of_incomings = header->GetPredecessors().size() - info->NumberOfBackEdges();
    519   if (number_of_incomings != 1 || (GetEntryBlock()->GetSingleSuccessor() == header)) {
    520     TransformLoopToSinglePreheaderFormat(header);
    521   }
    522 
    523   OrderLoopHeaderPredecessors(header);
    524 
    525   HInstruction* first_instruction = header->GetFirstInstruction();
    526   if (first_instruction != nullptr && first_instruction->IsSuspendCheck()) {
    527     // Called from DeadBlockElimination. Update SuspendCheck pointer.
    528     info->SetSuspendCheck(first_instruction->AsSuspendCheck());
    529   }
    530 }
    531 
    532 void HGraph::ComputeTryBlockInformation() {
    533   // Iterate in reverse post order to propagate try membership information from
    534   // predecessors to their successors.
    535   for (HBasicBlock* block : GetReversePostOrder()) {
    536     if (block->IsEntryBlock() || block->IsCatchBlock()) {
    537       // Catch blocks after simplification have only exceptional predecessors
    538       // and hence are never in tries.
    539       continue;
    540     }
    541 
    542     // Infer try membership from the first predecessor. Having simplified loops,
    543     // the first predecessor can never be a back edge and therefore it must have
    544     // been visited already and had its try membership set.
    545     HBasicBlock* first_predecessor = block->GetPredecessors()[0];
    546     DCHECK(!block->IsLoopHeader() || !block->GetLoopInformation()->IsBackEdge(*first_predecessor));
    547     const HTryBoundary* try_entry = first_predecessor->ComputeTryEntryOfSuccessors();
    548     if (try_entry != nullptr &&
    549         (block->GetTryCatchInformation() == nullptr ||
    550          try_entry != &block->GetTryCatchInformation()->GetTryEntry())) {
    551       // We are either setting try block membership for the first time or it
    552       // has changed.
    553       block->SetTryCatchInformation(new (allocator_) TryCatchInformation(*try_entry));
    554     }
    555   }
    556 }
    557 
    558 void HGraph::SimplifyCFG() {
    559 // Simplify the CFG for future analysis, and code generation:
    560   // (1): Split critical edges.
    561   // (2): Simplify loops by having only one preheader.
    562   // NOTE: We're appending new blocks inside the loop, so we need to use index because iterators
    563   // can be invalidated. We remember the initial size to avoid iterating over the new blocks.
    564   for (size_t block_id = 0u, end = blocks_.size(); block_id != end; ++block_id) {
    565     HBasicBlock* block = blocks_[block_id];
    566     if (block == nullptr) continue;
    567     if (block->GetSuccessors().size() > 1) {
    568       // Only split normal-flow edges. We cannot split exceptional edges as they
    569       // are synthesized (approximate real control flow), and we do not need to
    570       // anyway. Moves that would be inserted there are performed by the runtime.
    571       ArrayRef<HBasicBlock* const> normal_successors = block->GetNormalSuccessors();
    572       for (size_t j = 0, e = normal_successors.size(); j < e; ++j) {
    573         HBasicBlock* successor = normal_successors[j];
    574         DCHECK(!successor->IsCatchBlock());
    575         if (successor == exit_block_) {
    576           // (Throw/Return/ReturnVoid)->TryBoundary->Exit. Special case which we
    577           // do not want to split because Goto->Exit is not allowed.
    578           DCHECK(block->IsSingleTryBoundary());
    579         } else if (successor->GetPredecessors().size() > 1) {
    580           SplitCriticalEdge(block, successor);
    581           // SplitCriticalEdge could have invalidated the `normal_successors`
    582           // ArrayRef. We must re-acquire it.
    583           normal_successors = block->GetNormalSuccessors();
    584           DCHECK_EQ(normal_successors[j]->GetSingleSuccessor(), successor);
    585           DCHECK_EQ(e, normal_successors.size());
    586         }
    587       }
    588     }
    589     if (block->IsLoopHeader()) {
    590       SimplifyLoop(block);
    591     } else if (!block->IsEntryBlock() &&
    592                block->GetFirstInstruction() != nullptr &&
    593                block->GetFirstInstruction()->IsSuspendCheck()) {
    594       // We are being called by the dead code elimiation pass, and what used to be
    595       // a loop got dismantled. Just remove the suspend check.
    596       block->RemoveInstruction(block->GetFirstInstruction());
    597     }
    598   }
    599 }
    600 
    601 GraphAnalysisResult HGraph::AnalyzeLoops() const {
    602   // We iterate post order to ensure we visit inner loops before outer loops.
    603   // `PopulateRecursive` needs this guarantee to know whether a natural loop
    604   // contains an irreducible loop.
    605   for (HBasicBlock* block : GetPostOrder()) {
    606     if (block->IsLoopHeader()) {
    607       if (block->IsCatchBlock()) {
    608         // TODO: Dealing with exceptional back edges could be tricky because
    609         //       they only approximate the real control flow. Bail out for now.
    610         VLOG(compiler) << "Not compiled: Exceptional back edges";
    611         return kAnalysisFailThrowCatchLoop;
    612       }
    613       block->GetLoopInformation()->Populate();
    614     }
    615   }
    616   return kAnalysisSuccess;
    617 }
    618 
    619 void HLoopInformation::Dump(std::ostream& os) {
    620   os << "header: " << header_->GetBlockId() << std::endl;
    621   os << "pre header: " << GetPreHeader()->GetBlockId() << std::endl;
    622   for (HBasicBlock* block : back_edges_) {
    623     os << "back edge: " << block->GetBlockId() << std::endl;
    624   }
    625   for (HBasicBlock* block : header_->GetPredecessors()) {
    626     os << "predecessor: " << block->GetBlockId() << std::endl;
    627   }
    628   for (uint32_t idx : blocks_.Indexes()) {
    629     os << "  in loop: " << idx << std::endl;
    630   }
    631 }
    632 
    633 void HGraph::InsertConstant(HConstant* constant) {
    634   // New constants are inserted before the SuspendCheck at the bottom of the
    635   // entry block. Note that this method can be called from the graph builder and
    636   // the entry block therefore may not end with SuspendCheck->Goto yet.
    637   HInstruction* insert_before = nullptr;
    638 
    639   HInstruction* gota = entry_block_->GetLastInstruction();
    640   if (gota != nullptr && gota->IsGoto()) {
    641     HInstruction* suspend_check = gota->GetPrevious();
    642     if (suspend_check != nullptr && suspend_check->IsSuspendCheck()) {
    643       insert_before = suspend_check;
    644     } else {
    645       insert_before = gota;
    646     }
    647   }
    648 
    649   if (insert_before == nullptr) {
    650     entry_block_->AddInstruction(constant);
    651   } else {
    652     entry_block_->InsertInstructionBefore(constant, insert_before);
    653   }
    654 }
    655 
    656 HNullConstant* HGraph::GetNullConstant(uint32_t dex_pc) {
    657   // For simplicity, don't bother reviving the cached null constant if it is
    658   // not null and not in a block. Otherwise, we need to clear the instruction
    659   // id and/or any invariants the graph is assuming when adding new instructions.
    660   if ((cached_null_constant_ == nullptr) || (cached_null_constant_->GetBlock() == nullptr)) {
    661     cached_null_constant_ = new (allocator_) HNullConstant(dex_pc);
    662     cached_null_constant_->SetReferenceTypeInfo(inexact_object_rti_);
    663     InsertConstant(cached_null_constant_);
    664   }
    665   if (kIsDebugBuild) {
    666     ScopedObjectAccess soa(Thread::Current());
    667     DCHECK(cached_null_constant_->GetReferenceTypeInfo().IsValid());
    668   }
    669   return cached_null_constant_;
    670 }
    671 
    672 HCurrentMethod* HGraph::GetCurrentMethod() {
    673   // For simplicity, don't bother reviving the cached current method if it is
    674   // not null and not in a block. Otherwise, we need to clear the instruction
    675   // id and/or any invariants the graph is assuming when adding new instructions.
    676   if ((cached_current_method_ == nullptr) || (cached_current_method_->GetBlock() == nullptr)) {
    677     cached_current_method_ = new (allocator_) HCurrentMethod(
    678         Is64BitInstructionSet(instruction_set_) ? DataType::Type::kInt64 : DataType::Type::kInt32,
    679         entry_block_->GetDexPc());
    680     if (entry_block_->GetFirstInstruction() == nullptr) {
    681       entry_block_->AddInstruction(cached_current_method_);
    682     } else {
    683       entry_block_->InsertInstructionBefore(
    684           cached_current_method_, entry_block_->GetFirstInstruction());
    685     }
    686   }
    687   return cached_current_method_;
    688 }
    689 
    690 const char* HGraph::GetMethodName() const {
    691   const DexFile::MethodId& method_id = dex_file_.GetMethodId(method_idx_);
    692   return dex_file_.GetMethodName(method_id);
    693 }
    694 
    695 std::string HGraph::PrettyMethod(bool with_signature) const {
    696   return dex_file_.PrettyMethod(method_idx_, with_signature);
    697 }
    698 
    699 HConstant* HGraph::GetConstant(DataType::Type type, int64_t value, uint32_t dex_pc) {
    700   switch (type) {
    701     case DataType::Type::kBool:
    702       DCHECK(IsUint<1>(value));
    703       FALLTHROUGH_INTENDED;
    704     case DataType::Type::kUint8:
    705     case DataType::Type::kInt8:
    706     case DataType::Type::kUint16:
    707     case DataType::Type::kInt16:
    708     case DataType::Type::kInt32:
    709       DCHECK(IsInt(DataType::Size(type) * kBitsPerByte, value));
    710       return GetIntConstant(static_cast<int32_t>(value), dex_pc);
    711 
    712     case DataType::Type::kInt64:
    713       return GetLongConstant(value, dex_pc);
    714 
    715     default:
    716       LOG(FATAL) << "Unsupported constant type";
    717       UNREACHABLE();
    718   }
    719 }
    720 
    721 void HGraph::CacheFloatConstant(HFloatConstant* constant) {
    722   int32_t value = bit_cast<int32_t, float>(constant->GetValue());
    723   DCHECK(cached_float_constants_.find(value) == cached_float_constants_.end());
    724   cached_float_constants_.Overwrite(value, constant);
    725 }
    726 
    727 void HGraph::CacheDoubleConstant(HDoubleConstant* constant) {
    728   int64_t value = bit_cast<int64_t, double>(constant->GetValue());
    729   DCHECK(cached_double_constants_.find(value) == cached_double_constants_.end());
    730   cached_double_constants_.Overwrite(value, constant);
    731 }
    732 
    733 void HLoopInformation::Add(HBasicBlock* block) {
    734   blocks_.SetBit(block->GetBlockId());
    735 }
    736 
    737 void HLoopInformation::Remove(HBasicBlock* block) {
    738   blocks_.ClearBit(block->GetBlockId());
    739 }
    740 
    741 void HLoopInformation::PopulateRecursive(HBasicBlock* block) {
    742   if (blocks_.IsBitSet(block->GetBlockId())) {
    743     return;
    744   }
    745 
    746   blocks_.SetBit(block->GetBlockId());
    747   block->SetInLoop(this);
    748   if (block->IsLoopHeader()) {
    749     // We're visiting loops in post-order, so inner loops must have been
    750     // populated already.
    751     DCHECK(block->GetLoopInformation()->IsPopulated());
    752     if (block->GetLoopInformation()->IsIrreducible()) {
    753       contains_irreducible_loop_ = true;
    754     }
    755   }
    756   for (HBasicBlock* predecessor : block->GetPredecessors()) {
    757     PopulateRecursive(predecessor);
    758   }
    759 }
    760 
    761 void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized) {
    762   size_t block_id = block->GetBlockId();
    763 
    764   // If `block` is in `finalized`, we know its membership in the loop has been
    765   // decided and it does not need to be revisited.
    766   if (finalized->IsBitSet(block_id)) {
    767     return;
    768   }
    769 
    770   bool is_finalized = false;
    771   if (block->IsLoopHeader()) {
    772     // If we hit a loop header in an irreducible loop, we first check if the
    773     // pre header of that loop belongs to the currently analyzed loop. If it does,
    774     // then we visit the back edges.
    775     // Note that we cannot use GetPreHeader, as the loop may have not been populated
    776     // yet.
    777     HBasicBlock* pre_header = block->GetPredecessors()[0];
    778     PopulateIrreducibleRecursive(pre_header, finalized);
    779     if (blocks_.IsBitSet(pre_header->GetBlockId())) {
    780       block->SetInLoop(this);
    781       blocks_.SetBit(block_id);
    782       finalized->SetBit(block_id);
    783       is_finalized = true;
    784 
    785       HLoopInformation* info = block->GetLoopInformation();
    786       for (HBasicBlock* back_edge : info->GetBackEdges()) {
    787         PopulateIrreducibleRecursive(back_edge, finalized);
    788       }
    789     }
    790   } else {
    791     // Visit all predecessors. If one predecessor is part of the loop, this
    792     // block is also part of this loop.
    793     for (HBasicBlock* predecessor : block->GetPredecessors()) {
    794       PopulateIrreducibleRecursive(predecessor, finalized);
    795       if (!is_finalized && blocks_.IsBitSet(predecessor->GetBlockId())) {
    796         block->SetInLoop(this);
    797         blocks_.SetBit(block_id);
    798         finalized->SetBit(block_id);
    799         is_finalized = true;
    800       }
    801     }
    802   }
    803 
    804   // All predecessors have been recursively visited. Mark finalized if not marked yet.
    805   if (!is_finalized) {
    806     finalized->SetBit(block_id);
    807   }
    808 }
    809 
    810 void HLoopInformation::Populate() {
    811   DCHECK_EQ(blocks_.NumSetBits(), 0u) << "Loop information has already been populated";
    812   // Populate this loop: starting with the back edge, recursively add predecessors
    813   // that are not already part of that loop. Set the header as part of the loop
    814   // to end the recursion.
    815   // This is a recursive implementation of the algorithm described in
    816   // "Advanced Compiler Design & Implementation" (Muchnick) p192.
    817   HGraph* graph = header_->GetGraph();
    818   blocks_.SetBit(header_->GetBlockId());
    819   header_->SetInLoop(this);
    820 
    821   bool is_irreducible_loop = HasBackEdgeNotDominatedByHeader();
    822 
    823   if (is_irreducible_loop) {
    824     // Allocate memory from local ScopedArenaAllocator.
    825     ScopedArenaAllocator allocator(graph->GetArenaStack());
    826     ArenaBitVector visited(&allocator,
    827                            graph->GetBlocks().size(),
    828                            /* expandable */ false,
    829                            kArenaAllocGraphBuilder);
    830     visited.ClearAllBits();
    831     // Stop marking blocks at the loop header.
    832     visited.SetBit(header_->GetBlockId());
    833 
    834     for (HBasicBlock* back_edge : GetBackEdges()) {
    835       PopulateIrreducibleRecursive(back_edge, &visited);
    836     }
    837   } else {
    838     for (HBasicBlock* back_edge : GetBackEdges()) {
    839       PopulateRecursive(back_edge);
    840     }
    841   }
    842 
    843   if (!is_irreducible_loop && graph->IsCompilingOsr()) {
    844     // When compiling in OSR mode, all loops in the compiled method may be entered
    845     // from the interpreter. We treat this OSR entry point just like an extra entry
    846     // to an irreducible loop, so we need to mark the method's loops as irreducible.
    847     // This does not apply to inlined loops which do not act as OSR entry points.
    848     if (suspend_check_ == nullptr) {
    849       // Just building the graph in OSR mode, this loop is not inlined. We never build an
    850       // inner graph in OSR mode as we can do OSR transition only from the outer method.
    851       is_irreducible_loop = true;
    852     } else {
    853       // Look at the suspend check's environment to determine if the loop was inlined.
    854       DCHECK(suspend_check_->HasEnvironment());
    855       if (!suspend_check_->GetEnvironment()->IsFromInlinedInvoke()) {
    856         is_irreducible_loop = true;
    857       }
    858     }
    859   }
    860   if (is_irreducible_loop) {
    861     irreducible_ = true;
    862     contains_irreducible_loop_ = true;
    863     graph->SetHasIrreducibleLoops(true);
    864   }
    865   graph->SetHasLoops(true);
    866 }
    867 
    868 void HLoopInformation::PopulateInnerLoopUpwards(HLoopInformation* inner_loop) {
    869   DCHECK(inner_loop->GetPreHeader()->GetLoopInformation() == this);
    870   blocks_.Union(&inner_loop->blocks_);
    871   HLoopInformation* outer_loop = GetPreHeader()->GetLoopInformation();
    872   if (outer_loop != nullptr) {
    873     outer_loop->PopulateInnerLoopUpwards(this);
    874   }
    875 }
    876 
    877 HBasicBlock* HLoopInformation::GetPreHeader() const {
    878   HBasicBlock* block = header_->GetPredecessors()[0];
    879   DCHECK(irreducible_ || (block == header_->GetDominator()));
    880   return block;
    881 }
    882 
    883 bool HLoopInformation::Contains(const HBasicBlock& block) const {
    884   return blocks_.IsBitSet(block.GetBlockId());
    885 }
    886 
    887 bool HLoopInformation::IsIn(const HLoopInformation& other) const {
    888   return other.blocks_.IsBitSet(header_->GetBlockId());
    889 }
    890 
    891 bool HLoopInformation::IsDefinedOutOfTheLoop(HInstruction* instruction) const {
    892   return !blocks_.IsBitSet(instruction->GetBlock()->GetBlockId());
    893 }
    894 
    895 size_t HLoopInformation::GetLifetimeEnd() const {
    896   size_t last_position = 0;
    897   for (HBasicBlock* back_edge : GetBackEdges()) {
    898     last_position = std::max(back_edge->GetLifetimeEnd(), last_position);
    899   }
    900   return last_position;
    901 }
    902 
    903 bool HLoopInformation::HasBackEdgeNotDominatedByHeader() const {
    904   for (HBasicBlock* back_edge : GetBackEdges()) {
    905     DCHECK(back_edge->GetDominator() != nullptr);
    906     if (!header_->Dominates(back_edge)) {
    907       return true;
    908     }
    909   }
    910   return false;
    911 }
    912 
    913 bool HLoopInformation::DominatesAllBackEdges(HBasicBlock* block) {
    914   for (HBasicBlock* back_edge : GetBackEdges()) {
    915     if (!block->Dominates(back_edge)) {
    916       return false;
    917     }
    918   }
    919   return true;
    920 }
    921 
    922 
    923 bool HLoopInformation::HasExitEdge() const {
    924   // Determine if this loop has at least one exit edge.
    925   HBlocksInLoopReversePostOrderIterator it_loop(*this);
    926   for (; !it_loop.Done(); it_loop.Advance()) {
    927     for (HBasicBlock* successor : it_loop.Current()->GetSuccessors()) {
    928       if (!Contains(*successor)) {
    929         return true;
    930       }
    931     }
    932   }
    933   return false;
    934 }
    935 
    936 bool HBasicBlock::Dominates(HBasicBlock* other) const {
    937   // Walk up the dominator tree from `other`, to find out if `this`
    938   // is an ancestor.
    939   HBasicBlock* current = other;
    940   while (current != nullptr) {
    941     if (current == this) {
    942       return true;
    943     }
    944     current = current->GetDominator();
    945   }
    946   return false;
    947 }
    948 
    949 static void UpdateInputsUsers(HInstruction* instruction) {
    950   HInputsRef inputs = instruction->GetInputs();
    951   for (size_t i = 0; i < inputs.size(); ++i) {
    952     inputs[i]->AddUseAt(instruction, i);
    953   }
    954   // Environment should be created later.
    955   DCHECK(!instruction->HasEnvironment());
    956 }
    957 
    958 void HBasicBlock::ReplaceAndRemovePhiWith(HPhi* initial, HPhi* replacement) {
    959   DCHECK(initial->GetBlock() == this);
    960   InsertPhiAfter(replacement, initial);
    961   initial->ReplaceWith(replacement);
    962   RemovePhi(initial);
    963 }
    964 
    965 void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial,
    966                                                   HInstruction* replacement) {
    967   DCHECK(initial->GetBlock() == this);
    968   if (initial->IsControlFlow()) {
    969     // We can only replace a control flow instruction with another control flow instruction.
    970     DCHECK(replacement->IsControlFlow());
    971     DCHECK_EQ(replacement->GetId(), -1);
    972     DCHECK_EQ(replacement->GetType(), DataType::Type::kVoid);
    973     DCHECK_EQ(initial->GetBlock(), this);
    974     DCHECK_EQ(initial->GetType(), DataType::Type::kVoid);
    975     DCHECK(initial->GetUses().empty());
    976     DCHECK(initial->GetEnvUses().empty());
    977     replacement->SetBlock(this);
    978     replacement->SetId(GetGraph()->GetNextInstructionId());
    979     instructions_.InsertInstructionBefore(replacement, initial);
    980     UpdateInputsUsers(replacement);
    981   } else {
    982     InsertInstructionBefore(replacement, initial);
    983     initial->ReplaceWith(replacement);
    984   }
    985   RemoveInstruction(initial);
    986 }
    987 
    988 static void Add(HInstructionList* instruction_list,
    989                 HBasicBlock* block,
    990                 HInstruction* instruction) {
    991   DCHECK(instruction->GetBlock() == nullptr);
    992   DCHECK_EQ(instruction->GetId(), -1);
    993   instruction->SetBlock(block);
    994   instruction->SetId(block->GetGraph()->GetNextInstructionId());
    995   UpdateInputsUsers(instruction);
    996   instruction_list->AddInstruction(instruction);
    997 }
    998 
    999 void HBasicBlock::AddInstruction(HInstruction* instruction) {
   1000   Add(&instructions_, this, instruction);
   1001 }
   1002 
   1003 void HBasicBlock::AddPhi(HPhi* phi) {
   1004   Add(&phis_, this, phi);
   1005 }
   1006 
   1007 void HBasicBlock::InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor) {
   1008   DCHECK(!cursor->IsPhi());
   1009   DCHECK(!instruction->IsPhi());
   1010   DCHECK_EQ(instruction->GetId(), -1);
   1011   DCHECK_NE(cursor->GetId(), -1);
   1012   DCHECK_EQ(cursor->GetBlock(), this);
   1013   DCHECK(!instruction->IsControlFlow());
   1014   instruction->SetBlock(this);
   1015   instruction->SetId(GetGraph()->GetNextInstructionId());
   1016   UpdateInputsUsers(instruction);
   1017   instructions_.InsertInstructionBefore(instruction, cursor);
   1018 }
   1019 
   1020 void HBasicBlock::InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor) {
   1021   DCHECK(!cursor->IsPhi());
   1022   DCHECK(!instruction->IsPhi());
   1023   DCHECK_EQ(instruction->GetId(), -1);
   1024   DCHECK_NE(cursor->GetId(), -1);
   1025   DCHECK_EQ(cursor->GetBlock(), this);
   1026   DCHECK(!instruction->IsControlFlow());
   1027   DCHECK(!cursor->IsControlFlow());
   1028   instruction->SetBlock(this);
   1029   instruction->SetId(GetGraph()->GetNextInstructionId());
   1030   UpdateInputsUsers(instruction);
   1031   instructions_.InsertInstructionAfter(instruction, cursor);
   1032 }
   1033 
   1034 void HBasicBlock::InsertPhiAfter(HPhi* phi, HPhi* cursor) {
   1035   DCHECK_EQ(phi->GetId(), -1);
   1036   DCHECK_NE(cursor->GetId(), -1);
   1037   DCHECK_EQ(cursor->GetBlock(), this);
   1038   phi->SetBlock(this);
   1039   phi->SetId(GetGraph()->GetNextInstructionId());
   1040   UpdateInputsUsers(phi);
   1041   phis_.InsertInstructionAfter(phi, cursor);
   1042 }
   1043 
   1044 static void Remove(HInstructionList* instruction_list,
   1045                    HBasicBlock* block,
   1046                    HInstruction* instruction,
   1047                    bool ensure_safety) {
   1048   DCHECK_EQ(block, instruction->GetBlock());
   1049   instruction->SetBlock(nullptr);
   1050   instruction_list->RemoveInstruction(instruction);
   1051   if (ensure_safety) {
   1052     DCHECK(instruction->GetUses().empty());
   1053     DCHECK(instruction->GetEnvUses().empty());
   1054     RemoveAsUser(instruction);
   1055   }
   1056 }
   1057 
   1058 void HBasicBlock::RemoveInstruction(HInstruction* instruction, bool ensure_safety) {
   1059   DCHECK(!instruction->IsPhi());
   1060   Remove(&instructions_, this, instruction, ensure_safety);
   1061 }
   1062 
   1063 void HBasicBlock::RemovePhi(HPhi* phi, bool ensure_safety) {
   1064   Remove(&phis_, this, phi, ensure_safety);
   1065 }
   1066 
   1067 void HBasicBlock::RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety) {
   1068   if (instruction->IsPhi()) {
   1069     RemovePhi(instruction->AsPhi(), ensure_safety);
   1070   } else {
   1071     RemoveInstruction(instruction, ensure_safety);
   1072   }
   1073 }
   1074 
   1075 void HEnvironment::CopyFrom(ArrayRef<HInstruction* const> locals) {
   1076   for (size_t i = 0; i < locals.size(); i++) {
   1077     HInstruction* instruction = locals[i];
   1078     SetRawEnvAt(i, instruction);
   1079     if (instruction != nullptr) {
   1080       instruction->AddEnvUseAt(this, i);
   1081     }
   1082   }
   1083 }
   1084 
   1085 void HEnvironment::CopyFrom(HEnvironment* env) {
   1086   for (size_t i = 0; i < env->Size(); i++) {
   1087     HInstruction* instruction = env->GetInstructionAt(i);
   1088     SetRawEnvAt(i, instruction);
   1089     if (instruction != nullptr) {
   1090       instruction->AddEnvUseAt(this, i);
   1091     }
   1092   }
   1093 }
   1094 
   1095 void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
   1096                                                  HBasicBlock* loop_header) {
   1097   DCHECK(loop_header->IsLoopHeader());
   1098   for (size_t i = 0; i < env->Size(); i++) {
   1099     HInstruction* instruction = env->GetInstructionAt(i);
   1100     SetRawEnvAt(i, instruction);
   1101     if (instruction == nullptr) {
   1102       continue;
   1103     }
   1104     if (instruction->IsLoopHeaderPhi() && (instruction->GetBlock() == loop_header)) {
   1105       // At the end of the loop pre-header, the corresponding value for instruction
   1106       // is the first input of the phi.
   1107       HInstruction* initial = instruction->AsPhi()->InputAt(0);
   1108       SetRawEnvAt(i, initial);
   1109       initial->AddEnvUseAt(this, i);
   1110     } else {
   1111       instruction->AddEnvUseAt(this, i);
   1112     }
   1113   }
   1114 }
   1115 
   1116 void HEnvironment::RemoveAsUserOfInput(size_t index) const {
   1117   const HUserRecord<HEnvironment*>& env_use = vregs_[index];
   1118   HInstruction* user = env_use.GetInstruction();
   1119   auto before_env_use_node = env_use.GetBeforeUseNode();
   1120   user->env_uses_.erase_after(before_env_use_node);
   1121   user->FixUpUserRecordsAfterEnvUseRemoval(before_env_use_node);
   1122 }
   1123 
   1124 HInstruction* HInstruction::GetNextDisregardingMoves() const {
   1125   HInstruction* next = GetNext();
   1126   while (next != nullptr && next->IsParallelMove()) {
   1127     next = next->GetNext();
   1128   }
   1129   return next;
   1130 }
   1131 
   1132 HInstruction* HInstruction::GetPreviousDisregardingMoves() const {
   1133   HInstruction* previous = GetPrevious();
   1134   while (previous != nullptr && previous->IsParallelMove()) {
   1135     previous = previous->GetPrevious();
   1136   }
   1137   return previous;
   1138 }
   1139 
   1140 void HInstructionList::AddInstruction(HInstruction* instruction) {
   1141   if (first_instruction_ == nullptr) {
   1142     DCHECK(last_instruction_ == nullptr);
   1143     first_instruction_ = last_instruction_ = instruction;
   1144   } else {
   1145     DCHECK(last_instruction_ != nullptr);
   1146     last_instruction_->next_ = instruction;
   1147     instruction->previous_ = last_instruction_;
   1148     last_instruction_ = instruction;
   1149   }
   1150 }
   1151 
   1152 void HInstructionList::InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor) {
   1153   DCHECK(Contains(cursor));
   1154   if (cursor == first_instruction_) {
   1155     cursor->previous_ = instruction;
   1156     instruction->next_ = cursor;
   1157     first_instruction_ = instruction;
   1158   } else {
   1159     instruction->previous_ = cursor->previous_;
   1160     instruction->next_ = cursor;
   1161     cursor->previous_ = instruction;
   1162     instruction->previous_->next_ = instruction;
   1163   }
   1164 }
   1165 
   1166 void HInstructionList::InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor) {
   1167   DCHECK(Contains(cursor));
   1168   if (cursor == last_instruction_) {
   1169     cursor->next_ = instruction;
   1170     instruction->previous_ = cursor;
   1171     last_instruction_ = instruction;
   1172   } else {
   1173     instruction->next_ = cursor->next_;
   1174     instruction->previous_ = cursor;
   1175     cursor->next_ = instruction;
   1176     instruction->next_->previous_ = instruction;
   1177   }
   1178 }
   1179 
   1180 void HInstructionList::RemoveInstruction(HInstruction* instruction) {
   1181   if (instruction->previous_ != nullptr) {
   1182     instruction->previous_->next_ = instruction->next_;
   1183   }
   1184   if (instruction->next_ != nullptr) {
   1185     instruction->next_->previous_ = instruction->previous_;
   1186   }
   1187   if (instruction == first_instruction_) {
   1188     first_instruction_ = instruction->next_;
   1189   }
   1190   if (instruction == last_instruction_) {
   1191     last_instruction_ = instruction->previous_;
   1192   }
   1193 }
   1194 
   1195 bool HInstructionList::Contains(HInstruction* instruction) const {
   1196   for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
   1197     if (it.Current() == instruction) {
   1198       return true;
   1199     }
   1200   }
   1201   return false;
   1202 }
   1203 
   1204 bool HInstructionList::FoundBefore(const HInstruction* instruction1,
   1205                                    const HInstruction* instruction2) const {
   1206   DCHECK_EQ(instruction1->GetBlock(), instruction2->GetBlock());
   1207   for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
   1208     if (it.Current() == instruction1) {
   1209       return true;
   1210     }
   1211     if (it.Current() == instruction2) {
   1212       return false;
   1213     }
   1214   }
   1215   LOG(FATAL) << "Did not find an order between two instructions of the same block.";
   1216   return true;
   1217 }
   1218 
   1219 bool HInstruction::StrictlyDominates(HInstruction* other_instruction) const {
   1220   if (other_instruction == this) {
   1221     // An instruction does not strictly dominate itself.
   1222     return false;
   1223   }
   1224   HBasicBlock* block = GetBlock();
   1225   HBasicBlock* other_block = other_instruction->GetBlock();
   1226   if (block != other_block) {
   1227     return GetBlock()->Dominates(other_instruction->GetBlock());
   1228   } else {
   1229     // If both instructions are in the same block, ensure this
   1230     // instruction comes before `other_instruction`.
   1231     if (IsPhi()) {
   1232       if (!other_instruction->IsPhi()) {
   1233         // Phis appear before non phi-instructions so this instruction
   1234         // dominates `other_instruction`.
   1235         return true;
   1236       } else {
   1237         // There is no order among phis.
   1238         LOG(FATAL) << "There is no dominance between phis of a same block.";
   1239         return false;
   1240       }
   1241     } else {
   1242       // `this` is not a phi.
   1243       if (other_instruction->IsPhi()) {
   1244         // Phis appear before non phi-instructions so this instruction
   1245         // does not dominate `other_instruction`.
   1246         return false;
   1247       } else {
   1248         // Check whether this instruction comes before
   1249         // `other_instruction` in the instruction list.
   1250         return block->GetInstructions().FoundBefore(this, other_instruction);
   1251       }
   1252     }
   1253   }
   1254 }
   1255 
   1256 void HInstruction::RemoveEnvironment() {
   1257   RemoveEnvironmentUses(this);
   1258   environment_ = nullptr;
   1259 }
   1260 
   1261 void HInstruction::ReplaceWith(HInstruction* other) {
   1262   DCHECK(other != nullptr);
   1263   // Note: fixup_end remains valid across splice_after().
   1264   auto fixup_end = other->uses_.empty() ? other->uses_.begin() : ++other->uses_.begin();
   1265   other->uses_.splice_after(other->uses_.before_begin(), uses_);
   1266   other->FixUpUserRecordsAfterUseInsertion(fixup_end);
   1267 
   1268   // Note: env_fixup_end remains valid across splice_after().
   1269   auto env_fixup_end =
   1270       other->env_uses_.empty() ? other->env_uses_.begin() : ++other->env_uses_.begin();
   1271   other->env_uses_.splice_after(other->env_uses_.before_begin(), env_uses_);
   1272   other->FixUpUserRecordsAfterEnvUseInsertion(env_fixup_end);
   1273 
   1274   DCHECK(uses_.empty());
   1275   DCHECK(env_uses_.empty());
   1276 }
   1277 
   1278 void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement) {
   1279   const HUseList<HInstruction*>& uses = GetUses();
   1280   for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
   1281     HInstruction* user = it->GetUser();
   1282     size_t index = it->GetIndex();
   1283     // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
   1284     ++it;
   1285     if (dominator->StrictlyDominates(user)) {
   1286       user->ReplaceInput(replacement, index);
   1287     }
   1288   }
   1289 }
   1290 
   1291 void HInstruction::ReplaceInput(HInstruction* replacement, size_t index) {
   1292   HUserRecord<HInstruction*> input_use = InputRecordAt(index);
   1293   if (input_use.GetInstruction() == replacement) {
   1294     // Nothing to do.
   1295     return;
   1296   }
   1297   HUseList<HInstruction*>::iterator before_use_node = input_use.GetBeforeUseNode();
   1298   // Note: fixup_end remains valid across splice_after().
   1299   auto fixup_end =
   1300       replacement->uses_.empty() ? replacement->uses_.begin() : ++replacement->uses_.begin();
   1301   replacement->uses_.splice_after(replacement->uses_.before_begin(),
   1302                                   input_use.GetInstruction()->uses_,
   1303                                   before_use_node);
   1304   replacement->FixUpUserRecordsAfterUseInsertion(fixup_end);
   1305   input_use.GetInstruction()->FixUpUserRecordsAfterUseRemoval(before_use_node);
   1306 }
   1307 
   1308 size_t HInstruction::EnvironmentSize() const {
   1309   return HasEnvironment() ? environment_->Size() : 0;
   1310 }
   1311 
   1312 void HVariableInputSizeInstruction::AddInput(HInstruction* input) {
   1313   DCHECK(input->GetBlock() != nullptr);
   1314   inputs_.push_back(HUserRecord<HInstruction*>(input));
   1315   input->AddUseAt(this, inputs_.size() - 1);
   1316 }
   1317 
   1318 void HVariableInputSizeInstruction::InsertInputAt(size_t index, HInstruction* input) {
   1319   inputs_.insert(inputs_.begin() + index, HUserRecord<HInstruction*>(input));
   1320   input->AddUseAt(this, index);
   1321   // Update indexes in use nodes of inputs that have been pushed further back by the insert().
   1322   for (size_t i = index + 1u, e = inputs_.size(); i < e; ++i) {
   1323     DCHECK_EQ(inputs_[i].GetUseNode()->GetIndex(), i - 1u);
   1324     inputs_[i].GetUseNode()->SetIndex(i);
   1325   }
   1326 }
   1327 
   1328 void HVariableInputSizeInstruction::RemoveInputAt(size_t index) {
   1329   RemoveAsUserOfInput(index);
   1330   inputs_.erase(inputs_.begin() + index);
   1331   // Update indexes in use nodes of inputs that have been pulled forward by the erase().
   1332   for (size_t i = index, e = inputs_.size(); i < e; ++i) {
   1333     DCHECK_EQ(inputs_[i].GetUseNode()->GetIndex(), i + 1u);
   1334     inputs_[i].GetUseNode()->SetIndex(i);
   1335   }
   1336 }
   1337 
   1338 void HVariableInputSizeInstruction::RemoveAllInputs() {
   1339   RemoveAsUserOfAllInputs();
   1340   DCHECK(!HasNonEnvironmentUses());
   1341 
   1342   inputs_.clear();
   1343   DCHECK_EQ(0u, InputCount());
   1344 }
   1345 
   1346 size_t HConstructorFence::RemoveConstructorFences(HInstruction* instruction) {
   1347   DCHECK(instruction->GetBlock() != nullptr);
   1348   // Removing constructor fences only makes sense for instructions with an object return type.
   1349   DCHECK_EQ(DataType::Type::kReference, instruction->GetType());
   1350 
   1351   // Return how many instructions were removed for statistic purposes.
   1352   size_t remove_count = 0;
   1353 
   1354   // Efficient implementation that simultaneously (in one pass):
   1355   // * Scans the uses list for all constructor fences.
   1356   // * Deletes that constructor fence from the uses list of `instruction`.
   1357   // * Deletes `instruction` from the constructor fence's inputs.
   1358   // * Deletes the constructor fence if it now has 0 inputs.
   1359 
   1360   const HUseList<HInstruction*>& uses = instruction->GetUses();
   1361   // Warning: Although this is "const", we might mutate the list when calling RemoveInputAt.
   1362   for (auto it = uses.begin(), end = uses.end(); it != end; ) {
   1363     const HUseListNode<HInstruction*>& use_node = *it;
   1364     HInstruction* const use_instruction = use_node.GetUser();
   1365 
   1366     // Advance the iterator immediately once we fetch the use_node.
   1367     // Warning: If the input is removed, the current iterator becomes invalid.
   1368     ++it;
   1369 
   1370     if (use_instruction->IsConstructorFence()) {
   1371       HConstructorFence* ctor_fence = use_instruction->AsConstructorFence();
   1372       size_t input_index = use_node.GetIndex();
   1373 
   1374       // Process the candidate instruction for removal
   1375       // from the graph.
   1376 
   1377       // Constructor fence instructions are never
   1378       // used by other instructions.
   1379       //
   1380       // If we wanted to make this more generic, it
   1381       // could be a runtime if statement.
   1382       DCHECK(!ctor_fence->HasUses());
   1383 
   1384       // A constructor fence's return type is "kPrimVoid"
   1385       // and therefore it can't have any environment uses.
   1386       DCHECK(!ctor_fence->HasEnvironmentUses());
   1387 
   1388       // Remove the inputs first, otherwise removing the instruction
   1389       // will try to remove its uses while we are already removing uses
   1390       // and this operation will fail.
   1391       DCHECK_EQ(instruction, ctor_fence->InputAt(input_index));
   1392 
   1393       // Removing the input will also remove the `use_node`.
   1394       // (Do not look at `use_node` after this, it will be a dangling reference).
   1395       ctor_fence->RemoveInputAt(input_index);
   1396 
   1397       // Once all inputs are removed, the fence is considered dead and
   1398       // is removed.
   1399       if (ctor_fence->InputCount() == 0u) {
   1400         ctor_fence->GetBlock()->RemoveInstruction(ctor_fence);
   1401         ++remove_count;
   1402       }
   1403     }
   1404   }
   1405 
   1406   if (kIsDebugBuild) {
   1407     // Post-condition checks:
   1408     // * None of the uses of `instruction` are a constructor fence.
   1409     // * The `instruction` itself did not get removed from a block.
   1410     for (const HUseListNode<HInstruction*>& use_node : instruction->GetUses()) {
   1411       CHECK(!use_node.GetUser()->IsConstructorFence());
   1412     }
   1413     CHECK(instruction->GetBlock() != nullptr);
   1414   }
   1415 
   1416   return remove_count;
   1417 }
   1418 
   1419 void HConstructorFence::Merge(HConstructorFence* other) {
   1420   // Do not delete yourself from the graph.
   1421   DCHECK(this != other);
   1422   // Don't try to merge with an instruction not associated with a block.
   1423   DCHECK(other->GetBlock() != nullptr);
   1424   // A constructor fence's return type is "kPrimVoid"
   1425   // and therefore it cannot have any environment uses.
   1426   DCHECK(!other->HasEnvironmentUses());
   1427 
   1428   auto has_input = [](HInstruction* haystack, HInstruction* needle) {
   1429     // Check if `haystack` has `needle` as any of its inputs.
   1430     for (size_t input_count = 0; input_count < haystack->InputCount(); ++input_count) {
   1431       if (haystack->InputAt(input_count) == needle) {
   1432         return true;
   1433       }
   1434     }
   1435     return false;
   1436   };
   1437 
   1438   // Add any inputs from `other` into `this` if it wasn't already an input.
   1439   for (size_t input_count = 0; input_count < other->InputCount(); ++input_count) {
   1440     HInstruction* other_input = other->InputAt(input_count);
   1441     if (!has_input(this, other_input)) {
   1442       AddInput(other_input);
   1443     }
   1444   }
   1445 
   1446   other->GetBlock()->RemoveInstruction(other);
   1447 }
   1448 
   1449 HInstruction* HConstructorFence::GetAssociatedAllocation(bool ignore_inputs) {
   1450   HInstruction* new_instance_inst = GetPrevious();
   1451   // Check if the immediately preceding instruction is a new-instance/new-array.
   1452   // Otherwise this fence is for protecting final fields.
   1453   if (new_instance_inst != nullptr &&
   1454       (new_instance_inst->IsNewInstance() || new_instance_inst->IsNewArray())) {
   1455     if (ignore_inputs) {
   1456       // If inputs are ignored, simply check if the predecessor is
   1457       // *any* HNewInstance/HNewArray.
   1458       //
   1459       // Inputs are normally only ignored for prepare_for_register_allocation,
   1460       // at which point *any* prior HNewInstance/Array can be considered
   1461       // associated.
   1462       return new_instance_inst;
   1463     } else {
   1464       // Normal case: There must be exactly 1 input and the previous instruction
   1465       // must be that input.
   1466       if (InputCount() == 1u && InputAt(0) == new_instance_inst) {
   1467         return new_instance_inst;
   1468       }
   1469     }
   1470   }
   1471   return nullptr;
   1472 }
   1473 
   1474 #define DEFINE_ACCEPT(name, super)                                             \
   1475 void H##name::Accept(HGraphVisitor* visitor) {                                 \
   1476   visitor->Visit##name(this);                                                  \
   1477 }
   1478 
   1479 FOR_EACH_CONCRETE_INSTRUCTION(DEFINE_ACCEPT)
   1480 
   1481 #undef DEFINE_ACCEPT
   1482 
   1483 void HGraphVisitor::VisitInsertionOrder() {
   1484   const ArenaVector<HBasicBlock*>& blocks = graph_->GetBlocks();
   1485   for (HBasicBlock* block : blocks) {
   1486     if (block != nullptr) {
   1487       VisitBasicBlock(block);
   1488     }
   1489   }
   1490 }
   1491 
   1492 void HGraphVisitor::VisitReversePostOrder() {
   1493   for (HBasicBlock* block : graph_->GetReversePostOrder()) {
   1494     VisitBasicBlock(block);
   1495   }
   1496 }
   1497 
   1498 void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) {
   1499   for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
   1500     it.Current()->Accept(this);
   1501   }
   1502   for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
   1503     it.Current()->Accept(this);
   1504   }
   1505 }
   1506 
   1507 HConstant* HTypeConversion::TryStaticEvaluation() const {
   1508   HGraph* graph = GetBlock()->GetGraph();
   1509   if (GetInput()->IsIntConstant()) {
   1510     int32_t value = GetInput()->AsIntConstant()->GetValue();
   1511     switch (GetResultType()) {
   1512       case DataType::Type::kInt8:
   1513         return graph->GetIntConstant(static_cast<int8_t>(value), GetDexPc());
   1514       case DataType::Type::kUint8:
   1515         return graph->GetIntConstant(static_cast<uint8_t>(value), GetDexPc());
   1516       case DataType::Type::kInt16:
   1517         return graph->GetIntConstant(static_cast<int16_t>(value), GetDexPc());
   1518       case DataType::Type::kUint16:
   1519         return graph->GetIntConstant(static_cast<uint16_t>(value), GetDexPc());
   1520       case DataType::Type::kInt64:
   1521         return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
   1522       case DataType::Type::kFloat32:
   1523         return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
   1524       case DataType::Type::kFloat64:
   1525         return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
   1526       default:
   1527         return nullptr;
   1528     }
   1529   } else if (GetInput()->IsLongConstant()) {
   1530     int64_t value = GetInput()->AsLongConstant()->GetValue();
   1531     switch (GetResultType()) {
   1532       case DataType::Type::kInt8:
   1533         return graph->GetIntConstant(static_cast<int8_t>(value), GetDexPc());
   1534       case DataType::Type::kUint8:
   1535         return graph->GetIntConstant(static_cast<uint8_t>(value), GetDexPc());
   1536       case DataType::Type::kInt16:
   1537         return graph->GetIntConstant(static_cast<int16_t>(value), GetDexPc());
   1538       case DataType::Type::kUint16:
   1539         return graph->GetIntConstant(static_cast<uint16_t>(value), GetDexPc());
   1540       case DataType::Type::kInt32:
   1541         return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
   1542       case DataType::Type::kFloat32:
   1543         return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
   1544       case DataType::Type::kFloat64:
   1545         return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
   1546       default:
   1547         return nullptr;
   1548     }
   1549   } else if (GetInput()->IsFloatConstant()) {
   1550     float value = GetInput()->AsFloatConstant()->GetValue();
   1551     switch (GetResultType()) {
   1552       case DataType::Type::kInt32:
   1553         if (std::isnan(value))
   1554           return graph->GetIntConstant(0, GetDexPc());
   1555         if (value >= kPrimIntMax)
   1556           return graph->GetIntConstant(kPrimIntMax, GetDexPc());
   1557         if (value <= kPrimIntMin)
   1558           return graph->GetIntConstant(kPrimIntMin, GetDexPc());
   1559         return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
   1560       case DataType::Type::kInt64:
   1561         if (std::isnan(value))
   1562           return graph->GetLongConstant(0, GetDexPc());
   1563         if (value >= kPrimLongMax)
   1564           return graph->GetLongConstant(kPrimLongMax, GetDexPc());
   1565         if (value <= kPrimLongMin)
   1566           return graph->GetLongConstant(kPrimLongMin, GetDexPc());
   1567         return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
   1568       case DataType::Type::kFloat64:
   1569         return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
   1570       default:
   1571         return nullptr;
   1572     }
   1573   } else if (GetInput()->IsDoubleConstant()) {
   1574     double value = GetInput()->AsDoubleConstant()->GetValue();
   1575     switch (GetResultType()) {
   1576       case DataType::Type::kInt32:
   1577         if (std::isnan(value))
   1578           return graph->GetIntConstant(0, GetDexPc());
   1579         if (value >= kPrimIntMax)
   1580           return graph->GetIntConstant(kPrimIntMax, GetDexPc());
   1581         if (value <= kPrimLongMin)
   1582           return graph->GetIntConstant(kPrimIntMin, GetDexPc());
   1583         return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
   1584       case DataType::Type::kInt64:
   1585         if (std::isnan(value))
   1586           return graph->GetLongConstant(0, GetDexPc());
   1587         if (value >= kPrimLongMax)
   1588           return graph->GetLongConstant(kPrimLongMax, GetDexPc());
   1589         if (value <= kPrimLongMin)
   1590           return graph->GetLongConstant(kPrimLongMin, GetDexPc());
   1591         return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
   1592       case DataType::Type::kFloat32:
   1593         return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
   1594       default:
   1595         return nullptr;
   1596     }
   1597   }
   1598   return nullptr;
   1599 }
   1600 
   1601 HConstant* HUnaryOperation::TryStaticEvaluation() const {
   1602   if (GetInput()->IsIntConstant()) {
   1603     return Evaluate(GetInput()->AsIntConstant());
   1604   } else if (GetInput()->IsLongConstant()) {
   1605     return Evaluate(GetInput()->AsLongConstant());
   1606   } else if (kEnableFloatingPointStaticEvaluation) {
   1607     if (GetInput()->IsFloatConstant()) {
   1608       return Evaluate(GetInput()->AsFloatConstant());
   1609     } else if (GetInput()->IsDoubleConstant()) {
   1610       return Evaluate(GetInput()->AsDoubleConstant());
   1611     }
   1612   }
   1613   return nullptr;
   1614 }
   1615 
   1616 HConstant* HBinaryOperation::TryStaticEvaluation() const {
   1617   if (GetLeft()->IsIntConstant() && GetRight()->IsIntConstant()) {
   1618     return Evaluate(GetLeft()->AsIntConstant(), GetRight()->AsIntConstant());
   1619   } else if (GetLeft()->IsLongConstant()) {
   1620     if (GetRight()->IsIntConstant()) {
   1621       // The binop(long, int) case is only valid for shifts and rotations.
   1622       DCHECK(IsShl() || IsShr() || IsUShr() || IsRor()) << DebugName();
   1623       return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsIntConstant());
   1624     } else if (GetRight()->IsLongConstant()) {
   1625       return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsLongConstant());
   1626     }
   1627   } else if (GetLeft()->IsNullConstant() && GetRight()->IsNullConstant()) {
   1628     // The binop(null, null) case is only valid for equal and not-equal conditions.
   1629     DCHECK(IsEqual() || IsNotEqual()) << DebugName();
   1630     return Evaluate(GetLeft()->AsNullConstant(), GetRight()->AsNullConstant());
   1631   } else if (kEnableFloatingPointStaticEvaluation) {
   1632     if (GetLeft()->IsFloatConstant() && GetRight()->IsFloatConstant()) {
   1633       return Evaluate(GetLeft()->AsFloatConstant(), GetRight()->AsFloatConstant());
   1634     } else if (GetLeft()->IsDoubleConstant() && GetRight()->IsDoubleConstant()) {
   1635       return Evaluate(GetLeft()->AsDoubleConstant(), GetRight()->AsDoubleConstant());
   1636     }
   1637   }
   1638   return nullptr;
   1639 }
   1640 
   1641 HConstant* HBinaryOperation::GetConstantRight() const {
   1642   if (GetRight()->IsConstant()) {
   1643     return GetRight()->AsConstant();
   1644   } else if (IsCommutative() && GetLeft()->IsConstant()) {
   1645     return GetLeft()->AsConstant();
   1646   } else {
   1647     return nullptr;
   1648   }
   1649 }
   1650 
   1651 // If `GetConstantRight()` returns one of the input, this returns the other
   1652 // one. Otherwise it returns null.
   1653 HInstruction* HBinaryOperation::GetLeastConstantLeft() const {
   1654   HInstruction* most_constant_right = GetConstantRight();
   1655   if (most_constant_right == nullptr) {
   1656     return nullptr;
   1657   } else if (most_constant_right == GetLeft()) {
   1658     return GetRight();
   1659   } else {
   1660     return GetLeft();
   1661   }
   1662 }
   1663 
   1664 std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs) {
   1665   switch (rhs) {
   1666     case ComparisonBias::kNoBias:
   1667       return os << "no_bias";
   1668     case ComparisonBias::kGtBias:
   1669       return os << "gt_bias";
   1670     case ComparisonBias::kLtBias:
   1671       return os << "lt_bias";
   1672     default:
   1673       LOG(FATAL) << "Unknown ComparisonBias: " << static_cast<int>(rhs);
   1674       UNREACHABLE();
   1675   }
   1676 }
   1677 
   1678 bool HCondition::IsBeforeWhenDisregardMoves(HInstruction* instruction) const {
   1679   return this == instruction->GetPreviousDisregardingMoves();
   1680 }
   1681 
   1682 bool HInstruction::Equals(const HInstruction* other) const {
   1683   if (!InstructionTypeEquals(other)) return false;
   1684   DCHECK_EQ(GetKind(), other->GetKind());
   1685   if (!InstructionDataEquals(other)) return false;
   1686   if (GetType() != other->GetType()) return false;
   1687   HConstInputsRef inputs = GetInputs();
   1688   HConstInputsRef other_inputs = other->GetInputs();
   1689   if (inputs.size() != other_inputs.size()) return false;
   1690   for (size_t i = 0; i != inputs.size(); ++i) {
   1691     if (inputs[i] != other_inputs[i]) return false;
   1692   }
   1693 
   1694   DCHECK_EQ(ComputeHashCode(), other->ComputeHashCode());
   1695   return true;
   1696 }
   1697 
   1698 std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs) {
   1699 #define DECLARE_CASE(type, super) case HInstruction::k##type: os << #type; break;
   1700   switch (rhs) {
   1701     FOR_EACH_INSTRUCTION(DECLARE_CASE)
   1702     default:
   1703       os << "Unknown instruction kind " << static_cast<int>(rhs);
   1704       break;
   1705   }
   1706 #undef DECLARE_CASE
   1707   return os;
   1708 }
   1709 
   1710 void HInstruction::MoveBefore(HInstruction* cursor, bool do_checks) {
   1711   if (do_checks) {
   1712     DCHECK(!IsPhi());
   1713     DCHECK(!IsControlFlow());
   1714     DCHECK(CanBeMoved() ||
   1715            // HShouldDeoptimizeFlag can only be moved by CHAGuardOptimization.
   1716            IsShouldDeoptimizeFlag());
   1717     DCHECK(!cursor->IsPhi());
   1718   }
   1719 
   1720   next_->previous_ = previous_;
   1721   if (previous_ != nullptr) {
   1722     previous_->next_ = next_;
   1723   }
   1724   if (block_->instructions_.first_instruction_ == this) {
   1725     block_->instructions_.first_instruction_ = next_;
   1726   }
   1727   DCHECK_NE(block_->instructions_.last_instruction_, this);
   1728 
   1729   previous_ = cursor->previous_;
   1730   if (previous_ != nullptr) {
   1731     previous_->next_ = this;
   1732   }
   1733   next_ = cursor;
   1734   cursor->previous_ = this;
   1735   block_ = cursor->block_;
   1736 
   1737   if (block_->instructions_.first_instruction_ == cursor) {
   1738     block_->instructions_.first_instruction_ = this;
   1739   }
   1740 }
   1741 
   1742 void HInstruction::MoveBeforeFirstUserAndOutOfLoops() {
   1743   DCHECK(!CanThrow());
   1744   DCHECK(!HasSideEffects());
   1745   DCHECK(!HasEnvironmentUses());
   1746   DCHECK(HasNonEnvironmentUses());
   1747   DCHECK(!IsPhi());  // Makes no sense for Phi.
   1748   DCHECK_EQ(InputCount(), 0u);
   1749 
   1750   // Find the target block.
   1751   auto uses_it = GetUses().begin();
   1752   auto uses_end = GetUses().end();
   1753   HBasicBlock* target_block = uses_it->GetUser()->GetBlock();
   1754   ++uses_it;
   1755   while (uses_it != uses_end && uses_it->GetUser()->GetBlock() == target_block) {
   1756     ++uses_it;
   1757   }
   1758   if (uses_it != uses_end) {
   1759     // This instruction has uses in two or more blocks. Find the common dominator.
   1760     CommonDominator finder(target_block);
   1761     for (; uses_it != uses_end; ++uses_it) {
   1762       finder.Update(uses_it->GetUser()->GetBlock());
   1763     }
   1764     target_block = finder.Get();
   1765     DCHECK(target_block != nullptr);
   1766   }
   1767   // Move to the first dominator not in a loop.
   1768   while (target_block->IsInLoop()) {
   1769     target_block = target_block->GetDominator();
   1770     DCHECK(target_block != nullptr);
   1771   }
   1772 
   1773   // Find insertion position.
   1774   HInstruction* insert_pos = nullptr;
   1775   for (const HUseListNode<HInstruction*>& use : GetUses()) {
   1776     if (use.GetUser()->GetBlock() == target_block &&
   1777         (insert_pos == nullptr || use.GetUser()->StrictlyDominates(insert_pos))) {
   1778       insert_pos = use.GetUser();
   1779     }
   1780   }
   1781   if (insert_pos == nullptr) {
   1782     // No user in `target_block`, insert before the control flow instruction.
   1783     insert_pos = target_block->GetLastInstruction();
   1784     DCHECK(insert_pos->IsControlFlow());
   1785     // Avoid splitting HCondition from HIf to prevent unnecessary materialization.
   1786     if (insert_pos->IsIf()) {
   1787       HInstruction* if_input = insert_pos->AsIf()->InputAt(0);
   1788       if (if_input == insert_pos->GetPrevious()) {
   1789         insert_pos = if_input;
   1790       }
   1791     }
   1792   }
   1793   MoveBefore(insert_pos);
   1794 }
   1795 
   1796 HBasicBlock* HBasicBlock::SplitBefore(HInstruction* cursor) {
   1797   DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented.";
   1798   DCHECK_EQ(cursor->GetBlock(), this);
   1799 
   1800   HBasicBlock* new_block =
   1801       new (GetGraph()->GetAllocator()) HBasicBlock(GetGraph(), cursor->GetDexPc());
   1802   new_block->instructions_.first_instruction_ = cursor;
   1803   new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
   1804   instructions_.last_instruction_ = cursor->previous_;
   1805   if (cursor->previous_ == nullptr) {
   1806     instructions_.first_instruction_ = nullptr;
   1807   } else {
   1808     cursor->previous_->next_ = nullptr;
   1809     cursor->previous_ = nullptr;
   1810   }
   1811 
   1812   new_block->instructions_.SetBlockOfInstructions(new_block);
   1813   AddInstruction(new (GetGraph()->GetAllocator()) HGoto(new_block->GetDexPc()));
   1814 
   1815   for (HBasicBlock* successor : GetSuccessors()) {
   1816     successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
   1817   }
   1818   new_block->successors_.swap(successors_);
   1819   DCHECK(successors_.empty());
   1820   AddSuccessor(new_block);
   1821 
   1822   GetGraph()->AddBlock(new_block);
   1823   return new_block;
   1824 }
   1825 
   1826 HBasicBlock* HBasicBlock::CreateImmediateDominator() {
   1827   DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented.";
   1828   DCHECK(!IsCatchBlock()) << "Support for updating try/catch information not implemented.";
   1829 
   1830   HBasicBlock* new_block = new (GetGraph()->GetAllocator()) HBasicBlock(GetGraph(), GetDexPc());
   1831 
   1832   for (HBasicBlock* predecessor : GetPredecessors()) {
   1833     predecessor->successors_[predecessor->GetSuccessorIndexOf(this)] = new_block;
   1834   }
   1835   new_block->predecessors_.swap(predecessors_);
   1836   DCHECK(predecessors_.empty());
   1837   AddPredecessor(new_block);
   1838 
   1839   GetGraph()->AddBlock(new_block);
   1840   return new_block;
   1841 }
   1842 
   1843 HBasicBlock* HBasicBlock::SplitBeforeForInlining(HInstruction* cursor) {
   1844   DCHECK_EQ(cursor->GetBlock(), this);
   1845 
   1846   HBasicBlock* new_block =
   1847       new (GetGraph()->GetAllocator()) HBasicBlock(GetGraph(), cursor->GetDexPc());
   1848   new_block->instructions_.first_instruction_ = cursor;
   1849   new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
   1850   instructions_.last_instruction_ = cursor->previous_;
   1851   if (cursor->previous_ == nullptr) {
   1852     instructions_.first_instruction_ = nullptr;
   1853   } else {
   1854     cursor->previous_->next_ = nullptr;
   1855     cursor->previous_ = nullptr;
   1856   }
   1857 
   1858   new_block->instructions_.SetBlockOfInstructions(new_block);
   1859 
   1860   for (HBasicBlock* successor : GetSuccessors()) {
   1861     successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
   1862   }
   1863   new_block->successors_.swap(successors_);
   1864   DCHECK(successors_.empty());
   1865 
   1866   for (HBasicBlock* dominated : GetDominatedBlocks()) {
   1867     dominated->dominator_ = new_block;
   1868   }
   1869   new_block->dominated_blocks_.swap(dominated_blocks_);
   1870   DCHECK(dominated_blocks_.empty());
   1871   return new_block;
   1872 }
   1873 
   1874 HBasicBlock* HBasicBlock::SplitAfterForInlining(HInstruction* cursor) {
   1875   DCHECK(!cursor->IsControlFlow());
   1876   DCHECK_NE(instructions_.last_instruction_, cursor);
   1877   DCHECK_EQ(cursor->GetBlock(), this);
   1878 
   1879   HBasicBlock* new_block = new (GetGraph()->GetAllocator()) HBasicBlock(GetGraph(), GetDexPc());
   1880   new_block->instructions_.first_instruction_ = cursor->GetNext();
   1881   new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
   1882   cursor->next_->previous_ = nullptr;
   1883   cursor->next_ = nullptr;
   1884   instructions_.last_instruction_ = cursor;
   1885 
   1886   new_block->instructions_.SetBlockOfInstructions(new_block);
   1887   for (HBasicBlock* successor : GetSuccessors()) {
   1888     successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
   1889   }
   1890   new_block->successors_.swap(successors_);
   1891   DCHECK(successors_.empty());
   1892 
   1893   for (HBasicBlock* dominated : GetDominatedBlocks()) {
   1894     dominated->dominator_ = new_block;
   1895   }
   1896   new_block->dominated_blocks_.swap(dominated_blocks_);
   1897   DCHECK(dominated_blocks_.empty());
   1898   return new_block;
   1899 }
   1900 
   1901 const HTryBoundary* HBasicBlock::ComputeTryEntryOfSuccessors() const {
   1902   if (EndsWithTryBoundary()) {
   1903     HTryBoundary* try_boundary = GetLastInstruction()->AsTryBoundary();
   1904     if (try_boundary->IsEntry()) {
   1905       DCHECK(!IsTryBlock());
   1906       return try_boundary;
   1907     } else {
   1908       DCHECK(IsTryBlock());
   1909       DCHECK(try_catch_information_->GetTryEntry().HasSameExceptionHandlersAs(*try_boundary));
   1910       return nullptr;
   1911     }
   1912   } else if (IsTryBlock()) {
   1913     return &try_catch_information_->GetTryEntry();
   1914   } else {
   1915     return nullptr;
   1916   }
   1917 }
   1918 
   1919 bool HBasicBlock::HasThrowingInstructions() const {
   1920   for (HInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
   1921     if (it.Current()->CanThrow()) {
   1922       return true;
   1923     }
   1924   }
   1925   return false;
   1926 }
   1927 
   1928 static bool HasOnlyOneInstruction(const HBasicBlock& block) {
   1929   return block.GetPhis().IsEmpty()
   1930       && !block.GetInstructions().IsEmpty()
   1931       && block.GetFirstInstruction() == block.GetLastInstruction();
   1932 }
   1933 
   1934 bool HBasicBlock::IsSingleGoto() const {
   1935   return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsGoto();
   1936 }
   1937 
   1938 bool HBasicBlock::IsSingleReturn() const {
   1939   return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsReturn();
   1940 }
   1941 
   1942 bool HBasicBlock::IsSingleReturnOrReturnVoidAllowingPhis() const {
   1943   return (GetFirstInstruction() == GetLastInstruction()) &&
   1944          (GetLastInstruction()->IsReturn() || GetLastInstruction()->IsReturnVoid());
   1945 }
   1946 
   1947 bool HBasicBlock::IsSingleTryBoundary() const {
   1948   return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsTryBoundary();
   1949 }
   1950 
   1951 bool HBasicBlock::EndsWithControlFlowInstruction() const {
   1952   return !GetInstructions().IsEmpty() && GetLastInstruction()->IsControlFlow();
   1953 }
   1954 
   1955 bool HBasicBlock::EndsWithIf() const {
   1956   return !GetInstructions().IsEmpty() && GetLastInstruction()->IsIf();
   1957 }
   1958 
   1959 bool HBasicBlock::EndsWithTryBoundary() const {
   1960   return !GetInstructions().IsEmpty() && GetLastInstruction()->IsTryBoundary();
   1961 }
   1962 
   1963 bool HBasicBlock::HasSinglePhi() const {
   1964   return !GetPhis().IsEmpty() && GetFirstPhi()->GetNext() == nullptr;
   1965 }
   1966 
   1967 ArrayRef<HBasicBlock* const> HBasicBlock::GetNormalSuccessors() const {
   1968   if (EndsWithTryBoundary()) {
   1969     // The normal-flow successor of HTryBoundary is always stored at index zero.
   1970     DCHECK_EQ(successors_[0], GetLastInstruction()->AsTryBoundary()->GetNormalFlowSuccessor());
   1971     return ArrayRef<HBasicBlock* const>(successors_).SubArray(0u, 1u);
   1972   } else {
   1973     // All successors of blocks not ending with TryBoundary are normal.
   1974     return ArrayRef<HBasicBlock* const>(successors_);
   1975   }
   1976 }
   1977 
   1978 ArrayRef<HBasicBlock* const> HBasicBlock::GetExceptionalSuccessors() const {
   1979   if (EndsWithTryBoundary()) {
   1980     return GetLastInstruction()->AsTryBoundary()->GetExceptionHandlers();
   1981   } else {
   1982     // Blocks not ending with TryBoundary do not have exceptional successors.
   1983     return ArrayRef<HBasicBlock* const>();
   1984   }
   1985 }
   1986 
   1987 bool HTryBoundary::HasSameExceptionHandlersAs(const HTryBoundary& other) const {
   1988   ArrayRef<HBasicBlock* const> handlers1 = GetExceptionHandlers();
   1989   ArrayRef<HBasicBlock* const> handlers2 = other.GetExceptionHandlers();
   1990 
   1991   size_t length = handlers1.size();
   1992   if (length != handlers2.size()) {
   1993     return false;
   1994   }
   1995 
   1996   // Exception handlers need to be stored in the same order.
   1997   for (size_t i = 0; i < length; ++i) {
   1998     if (handlers1[i] != handlers2[i]) {
   1999       return false;
   2000     }
   2001   }
   2002   return true;
   2003 }
   2004 
   2005 size_t HInstructionList::CountSize() const {
   2006   size_t size = 0;
   2007   HInstruction* current = first_instruction_;
   2008   for (; current != nullptr; current = current->GetNext()) {
   2009     size++;
   2010   }
   2011   return size;
   2012 }
   2013 
   2014 void HInstructionList::SetBlockOfInstructions(HBasicBlock* block) const {
   2015   for (HInstruction* current = first_instruction_;
   2016        current != nullptr;
   2017        current = current->GetNext()) {
   2018     current->SetBlock(block);
   2019   }
   2020 }
   2021 
   2022 void HInstructionList::AddAfter(HInstruction* cursor, const HInstructionList& instruction_list) {
   2023   DCHECK(Contains(cursor));
   2024   if (!instruction_list.IsEmpty()) {
   2025     if (cursor == last_instruction_) {
   2026       last_instruction_ = instruction_list.last_instruction_;
   2027     } else {
   2028       cursor->next_->previous_ = instruction_list.last_instruction_;
   2029     }
   2030     instruction_list.last_instruction_->next_ = cursor->next_;
   2031     cursor->next_ = instruction_list.first_instruction_;
   2032     instruction_list.first_instruction_->previous_ = cursor;
   2033   }
   2034 }
   2035 
   2036 void HInstructionList::AddBefore(HInstruction* cursor, const HInstructionList& instruction_list) {
   2037   DCHECK(Contains(cursor));
   2038   if (!instruction_list.IsEmpty()) {
   2039     if (cursor == first_instruction_) {
   2040       first_instruction_ = instruction_list.first_instruction_;
   2041     } else {
   2042       cursor->previous_->next_ = instruction_list.first_instruction_;
   2043     }
   2044     instruction_list.last_instruction_->next_ = cursor;
   2045     instruction_list.first_instruction_->previous_ = cursor->previous_;
   2046     cursor->previous_ = instruction_list.last_instruction_;
   2047   }
   2048 }
   2049 
   2050 void HInstructionList::Add(const HInstructionList& instruction_list) {
   2051   if (IsEmpty()) {
   2052     first_instruction_ = instruction_list.first_instruction_;
   2053     last_instruction_ = instruction_list.last_instruction_;
   2054   } else {
   2055     AddAfter(last_instruction_, instruction_list);
   2056   }
   2057 }
   2058 
   2059 // Should be called on instructions in a dead block in post order. This method
   2060 // assumes `insn` has been removed from all users with the exception of catch
   2061 // phis because of missing exceptional edges in the graph. It removes the
   2062 // instruction from catch phi uses, together with inputs of other catch phis in
   2063 // the catch block at the same index, as these must be dead too.
   2064 static void RemoveUsesOfDeadInstruction(HInstruction* insn) {
   2065   DCHECK(!insn->HasEnvironmentUses());
   2066   while (insn->HasNonEnvironmentUses()) {
   2067     const HUseListNode<HInstruction*>& use = insn->GetUses().front();
   2068     size_t use_index = use.GetIndex();
   2069     HBasicBlock* user_block =  use.GetUser()->GetBlock();
   2070     DCHECK(use.GetUser()->IsPhi() && user_block->IsCatchBlock());
   2071     for (HInstructionIterator phi_it(user_block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
   2072       phi_it.Current()->AsPhi()->RemoveInputAt(use_index);
   2073     }
   2074   }
   2075 }
   2076 
   2077 void HBasicBlock::DisconnectAndDelete() {
   2078   // Dominators must be removed after all the blocks they dominate. This way
   2079   // a loop header is removed last, a requirement for correct loop information
   2080   // iteration.
   2081   DCHECK(dominated_blocks_.empty());
   2082 
   2083   // The following steps gradually remove the block from all its dependants in
   2084   // post order (b/27683071).
   2085 
   2086   // (1) Store a basic block that we'll use in step (5) to find loops to be updated.
   2087   //     We need to do this before step (4) which destroys the predecessor list.
   2088   HBasicBlock* loop_update_start = this;
   2089   if (IsLoopHeader()) {
   2090     HLoopInformation* loop_info = GetLoopInformation();
   2091     // All other blocks in this loop should have been removed because the header
   2092     // was their dominator.
   2093     // Note that we do not remove `this` from `loop_info` as it is unreachable.
   2094     DCHECK(!loop_info->IsIrreducible());
   2095     DCHECK_EQ(loop_info->GetBlocks().NumSetBits(), 1u);
   2096     DCHECK_EQ(static_cast<uint32_t>(loop_info->GetBlocks().GetHighestBitSet()), GetBlockId());
   2097     loop_update_start = loop_info->GetPreHeader();
   2098   }
   2099 
   2100   // (2) Disconnect the block from its successors and update their phis.
   2101   for (HBasicBlock* successor : successors_) {
   2102     // Delete this block from the list of predecessors.
   2103     size_t this_index = successor->GetPredecessorIndexOf(this);
   2104     successor->predecessors_.erase(successor->predecessors_.begin() + this_index);
   2105 
   2106     // Check that `successor` has other predecessors, otherwise `this` is the
   2107     // dominator of `successor` which violates the order DCHECKed at the top.
   2108     DCHECK(!successor->predecessors_.empty());
   2109 
   2110     // Remove this block's entries in the successor's phis. Skip exceptional
   2111     // successors because catch phi inputs do not correspond to predecessor
   2112     // blocks but throwing instructions. The inputs of the catch phis will be
   2113     // updated in step (3).
   2114     if (!successor->IsCatchBlock()) {
   2115       if (successor->predecessors_.size() == 1u) {
   2116         // The successor has just one predecessor left. Replace phis with the only
   2117         // remaining input.
   2118         for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
   2119           HPhi* phi = phi_it.Current()->AsPhi();
   2120           phi->ReplaceWith(phi->InputAt(1 - this_index));
   2121           successor->RemovePhi(phi);
   2122         }
   2123       } else {
   2124         for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
   2125           phi_it.Current()->AsPhi()->RemoveInputAt(this_index);
   2126         }
   2127       }
   2128     }
   2129   }
   2130   successors_.clear();
   2131 
   2132   // (3) Remove instructions and phis. Instructions should have no remaining uses
   2133   //     except in catch phis. If an instruction is used by a catch phi at `index`,
   2134   //     remove `index`-th input of all phis in the catch block since they are
   2135   //     guaranteed dead. Note that we may miss dead inputs this way but the
   2136   //     graph will always remain consistent.
   2137   for (HBackwardInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
   2138     HInstruction* insn = it.Current();
   2139     RemoveUsesOfDeadInstruction(insn);
   2140     RemoveInstruction(insn);
   2141   }
   2142   for (HInstructionIterator it(GetPhis()); !it.Done(); it.Advance()) {
   2143     HPhi* insn = it.Current()->AsPhi();
   2144     RemoveUsesOfDeadInstruction(insn);
   2145     RemovePhi(insn);
   2146   }
   2147 
   2148   // (4) Disconnect the block from its predecessors and update their
   2149   //     control-flow instructions.
   2150   for (HBasicBlock* predecessor : predecessors_) {
   2151     // We should not see any back edges as they would have been removed by step (3).
   2152     DCHECK(!IsInLoop() || !GetLoopInformation()->IsBackEdge(*predecessor));
   2153 
   2154     HInstruction* last_instruction = predecessor->GetLastInstruction();
   2155     if (last_instruction->IsTryBoundary() && !IsCatchBlock()) {
   2156       // This block is the only normal-flow successor of the TryBoundary which
   2157       // makes `predecessor` dead. Since DCE removes blocks in post order,
   2158       // exception handlers of this TryBoundary were already visited and any
   2159       // remaining handlers therefore must be live. We remove `predecessor` from
   2160       // their list of predecessors.
   2161       DCHECK_EQ(last_instruction->AsTryBoundary()->GetNormalFlowSuccessor(), this);
   2162       while (predecessor->GetSuccessors().size() > 1) {
   2163         HBasicBlock* handler = predecessor->GetSuccessors()[1];
   2164         DCHECK(handler->IsCatchBlock());
   2165         predecessor->RemoveSuccessor(handler);
   2166         handler->RemovePredecessor(predecessor);
   2167       }
   2168     }
   2169 
   2170     predecessor->RemoveSuccessor(this);
   2171     uint32_t num_pred_successors = predecessor->GetSuccessors().size();
   2172     if (num_pred_successors == 1u) {
   2173       // If we have one successor after removing one, then we must have
   2174       // had an HIf, HPackedSwitch or HTryBoundary, as they have more than one
   2175       // successor. Replace those with a HGoto.
   2176       DCHECK(last_instruction->IsIf() ||
   2177              last_instruction->IsPackedSwitch() ||
   2178              (last_instruction->IsTryBoundary() && IsCatchBlock()));
   2179       predecessor->RemoveInstruction(last_instruction);
   2180       predecessor->AddInstruction(new (graph_->GetAllocator()) HGoto(last_instruction->GetDexPc()));
   2181     } else if (num_pred_successors == 0u) {
   2182       // The predecessor has no remaining successors and therefore must be dead.
   2183       // We deliberately leave it without a control-flow instruction so that the
   2184       // GraphChecker fails unless it is not removed during the pass too.
   2185       predecessor->RemoveInstruction(last_instruction);
   2186     } else {
   2187       // There are multiple successors left. The removed block might be a successor
   2188       // of a PackedSwitch which will be completely removed (perhaps replaced with
   2189       // a Goto), or we are deleting a catch block from a TryBoundary. In either
   2190       // case, leave `last_instruction` as is for now.
   2191       DCHECK(last_instruction->IsPackedSwitch() ||
   2192              (last_instruction->IsTryBoundary() && IsCatchBlock()));
   2193     }
   2194   }
   2195   predecessors_.clear();
   2196 
   2197   // (5) Remove the block from all loops it is included in. Skip the inner-most
   2198   //     loop if this is the loop header (see definition of `loop_update_start`)
   2199   //     because the loop header's predecessor list has been destroyed in step (4).
   2200   for (HLoopInformationOutwardIterator it(*loop_update_start); !it.Done(); it.Advance()) {
   2201     HLoopInformation* loop_info = it.Current();
   2202     loop_info->Remove(this);
   2203     if (loop_info->IsBackEdge(*this)) {
   2204       // If this was the last back edge of the loop, we deliberately leave the
   2205       // loop in an inconsistent state and will fail GraphChecker unless the
   2206       // entire loop is removed during the pass.
   2207       loop_info->RemoveBackEdge(this);
   2208     }
   2209   }
   2210 
   2211   // (6) Disconnect from the dominator.
   2212   dominator_->RemoveDominatedBlock(this);
   2213   SetDominator(nullptr);
   2214 
   2215   // (7) Delete from the graph, update reverse post order.
   2216   graph_->DeleteDeadEmptyBlock(this);
   2217   SetGraph(nullptr);
   2218 }
   2219 
   2220 void HBasicBlock::MergeInstructionsWith(HBasicBlock* other) {
   2221   DCHECK(EndsWithControlFlowInstruction());
   2222   RemoveInstruction(GetLastInstruction());
   2223   instructions_.Add(other->GetInstructions());
   2224   other->instructions_.SetBlockOfInstructions(this);
   2225   other->instructions_.Clear();
   2226 }
   2227 
   2228 void HBasicBlock::MergeWith(HBasicBlock* other) {
   2229   DCHECK_EQ(GetGraph(), other->GetGraph());
   2230   DCHECK(ContainsElement(dominated_blocks_, other));
   2231   DCHECK_EQ(GetSingleSuccessor(), other);
   2232   DCHECK_EQ(other->GetSinglePredecessor(), this);
   2233   DCHECK(other->GetPhis().IsEmpty());
   2234 
   2235   // Move instructions from `other` to `this`.
   2236   MergeInstructionsWith(other);
   2237 
   2238   // Remove `other` from the loops it is included in.
   2239   for (HLoopInformationOutwardIterator it(*other); !it.Done(); it.Advance()) {
   2240     HLoopInformation* loop_info = it.Current();
   2241     loop_info->Remove(other);
   2242     if (loop_info->IsBackEdge(*other)) {
   2243       loop_info->ReplaceBackEdge(other, this);
   2244     }
   2245   }
   2246 
   2247   // Update links to the successors of `other`.
   2248   successors_.clear();
   2249   for (HBasicBlock* successor : other->GetSuccessors()) {
   2250     successor->predecessors_[successor->GetPredecessorIndexOf(other)] = this;
   2251   }
   2252   successors_.swap(other->successors_);
   2253   DCHECK(other->successors_.empty());
   2254 
   2255   // Update the dominator tree.
   2256   RemoveDominatedBlock(other);
   2257   for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
   2258     dominated->SetDominator(this);
   2259   }
   2260   dominated_blocks_.insert(
   2261       dominated_blocks_.end(), other->dominated_blocks_.begin(), other->dominated_blocks_.end());
   2262   other->dominated_blocks_.clear();
   2263   other->dominator_ = nullptr;
   2264 
   2265   // Clear the list of predecessors of `other` in preparation of deleting it.
   2266   other->predecessors_.clear();
   2267 
   2268   // Delete `other` from the graph. The function updates reverse post order.
   2269   graph_->DeleteDeadEmptyBlock(other);
   2270   other->SetGraph(nullptr);
   2271 }
   2272 
   2273 void HBasicBlock::MergeWithInlined(HBasicBlock* other) {
   2274   DCHECK_NE(GetGraph(), other->GetGraph());
   2275   DCHECK(GetDominatedBlocks().empty());
   2276   DCHECK(GetSuccessors().empty());
   2277   DCHECK(!EndsWithControlFlowInstruction());
   2278   DCHECK(other->GetSinglePredecessor()->IsEntryBlock());
   2279   DCHECK(other->GetPhis().IsEmpty());
   2280   DCHECK(!other->IsInLoop());
   2281 
   2282   // Move instructions from `other` to `this`.
   2283   instructions_.Add(other->GetInstructions());
   2284   other->instructions_.SetBlockOfInstructions(this);
   2285 
   2286   // Update links to the successors of `other`.
   2287   successors_.clear();
   2288   for (HBasicBlock* successor : other->GetSuccessors()) {
   2289     successor->predecessors_[successor->GetPredecessorIndexOf(other)] = this;
   2290   }
   2291   successors_.swap(other->successors_);
   2292   DCHECK(other->successors_.empty());
   2293 
   2294   // Update the dominator tree.
   2295   for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
   2296     dominated->SetDominator(this);
   2297   }
   2298   dominated_blocks_.insert(
   2299       dominated_blocks_.end(), other->dominated_blocks_.begin(), other->dominated_blocks_.end());
   2300   other->dominated_blocks_.clear();
   2301   other->dominator_ = nullptr;
   2302   other->graph_ = nullptr;
   2303 }
   2304 
   2305 void HBasicBlock::ReplaceWith(HBasicBlock* other) {
   2306   while (!GetPredecessors().empty()) {
   2307     HBasicBlock* predecessor = GetPredecessors()[0];
   2308     predecessor->ReplaceSuccessor(this, other);
   2309   }
   2310   while (!GetSuccessors().empty()) {
   2311     HBasicBlock* successor = GetSuccessors()[0];
   2312     successor->ReplacePredecessor(this, other);
   2313   }
   2314   for (HBasicBlock* dominated : GetDominatedBlocks()) {
   2315     other->AddDominatedBlock(dominated);
   2316   }
   2317   GetDominator()->ReplaceDominatedBlock(this, other);
   2318   other->SetDominator(GetDominator());
   2319   dominator_ = nullptr;
   2320   graph_ = nullptr;
   2321 }
   2322 
   2323 void HGraph::DeleteDeadEmptyBlock(HBasicBlock* block) {
   2324   DCHECK_EQ(block->GetGraph(), this);
   2325   DCHECK(block->GetSuccessors().empty());
   2326   DCHECK(block->GetPredecessors().empty());
   2327   DCHECK(block->GetDominatedBlocks().empty());
   2328   DCHECK(block->GetDominator() == nullptr);
   2329   DCHECK(block->GetInstructions().IsEmpty());
   2330   DCHECK(block->GetPhis().IsEmpty());
   2331 
   2332   if (block->IsExitBlock()) {
   2333     SetExitBlock(nullptr);
   2334   }
   2335 
   2336   RemoveElement(reverse_post_order_, block);
   2337   blocks_[block->GetBlockId()] = nullptr;
   2338   block->SetGraph(nullptr);
   2339 }
   2340 
   2341 void HGraph::UpdateLoopAndTryInformationOfNewBlock(HBasicBlock* block,
   2342                                                    HBasicBlock* reference,
   2343                                                    bool replace_if_back_edge) {
   2344   if (block->IsLoopHeader()) {
   2345     // Clear the information of which blocks are contained in that loop. Since the
   2346     // information is stored as a bit vector based on block ids, we have to update
   2347     // it, as those block ids were specific to the callee graph and we are now adding
   2348     // these blocks to the caller graph.
   2349     block->GetLoopInformation()->ClearAllBlocks();
   2350   }
   2351 
   2352   // If not already in a loop, update the loop information.
   2353   if (!block->IsInLoop()) {
   2354     block->SetLoopInformation(reference->GetLoopInformation());
   2355   }
   2356 
   2357   // If the block is in a loop, update all its outward loops.
   2358   HLoopInformation* loop_info = block->GetLoopInformation();
   2359   if (loop_info != nullptr) {
   2360     for (HLoopInformationOutwardIterator loop_it(*block);
   2361          !loop_it.Done();
   2362          loop_it.Advance()) {
   2363       loop_it.Current()->Add(block);
   2364     }
   2365     if (replace_if_back_edge && loop_info->IsBackEdge(*reference)) {
   2366       loop_info->ReplaceBackEdge(reference, block);
   2367     }
   2368   }
   2369 
   2370   // Copy TryCatchInformation if `reference` is a try block, not if it is a catch block.
   2371   TryCatchInformation* try_catch_info = reference->IsTryBlock()
   2372       ? reference->GetTryCatchInformation()
   2373       : nullptr;
   2374   block->SetTryCatchInformation(try_catch_info);
   2375 }
   2376 
   2377 HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
   2378   DCHECK(HasExitBlock()) << "Unimplemented scenario";
   2379   // Update the environments in this graph to have the invoke's environment
   2380   // as parent.
   2381   {
   2382     // Skip the entry block, we do not need to update the entry's suspend check.
   2383     for (HBasicBlock* block : GetReversePostOrderSkipEntryBlock()) {
   2384       for (HInstructionIterator instr_it(block->GetInstructions());
   2385            !instr_it.Done();
   2386            instr_it.Advance()) {
   2387         HInstruction* current = instr_it.Current();
   2388         if (current->NeedsEnvironment()) {
   2389           DCHECK(current->HasEnvironment());
   2390           current->GetEnvironment()->SetAndCopyParentChain(
   2391               outer_graph->GetAllocator(), invoke->GetEnvironment());
   2392         }
   2393       }
   2394     }
   2395   }
   2396   outer_graph->UpdateMaximumNumberOfOutVRegs(GetMaximumNumberOfOutVRegs());
   2397 
   2398   if (HasBoundsChecks()) {
   2399     outer_graph->SetHasBoundsChecks(true);
   2400   }
   2401   if (HasLoops()) {
   2402     outer_graph->SetHasLoops(true);
   2403   }
   2404   if (HasIrreducibleLoops()) {
   2405     outer_graph->SetHasIrreducibleLoops(true);
   2406   }
   2407   if (HasTryCatch()) {
   2408     outer_graph->SetHasTryCatch(true);
   2409   }
   2410   if (HasSIMD()) {
   2411     outer_graph->SetHasSIMD(true);
   2412   }
   2413 
   2414   HInstruction* return_value = nullptr;
   2415   if (GetBlocks().size() == 3) {
   2416     // Inliner already made sure we don't inline methods that always throw.
   2417     DCHECK(!GetBlocks()[1]->GetLastInstruction()->IsThrow());
   2418     // Simple case of an entry block, a body block, and an exit block.
   2419     // Put the body block's instruction into `invoke`'s block.
   2420     HBasicBlock* body = GetBlocks()[1];
   2421     DCHECK(GetBlocks()[0]->IsEntryBlock());
   2422     DCHECK(GetBlocks()[2]->IsExitBlock());
   2423     DCHECK(!body->IsExitBlock());
   2424     DCHECK(!body->IsInLoop());
   2425     HInstruction* last = body->GetLastInstruction();
   2426 
   2427     // Note that we add instructions before the invoke only to simplify polymorphic inlining.
   2428     invoke->GetBlock()->instructions_.AddBefore(invoke, body->GetInstructions());
   2429     body->GetInstructions().SetBlockOfInstructions(invoke->GetBlock());
   2430 
   2431     // Replace the invoke with the return value of the inlined graph.
   2432     if (last->IsReturn()) {
   2433       return_value = last->InputAt(0);
   2434     } else {
   2435       DCHECK(last->IsReturnVoid());
   2436     }
   2437 
   2438     invoke->GetBlock()->RemoveInstruction(last);
   2439   } else {
   2440     // Need to inline multiple blocks. We split `invoke`'s block
   2441     // into two blocks, merge the first block of the inlined graph into
   2442     // the first half, and replace the exit block of the inlined graph
   2443     // with the second half.
   2444     ArenaAllocator* allocator = outer_graph->GetAllocator();
   2445     HBasicBlock* at = invoke->GetBlock();
   2446     // Note that we split before the invoke only to simplify polymorphic inlining.
   2447     HBasicBlock* to = at->SplitBeforeForInlining(invoke);
   2448 
   2449     HBasicBlock* first = entry_block_->GetSuccessors()[0];
   2450     DCHECK(!first->IsInLoop());
   2451     at->MergeWithInlined(first);
   2452     exit_block_->ReplaceWith(to);
   2453 
   2454     // Update the meta information surrounding blocks:
   2455     // (1) the graph they are now in,
   2456     // (2) the reverse post order of that graph,
   2457     // (3) their potential loop information, inner and outer,
   2458     // (4) try block membership.
   2459     // Note that we do not need to update catch phi inputs because they
   2460     // correspond to the register file of the outer method which the inlinee
   2461     // cannot modify.
   2462 
   2463     // We don't add the entry block, the exit block, and the first block, which
   2464     // has been merged with `at`.
   2465     static constexpr int kNumberOfSkippedBlocksInCallee = 3;
   2466 
   2467     // We add the `to` block.
   2468     static constexpr int kNumberOfNewBlocksInCaller = 1;
   2469     size_t blocks_added = (reverse_post_order_.size() - kNumberOfSkippedBlocksInCallee)
   2470         + kNumberOfNewBlocksInCaller;
   2471 
   2472     // Find the location of `at` in the outer graph's reverse post order. The new
   2473     // blocks will be added after it.
   2474     size_t index_of_at = IndexOfElement(outer_graph->reverse_post_order_, at);
   2475     MakeRoomFor(&outer_graph->reverse_post_order_, blocks_added, index_of_at);
   2476 
   2477     // Do a reverse post order of the blocks in the callee and do (1), (2), (3)
   2478     // and (4) to the blocks that apply.
   2479     for (HBasicBlock* current : GetReversePostOrder()) {
   2480       if (current != exit_block_ && current != entry_block_ && current != first) {
   2481         DCHECK(current->GetTryCatchInformation() == nullptr);
   2482         DCHECK(current->GetGraph() == this);
   2483         current->SetGraph(outer_graph);
   2484         outer_graph->AddBlock(current);
   2485         outer_graph->reverse_post_order_[++index_of_at] = current;
   2486         UpdateLoopAndTryInformationOfNewBlock(current, at,  /* replace_if_back_edge */ false);
   2487       }
   2488     }
   2489 
   2490     // Do (1), (2), (3) and (4) to `to`.
   2491     to->SetGraph(outer_graph);
   2492     outer_graph->AddBlock(to);
   2493     outer_graph->reverse_post_order_[++index_of_at] = to;
   2494     // Only `to` can become a back edge, as the inlined blocks
   2495     // are predecessors of `to`.
   2496     UpdateLoopAndTryInformationOfNewBlock(to, at, /* replace_if_back_edge */ true);
   2497 
   2498     // Update all predecessors of the exit block (now the `to` block)
   2499     // to not `HReturn` but `HGoto` instead. Special case throwing blocks
   2500     // to now get the outer graph exit block as successor. Note that the inliner
   2501     // currently doesn't support inlining methods with try/catch.
   2502     HPhi* return_value_phi = nullptr;
   2503     bool rerun_dominance = false;
   2504     bool rerun_loop_analysis = false;
   2505     for (size_t pred = 0; pred < to->GetPredecessors().size(); ++pred) {
   2506       HBasicBlock* predecessor = to->GetPredecessors()[pred];
   2507       HInstruction* last = predecessor->GetLastInstruction();
   2508       if (last->IsThrow()) {
   2509         DCHECK(!at->IsTryBlock());
   2510         predecessor->ReplaceSuccessor(to, outer_graph->GetExitBlock());
   2511         --pred;
   2512         // We need to re-run dominance information, as the exit block now has
   2513         // a new dominator.
   2514         rerun_dominance = true;
   2515         if (predecessor->GetLoopInformation() != nullptr) {
   2516           // The exit block and blocks post dominated by the exit block do not belong
   2517           // to any loop. Because we do not compute the post dominators, we need to re-run
   2518           // loop analysis to get the loop information correct.
   2519           rerun_loop_analysis = true;
   2520         }
   2521       } else {
   2522         if (last->IsReturnVoid()) {
   2523           DCHECK(return_value == nullptr);
   2524           DCHECK(return_value_phi == nullptr);
   2525         } else {
   2526           DCHECK(last->IsReturn());
   2527           if (return_value_phi != nullptr) {
   2528             return_value_phi->AddInput(last->InputAt(0));
   2529           } else if (return_value == nullptr) {
   2530             return_value = last->InputAt(0);
   2531           } else {
   2532             // There will be multiple returns.
   2533             return_value_phi = new (allocator) HPhi(
   2534                 allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()), to->GetDexPc());
   2535             to->AddPhi(return_value_phi);
   2536             return_value_phi->AddInput(return_value);
   2537             return_value_phi->AddInput(last->InputAt(0));
   2538             return_value = return_value_phi;
   2539           }
   2540         }
   2541         predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
   2542         predecessor->RemoveInstruction(last);
   2543       }
   2544     }
   2545     if (rerun_loop_analysis) {
   2546       DCHECK(!outer_graph->HasIrreducibleLoops())
   2547           << "Recomputing loop information in graphs with irreducible loops "
   2548           << "is unsupported, as it could lead to loop header changes";
   2549       outer_graph->ClearLoopInformation();
   2550       outer_graph->ClearDominanceInformation();
   2551       outer_graph->BuildDominatorTree();
   2552     } else if (rerun_dominance) {
   2553       outer_graph->ClearDominanceInformation();
   2554       outer_graph->ComputeDominanceInformation();
   2555     }
   2556   }
   2557 
   2558   // Walk over the entry block and:
   2559   // - Move constants from the entry block to the outer_graph's entry block,
   2560   // - Replace HParameterValue instructions with their real value.
   2561   // - Remove suspend checks, that hold an environment.
   2562   // We must do this after the other blocks have been inlined, otherwise ids of
   2563   // constants could overlap with the inner graph.
   2564   size_t parameter_index = 0;
   2565   for (HInstructionIterator it(entry_block_->GetInstructions()); !it.Done(); it.Advance()) {
   2566     HInstruction* current = it.Current();
   2567     HInstruction* replacement = nullptr;
   2568     if (current->IsNullConstant()) {
   2569       replacement = outer_graph->GetNullConstant(current->GetDexPc());
   2570     } else if (current->IsIntConstant()) {
   2571       replacement = outer_graph->GetIntConstant(
   2572           current->AsIntConstant()->GetValue(), current->GetDexPc());
   2573     } else if (current->IsLongConstant()) {
   2574       replacement = outer_graph->GetLongConstant(
   2575           current->AsLongConstant()->GetValue(), current->GetDexPc());
   2576     } else if (current->IsFloatConstant()) {
   2577       replacement = outer_graph->GetFloatConstant(
   2578           current->AsFloatConstant()->GetValue(), current->GetDexPc());
   2579     } else if (current->IsDoubleConstant()) {
   2580       replacement = outer_graph->GetDoubleConstant(
   2581           current->AsDoubleConstant()->GetValue(), current->GetDexPc());
   2582     } else if (current->IsParameterValue()) {
   2583       if (kIsDebugBuild
   2584           && invoke->IsInvokeStaticOrDirect()
   2585           && invoke->AsInvokeStaticOrDirect()->IsStaticWithExplicitClinitCheck()) {
   2586         // Ensure we do not use the last input of `invoke`, as it
   2587         // contains a clinit check which is not an actual argument.
   2588         size_t last_input_index = invoke->InputCount() - 1;
   2589         DCHECK(parameter_index != last_input_index);
   2590       }
   2591       replacement = invoke->InputAt(parameter_index++);
   2592     } else if (current->IsCurrentMethod()) {
   2593       replacement = outer_graph->GetCurrentMethod();
   2594     } else {
   2595       DCHECK(current->IsGoto() || current->IsSuspendCheck());
   2596       entry_block_->RemoveInstruction(current);
   2597     }
   2598     if (replacement != nullptr) {
   2599       current->ReplaceWith(replacement);
   2600       // If the current is the return value then we need to update the latter.
   2601       if (current == return_value) {
   2602         DCHECK_EQ(entry_block_, return_value->GetBlock());
   2603         return_value = replacement;
   2604       }
   2605     }
   2606   }
   2607 
   2608   return return_value;
   2609 }
   2610 
   2611 /*
   2612  * Loop will be transformed to:
   2613  *       old_pre_header
   2614  *             |
   2615  *          if_block
   2616  *           /    \
   2617  *  true_block   false_block
   2618  *           \    /
   2619  *       new_pre_header
   2620  *             |
   2621  *           header
   2622  */
   2623 void HGraph::TransformLoopHeaderForBCE(HBasicBlock* header) {
   2624   DCHECK(header->IsLoopHeader());
   2625   HBasicBlock* old_pre_header = header->GetDominator();
   2626 
   2627   // Need extra block to avoid critical edge.
   2628   HBasicBlock* if_block = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2629   HBasicBlock* true_block = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2630   HBasicBlock* false_block = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2631   HBasicBlock* new_pre_header = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2632   AddBlock(if_block);
   2633   AddBlock(true_block);
   2634   AddBlock(false_block);
   2635   AddBlock(new_pre_header);
   2636 
   2637   header->ReplacePredecessor(old_pre_header, new_pre_header);
   2638   old_pre_header->successors_.clear();
   2639   old_pre_header->dominated_blocks_.clear();
   2640 
   2641   old_pre_header->AddSuccessor(if_block);
   2642   if_block->AddSuccessor(true_block);  // True successor
   2643   if_block->AddSuccessor(false_block);  // False successor
   2644   true_block->AddSuccessor(new_pre_header);
   2645   false_block->AddSuccessor(new_pre_header);
   2646 
   2647   old_pre_header->dominated_blocks_.push_back(if_block);
   2648   if_block->SetDominator(old_pre_header);
   2649   if_block->dominated_blocks_.push_back(true_block);
   2650   true_block->SetDominator(if_block);
   2651   if_block->dominated_blocks_.push_back(false_block);
   2652   false_block->SetDominator(if_block);
   2653   if_block->dominated_blocks_.push_back(new_pre_header);
   2654   new_pre_header->SetDominator(if_block);
   2655   new_pre_header->dominated_blocks_.push_back(header);
   2656   header->SetDominator(new_pre_header);
   2657 
   2658   // Fix reverse post order.
   2659   size_t index_of_header = IndexOfElement(reverse_post_order_, header);
   2660   MakeRoomFor(&reverse_post_order_, 4, index_of_header - 1);
   2661   reverse_post_order_[index_of_header++] = if_block;
   2662   reverse_post_order_[index_of_header++] = true_block;
   2663   reverse_post_order_[index_of_header++] = false_block;
   2664   reverse_post_order_[index_of_header++] = new_pre_header;
   2665 
   2666   // The pre_header can never be a back edge of a loop.
   2667   DCHECK((old_pre_header->GetLoopInformation() == nullptr) ||
   2668          !old_pre_header->GetLoopInformation()->IsBackEdge(*old_pre_header));
   2669   UpdateLoopAndTryInformationOfNewBlock(
   2670       if_block, old_pre_header, /* replace_if_back_edge */ false);
   2671   UpdateLoopAndTryInformationOfNewBlock(
   2672       true_block, old_pre_header, /* replace_if_back_edge */ false);
   2673   UpdateLoopAndTryInformationOfNewBlock(
   2674       false_block, old_pre_header, /* replace_if_back_edge */ false);
   2675   UpdateLoopAndTryInformationOfNewBlock(
   2676       new_pre_header, old_pre_header, /* replace_if_back_edge */ false);
   2677 }
   2678 
   2679 HBasicBlock* HGraph::TransformLoopForVectorization(HBasicBlock* header,
   2680                                                    HBasicBlock* body,
   2681                                                    HBasicBlock* exit) {
   2682   DCHECK(header->IsLoopHeader());
   2683   HLoopInformation* loop = header->GetLoopInformation();
   2684 
   2685   // Add new loop blocks.
   2686   HBasicBlock* new_pre_header = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2687   HBasicBlock* new_header = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2688   HBasicBlock* new_body = new (allocator_) HBasicBlock(this, header->GetDexPc());
   2689   AddBlock(new_pre_header);
   2690   AddBlock(new_header);
   2691   AddBlock(new_body);
   2692 
   2693   // Set up control flow.
   2694   header->ReplaceSuccessor(exit, new_pre_header);
   2695   new_pre_header->AddSuccessor(new_header);
   2696   new_header->AddSuccessor(exit);
   2697   new_header->AddSuccessor(new_body);
   2698   new_body->AddSuccessor(new_header);
   2699 
   2700   // Set up dominators.
   2701   header->ReplaceDominatedBlock(exit, new_pre_header);
   2702   new_pre_header->SetDominator(header);
   2703   new_pre_header->dominated_blocks_.push_back(new_header);
   2704   new_header->SetDominator(new_pre_header);
   2705   new_header->dominated_blocks_.push_back(new_body);
   2706   new_body->SetDominator(new_header);
   2707   new_header->dominated_blocks_.push_back(exit);
   2708   exit->SetDominator(new_header);
   2709 
   2710   // Fix reverse post order.
   2711   size_t index_of_header = IndexOfElement(reverse_post_order_, header);
   2712   MakeRoomFor(&reverse_post_order_, 2, index_of_header);
   2713   reverse_post_order_[++index_of_header] = new_pre_header;
   2714   reverse_post_order_[++index_of_header] = new_header;
   2715   size_t index_of_body = IndexOfElement(reverse_post_order_, body);
   2716   MakeRoomFor(&reverse_post_order_, 1, index_of_body - 1);
   2717   reverse_post_order_[index_of_body] = new_body;
   2718 
   2719   // Add gotos and suspend check (client must add conditional in header).
   2720   new_pre_header->AddInstruction(new (allocator_) HGoto());
   2721   HSuspendCheck* suspend_check = new (allocator_) HSuspendCheck(header->GetDexPc());
   2722   new_header->AddInstruction(suspend_check);
   2723   new_body->AddInstruction(new (allocator_) HGoto());
   2724   suspend_check->CopyEnvironmentFromWithLoopPhiAdjustment(
   2725       loop->GetSuspendCheck()->GetEnvironment(), header);
   2726 
   2727   // Update loop information.
   2728   new_header->AddBackEdge(new_body);
   2729   new_header->GetLoopInformation()->SetSuspendCheck(suspend_check);
   2730   new_header->GetLoopInformation()->Populate();
   2731   new_pre_header->SetLoopInformation(loop->GetPreHeader()->GetLoopInformation());  // outward
   2732   HLoopInformationOutwardIterator it(*new_header);
   2733   for (it.Advance(); !it.Done(); it.Advance()) {
   2734     it.Current()->Add(new_pre_header);
   2735     it.Current()->Add(new_header);
   2736     it.Current()->Add(new_body);
   2737   }
   2738   return new_pre_header;
   2739 }
   2740 
   2741 static void CheckAgainstUpperBound(ReferenceTypeInfo rti, ReferenceTypeInfo upper_bound_rti)
   2742     REQUIRES_SHARED(Locks::mutator_lock_) {
   2743   if (rti.IsValid()) {
   2744     DCHECK(upper_bound_rti.IsSupertypeOf(rti))
   2745         << " upper_bound_rti: " << upper_bound_rti
   2746         << " rti: " << rti;
   2747     DCHECK(!upper_bound_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes() || rti.IsExact())
   2748         << " upper_bound_rti: " << upper_bound_rti
   2749         << " rti: " << rti;
   2750   }
   2751 }
   2752 
   2753 void HInstruction::SetReferenceTypeInfo(ReferenceTypeInfo rti) {
   2754   if (kIsDebugBuild) {
   2755     DCHECK_EQ(GetType(), DataType::Type::kReference);
   2756     ScopedObjectAccess soa(Thread::Current());
   2757     DCHECK(rti.IsValid()) << "Invalid RTI for " << DebugName();
   2758     if (IsBoundType()) {
   2759       // Having the test here spares us from making the method virtual just for
   2760       // the sake of a DCHECK.
   2761       CheckAgainstUpperBound(rti, AsBoundType()->GetUpperBound());
   2762     }
   2763   }
   2764   reference_type_handle_ = rti.GetTypeHandle();
   2765   SetPackedFlag<kFlagReferenceTypeIsExact>(rti.IsExact());
   2766 }
   2767 
   2768 void HBoundType::SetUpperBound(const ReferenceTypeInfo& upper_bound, bool can_be_null) {
   2769   if (kIsDebugBuild) {
   2770     ScopedObjectAccess soa(Thread::Current());
   2771     DCHECK(upper_bound.IsValid());
   2772     DCHECK(!upper_bound_.IsValid()) << "Upper bound should only be set once.";
   2773     CheckAgainstUpperBound(GetReferenceTypeInfo(), upper_bound);
   2774   }
   2775   upper_bound_ = upper_bound;
   2776   SetPackedFlag<kFlagUpperCanBeNull>(can_be_null);
   2777 }
   2778 
   2779 ReferenceTypeInfo ReferenceTypeInfo::Create(TypeHandle type_handle, bool is_exact) {
   2780   if (kIsDebugBuild) {
   2781     ScopedObjectAccess soa(Thread::Current());
   2782     DCHECK(IsValidHandle(type_handle));
   2783     if (!is_exact) {
   2784       DCHECK(!type_handle->CannotBeAssignedFromOtherTypes())
   2785           << "Callers of ReferenceTypeInfo::Create should ensure is_exact is properly computed";
   2786     }
   2787   }
   2788   return ReferenceTypeInfo(type_handle, is_exact);
   2789 }
   2790 
   2791 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs) {
   2792   ScopedObjectAccess soa(Thread::Current());
   2793   os << "["
   2794      << " is_valid=" << rhs.IsValid()
   2795      << " type=" << (!rhs.IsValid() ? "?" : mirror::Class::PrettyClass(rhs.GetTypeHandle().Get()))
   2796      << " is_exact=" << rhs.IsExact()
   2797      << " ]";
   2798   return os;
   2799 }
   2800 
   2801 bool HInstruction::HasAnyEnvironmentUseBefore(HInstruction* other) {
   2802   // For now, assume that instructions in different blocks may use the
   2803   // environment.
   2804   // TODO: Use the control flow to decide if this is true.
   2805   if (GetBlock() != other->GetBlock()) {
   2806     return true;
   2807   }
   2808 
   2809   // We know that we are in the same block. Walk from 'this' to 'other',
   2810   // checking to see if there is any instruction with an environment.
   2811   HInstruction* current = this;
   2812   for (; current != other && current != nullptr; current = current->GetNext()) {
   2813     // This is a conservative check, as the instruction result may not be in
   2814     // the referenced environment.
   2815     if (current->HasEnvironment()) {
   2816       return true;
   2817     }
   2818   }
   2819 
   2820   // We should have been called with 'this' before 'other' in the block.
   2821   // Just confirm this.
   2822   DCHECK(current != nullptr);
   2823   return false;
   2824 }
   2825 
   2826 void HInvoke::SetIntrinsic(Intrinsics intrinsic,
   2827                            IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
   2828                            IntrinsicSideEffects side_effects,
   2829                            IntrinsicExceptions exceptions) {
   2830   intrinsic_ = intrinsic;
   2831   IntrinsicOptimizations opt(this);
   2832 
   2833   // Adjust method's side effects from intrinsic table.
   2834   switch (side_effects) {
   2835     case kNoSideEffects: SetSideEffects(SideEffects::None()); break;
   2836     case kReadSideEffects: SetSideEffects(SideEffects::AllReads()); break;
   2837     case kWriteSideEffects: SetSideEffects(SideEffects::AllWrites()); break;
   2838     case kAllSideEffects: SetSideEffects(SideEffects::AllExceptGCDependency()); break;
   2839   }
   2840 
   2841   if (needs_env_or_cache == kNoEnvironmentOrCache) {
   2842     opt.SetDoesNotNeedDexCache();
   2843     opt.SetDoesNotNeedEnvironment();
   2844   } else {
   2845     // If we need an environment, that means there will be a call, which can trigger GC.
   2846     SetSideEffects(GetSideEffects().Union(SideEffects::CanTriggerGC()));
   2847   }
   2848   // Adjust method's exception status from intrinsic table.
   2849   SetCanThrow(exceptions == kCanThrow);
   2850 }
   2851 
   2852 bool HNewInstance::IsStringAlloc() const {
   2853   ScopedObjectAccess soa(Thread::Current());
   2854   return GetReferenceTypeInfo().IsStringClass();
   2855 }
   2856 
   2857 bool HInvoke::NeedsEnvironment() const {
   2858   if (!IsIntrinsic()) {
   2859     return true;
   2860   }
   2861   IntrinsicOptimizations opt(*this);
   2862   return !opt.GetDoesNotNeedEnvironment();
   2863 }
   2864 
   2865 const DexFile& HInvokeStaticOrDirect::GetDexFileForPcRelativeDexCache() const {
   2866   ArtMethod* caller = GetEnvironment()->GetMethod();
   2867   ScopedObjectAccess soa(Thread::Current());
   2868   // `caller` is null for a top-level graph representing a method whose declaring
   2869   // class was not resolved.
   2870   return caller == nullptr ? GetBlock()->GetGraph()->GetDexFile() : *caller->GetDexFile();
   2871 }
   2872 
   2873 bool HInvokeStaticOrDirect::NeedsDexCacheOfDeclaringClass() const {
   2874   if (GetMethodLoadKind() != MethodLoadKind::kRuntimeCall) {
   2875     return false;
   2876   }
   2877   if (!IsIntrinsic()) {
   2878     return true;
   2879   }
   2880   IntrinsicOptimizations opt(*this);
   2881   return !opt.GetDoesNotNeedDexCache();
   2882 }
   2883 
   2884 std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs) {
   2885   switch (rhs) {
   2886     case HInvokeStaticOrDirect::MethodLoadKind::kStringInit:
   2887       return os << "StringInit";
   2888     case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
   2889       return os << "Recursive";
   2890     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
   2891       return os << "BootImageLinkTimePcRelative";
   2892     case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
   2893       return os << "DirectAddress";
   2894     case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
   2895       return os << "BssEntry";
   2896     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
   2897       return os << "RuntimeCall";
   2898     default:
   2899       LOG(FATAL) << "Unknown MethodLoadKind: " << static_cast<int>(rhs);
   2900       UNREACHABLE();
   2901   }
   2902 }
   2903 
   2904 std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs) {
   2905   switch (rhs) {
   2906     case HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit:
   2907       return os << "explicit";
   2908     case HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit:
   2909       return os << "implicit";
   2910     case HInvokeStaticOrDirect::ClinitCheckRequirement::kNone:
   2911       return os << "none";
   2912     default:
   2913       LOG(FATAL) << "Unknown ClinitCheckRequirement: " << static_cast<int>(rhs);
   2914       UNREACHABLE();
   2915   }
   2916 }
   2917 
   2918 bool HLoadClass::InstructionDataEquals(const HInstruction* other) const {
   2919   const HLoadClass* other_load_class = other->AsLoadClass();
   2920   // TODO: To allow GVN for HLoadClass from different dex files, we should compare the type
   2921   // names rather than type indexes. However, we shall also have to re-think the hash code.
   2922   if (type_index_ != other_load_class->type_index_ ||
   2923       GetPackedFields() != other_load_class->GetPackedFields()) {
   2924     return false;
   2925   }
   2926   switch (GetLoadKind()) {
   2927     case LoadKind::kBootImageAddress:
   2928     case LoadKind::kBootImageClassTable:
   2929     case LoadKind::kJitTableAddress: {
   2930       ScopedObjectAccess soa(Thread::Current());
   2931       return GetClass().Get() == other_load_class->GetClass().Get();
   2932     }
   2933     default:
   2934       DCHECK(HasTypeReference(GetLoadKind()));
   2935       return IsSameDexFile(GetDexFile(), other_load_class->GetDexFile());
   2936   }
   2937 }
   2938 
   2939 std::ostream& operator<<(std::ostream& os, HLoadClass::LoadKind rhs) {
   2940   switch (rhs) {
   2941     case HLoadClass::LoadKind::kReferrersClass:
   2942       return os << "ReferrersClass";
   2943     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
   2944       return os << "BootImageLinkTimePcRelative";
   2945     case HLoadClass::LoadKind::kBootImageAddress:
   2946       return os << "BootImageAddress";
   2947     case HLoadClass::LoadKind::kBootImageClassTable:
   2948       return os << "BootImageClassTable";
   2949     case HLoadClass::LoadKind::kBssEntry:
   2950       return os << "BssEntry";
   2951     case HLoadClass::LoadKind::kJitTableAddress:
   2952       return os << "JitTableAddress";
   2953     case HLoadClass::LoadKind::kRuntimeCall:
   2954       return os << "RuntimeCall";
   2955     default:
   2956       LOG(FATAL) << "Unknown HLoadClass::LoadKind: " << static_cast<int>(rhs);
   2957       UNREACHABLE();
   2958   }
   2959 }
   2960 
   2961 bool HLoadString::InstructionDataEquals(const HInstruction* other) const {
   2962   const HLoadString* other_load_string = other->AsLoadString();
   2963   // TODO: To allow GVN for HLoadString from different dex files, we should compare the strings
   2964   // rather than their indexes. However, we shall also have to re-think the hash code.
   2965   if (string_index_ != other_load_string->string_index_ ||
   2966       GetPackedFields() != other_load_string->GetPackedFields()) {
   2967     return false;
   2968   }
   2969   switch (GetLoadKind()) {
   2970     case LoadKind::kBootImageAddress:
   2971     case LoadKind::kBootImageInternTable:
   2972     case LoadKind::kJitTableAddress: {
   2973       ScopedObjectAccess soa(Thread::Current());
   2974       return GetString().Get() == other_load_string->GetString().Get();
   2975     }
   2976     default:
   2977       return IsSameDexFile(GetDexFile(), other_load_string->GetDexFile());
   2978   }
   2979 }
   2980 
   2981 std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs) {
   2982   switch (rhs) {
   2983     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
   2984       return os << "BootImageLinkTimePcRelative";
   2985     case HLoadString::LoadKind::kBootImageAddress:
   2986       return os << "BootImageAddress";
   2987     case HLoadString::LoadKind::kBootImageInternTable:
   2988       return os << "BootImageInternTable";
   2989     case HLoadString::LoadKind::kBssEntry:
   2990       return os << "BssEntry";
   2991     case HLoadString::LoadKind::kJitTableAddress:
   2992       return os << "JitTableAddress";
   2993     case HLoadString::LoadKind::kRuntimeCall:
   2994       return os << "RuntimeCall";
   2995     default:
   2996       LOG(FATAL) << "Unknown HLoadString::LoadKind: " << static_cast<int>(rhs);
   2997       UNREACHABLE();
   2998   }
   2999 }
   3000 
   3001 void HInstruction::RemoveEnvironmentUsers() {
   3002   for (const HUseListNode<HEnvironment*>& use : GetEnvUses()) {
   3003     HEnvironment* user = use.GetUser();
   3004     user->SetRawEnvAt(use.GetIndex(), nullptr);
   3005   }
   3006   env_uses_.clear();
   3007 }
   3008 
   3009 HInstruction* ReplaceInstrOrPhiByClone(HInstruction* instr) {
   3010   HInstruction* clone = instr->Clone(instr->GetBlock()->GetGraph()->GetAllocator());
   3011   HBasicBlock* block = instr->GetBlock();
   3012 
   3013   if (instr->IsPhi()) {
   3014     HPhi* phi = instr->AsPhi();
   3015     DCHECK(!phi->HasEnvironment());
   3016     HPhi* phi_clone = clone->AsPhi();
   3017     block->ReplaceAndRemovePhiWith(phi, phi_clone);
   3018   } else {
   3019     block->ReplaceAndRemoveInstructionWith(instr, clone);
   3020     if (instr->HasEnvironment()) {
   3021       clone->CopyEnvironmentFrom(instr->GetEnvironment());
   3022       HLoopInformation* loop_info = block->GetLoopInformation();
   3023       if (instr->IsSuspendCheck() && loop_info != nullptr) {
   3024         loop_info->SetSuspendCheck(clone->AsSuspendCheck());
   3025       }
   3026     }
   3027   }
   3028   return clone;
   3029 }
   3030 
   3031 // Returns an instruction with the opposite Boolean value from 'cond'.
   3032 HInstruction* HGraph::InsertOppositeCondition(HInstruction* cond, HInstruction* cursor) {
   3033   ArenaAllocator* allocator = GetAllocator();
   3034 
   3035   if (cond->IsCondition() &&
   3036       !DataType::IsFloatingPointType(cond->InputAt(0)->GetType())) {
   3037     // Can't reverse floating point conditions.  We have to use HBooleanNot in that case.
   3038     HInstruction* lhs = cond->InputAt(0);
   3039     HInstruction* rhs = cond->InputAt(1);
   3040     HInstruction* replacement = nullptr;
   3041     switch (cond->AsCondition()->GetOppositeCondition()) {  // get *opposite*
   3042       case kCondEQ: replacement = new (allocator) HEqual(lhs, rhs); break;
   3043       case kCondNE: replacement = new (allocator) HNotEqual(lhs, rhs); break;
   3044       case kCondLT: replacement = new (allocator) HLessThan(lhs, rhs); break;
   3045       case kCondLE: replacement = new (allocator) HLessThanOrEqual(lhs, rhs); break;
   3046       case kCondGT: replacement = new (allocator) HGreaterThan(lhs, rhs); break;
   3047       case kCondGE: replacement = new (allocator) HGreaterThanOrEqual(lhs, rhs); break;
   3048       case kCondB:  replacement = new (allocator) HBelow(lhs, rhs); break;
   3049       case kCondBE: replacement = new (allocator) HBelowOrEqual(lhs, rhs); break;
   3050       case kCondA:  replacement = new (allocator) HAbove(lhs, rhs); break;
   3051       case kCondAE: replacement = new (allocator) HAboveOrEqual(lhs, rhs); break;
   3052       default:
   3053         LOG(FATAL) << "Unexpected condition";
   3054         UNREACHABLE();
   3055     }
   3056     cursor->GetBlock()->InsertInstructionBefore(replacement, cursor);
   3057     return replacement;
   3058   } else if (cond->IsIntConstant()) {
   3059     HIntConstant* int_const = cond->AsIntConstant();
   3060     if (int_const->IsFalse()) {
   3061       return GetIntConstant(1);
   3062     } else {
   3063       DCHECK(int_const->IsTrue()) << int_const->GetValue();
   3064       return GetIntConstant(0);
   3065     }
   3066   } else {
   3067     HInstruction* replacement = new (allocator) HBooleanNot(cond);
   3068     cursor->GetBlock()->InsertInstructionBefore(replacement, cursor);
   3069     return replacement;
   3070   }
   3071 }
   3072 
   3073 std::ostream& operator<<(std::ostream& os, const MoveOperands& rhs) {
   3074   os << "["
   3075      << " source=" << rhs.GetSource()
   3076      << " destination=" << rhs.GetDestination()
   3077      << " type=" << rhs.GetType()
   3078      << " instruction=";
   3079   if (rhs.GetInstruction() != nullptr) {
   3080     os << rhs.GetInstruction()->DebugName() << ' ' << rhs.GetInstruction()->GetId();
   3081   } else {
   3082     os << "null";
   3083   }
   3084   os << " ]";
   3085   return os;
   3086 }
   3087 
   3088 std::ostream& operator<<(std::ostream& os, TypeCheckKind rhs) {
   3089   switch (rhs) {
   3090     case TypeCheckKind::kUnresolvedCheck:
   3091       return os << "unresolved_check";
   3092     case TypeCheckKind::kExactCheck:
   3093       return os << "exact_check";
   3094     case TypeCheckKind::kClassHierarchyCheck:
   3095       return os << "class_hierarchy_check";
   3096     case TypeCheckKind::kAbstractClassCheck:
   3097       return os << "abstract_class_check";
   3098     case TypeCheckKind::kInterfaceCheck:
   3099       return os << "interface_check";
   3100     case TypeCheckKind::kArrayObjectCheck:
   3101       return os << "array_object_check";
   3102     case TypeCheckKind::kArrayCheck:
   3103       return os << "array_check";
   3104     default:
   3105       LOG(FATAL) << "Unknown TypeCheckKind: " << static_cast<int>(rhs);
   3106       UNREACHABLE();
   3107   }
   3108 }
   3109 
   3110 std::ostream& operator<<(std::ostream& os, const MemBarrierKind& kind) {
   3111   switch (kind) {
   3112     case MemBarrierKind::kAnyStore:
   3113       return os << "AnyStore";
   3114     case MemBarrierKind::kLoadAny:
   3115       return os << "LoadAny";
   3116     case MemBarrierKind::kStoreStore:
   3117       return os << "StoreStore";
   3118     case MemBarrierKind::kAnyAny:
   3119       return os << "AnyAny";
   3120     case MemBarrierKind::kNTStoreStore:
   3121       return os << "NTStoreStore";
   3122 
   3123     default:
   3124       LOG(FATAL) << "Unknown MemBarrierKind: " << static_cast<int>(kind);
   3125       UNREACHABLE();
   3126   }
   3127 }
   3128 
   3129 }  // namespace art
   3130