1818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray/*
2818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray *
4818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * you may not use this file except in compliance with the License.
6818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * You may obtain a copy of the License at
7818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray *
8818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray *
10818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * See the License for the specific language governing permissions and
14818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray * limitations under the License.
15818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray */
16818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray#include "nodes.h"
1777520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle
1831dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain#include <cfloat>
1931dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain
20e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell#include "code_generator.h"
21391d01f3e8dedf3af3727bdf5d5b76ab35d52795Vladimir Marko#include "common_dominator.h"
22c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "ssa_builder.h"
23a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil#include "base/bit_vector-inl.h"
2480afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h"
251f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko#include "base/stl_util.h"
26a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#include "intrinsics.h"
27baf89b8f2591df93686df545bc6ccc6eb3b128ccDavid Brazdil#include "mirror/class-inl.h"
28acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "scoped_thread_state_change.h"
29818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
30818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffraynamespace art {
31818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
3231dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain// Enable floating-point static evaluation during constant folding
3331dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain// only if all floating-point operations and constants evaluate in the
3431dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain// range and precision of the type used (i.e., 32-bit float, 64-bit
3531dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain// double).
3631dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillainstatic constexpr bool kEnableFloatingPointStaticEvaluation = (FLT_EVAL_METHOD == 0);
3731dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain
38badd826664896d4a9628a5a89b78016894aa414bDavid Brazdilvoid HGraph::InitializeInexactObjectRTI(StackHandleScopeCollection* handles) {
39badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  ScopedObjectAccess soa(Thread::Current());
40badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  // Create the inexact Object reference type and store it in the HGraph.
41badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  ClassLinker* linker = Runtime::Current()->GetClassLinker();
42badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  inexact_object_rti_ = ReferenceTypeInfo::Create(
43badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)),
44badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      /* is_exact */ false);
45badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil}
46badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil
47818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffrayvoid HGraph::AddBlock(HBasicBlock* block) {
48fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  block->SetBlockId(blocks_.size());
49fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  blocks_.push_back(block);
50818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray}
51818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
52804d09372cc3d80d537da1489da4a45e0e19aa5dNicolas Geoffrayvoid HGraph::FindBackEdges(ArenaBitVector* visited) {
531f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  // "visited" must be empty on entry, it's an output argument for all visited (i.e. live) blocks.
541f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  DCHECK_EQ(visited->GetHighestBitSet(), -1);
551f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko
561f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  // Nodes that we're currently visiting, indexed by block id.
57f6a35de9eeefb20f6446f1b4815b4dcb0161d09cVladimir Marko  ArenaBitVector visiting(arena_, blocks_.size(), false, kArenaAllocGraphBuilder);
581f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  // Number of successors visited from a given node, indexed by block id.
59a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko  ArenaVector<size_t> successors_visited(blocks_.size(),
60a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko                                         0u,
61a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko                                         arena_->Adapter(kArenaAllocGraphBuilder));
621f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  // Stack of nodes that we're currently visiting (same as marked in "visiting" above).
63a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko  ArenaVector<HBasicBlock*> worklist(arena_->Adapter(kArenaAllocGraphBuilder));
641f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  constexpr size_t kDefaultWorklistSize = 8;
651f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  worklist.reserve(kDefaultWorklistSize);
661f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  visited->SetBit(entry_block_->GetBlockId());
671f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  visiting.SetBit(entry_block_->GetBlockId());
681f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  worklist.push_back(entry_block_);
691f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko
701f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  while (!worklist.empty()) {
711f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko    HBasicBlock* current = worklist.back();
721f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko    uint32_t current_id = current->GetBlockId();
731f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko    if (successors_visited[current_id] == current->GetSuccessors().size()) {
741f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      visiting.ClearBit(current_id);
751f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      worklist.pop_back();
761f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko    } else {
771f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++];
781f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      uint32_t successor_id = successor->GetBlockId();
791f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      if (visiting.IsBitSet(successor_id)) {
801f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko        DCHECK(ContainsElement(worklist, successor));
811f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko        successor->AddBackEdge(current);
821f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      } else if (!visited->IsBitSet(successor_id)) {
831f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko        visited->SetBit(successor_id);
841f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko        visiting.SetBit(successor_id);
851f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko        worklist.push_back(successor);
861f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko      }
871f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko    }
881f8695ca0c0d443a3d2754637ea5c9459147af55Vladimir Marko  }
89be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray}
90be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray
91cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markostatic void RemoveEnvironmentUses(HInstruction* instruction) {
920a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  for (HEnvironment* environment = instruction->GetEnvironment();
930a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray       environment != nullptr;
940a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray       environment = environment->GetParent()) {
95fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain    for (size_t i = 0, e = environment->Size(); i < e; ++i) {
961abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil      if (environment->GetInstructionAt(i) != nullptr) {
971abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil        environment->RemoveAsUserOfInput(i);
98fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain      }
99fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain    }
100fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain  }
101fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain}
102fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain
103cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markostatic void RemoveAsUser(HInstruction* instruction) {
104cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  for (size_t i = 0; i < instruction->InputCount(); i++) {
105cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    instruction->RemoveAsUserOfInput(i);
106cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
107cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
108cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  RemoveEnvironmentUses(instruction);
109cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
110cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
111fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillainvoid HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const {
112fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  for (size_t i = 0; i < blocks_.size(); ++i) {
113fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain    if (!visited.IsBitSet(i)) {
114ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko      HBasicBlock* block = blocks_[i];
11515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      if (block == nullptr) continue;
116f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffray      DCHECK(block->GetPhis().IsEmpty()) << "Phis are not inserted at this stage";
117fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain      for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
118fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain        RemoveAsUser(it.Current());
119fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain      }
120fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain    }
121fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain  }
122fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain}
123fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain
124f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffrayvoid HGraph::RemoveDeadBlocks(const ArenaBitVector& visited) {
125fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  for (size_t i = 0; i < blocks_.size(); ++i) {
126be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray    if (!visited.IsBitSet(i)) {
127ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko      HBasicBlock* block = blocks_[i];
12815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      if (block == nullptr) continue;
129f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffray      // We only need to update the successor, which might be live.
1306058455d486219994921b63a2d774dc9908415a2Vladimir Marko      for (HBasicBlock* successor : block->GetSuccessors()) {
1316058455d486219994921b63a2d774dc9908415a2Vladimir Marko        successor->RemovePredecessor(block);
1321abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil      }
133f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffray      // Remove the block from the list of blocks, so that further analyses
134f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffray      // never see it.
135fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko      blocks_[i] = nullptr;
1367ba9966b76bbf818513018fa1da72c89330fe384Serguei Katkov      if (block->IsExitBlock()) {
1377ba9966b76bbf818513018fa1da72c89330fe384Serguei Katkov        SetExitBlock(nullptr);
1387ba9966b76bbf818513018fa1da72c89330fe384Serguei Katkov      }
13986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      // Mark the block as removed. This is used by the HGraphBuilder to discard
14086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      // the block as a branch target.
14186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      block->SetGraph(nullptr);
142be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray    }
143be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray  }
144be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray}
145be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray
14615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas GeoffrayGraphAnalysisResult HGraph::BuildDominatorTree() {
147f6a35de9eeefb20f6446f1b4815b4dcb0161d09cVladimir Marko  ArenaBitVector visited(arena_, blocks_.size(), false, kArenaAllocGraphBuilder);
148be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray
14986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (1) Find the back edges in the graph doing a DFS traversal.
150be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray  FindBackEdges(&visited);
151be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray
15286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (2) Remove instructions and phis from blocks not visited during
153fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain  //     the initial DFS as users from other instructions, so that
154fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain  //     users can be safely removed before uses later.
155fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain  RemoveInstructionsAsUsersFromDeadBlocks(visited);
156fc600dccd7797a9a10cdd457034ea8e148ccd631Roland Levillain
15786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (3) Remove blocks not visited during the initial DFS.
15815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  //     Step (5) requires dead blocks to be removed from the
159be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray  //     predecessors list of live blocks.
160be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray  RemoveDeadBlocks(visited);
161be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray
16286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (4) Simplify the CFG now, so that we don't need to recompute
163622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  //     dominators and the reverse post order.
164622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  SimplifyCFG();
165622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
16686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (5) Compute the dominance information and the reverse post order.
1671f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray  ComputeDominanceInformation();
16815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray
16986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (6) Analyze loops discovered through back edge analysis, and
17015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  //     set the loop information on each block.
17115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  GraphAnalysisResult result = AnalyzeLoops();
17215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  if (result != kAnalysisSuccess) {
17315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    return result;
17415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
17515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray
17686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // (7) Precompute per-block try membership before entering the SSA builder,
17715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  //     which needs the information to build catch block phis from values of
17815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  //     locals at throwing instructions inside try blocks.
17915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  ComputeTryBlockInformation();
18015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray
18115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  return kAnalysisSuccess;
1821f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray}
1831f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray
1841f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffrayvoid HGraph::ClearDominanceInformation() {
1851f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray  for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
1861f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray    it.Current()->ClearDominanceInformation();
1871f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray  }
188fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  reverse_post_order_.clear();
1891f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray}
1901f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray
19115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffrayvoid HGraph::ClearLoopInformation() {
19215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  SetHasIrreducibleLoops(false);
19315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
19409aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray    it.Current()->SetLoopInformation(nullptr);
19515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
19615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray}
19715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray
1981f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffrayvoid HBasicBlock::ClearDominanceInformation() {
1996058455d486219994921b63a2d774dc9908415a2Vladimir Marko  dominated_blocks_.clear();
2001f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray  dominator_ = nullptr;
2011f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray}
2021f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffray
20309aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas GeoffrayHInstruction* HBasicBlock::GetFirstInstructionDisregardMoves() const {
20409aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray  HInstruction* instruction = GetFirstInstruction();
20509aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray  while (instruction->IsParallelMove()) {
20609aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray    instruction = instruction->GetNext();
20709aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray  }
20809aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray  return instruction;
20909aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray}
21009aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray
2117e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdilstatic bool UpdateDominatorOfSuccessor(HBasicBlock* block, HBasicBlock* successor) {
2127e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  DCHECK(ContainsElement(block->GetSuccessors(), successor));
2137e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil
2147e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  HBasicBlock* old_dominator = successor->GetDominator();
2157e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  HBasicBlock* new_dominator =
2167e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      (old_dominator == nullptr) ? block
2177e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil                                 : CommonDominator::ForPair(old_dominator, block);
2187e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil
2197e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  if (old_dominator == new_dominator) {
2207e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    return false;
2217e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  } else {
2227e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    successor->SetDominator(new_dominator);
2237e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    return true;
2247e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  }
2257e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil}
2267e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil
2271f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1Nicolas Geoffrayvoid HGraph::ComputeDominanceInformation() {
228fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  DCHECK(reverse_post_order_.empty());
229fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  reverse_post_order_.reserve(blocks_.size());
230fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  reverse_post_order_.push_back(entry_block_);
231d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko
232d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  // Number of visits of a given node, indexed by block id.
233a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko  ArenaVector<size_t> visits(blocks_.size(), 0u, arena_->Adapter(kArenaAllocGraphBuilder));
234d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  // Number of successors visited from a given node, indexed by block id.
235a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko  ArenaVector<size_t> successors_visited(blocks_.size(),
236a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko                                         0u,
237a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko                                         arena_->Adapter(kArenaAllocGraphBuilder));
238d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  // Nodes for which we need to visit successors.
239a26b3c51bfd97be1100d267f20c46535913e6bb7Vladimir Marko  ArenaVector<HBasicBlock*> worklist(arena_->Adapter(kArenaAllocGraphBuilder));
240d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  constexpr size_t kDefaultWorklistSize = 8;
241d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  worklist.reserve(kDefaultWorklistSize);
242d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  worklist.push_back(entry_block_);
243d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko
244d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko  while (!worklist.empty()) {
245d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko    HBasicBlock* current = worklist.back();
246d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko    uint32_t current_id = current->GetBlockId();
247d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko    if (successors_visited[current_id] == current->GetSuccessors().size()) {
248d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko      worklist.pop_back();
249d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko    } else {
250d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko      HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++];
2517e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      UpdateDominatorOfSuccessor(current, successor);
252d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko
253d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko      // Once all the forward edges have been visited, we know the immediate
254d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko      // dominator of the block. We can then start visiting its successors.
255d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko      if (++visits[successor->GetBlockId()] ==
256d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko          successor->GetPredecessors().size() - successor->NumberOfBackEdges()) {
257d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko        reverse_post_order_.push_back(successor);
258d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko        worklist.push_back(successor);
259d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko      }
260d76d1390b04a4db9ca1f74eb4873d926643d979bVladimir Marko    }
261be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray  }
262be9a92aa804c0d210f80966b74ef8ed3987f335aNicolas Geoffray
2637e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // Check if the graph has back edges not dominated by their respective headers.
2647e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // If so, we need to update the dominators of those headers and recursively of
2657e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // their successors. We do that with a fix-point iteration over all blocks.
2667e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // The algorithm is guaranteed to terminate because it loops only if the sum
2677e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // of all dominator chains has decreased in the current iteration.
2687e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  bool must_run_fix_point = false;
2697e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  for (HBasicBlock* block : blocks_) {
2707e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    if (block != nullptr &&
2717e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil        block->IsLoopHeader() &&
2727e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil        block->GetLoopInformation()->HasBackEdgeNotDominatedByHeader()) {
2737e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      must_run_fix_point = true;
2747e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      break;
2757e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    }
2767e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  }
2777e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  if (must_run_fix_point) {
2787e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    bool update_occurred = true;
2797e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    while (update_occurred) {
2807e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      update_occurred = false;
2817e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
2827e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil        HBasicBlock* block = it.Current();
2837e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil        for (HBasicBlock* successor : block->GetSuccessors()) {
2847e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil          update_occurred |= UpdateDominatorOfSuccessor(block, successor);
2857e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil        }
2867e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      }
2877e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    }
2887e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  }
2897e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil
2907e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // Make sure that there are no remaining blocks whose dominator information
2917e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  // needs to be updated.
2927e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  if (kIsDebugBuild) {
2937e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
2947e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      HBasicBlock* block = it.Current();
2957e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      for (HBasicBlock* successor : block->GetSuccessors()) {
2967e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil        DCHECK(!UpdateDominatorOfSuccessor(block, successor));
2977e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      }
2987e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    }
2997e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  }
3007e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil
30115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  // Populate `dominated_blocks_` information after computing all dominators.
302c9b21f83c2eab8bdd16241992193c3049dc68e43Roland Levillain  // The potential presence of irreducible loops requires to do it after.
30315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
30415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    HBasicBlock* block = it.Current();
30515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    if (!block->IsEntryBlock()) {
30615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      block->GetDominator()->AddDominatedBlock(block);
30715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    }
30815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
30915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray}
3104833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil
311fc6a86ab2b70781e72b807c1798b83829ca7f931David BrazdilHBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) {
3123c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  HBasicBlock* new_block = new (arena_) HBasicBlock(this, successor->GetDexPc());
313622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  AddBlock(new_block);
3148b20f88b0a8d1b374dd5eaae289d19734c77b8f8Nicolas Geoffray  // Use `InsertBetween` to ensure the predecessor index and successor index of
3158b20f88b0a8d1b374dd5eaae289d19734c77b8f8Nicolas Geoffray  // `block` and `successor` are preserved.
3168b20f88b0a8d1b374dd5eaae289d19734c77b8f8Nicolas Geoffray  new_block->InsertBetween(block, successor);
317fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  return new_block;
318fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil}
319fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
320fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdilvoid HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) {
321fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  // Insert a new node between `block` and `successor` to split the
322fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  // critical edge.
323fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  HBasicBlock* new_block = SplitEdge(block, successor);
3243ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban  new_block->AddInstruction(new (arena_) HGoto(successor->GetDexPc()));
325622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  if (successor->IsLoopHeader()) {
326622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    // If we split at a back edge boundary, make the new block the back edge.
327622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    HLoopInformation* info = successor->GetLoopInformation();
32846e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil    if (info->IsBackEdge(*block)) {
329622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray      info->RemoveBackEdge(block);
330622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray      info->AddBackEdge(new_block);
331622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    }
332622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  }
333622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
334622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
335622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffrayvoid HGraph::SimplifyLoop(HBasicBlock* header) {
336622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  HLoopInformation* info = header->GetLoopInformation();
337622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
338622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  // Make sure the loop has only one pre header. This simplifies SSA building by having
339622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  // to just look at the pre header to know which locals are initialized at entry of the
340788f2f05c3e5b0e5bda247b00e34f0094585546fNicolas Geoffray  // loop. Also, don't allow the entry block to be a pre header: this simplifies inlining
341788f2f05c3e5b0e5bda247b00e34f0094585546fNicolas Geoffray  // this graph.
3426058455d486219994921b63a2d774dc9908415a2Vladimir Marko  size_t number_of_incomings = header->GetPredecessors().size() - info->NumberOfBackEdges();
343788f2f05c3e5b0e5bda247b00e34f0094585546fNicolas Geoffray  if (number_of_incomings != 1 || (GetEntryBlock()->GetSingleSuccessor() == header)) {
3443c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    HBasicBlock* pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
345622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    AddBlock(pre_header);
3463ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban    pre_header->AddInstruction(new (arena_) HGoto(header->GetDexPc()));
347622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
3486058455d486219994921b63a2d774dc9908415a2Vladimir Marko    for (size_t pred = 0; pred < header->GetPredecessors().size(); ++pred) {
349ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko      HBasicBlock* predecessor = header->GetPredecessors()[pred];
350db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray      if (!info->IsBackEdge(*predecessor)) {
351ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray        predecessor->ReplaceSuccessor(header, pre_header);
352622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray        pred--;
353622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray      }
354622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    }
355622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    pre_header->AddSuccessor(header);
356622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  }
357604c6e4764edb2fd244e9f47626868cda5644a7aNicolas Geoffray
358db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray  // Make sure the first predecessor of a loop header is the incoming block.
359ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  if (info->IsBackEdge(*header->GetPredecessors()[0])) {
360ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* to_swap = header->GetPredecessors()[0];
3616058455d486219994921b63a2d774dc9908415a2Vladimir Marko    for (size_t pred = 1, e = header->GetPredecessors().size(); pred < e; ++pred) {
362ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko      HBasicBlock* predecessor = header->GetPredecessors()[pred];
363db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray      if (!info->IsBackEdge(*predecessor)) {
3646058455d486219994921b63a2d774dc9908415a2Vladimir Marko        header->predecessors_[pred] = to_swap;
3656058455d486219994921b63a2d774dc9908415a2Vladimir Marko        header->predecessors_[0] = predecessor;
366db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray        break;
367db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray      }
368db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray    }
369604c6e4764edb2fd244e9f47626868cda5644a7aNicolas Geoffray  }
3703c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray
3713c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  HInstruction* first_instruction = header->GetFirstInstruction();
372dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil  if (first_instruction != nullptr && first_instruction->IsSuspendCheck()) {
373dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    // Called from DeadBlockElimination. Update SuspendCheck pointer.
374dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    info->SetSuspendCheck(first_instruction->AsSuspendCheck());
3753c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  }
376622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
377622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
378ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdilvoid HGraph::ComputeTryBlockInformation() {
379ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  // Iterate in reverse post order to propagate try membership information from
380ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  // predecessors to their successors.
381ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
382ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    HBasicBlock* block = it.Current();
383ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    if (block->IsEntryBlock() || block->IsCatchBlock()) {
384ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      // Catch blocks after simplification have only exceptional predecessors
385ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      // and hence are never in tries.
386ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      continue;
387ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    }
388ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil
389ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    // Infer try membership from the first predecessor. Having simplified loops,
390ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    // the first predecessor can never be a back edge and therefore it must have
391ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    // been visited already and had its try membership set.
392ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* first_predecessor = block->GetPredecessors()[0];
393ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    DCHECK(!block->IsLoopHeader() || !block->GetLoopInformation()->IsBackEdge(*first_predecessor));
394ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil    const HTryBoundary* try_entry = first_predecessor->ComputeTryEntryOfSuccessors();
3958a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil    if (try_entry != nullptr &&
3968a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil        (block->GetTryCatchInformation() == nullptr ||
3978a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil         try_entry != &block->GetTryCatchInformation()->GetTryEntry())) {
3988a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // We are either setting try block membership for the first time or it
3998a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // has changed.
400ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil      block->SetTryCatchInformation(new (arena_) TryCatchInformation(*try_entry));
401ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil    }
402ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  }
403ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil}
404ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil
405c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HGraph::SimplifyCFG() {
406db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil// Simplify the CFG for future analysis, and code generation:
407622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  // (1): Split critical edges.
408db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil  // (2): Simplify loops by having only one preheader.
409b7d8e8cf7063fdec1cce6ebd33e33804976bd978Vladimir Marko  // NOTE: We're appending new blocks inside the loop, so we need to use index because iterators
410b7d8e8cf7063fdec1cce6ebd33e33804976bd978Vladimir Marko  // can be invalidated. We remember the initial size to avoid iterating over the new blocks.
411b7d8e8cf7063fdec1cce6ebd33e33804976bd978Vladimir Marko  for (size_t block_id = 0u, end = blocks_.size(); block_id != end; ++block_id) {
412b7d8e8cf7063fdec1cce6ebd33e33804976bd978Vladimir Marko    HBasicBlock* block = blocks_[block_id];
413f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffray    if (block == nullptr) continue;
414db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil    if (block->GetSuccessors().size() > 1) {
415db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil      // Only split normal-flow edges. We cannot split exceptional edges as they
416db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil      // are synthesized (approximate real control flow), and we do not need to
417db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil      // anyway. Moves that would be inserted there are performed by the runtime.
418d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil      ArrayRef<HBasicBlock* const> normal_successors = block->GetNormalSuccessors();
419d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil      for (size_t j = 0, e = normal_successors.size(); j < e; ++j) {
420d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil        HBasicBlock* successor = normal_successors[j];
421ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil        DCHECK(!successor->IsCatchBlock());
422db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil        if (successor == exit_block_) {
42386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil          // (Throw/Return/ReturnVoid)->TryBoundary->Exit. Special case which we
42486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil          // do not want to split because Goto->Exit is not allowed.
425db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil          DCHECK(block->IsSingleTryBoundary());
426db51efb3617d15f1cd9e5ff0cc2d934777014e9aDavid Brazdil        } else if (successor->GetPredecessors().size() > 1) {
427622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray          SplitCriticalEdge(block, successor);
428d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil          // SplitCriticalEdge could have invalidated the `normal_successors`
429d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil          // ArrayRef. We must re-acquire it.
430d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil          normal_successors = block->GetNormalSuccessors();
431d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil          DCHECK_EQ(normal_successors[j]->GetSingleSuccessor(), successor);
432d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil          DCHECK_EQ(e, normal_successors.size());
433c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray        }
434c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray      }
435622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    }
436622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    if (block->IsLoopHeader()) {
437622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray      SimplifyLoop(block);
43886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil    } else if (!block->IsEntryBlock() &&
43986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil               block->GetFirstInstruction() != nullptr &&
44086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil               block->GetFirstInstruction()->IsSuspendCheck()) {
44186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      // We are being called by the dead code elimiation pass, and what used to be
44209aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray      // a loop got dismantled. Just remove the suspend check.
44309aa147f0891ef28a95d89e8ad61c429f82ddd5bNicolas Geoffray      block->RemoveInstruction(block->GetFirstInstruction());
444c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    }
445c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
446c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
447c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
44815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas GeoffrayGraphAnalysisResult HGraph::AnalyzeLoops() const {
44977ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray  // We iterate post order to ensure we visit inner loops before outer loops.
45077ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray  // `PopulateRecursive` needs this guarantee to know whether a natural loop
45177ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray  // contains an irreducible loop.
45277ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray  for (HPostOrderIterator it(*this); !it.Done(); it.Advance()) {
453f776b92a0d52bb522043812dacb9c21ac11858e2Nicolas Geoffray    HBasicBlock* block = it.Current();
454622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    if (block->IsLoopHeader()) {
455ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      if (block->IsCatchBlock()) {
456ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil        // TODO: Dealing with exceptional back edges could be tricky because
457ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil        //       they only approximate the real control flow. Bail out for now.
45815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray        return kAnalysisFailThrowCatchLoop;
459622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray      }
46015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      block->GetLoopInformation()->Populate();
461622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    }
462622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  }
46315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  return kAnalysisSuccess;
46415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray}
46515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray
46615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffrayvoid HLoopInformation::Dump(std::ostream& os) {
46715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  os << "header: " << header_->GetBlockId() << std::endl;
46815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  os << "pre header: " << GetPreHeader()->GetBlockId() << std::endl;
46915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  for (HBasicBlock* block : back_edges_) {
47015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    os << "back edge: " << block->GetBlockId() << std::endl;
47115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
47215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  for (HBasicBlock* block : header_->GetPredecessors()) {
47315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    os << "predecessor: " << block->GetBlockId() << std::endl;
47415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
47515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  for (uint32_t idx : blocks_.Indexes()) {
47615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    os << "  in loop: " << idx << std::endl;
47715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
478622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
479622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
4808d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdilvoid HGraph::InsertConstant(HConstant* constant) {
48186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // New constants are inserted before the SuspendCheck at the bottom of the
48286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // entry block. Note that this method can be called from the graph builder and
48386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  // the entry block therefore may not end with SuspendCheck->Goto yet.
48486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  HInstruction* insert_before = nullptr;
48586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil
48686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  HInstruction* gota = entry_block_->GetLastInstruction();
48786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  if (gota != nullptr && gota->IsGoto()) {
48886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil    HInstruction* suspend_check = gota->GetPrevious();
48986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil    if (suspend_check != nullptr && suspend_check->IsSuspendCheck()) {
49086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      insert_before = suspend_check;
49186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil    } else {
49286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      insert_before = gota;
49386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil    }
49486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  }
49586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil
49686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  if (insert_before == nullptr) {
4978d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    entry_block_->AddInstruction(constant);
49886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  } else {
49986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil    entry_block_->InsertInstructionBefore(constant, insert_before);
50046e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  }
50146e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil}
50246e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil
5033ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny RoubanHNullConstant* HGraph::GetNullConstant(uint32_t dex_pc) {
50418e6873c469b48aaed22148451523479eece98e3Nicolas Geoffray  // For simplicity, don't bother reviving the cached null constant if it is
50518e6873c469b48aaed22148451523479eece98e3Nicolas Geoffray  // not null and not in a block. Otherwise, we need to clear the instruction
50618e6873c469b48aaed22148451523479eece98e3Nicolas Geoffray  // id and/or any invariants the graph is assuming when adding new instructions.
50718e6873c469b48aaed22148451523479eece98e3Nicolas Geoffray  if ((cached_null_constant_ == nullptr) || (cached_null_constant_->GetBlock() == nullptr)) {
5083ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban    cached_null_constant_ = new (arena_) HNullConstant(dex_pc);
5094833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil    cached_null_constant_->SetReferenceTypeInfo(inexact_object_rti_);
5108d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    InsertConstant(cached_null_constant_);
511d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
5124833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil  if (kIsDebugBuild) {
5134833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil    ScopedObjectAccess soa(Thread::Current());
5144833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil    DCHECK(cached_null_constant_->GetReferenceTypeInfo().IsValid());
5154833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil  }
516d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  return cached_null_constant_;
517d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray}
518d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
51976b1e1799a713a19218de26b171b0aef48a59e98Nicolas GeoffrayHCurrentMethod* HGraph::GetCurrentMethod() {
520f78848f2ced8466b5fb2d7148d608288ee88757bNicolas Geoffray  // For simplicity, don't bother reviving the cached current method if it is
521f78848f2ced8466b5fb2d7148d608288ee88757bNicolas Geoffray  // not null and not in a block. Otherwise, we need to clear the instruction
522f78848f2ced8466b5fb2d7148d608288ee88757bNicolas Geoffray  // id and/or any invariants the graph is assuming when adding new instructions.
523f78848f2ced8466b5fb2d7148d608288ee88757bNicolas Geoffray  if ((cached_current_method_ == nullptr) || (cached_current_method_->GetBlock() == nullptr)) {
524e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    cached_current_method_ = new (arena_) HCurrentMethod(
5253ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        Is64BitInstructionSet(instruction_set_) ? Primitive::kPrimLong : Primitive::kPrimInt,
5263ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        entry_block_->GetDexPc());
52776b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray    if (entry_block_->GetFirstInstruction() == nullptr) {
52876b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray      entry_block_->AddInstruction(cached_current_method_);
52976b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray    } else {
53076b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray      entry_block_->InsertInstructionBefore(
53176b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray          cached_current_method_, entry_block_->GetFirstInstruction());
53276b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray    }
53376b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray  }
53476b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray  return cached_current_method_;
53576b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray}
53676b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray
5373ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny RoubanHConstant* HGraph::GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc) {
5388d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil  switch (type) {
5398d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    case Primitive::Type::kPrimBoolean:
5408d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil      DCHECK(IsUint<1>(value));
5418d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil      FALLTHROUGH_INTENDED;
5428d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    case Primitive::Type::kPrimByte:
5438d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    case Primitive::Type::kPrimChar:
5448d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    case Primitive::Type::kPrimShort:
5458d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    case Primitive::Type::kPrimInt:
5468d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil      DCHECK(IsInt(Primitive::ComponentSize(type) * kBitsPerByte, value));
5473ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban      return GetIntConstant(static_cast<int32_t>(value), dex_pc);
5488d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil
5498d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    case Primitive::Type::kPrimLong:
5503ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban      return GetLongConstant(value, dex_pc);
5518d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil
5528d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    default:
5538d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil      LOG(FATAL) << "Unsupported constant type";
5548d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil      UNREACHABLE();
55546e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  }
55646e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil}
55746e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil
558f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffrayvoid HGraph::CacheFloatConstant(HFloatConstant* constant) {
559f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray  int32_t value = bit_cast<int32_t, float>(constant->GetValue());
560f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray  DCHECK(cached_float_constants_.find(value) == cached_float_constants_.end());
561f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray  cached_float_constants_.Overwrite(value, constant);
562f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray}
563f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray
564f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffrayvoid HGraph::CacheDoubleConstant(HDoubleConstant* constant) {
565f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray  int64_t value = bit_cast<int64_t, double>(constant->GetValue());
566f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray  DCHECK(cached_double_constants_.find(value) == cached_double_constants_.end());
567f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray  cached_double_constants_.Overwrite(value, constant);
568f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray}
569f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray
570276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffrayvoid HLoopInformation::Add(HBasicBlock* block) {
571276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  blocks_.SetBit(block->GetBlockId());
572276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
573276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
57446e2a3915aa68c77426b71e95b9f3658250646b7David Brazdilvoid HLoopInformation::Remove(HBasicBlock* block) {
57546e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  blocks_.ClearBit(block->GetBlockId());
57646e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil}
57746e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil
578622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffrayvoid HLoopInformation::PopulateRecursive(HBasicBlock* block) {
579622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  if (blocks_.IsBitSet(block->GetBlockId())) {
580622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    return;
581622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  }
582622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
583622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  blocks_.SetBit(block->GetBlockId());
584622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  block->SetInLoop(this);
58577ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray  if (block->IsLoopHeader()) {
58677ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray    // We're visiting loops in post-order, so inner loops must have been
58777ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray    // populated already.
58877ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray    DCHECK(block->GetLoopInformation()->IsPopulated());
58977ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray    if (block->GetLoopInformation()->IsIrreducible()) {
59077ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray      contains_irreducible_loop_ = true;
59177ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray    }
59277ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray  }
5936058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* predecessor : block->GetPredecessors()) {
5946058455d486219994921b63a2d774dc9908415a2Vladimir Marko    PopulateRecursive(predecessor);
595622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  }
596622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
597622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
598c2e8af9659db7e456b26febb1b971900057ad427David Brazdilvoid HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized) {
599c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  size_t block_id = block->GetBlockId();
600c2e8af9659db7e456b26febb1b971900057ad427David Brazdil
601c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  // If `block` is in `finalized`, we know its membership in the loop has been
602c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  // decided and it does not need to be revisited.
603c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  if (finalized->IsBitSet(block_id)) {
60415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    return;
605a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil  }
606a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil
607c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  bool is_finalized = false;
60815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  if (block->IsLoopHeader()) {
60915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // If we hit a loop header in an irreducible loop, we first check if the
61015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // pre header of that loop belongs to the currently analyzed loop. If it does,
61115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // then we visit the back edges.
61215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // Note that we cannot use GetPreHeader, as the loop may have not been populated
61315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // yet.
61415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    HBasicBlock* pre_header = block->GetPredecessors()[0];
615c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    PopulateIrreducibleRecursive(pre_header, finalized);
61615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    if (blocks_.IsBitSet(pre_header->GetBlockId())) {
61715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      block->SetInLoop(this);
618c2e8af9659db7e456b26febb1b971900057ad427David Brazdil      blocks_.SetBit(block_id);
619c2e8af9659db7e456b26febb1b971900057ad427David Brazdil      finalized->SetBit(block_id);
620c2e8af9659db7e456b26febb1b971900057ad427David Brazdil      is_finalized = true;
621c2e8af9659db7e456b26febb1b971900057ad427David Brazdil
62215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      HLoopInformation* info = block->GetLoopInformation();
62315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      for (HBasicBlock* back_edge : info->GetBackEdges()) {
624c2e8af9659db7e456b26febb1b971900057ad427David Brazdil        PopulateIrreducibleRecursive(back_edge, finalized);
62515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      }
62615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    }
627a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil  } else {
62815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // Visit all predecessors. If one predecessor is part of the loop, this
62915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // block is also part of this loop.
63015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    for (HBasicBlock* predecessor : block->GetPredecessors()) {
631c2e8af9659db7e456b26febb1b971900057ad427David Brazdil      PopulateIrreducibleRecursive(predecessor, finalized);
632c2e8af9659db7e456b26febb1b971900057ad427David Brazdil      if (!is_finalized && blocks_.IsBitSet(predecessor->GetBlockId())) {
63315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray        block->SetInLoop(this);
634c2e8af9659db7e456b26febb1b971900057ad427David Brazdil        blocks_.SetBit(block_id);
635c2e8af9659db7e456b26febb1b971900057ad427David Brazdil        finalized->SetBit(block_id);
636c2e8af9659db7e456b26febb1b971900057ad427David Brazdil        is_finalized = true;
637a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil      }
638a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil    }
63915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
640c2e8af9659db7e456b26febb1b971900057ad427David Brazdil
641c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  // All predecessors have been recursively visited. Mark finalized if not marked yet.
642c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  if (!is_finalized) {
643c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    finalized->SetBit(block_id);
644c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  }
64515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray}
64615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray
64715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffrayvoid HLoopInformation::Populate() {
64815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  DCHECK_EQ(blocks_.NumSetBits(), 0u) << "Loop information has already been populated";
64915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  // Populate this loop: starting with the back edge, recursively add predecessors
65015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  // that are not already part of that loop. Set the header as part of the loop
65115bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  // to end the recursion.
65215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  // This is a recursive implementation of the algorithm described in
65315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  // "Advanced Compiler Design & Implementation" (Muchnick) p192.
654c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  HGraph* graph = header_->GetGraph();
65515bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  blocks_.SetBit(header_->GetBlockId());
65615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  header_->SetInLoop(this);
657c2e8af9659db7e456b26febb1b971900057ad427David Brazdil
6587e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  bool is_irreducible_loop = HasBackEdgeNotDominatedByHeader();
659c2e8af9659db7e456b26febb1b971900057ad427David Brazdil
660c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  if (is_irreducible_loop) {
661c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    ArenaBitVector visited(graph->GetArena(),
662c2e8af9659db7e456b26febb1b971900057ad427David Brazdil                           graph->GetBlocks().size(),
663c2e8af9659db7e456b26febb1b971900057ad427David Brazdil                           /* expandable */ false,
664c2e8af9659db7e456b26febb1b971900057ad427David Brazdil                           kArenaAllocGraphBuilder);
665e4a97f926882ffb12707655a755a1c8f96620f91David Brazdil    // Stop marking blocks at the loop header.
666e4a97f926882ffb12707655a755a1c8f96620f91David Brazdil    visited.SetBit(header_->GetBlockId());
667e4a97f926882ffb12707655a755a1c8f96620f91David Brazdil
668c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    for (HBasicBlock* back_edge : GetBackEdges()) {
669c2e8af9659db7e456b26febb1b971900057ad427David Brazdil      PopulateIrreducibleRecursive(back_edge, &visited);
670c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    }
671c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  } else {
672c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    for (HBasicBlock* back_edge : GetBackEdges()) {
67315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray      PopulateRecursive(back_edge);
67415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    }
675a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil  }
676c2e8af9659db7e456b26febb1b971900057ad427David Brazdil
6773563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko  if (!is_irreducible_loop && graph->IsCompilingOsr()) {
6783563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    // When compiling in OSR mode, all loops in the compiled method may be entered
6793563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    // from the interpreter. We treat this OSR entry point just like an extra entry
6803563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    // to an irreducible loop, so we need to mark the method's loops as irreducible.
6813563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    // This does not apply to inlined loops which do not act as OSR entry points.
6823563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    if (suspend_check_ == nullptr) {
6833563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      // Just building the graph in OSR mode, this loop is not inlined. We never build an
6843563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      // inner graph in OSR mode as we can do OSR transition only from the outer method.
6853563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      is_irreducible_loop = true;
6863563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    } else {
6873563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      // Look at the suspend check's environment to determine if the loop was inlined.
6883563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      DCHECK(suspend_check_->HasEnvironment());
6893563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      if (!suspend_check_->GetEnvironment()->IsFromInlinedInvoke()) {
6903563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko        is_irreducible_loop = true;
6913563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko      }
6923563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko    }
6933563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko  }
6943563c44464ca55b2106373b35110e5ecaae38abfVladimir Marko  if (is_irreducible_loop) {
695c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    irreducible_ = true;
69677ce6430af2709432b22344ed656edd8ec80581bNicolas Geoffray    contains_irreducible_loop_ = true;
697c2e8af9659db7e456b26febb1b971900057ad427David Brazdil    graph->SetHasIrreducibleLoops(true);
698c2e8af9659db7e456b26febb1b971900057ad427David Brazdil  }
699a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil}
700a4b8c21dae70ae34aee13628632c39a675c06022David Brazdil
701622d9c31febd950255b36a48b47e1f630197c5feNicolas GeoffrayHBasicBlock* HLoopInformation::GetPreHeader() const {
70215bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  HBasicBlock* block = header_->GetPredecessors()[0];
70315bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  DCHECK(irreducible_ || (block == header_->GetDominator()));
70415bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  return block;
705622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
706622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
707622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffraybool HLoopInformation::Contains(const HBasicBlock& block) const {
708622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  return blocks_.IsBitSet(block.GetBlockId());
709622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
710622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
711622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffraybool HLoopInformation::IsIn(const HLoopInformation& other) const {
712622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  return other.blocks_.IsBitSet(header_->GetBlockId());
713622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray}
714622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray
7154b467ed97bc5886fb800209c0ee94df10163b88dMingyao Yangbool HLoopInformation::IsDefinedOutOfTheLoop(HInstruction* instruction) const {
7164b467ed97bc5886fb800209c0ee94df10163b88dMingyao Yang  return !blocks_.IsBitSet(instruction->GetBlock()->GetBlockId());
71773f1f3be46652d3f6df61b4234c366ebbf81274aAart Bik}
71873f1f3be46652d3f6df61b4234c366ebbf81274aAart Bik
719db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffraysize_t HLoopInformation::GetLifetimeEnd() const {
720db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray  size_t last_position = 0;
721fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  for (HBasicBlock* back_edge : GetBackEdges()) {
722fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko    last_position = std::max(back_edge->GetLifetimeEnd(), last_position);
723db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray  }
724db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray  return last_position;
725db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray}
726db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray
7277e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdilbool HLoopInformation::HasBackEdgeNotDominatedByHeader() const {
7287e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  for (HBasicBlock* back_edge : GetBackEdges()) {
7297e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    DCHECK(back_edge->GetDominator() != nullptr);
7307e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    if (!header_->Dominates(back_edge)) {
7317e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil      return true;
7327e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil    }
7337e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  }
7347e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil  return false;
7357e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil}
7367e589feab1b35203fbb8c431213f1d2b2a4ad530David Brazdil
737f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shaminbool HLoopInformation::DominatesAllBackEdges(HBasicBlock* block) {
738f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin  for (HBasicBlock* back_edge : GetBackEdges()) {
739f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin    if (!block->Dominates(back_edge)) {
740f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin      return false;
741f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin    }
742f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin  }
743f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin  return true;
744f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin}
745f479d7758dbe7e8740386fbf1d73e05b0277c5e3Anton Shamin
746622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffraybool HBasicBlock::Dominates(HBasicBlock* other) const {
747622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  // Walk up the dominator tree from `other`, to find out if `this`
748622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  // is an ancestor.
749622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  HBasicBlock* current = other;
750622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  while (current != nullptr) {
751622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    if (current == this) {
752622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray      return true;
753622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    }
754622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    current = current->GetDominator();
755622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  }
756622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray  return false;
757c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
758c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
759191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffraystatic void UpdateInputsUsers(HInstruction* instruction) {
760191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
761191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray    instruction->InputAt(i)->AddUseAt(instruction, i);
762191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  }
763191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  // Environment should be created later.
764191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  DCHECK(!instruction->HasEnvironment());
765191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray}
766191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
767ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillainvoid HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial,
768ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain                                                  HInstruction* replacement) {
769ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  DCHECK(initial->GetBlock() == this);
770805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell  if (initial->IsControlFlow()) {
771805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    // We can only replace a control flow instruction with another control flow instruction.
772805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    DCHECK(replacement->IsControlFlow());
773805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    DCHECK_EQ(replacement->GetId(), -1);
774805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    DCHECK_EQ(replacement->GetType(), Primitive::kPrimVoid);
775805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    DCHECK_EQ(initial->GetBlock(), this);
776805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    DCHECK_EQ(initial->GetType(), Primitive::kPrimVoid);
777d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    DCHECK(initial->GetUses().empty());
778d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    DCHECK(initial->GetEnvUses().empty());
779805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    replacement->SetBlock(this);
780805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    replacement->SetId(GetGraph()->GetNextInstructionId());
781805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    instructions_.InsertInstructionBefore(replacement, initial);
782805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    UpdateInputsUsers(replacement);
783805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell  } else {
784805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    InsertInstructionBefore(replacement, initial);
785805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell    initial->ReplaceWith(replacement);
786805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell  }
787ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  RemoveInstruction(initial);
788ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain}
789ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain
79074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdilvoid HBasicBlock::MoveInstructionBefore(HInstruction* insn, HInstruction* cursor) {
79174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  DCHECK(!cursor->IsPhi());
79274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  DCHECK(!insn->IsPhi());
79374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  DCHECK(!insn->IsControlFlow());
79474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  DCHECK(insn->CanBeMoved());
79574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  DCHECK(!insn->HasSideEffects());
79674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil
79774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  HBasicBlock* from_block = insn->GetBlock();
79874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  HBasicBlock* to_block = cursor->GetBlock();
79974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  DCHECK(from_block != to_block);
80074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil
80174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  from_block->RemoveInstruction(insn, /* ensure_safety */ false);
80274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  insn->SetBlock(to_block);
80374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  to_block->instructions_.InsertInstructionBefore(insn, cursor);
80474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil}
80574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil
806c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffraystatic void Add(HInstructionList* instruction_list,
807c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray                HBasicBlock* block,
808c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray                HInstruction* instruction) {
809787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  DCHECK(instruction->GetBlock() == nullptr);
81043c86422e210a3883729ab90997711e79f26bcccNicolas Geoffray  DCHECK_EQ(instruction->GetId(), -1);
811c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  instruction->SetBlock(block);
812c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  instruction->SetId(block->GetGraph()->GetNextInstructionId());
813191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  UpdateInputsUsers(instruction);
814c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  instruction_list->AddInstruction(instruction);
815c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
816c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
817c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HBasicBlock::AddInstruction(HInstruction* instruction) {
818c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  Add(&instructions_, this, instruction);
819c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
820c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
821c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HBasicBlock::AddPhi(HPhi* phi) {
822c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  Add(&phis_, this, phi);
823c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
824c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
825c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdilvoid HBasicBlock::InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor) {
826c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK(!cursor->IsPhi());
827c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK(!instruction->IsPhi());
828c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK_EQ(instruction->GetId(), -1);
829c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK_NE(cursor->GetId(), -1);
830c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK_EQ(cursor->GetBlock(), this);
831c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK(!instruction->IsControlFlow());
832c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  instruction->SetBlock(this);
833c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  instruction->SetId(GetGraph()->GetNextInstructionId());
834c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  UpdateInputsUsers(instruction);
835c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  instructions_.InsertInstructionBefore(instruction, cursor);
836c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil}
837c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil
8382967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchezvoid HBasicBlock::InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor) {
8392967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK(!cursor->IsPhi());
8402967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK(!instruction->IsPhi());
8412967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK_EQ(instruction->GetId(), -1);
8422967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK_NE(cursor->GetId(), -1);
8432967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK_EQ(cursor->GetBlock(), this);
8442967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK(!instruction->IsControlFlow());
8452967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  DCHECK(!cursor->IsControlFlow());
8462967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  instruction->SetBlock(this);
8472967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  instruction->SetId(GetGraph()->GetNextInstructionId());
8482967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  UpdateInputsUsers(instruction);
8492967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez  instructions_.InsertInstructionAfter(instruction, cursor);
8502967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez}
8512967ec6c3dad1c1dc15fc827188bd5ecfa75493bGuillaume "Vermeille" Sanchez
852102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffrayvoid HBasicBlock::InsertPhiAfter(HPhi* phi, HPhi* cursor) {
853102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  DCHECK_EQ(phi->GetId(), -1);
854102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  DCHECK_NE(cursor->GetId(), -1);
855102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  DCHECK_EQ(cursor->GetBlock(), this);
856102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  phi->SetBlock(this);
857102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  phi->SetId(GetGraph()->GetNextInstructionId());
858102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  UpdateInputsUsers(phi);
859c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  phis_.InsertInstructionAfter(phi, cursor);
860102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray}
861102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray
862c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffraystatic void Remove(HInstructionList* instruction_list,
863c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray                   HBasicBlock* block,
8641abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil                   HInstruction* instruction,
8651abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil                   bool ensure_safety) {
866c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  DCHECK_EQ(block, instruction->GetBlock());
867c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  instruction->SetBlock(nullptr);
868c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  instruction_list->RemoveInstruction(instruction);
8691abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil  if (ensure_safety) {
870d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    DCHECK(instruction->GetUses().empty());
871d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    DCHECK(instruction->GetEnvUses().empty());
8721abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil    RemoveAsUser(instruction);
8731abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil  }
874c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
875c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
8761abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdilvoid HBasicBlock::RemoveInstruction(HInstruction* instruction, bool ensure_safety) {
877c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil  DCHECK(!instruction->IsPhi());
8781abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil  Remove(&instructions_, this, instruction, ensure_safety);
879c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
880c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
8811abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdilvoid HBasicBlock::RemovePhi(HPhi* phi, bool ensure_safety) {
8821abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdil  Remove(&phis_, this, phi, ensure_safety);
883c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
884c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
885c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdilvoid HBasicBlock::RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety) {
886c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil  if (instruction->IsPhi()) {
887c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil    RemovePhi(instruction->AsPhi(), ensure_safety);
888c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil  } else {
889c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil    RemoveInstruction(instruction, ensure_safety);
890c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil  }
891c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil}
892c7508e93fa3df3a3890f6b62550cbd5e35bdd8dfDavid Brazdil
89371bf8090663d02869cafafdd530976f7f2a9db7fVladimir Markovoid HEnvironment::CopyFrom(const ArenaVector<HInstruction*>& locals) {
89471bf8090663d02869cafafdd530976f7f2a9db7fVladimir Marko  for (size_t i = 0; i < locals.size(); i++) {
89571bf8090663d02869cafafdd530976f7f2a9db7fVladimir Marko    HInstruction* instruction = locals[i];
8968c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray    SetRawEnvAt(i, instruction);
8978c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray    if (instruction != nullptr) {
8988c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray      instruction->AddEnvUseAt(this, i);
8998c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray    }
9008c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray  }
9018c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray}
9028c0c91a845568624815df026cfdac8c42ecccdf6Nicolas Geoffray
903ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdilvoid HEnvironment::CopyFrom(HEnvironment* env) {
904ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil  for (size_t i = 0; i < env->Size(); i++) {
905ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil    HInstruction* instruction = env->GetInstructionAt(i);
906ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil    SetRawEnvAt(i, instruction);
907ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil    if (instruction != nullptr) {
908ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil      instruction->AddEnvUseAt(this, i);
909ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil    }
910ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil  }
911ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil}
912ed59619b370ef23ffbb25d1d01f615e60a9262b6David Brazdil
913206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yangvoid HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
914206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang                                                 HBasicBlock* loop_header) {
915206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang  DCHECK(loop_header->IsLoopHeader());
916206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang  for (size_t i = 0; i < env->Size(); i++) {
917206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    HInstruction* instruction = env->GetInstructionAt(i);
918206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    SetRawEnvAt(i, instruction);
919206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    if (instruction == nullptr) {
920206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      continue;
921206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    }
922206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    if (instruction->IsLoopHeaderPhi() && (instruction->GetBlock() == loop_header)) {
923206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      // At the end of the loop pre-header, the corresponding value for instruction
924206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      // is the first input of the phi.
925206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      HInstruction* initial = instruction->AsPhi()->InputAt(0);
926206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      SetRawEnvAt(i, initial);
927206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      initial->AddEnvUseAt(this, i);
928206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    } else {
929206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang      instruction->AddEnvUseAt(this, i);
930206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang    }
931206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang  }
932206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang}
933206d6fd6cae5ba8c4d5f0e230111fe77b9d5c0a5Mingyao Yang
9341abb4191a2e56d8dbf518efcaeefb266c1acdf2bDavid Brazdilvoid HEnvironment::RemoveAsUserOfInput(size_t index) const {
935d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  const HUserRecord<HEnvironment*>& env_use = vregs_[index];
936d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  HInstruction* user = env_use.GetInstruction();
937d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  auto before_env_use_node = env_use.GetBeforeUseNode();
938d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  user->env_uses_.erase_after(before_env_use_node);
939d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  user->FixUpUserRecordsAfterEnvUseRemoval(before_env_use_node);
940c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
941c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
9425f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir MarkoHInstruction::InstructionKind HInstruction::GetKind() const {
9435f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko  return GetKindInternal();
9445f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko}
9455f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko
94677520bca97ec44e3758510cebd0f20e3bb4584eaCalin JuravleHInstruction* HInstruction::GetNextDisregardingMoves() const {
94777520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  HInstruction* next = GetNext();
94877520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  while (next != nullptr && next->IsParallelMove()) {
94977520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle    next = next->GetNext();
95077520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  }
95177520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  return next;
95277520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle}
95377520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle
95477520bca97ec44e3758510cebd0f20e3bb4584eaCalin JuravleHInstruction* HInstruction::GetPreviousDisregardingMoves() const {
95577520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  HInstruction* previous = GetPrevious();
95677520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  while (previous != nullptr && previous->IsParallelMove()) {
95777520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle    previous = previous->GetPrevious();
95877520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  }
95977520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  return previous;
96077520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle}
96177520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle
962c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HInstructionList::AddInstruction(HInstruction* instruction) {
963818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray  if (first_instruction_ == nullptr) {
964818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray    DCHECK(last_instruction_ == nullptr);
965818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray    first_instruction_ = last_instruction_ = instruction;
966818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray  } else {
967818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray    last_instruction_->next_ = instruction;
968818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray    instruction->previous_ = last_instruction_;
969818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray    last_instruction_ = instruction;
970818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray  }
971c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
972c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
973c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdilvoid HInstructionList::InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor) {
974c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK(Contains(cursor));
975c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  if (cursor == first_instruction_) {
976c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    cursor->previous_ = instruction;
977c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->next_ = cursor;
978c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    first_instruction_ = instruction;
979c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  } else {
980c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->previous_ = cursor->previous_;
981c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->next_ = cursor;
982c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    cursor->previous_ = instruction;
983c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->previous_->next_ = instruction;
984c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  }
985c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil}
986c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil
987c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdilvoid HInstructionList::InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor) {
988c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  DCHECK(Contains(cursor));
989c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  if (cursor == last_instruction_) {
990c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    cursor->next_ = instruction;
991c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->previous_ = cursor;
992c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    last_instruction_ = instruction;
993c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  } else {
994c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->next_ = cursor->next_;
995c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->previous_ = cursor;
996c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    cursor->next_ = instruction;
997c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil    instruction->next_->previous_ = instruction;
998c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil  }
999c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil}
1000c3d743fa2a26effcb35627d8a1338029c86e582aDavid Brazdil
1001c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HInstructionList::RemoveInstruction(HInstruction* instruction) {
1002c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  if (instruction->previous_ != nullptr) {
1003c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    instruction->previous_->next_ = instruction->next_;
1004c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
1005c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  if (instruction->next_ != nullptr) {
1006c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    instruction->next_->previous_ = instruction->previous_;
10073ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  }
1008c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  if (instruction == first_instruction_) {
1009c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    first_instruction_ = instruction->next_;
1010c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
1011c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  if (instruction == last_instruction_) {
1012c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    last_instruction_ = instruction->previous_;
1013c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
1014c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
1015c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
10166b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillainbool HInstructionList::Contains(HInstruction* instruction) const {
10176b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain  for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
10186b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain    if (it.Current() == instruction) {
10196b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain      return true;
10206b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain    }
10216b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain  }
10226b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain  return false;
10236b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain}
10246b46923ff0197c95f1e7ea0bc730961df6725cc9Roland Levillain
1025ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillainbool HInstructionList::FoundBefore(const HInstruction* instruction1,
1026ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain                                   const HInstruction* instruction2) const {
1027ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  DCHECK_EQ(instruction1->GetBlock(), instruction2->GetBlock());
1028ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
1029ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    if (it.Current() == instruction1) {
1030ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      return true;
1031ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    }
1032ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    if (it.Current() == instruction2) {
1033ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      return false;
1034ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    }
1035ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  }
1036ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  LOG(FATAL) << "Did not find an order between two instructions of the same block.";
1037ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  return true;
1038ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain}
1039ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain
10406c82d40eb142771086f5531998de2273ba5cc08cRoland Levillainbool HInstruction::StrictlyDominates(HInstruction* other_instruction) const {
10416c82d40eb142771086f5531998de2273ba5cc08cRoland Levillain  if (other_instruction == this) {
10426c82d40eb142771086f5531998de2273ba5cc08cRoland Levillain    // An instruction does not strictly dominate itself.
10436c82d40eb142771086f5531998de2273ba5cc08cRoland Levillain    return false;
10446c82d40eb142771086f5531998de2273ba5cc08cRoland Levillain  }
1045ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  HBasicBlock* block = GetBlock();
1046ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  HBasicBlock* other_block = other_instruction->GetBlock();
1047ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  if (block != other_block) {
1048ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    return GetBlock()->Dominates(other_instruction->GetBlock());
1049ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  } else {
1050ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    // If both instructions are in the same block, ensure this
1051ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    // instruction comes before `other_instruction`.
1052ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    if (IsPhi()) {
1053ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      if (!other_instruction->IsPhi()) {
1054ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // Phis appear before non phi-instructions so this instruction
1055ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // dominates `other_instruction`.
1056ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        return true;
1057ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      } else {
1058ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // There is no order among phis.
1059ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        LOG(FATAL) << "There is no dominance between phis of a same block.";
1060ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        return false;
1061ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      }
1062ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    } else {
1063ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      // `this` is not a phi.
1064ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      if (other_instruction->IsPhi()) {
1065ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // Phis appear before non phi-instructions so this instruction
1066ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // does not dominate `other_instruction`.
1067ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        return false;
1068ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      } else {
1069ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // Check whether this instruction comes before
1070ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        // `other_instruction` in the instruction list.
1071ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain        return block->GetInstructions().FoundBefore(this, other_instruction);
1072ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain      }
1073ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain    }
1074ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain  }
1075ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain}
1076ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain
1077cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markovoid HInstruction::RemoveEnvironment() {
1078cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  RemoveEnvironmentUses(this);
1079cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  environment_ = nullptr;
1080cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
1081cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
1082c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HInstruction::ReplaceWith(HInstruction* other) {
1083a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  DCHECK(other != nullptr);
1084fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  // Note: fixup_end remains valid across splice_after().
1085fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  auto fixup_end = other->uses_.empty() ? other->uses_.begin() : ++other->uses_.begin();
1086fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  other->uses_.splice_after(other->uses_.before_begin(), uses_);
1087fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  other->FixUpUserRecordsAfterUseInsertion(fixup_end);
1088c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
1089fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  // Note: env_fixup_end remains valid across splice_after().
1090fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  auto env_fixup_end =
1091fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko      other->env_uses_.empty() ? other->env_uses_.begin() : ++other->env_uses_.begin();
1092fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  other->env_uses_.splice_after(other->env_uses_.before_begin(), env_uses_);
1093fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  other->FixUpUserRecordsAfterEnvUseInsertion(env_fixup_end);
1094c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
1095fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  DCHECK(uses_.empty());
1096fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  DCHECK(env_uses_.empty());
1097c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
1098c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
1099102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffrayvoid HInstruction::ReplaceInput(HInstruction* replacement, size_t index) {
1100fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  HUserRecord<HInstruction*> input_use = InputRecordAt(index);
11019ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko  if (input_use.GetInstruction() == replacement) {
11029ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko    // Nothing to do.
11039ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko    return;
11049ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko  }
1105fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  HUseList<HInstruction*>::iterator before_use_node = input_use.GetBeforeUseNode();
1106fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  // Note: fixup_end remains valid across splice_after().
1107fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  auto fixup_end =
1108fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko      replacement->uses_.empty() ? replacement->uses_.begin() : ++replacement->uses_.begin();
1109fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  replacement->uses_.splice_after(replacement->uses_.before_begin(),
1110fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko                                  input_use.GetInstruction()->uses_,
1111fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko                                  before_use_node);
1112fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  replacement->FixUpUserRecordsAfterUseInsertion(fixup_end);
1113fa7f58935491fad5cb8e5af9ee38d1a4f73e872dVladimir Marko  input_use.GetInstruction()->FixUpUserRecordsAfterUseRemoval(before_use_node);
1114102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray}
1115102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray
11163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffraysize_t HInstruction::EnvironmentSize() const {
11173946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  return HasEnvironment() ? environment_->Size() : 0;
11183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray}
11193946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
1120c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffrayvoid HPhi::AddInput(HInstruction* input) {
1121c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  DCHECK(input->GetBlock() != nullptr);
1122fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  inputs_.push_back(HUserRecord<HInstruction*>(input));
1123fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  input->AddUseAt(this, inputs_.size() - 1);
1124818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray}
1125818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
11262d7352ba5311b8f57427b91b7a891e61497373c1David Brazdilvoid HPhi::RemoveInputAt(size_t index) {
11272d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  RemoveAsUserOfInput(index);
1128fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  inputs_.erase(inputs_.begin() + index);
11295d7b7f81ed5455893f984752c00571ef27cc97c5Nicolas Geoffray  for (size_t i = index, e = InputCount(); i < e; ++i) {
1130fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko    DCHECK_EQ(InputRecordAt(i).GetUseNode()->GetIndex(), i + 1u);
11315d7b7f81ed5455893f984752c00571ef27cc97c5Nicolas Geoffray    InputRecordAt(i).GetUseNode()->SetIndex(i);
11325d7b7f81ed5455893f984752c00571ef27cc97c5Nicolas Geoffray  }
11332d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil}
11342d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
1135360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#define DEFINE_ACCEPT(name, super)                                             \
1136818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffrayvoid H##name::Accept(HGraphVisitor* visitor) {                                 \
1137818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray  visitor->Visit##name(this);                                                  \
1138818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray}
1139818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
11405f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir MarkoFOR_EACH_CONCRETE_INSTRUCTION(DEFINE_ACCEPT)
1141818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
1142818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray#undef DEFINE_ACCEPT
1143818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
1144818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffrayvoid HGraphVisitor::VisitInsertionOrder() {
1145fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  const ArenaVector<HBasicBlock*>& blocks = graph_->GetBlocks();
1146fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  for (HBasicBlock* block : blocks) {
114746e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil    if (block != nullptr) {
114846e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil      VisitBasicBlock(block);
114946e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil    }
1150818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray  }
1151818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray}
1152818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
1153633021e6ff6b9a57a374a994e74cfd69275ce100Roland Levillainvoid HGraphVisitor::VisitReversePostOrder() {
1154633021e6ff6b9a57a374a994e74cfd69275ce100Roland Levillain  for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
1155633021e6ff6b9a57a374a994e74cfd69275ce100Roland Levillain    VisitBasicBlock(it.Current());
1156633021e6ff6b9a57a374a994e74cfd69275ce100Roland Levillain  }
1157633021e6ff6b9a57a374a994e74cfd69275ce100Roland Levillain}
1158633021e6ff6b9a57a374a994e74cfd69275ce100Roland Levillain
1159818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffrayvoid HGraphVisitor::VisitBasicBlock(HBasicBlock* block) {
1160f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
1161c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    it.Current()->Accept(this);
1162c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
1163f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray  for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
1164818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray    it.Current()->Accept(this);
1165818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray  }
1166818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray}
1167818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray
1168e82549b14c7def0a45461183964f7e6a34cbb70cMark MendellHConstant* HTypeConversion::TryStaticEvaluation() const {
1169e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  HGraph* graph = GetBlock()->GetGraph();
1170e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  if (GetInput()->IsIntConstant()) {
1171e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    int32_t value = GetInput()->AsIntConstant()->GetValue();
1172e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    switch (GetResultType()) {
1173e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimLong:
11743ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
1175e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimFloat:
11763ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
1177e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimDouble:
11783ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
1179e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      default:
1180e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        return nullptr;
1181e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    }
1182e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  } else if (GetInput()->IsLongConstant()) {
1183e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    int64_t value = GetInput()->AsLongConstant()->GetValue();
1184e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    switch (GetResultType()) {
1185e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimInt:
11863ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
1187e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimFloat:
11883ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
1189e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimDouble:
11903ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
1191e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      default:
1192e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        return nullptr;
1193e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    }
1194e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  } else if (GetInput()->IsFloatConstant()) {
1195e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    float value = GetInput()->AsFloatConstant()->GetValue();
1196e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    switch (GetResultType()) {
1197e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimInt:
1198e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (std::isnan(value))
11993ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetIntConstant(0, GetDexPc());
1200e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value >= kPrimIntMax)
12013ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetIntConstant(kPrimIntMax, GetDexPc());
1202e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value <= kPrimIntMin)
12033ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetIntConstant(kPrimIntMin, GetDexPc());
12043ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
1205e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimLong:
1206e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (std::isnan(value))
12073ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetLongConstant(0, GetDexPc());
1208e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value >= kPrimLongMax)
12093ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetLongConstant(kPrimLongMax, GetDexPc());
1210e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value <= kPrimLongMin)
12113ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetLongConstant(kPrimLongMin, GetDexPc());
12123ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
1213e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimDouble:
12143ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
1215e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      default:
1216e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        return nullptr;
1217e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    }
1218e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  } else if (GetInput()->IsDoubleConstant()) {
1219e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    double value = GetInput()->AsDoubleConstant()->GetValue();
1220e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    switch (GetResultType()) {
1221e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimInt:
1222e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (std::isnan(value))
12233ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetIntConstant(0, GetDexPc());
1224e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value >= kPrimIntMax)
12253ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetIntConstant(kPrimIntMax, GetDexPc());
1226e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value <= kPrimLongMin)
12273ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetIntConstant(kPrimIntMin, GetDexPc());
12283ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
1229e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimLong:
1230e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (std::isnan(value))
12313ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetLongConstant(0, GetDexPc());
1232e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value >= kPrimLongMax)
12333ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetLongConstant(kPrimLongMax, GetDexPc());
1234e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        if (value <= kPrimLongMin)
12353ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban          return graph->GetLongConstant(kPrimLongMin, GetDexPc());
12363ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
1237e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      case Primitive::kPrimFloat:
12383ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban        return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
1239e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell      default:
1240e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell        return nullptr;
1241e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell    }
1242e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  }
1243e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell  return nullptr;
1244e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell}
1245e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell
12469240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland LevillainHConstant* HUnaryOperation::TryStaticEvaluation() const {
12479240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  if (GetInput()->IsIntConstant()) {
12489867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain    return Evaluate(GetInput()->AsIntConstant());
12499240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  } else if (GetInput()->IsLongConstant()) {
12509867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain    return Evaluate(GetInput()->AsLongConstant());
125131dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain  } else if (kEnableFloatingPointStaticEvaluation) {
125231dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    if (GetInput()->IsFloatConstant()) {
125331dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return Evaluate(GetInput()->AsFloatConstant());
125431dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    } else if (GetInput()->IsDoubleConstant()) {
125531dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return Evaluate(GetInput()->AsDoubleConstant());
125631dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    }
12579240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  }
12589240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  return nullptr;
12599240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain}
12609240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
12619240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland LevillainHConstant* HBinaryOperation::TryStaticEvaluation() const {
1262e53bd8160ad2892f33849108d3b1099992a311fdRoland Levillain  if (GetLeft()->IsIntConstant() && GetRight()->IsIntConstant()) {
1263e53bd8160ad2892f33849108d3b1099992a311fdRoland Levillain    return Evaluate(GetLeft()->AsIntConstant(), GetRight()->AsIntConstant());
12649867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain  } else if (GetLeft()->IsLongConstant()) {
12659867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain    if (GetRight()->IsIntConstant()) {
1266e53bd8160ad2892f33849108d3b1099992a311fdRoland Levillain      // The binop(long, int) case is only valid for shifts and rotations.
1267e53bd8160ad2892f33849108d3b1099992a311fdRoland Levillain      DCHECK(IsShl() || IsShr() || IsUShr() || IsRor()) << DebugName();
12689867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain      return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsIntConstant());
12699867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain    } else if (GetRight()->IsLongConstant()) {
12709867bc722f7c41e07a95397bc08b790cd21dc758Roland Levillain      return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsLongConstant());
12719ee66183d8e046ea661f642ba884626f16b46e06Nicolas Geoffray    }
12729e23df5c21bed53ead79e3131b67105abc8871e4Vladimir Marko  } else if (GetLeft()->IsNullConstant() && GetRight()->IsNullConstant()) {
1273e53bd8160ad2892f33849108d3b1099992a311fdRoland Levillain    // The binop(null, null) case is only valid for equal and not-equal conditions.
1274e53bd8160ad2892f33849108d3b1099992a311fdRoland Levillain    DCHECK(IsEqual() || IsNotEqual()) << DebugName();
12759e23df5c21bed53ead79e3131b67105abc8871e4Vladimir Marko    return Evaluate(GetLeft()->AsNullConstant(), GetRight()->AsNullConstant());
127631dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain  } else if (kEnableFloatingPointStaticEvaluation) {
127731dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    if (GetLeft()->IsFloatConstant() && GetRight()->IsFloatConstant()) {
127831dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return Evaluate(GetLeft()->AsFloatConstant(), GetRight()->AsFloatConstant());
127931dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    } else if (GetLeft()->IsDoubleConstant() && GetRight()->IsDoubleConstant()) {
128031dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return Evaluate(GetLeft()->AsDoubleConstant(), GetRight()->AsDoubleConstant());
128131dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    }
1282556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  }
1283556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  return nullptr;
1284556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
128520dfc797dc631bf8d655dcf123f46f13332d3074Dave Allison
1286b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre RamesHConstant* HBinaryOperation::GetConstantRight() const {
1287b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  if (GetRight()->IsConstant()) {
1288b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames    return GetRight()->AsConstant();
1289b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  } else if (IsCommutative() && GetLeft()->IsConstant()) {
1290b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames    return GetLeft()->AsConstant();
1291b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  } else {
1292b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames    return nullptr;
1293b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  }
1294b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames}
1295b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames
1296b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames// If `GetConstantRight()` returns one of the input, this returns the other
12972cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier// one. Otherwise it returns null.
1298b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre RamesHInstruction* HBinaryOperation::GetLeastConstantLeft() const {
1299b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  HInstruction* most_constant_right = GetConstantRight();
1300b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  if (most_constant_right == nullptr) {
1301b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames    return nullptr;
1302b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  } else if (most_constant_right == GetLeft()) {
1303b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames    return GetRight();
1304b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  } else {
1305b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames    return GetLeft();
1306b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames  }
1307b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames}
1308b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames
130931dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillainstd::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs) {
131031dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain  switch (rhs) {
131131dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    case ComparisonBias::kNoBias:
131231dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return os << "no_bias";
131331dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    case ComparisonBias::kGtBias:
131431dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return os << "gt_bias";
131531dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    case ComparisonBias::kLtBias:
131631dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      return os << "lt_bias";
131731dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain    default:
131831dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      LOG(FATAL) << "Unknown ComparisonBias: " << static_cast<int>(rhs);
131931dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain      UNREACHABLE();
132031dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain  }
132131dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain}
132231dd3d60491148d345c1edae1ccd090a1b67dd2bRoland Levillain
1323d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yangbool HCondition::IsBeforeWhenDisregardMoves(HInstruction* instruction) const {
1324d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang  return this == instruction->GetPreviousDisregardingMoves();
132518efde5017369e005f1e8bcd3bbfb04e85053640Nicolas Geoffray}
132618efde5017369e005f1e8bcd3bbfb04e85053640Nicolas Geoffray
1327065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffraybool HInstruction::Equals(HInstruction* other) const {
1328065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  if (!InstructionTypeEquals(other)) return false;
1329d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  DCHECK_EQ(GetKind(), other->GetKind());
1330065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  if (!InstructionDataEquals(other)) return false;
1331065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  if (GetType() != other->GetType()) return false;
1332065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  if (InputCount() != other->InputCount()) return false;
1333065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray
1334065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  for (size_t i = 0, e = InputCount(); i < e; ++i) {
1335065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray    if (InputAt(i) != other->InputAt(i)) return false;
1336065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  }
1337d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  DCHECK_EQ(ComputeHashCode(), other->ComputeHashCode());
1338065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray  return true;
1339065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray}
1340065bf77b43c39da315b974ea08a5ed25e9049681Nicolas Geoffray
13416a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersstd::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs) {
13426a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#define DECLARE_CASE(type, super) case HInstruction::k##type: os << #type; break;
13436a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  switch (rhs) {
13446a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    FOR_EACH_INSTRUCTION(DECLARE_CASE)
13456a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    default:
13466a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers      os << "Unknown instruction kind " << static_cast<int>(rhs);
13476a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers      break;
13486a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  }
13496a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#undef DECLARE_CASE
13506a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  return os;
13516a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers}
13526a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers
135382091dad38f3e5bfaf3b6984c9ab73069fb68310Nicolas Geoffrayvoid HInstruction::MoveBefore(HInstruction* cursor) {
1354e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  next_->previous_ = previous_;
1355e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  if (previous_ != nullptr) {
1356e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray    previous_->next_ = next_;
1357e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  }
1358e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  if (block_->instructions_.first_instruction_ == this) {
1359e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray    block_->instructions_.first_instruction_ = next_;
1360e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  }
136182091dad38f3e5bfaf3b6984c9ab73069fb68310Nicolas Geoffray  DCHECK_NE(block_->instructions_.last_instruction_, this);
1362e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray
1363e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  previous_ = cursor->previous_;
1364e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  if (previous_ != nullptr) {
1365e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray    previous_->next_ = this;
1366e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  }
1367e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  next_ = cursor;
1368e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  cursor->previous_ = this;
1369e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  block_ = cursor->block_;
137082091dad38f3e5bfaf3b6984c9ab73069fb68310Nicolas Geoffray
137182091dad38f3e5bfaf3b6984c9ab73069fb68310Nicolas Geoffray  if (block_->instructions_.first_instruction_ == cursor) {
137282091dad38f3e5bfaf3b6984c9ab73069fb68310Nicolas Geoffray    block_->instructions_.first_instruction_ = this;
137382091dad38f3e5bfaf3b6984c9ab73069fb68310Nicolas Geoffray  }
1374e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray}
1375e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray
1376fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Markovoid HInstruction::MoveBeforeFirstUserAndOutOfLoops() {
1377fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  DCHECK(!CanThrow());
1378fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  DCHECK(!HasSideEffects());
1379fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  DCHECK(!HasEnvironmentUses());
1380fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  DCHECK(HasNonEnvironmentUses());
1381fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  DCHECK(!IsPhi());  // Makes no sense for Phi.
1382fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  DCHECK_EQ(InputCount(), 0u);
1383fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko
1384fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  // Find the target block.
1385d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  auto uses_it = GetUses().begin();
1386d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  auto uses_end = GetUses().end();
1387d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  HBasicBlock* target_block = uses_it->GetUser()->GetBlock();
1388d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  ++uses_it;
1389d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  while (uses_it != uses_end && uses_it->GetUser()->GetBlock() == target_block) {
1390d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    ++uses_it;
1391d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  }
1392d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  if (uses_it != uses_end) {
1393fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    // This instruction has uses in two or more blocks. Find the common dominator.
1394fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    CommonDominator finder(target_block);
1395d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    for (; uses_it != uses_end; ++uses_it) {
1396d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko      finder.Update(uses_it->GetUser()->GetBlock());
1397fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    }
1398fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    target_block = finder.Get();
1399fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    DCHECK(target_block != nullptr);
1400fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  }
1401fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  // Move to the first dominator not in a loop.
1402fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  while (target_block->IsInLoop()) {
1403fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    target_block = target_block->GetDominator();
1404fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    DCHECK(target_block != nullptr);
1405fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  }
1406fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko
1407fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  // Find insertion position.
1408fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  HInstruction* insert_pos = nullptr;
1409d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (const HUseListNode<HInstruction*>& use : GetUses()) {
1410d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    if (use.GetUser()->GetBlock() == target_block &&
1411d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko        (insert_pos == nullptr || use.GetUser()->StrictlyDominates(insert_pos))) {
1412d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko      insert_pos = use.GetUser();
1413fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    }
1414fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  }
1415fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  if (insert_pos == nullptr) {
1416fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    // No user in `target_block`, insert before the control flow instruction.
1417fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    insert_pos = target_block->GetLastInstruction();
1418fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    DCHECK(insert_pos->IsControlFlow());
1419fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    // Avoid splitting HCondition from HIf to prevent unnecessary materialization.
1420fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    if (insert_pos->IsIf()) {
1421fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      HInstruction* if_input = insert_pos->AsIf()->InputAt(0);
1422fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      if (if_input == insert_pos->GetPrevious()) {
1423fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko        insert_pos = if_input;
1424fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      }
1425fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    }
1426fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  }
1427fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  MoveBefore(insert_pos);
1428fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko}
1429fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko
1430fc6a86ab2b70781e72b807c1798b83829ca7f931David BrazdilHBasicBlock* HBasicBlock::SplitBefore(HInstruction* cursor) {
14319bc436160b4af99067973affb0b1008de9a2b04cDavid Brazdil  DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented.";
1432fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  DCHECK_EQ(cursor->GetBlock(), this);
1433fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
14343ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban  HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(),
14353ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban                                                                    cursor->GetDexPc());
1436fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  new_block->instructions_.first_instruction_ = cursor;
1437fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
1438fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  instructions_.last_instruction_ = cursor->previous_;
1439fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  if (cursor->previous_ == nullptr) {
1440fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil    instructions_.first_instruction_ = nullptr;
1441fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  } else {
1442fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil    cursor->previous_->next_ = nullptr;
1443fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil    cursor->previous_ = nullptr;
1444fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  }
1445fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
1446fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  new_block->instructions_.SetBlockOfInstructions(new_block);
14473ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban  AddInstruction(new (GetGraph()->GetArena()) HGoto(new_block->GetDexPc()));
1448fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
14496058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* successor : GetSuccessors()) {
14506058455d486219994921b63a2d774dc9908415a2Vladimir Marko    new_block->successors_.push_back(successor);
14516058455d486219994921b63a2d774dc9908415a2Vladimir Marko    successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
1452fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  }
14536058455d486219994921b63a2d774dc9908415a2Vladimir Marko  successors_.clear();
1454fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  AddSuccessor(new_block);
1455fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
145656e1accf3966ae92e151567abf4561ef3f6466f4David Brazdil  GetGraph()->AddBlock(new_block);
1457fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  return new_block;
1458fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil}
1459fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
1460d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid BrazdilHBasicBlock* HBasicBlock::CreateImmediateDominator() {
14619bc436160b4af99067973affb0b1008de9a2b04cDavid Brazdil  DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented.";
1462d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  DCHECK(!IsCatchBlock()) << "Support for updating try/catch information not implemented.";
1463d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil
1464d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
1465d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil
1466d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  for (HBasicBlock* predecessor : GetPredecessors()) {
1467d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil    new_block->predecessors_.push_back(predecessor);
1468d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil    predecessor->successors_[predecessor->GetSuccessorIndexOf(this)] = new_block;
1469d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  }
1470d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  predecessors_.clear();
1471d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  AddPredecessor(new_block);
1472d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil
1473d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  GetGraph()->AddBlock(new_block);
1474d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  return new_block;
1475d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil}
1476d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil
1477916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas GeoffrayHBasicBlock* HBasicBlock::SplitBeforeForInlining(HInstruction* cursor) {
1478916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  DCHECK_EQ(cursor->GetBlock(), this);
1479916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray
1480916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(),
1481916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray                                                                    cursor->GetDexPc());
1482916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  new_block->instructions_.first_instruction_ = cursor;
1483916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
1484916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  instructions_.last_instruction_ = cursor->previous_;
1485916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  if (cursor->previous_ == nullptr) {
1486916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    instructions_.first_instruction_ = nullptr;
1487916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  } else {
1488916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    cursor->previous_->next_ = nullptr;
1489916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    cursor->previous_ = nullptr;
1490916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  }
1491916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray
1492916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  new_block->instructions_.SetBlockOfInstructions(new_block);
1493916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray
1494916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  for (HBasicBlock* successor : GetSuccessors()) {
1495916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    new_block->successors_.push_back(successor);
1496916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
1497916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  }
1498916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  successors_.clear();
1499916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray
1500916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  for (HBasicBlock* dominated : GetDominatedBlocks()) {
1501916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    dominated->dominator_ = new_block;
1502916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    new_block->dominated_blocks_.push_back(dominated);
1503916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  }
1504916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  dominated_blocks_.clear();
1505916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  return new_block;
1506916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray}
1507916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray
1508916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas GeoffrayHBasicBlock* HBasicBlock::SplitAfterForInlining(HInstruction* cursor) {
1509276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  DCHECK(!cursor->IsControlFlow());
1510276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  DCHECK_NE(instructions_.last_instruction_, cursor);
1511276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  DCHECK_EQ(cursor->GetBlock(), this);
1512276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1513276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
1514276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  new_block->instructions_.first_instruction_ = cursor->GetNext();
1515276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
1516276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  cursor->next_->previous_ = nullptr;
1517276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  cursor->next_ = nullptr;
1518276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  instructions_.last_instruction_ = cursor;
1519276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1520276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  new_block->instructions_.SetBlockOfInstructions(new_block);
15216058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* successor : GetSuccessors()) {
15226058455d486219994921b63a2d774dc9908415a2Vladimir Marko    new_block->successors_.push_back(successor);
15236058455d486219994921b63a2d774dc9908415a2Vladimir Marko    successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
1524276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
15256058455d486219994921b63a2d774dc9908415a2Vladimir Marko  successors_.clear();
1526276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
15276058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* dominated : GetDominatedBlocks()) {
1528276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    dominated->dominator_ = new_block;
15296058455d486219994921b63a2d774dc9908415a2Vladimir Marko    new_block->dominated_blocks_.push_back(dominated);
1530276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
15316058455d486219994921b63a2d774dc9908415a2Vladimir Marko  dominated_blocks_.clear();
1532276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  return new_block;
1533276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
1534276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1535ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdilconst HTryBoundary* HBasicBlock::ComputeTryEntryOfSuccessors() const {
1536ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  if (EndsWithTryBoundary()) {
1537ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    HTryBoundary* try_boundary = GetLastInstruction()->AsTryBoundary();
1538ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    if (try_boundary->IsEntry()) {
1539ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil      DCHECK(!IsTryBlock());
1540ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      return try_boundary;
1541ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    } else {
1542ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil      DCHECK(IsTryBlock());
1543ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil      DCHECK(try_catch_information_->GetTryEntry().HasSameExceptionHandlersAs(*try_boundary));
1544ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      return nullptr;
1545ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    }
1546ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil  } else if (IsTryBlock()) {
1547ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil    return &try_catch_information_->GetTryEntry();
1548ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  } else {
1549ec16f79a4d0aeff319bf52139a0c82de3080d73cDavid Brazdil    return nullptr;
1550ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  }
1551fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil}
1552fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
1553d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdilbool HBasicBlock::HasThrowingInstructions() const {
1554d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  for (HInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
1555d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil    if (it.Current()->CanThrow()) {
1556d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil      return true;
1557d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil    }
1558d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  }
1559d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil  return false;
1560d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil}
1561d7558daaa86decf5a38f4f9bcd82267ab6e3e17fDavid Brazdil
1562fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdilstatic bool HasOnlyOneInstruction(const HBasicBlock& block) {
1563fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  return block.GetPhis().IsEmpty()
1564fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil      && !block.GetInstructions().IsEmpty()
1565fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil      && block.GetFirstInstruction() == block.GetLastInstruction();
1566fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil}
1567fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
156846e2a3915aa68c77426b71e95b9f3658250646b7David Brazdilbool HBasicBlock::IsSingleGoto() const {
1569fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsGoto();
1570fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil}
1571fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil
1572fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdilbool HBasicBlock::IsSingleTryBoundary() const {
1573fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsTryBoundary();
157446e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil}
157546e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil
15768d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdilbool HBasicBlock::EndsWithControlFlowInstruction() const {
15778d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil  return !GetInstructions().IsEmpty() && GetLastInstruction()->IsControlFlow();
15788d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil}
15798d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil
1580b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdilbool HBasicBlock::EndsWithIf() const {
1581b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdil  return !GetInstructions().IsEmpty() && GetLastInstruction()->IsIf();
1582b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdil}
1583b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdil
1584ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdilbool HBasicBlock::EndsWithTryBoundary() const {
1585ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  return !GetInstructions().IsEmpty() && GetLastInstruction()->IsTryBoundary();
1586ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil}
1587ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil
1588b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdilbool HBasicBlock::HasSinglePhi() const {
1589b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdil  return !GetPhis().IsEmpty() && GetFirstPhi()->GetNext() == nullptr;
1590b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdil}
1591b2bd1c5f9171f35fa5b71ada42d1a9e11189428dDavid Brazdil
1592d26a411adee1e71b3f09dd604ab9b23018037138David BrazdilArrayRef<HBasicBlock* const> HBasicBlock::GetNormalSuccessors() const {
1593d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  if (EndsWithTryBoundary()) {
1594d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    // The normal-flow successor of HTryBoundary is always stored at index zero.
1595d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    DCHECK_EQ(successors_[0], GetLastInstruction()->AsTryBoundary()->GetNormalFlowSuccessor());
1596d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    return ArrayRef<HBasicBlock* const>(successors_).SubArray(0u, 1u);
1597d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  } else {
1598d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    // All successors of blocks not ending with TryBoundary are normal.
1599d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    return ArrayRef<HBasicBlock* const>(successors_);
1600d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  }
1601d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil}
1602d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil
1603d26a411adee1e71b3f09dd604ab9b23018037138David BrazdilArrayRef<HBasicBlock* const> HBasicBlock::GetExceptionalSuccessors() const {
1604d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  if (EndsWithTryBoundary()) {
1605d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    return GetLastInstruction()->AsTryBoundary()->GetExceptionHandlers();
1606d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  } else {
1607d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    // Blocks not ending with TryBoundary do not have exceptional successors.
1608d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    return ArrayRef<HBasicBlock* const>();
1609d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  }
1610d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil}
1611d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil
1612ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdilbool HTryBoundary::HasSameExceptionHandlersAs(const HTryBoundary& other) const {
1613d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  ArrayRef<HBasicBlock* const> handlers1 = GetExceptionHandlers();
1614d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  ArrayRef<HBasicBlock* const> handlers2 = other.GetExceptionHandlers();
1615d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil
1616d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  size_t length = handlers1.size();
1617d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  if (length != handlers2.size()) {
1618ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    return false;
1619ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  }
1620ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil
1621b618adebbc19e50d7b1aa2f11b84341beb3c64dcDavid Brazdil  // Exception handlers need to be stored in the same order.
1622d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil  for (size_t i = 0; i < length; ++i) {
1623d26a411adee1e71b3f09dd604ab9b23018037138David Brazdil    if (handlers1[i] != handlers2[i]) {
1624ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil      return false;
1625ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil    }
1626ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  }
1627ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil  return true;
1628ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil}
1629ffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51David Brazdil
16302d7352ba5311b8f57427b91b7a891e61497373c1David Brazdilsize_t HInstructionList::CountSize() const {
16312d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  size_t size = 0;
16322d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  HInstruction* current = first_instruction_;
16332d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  for (; current != nullptr; current = current->GetNext()) {
16342d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    size++;
16352d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
16362d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  return size;
16372d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil}
16382d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
1639276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffrayvoid HInstructionList::SetBlockOfInstructions(HBasicBlock* block) const {
1640276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  for (HInstruction* current = first_instruction_;
1641276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray       current != nullptr;
1642276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray       current = current->GetNext()) {
1643276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    current->SetBlock(block);
1644276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
1645276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
1646276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1647276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffrayvoid HInstructionList::AddAfter(HInstruction* cursor, const HInstructionList& instruction_list) {
1648276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  DCHECK(Contains(cursor));
1649276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  if (!instruction_list.IsEmpty()) {
1650276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    if (cursor == last_instruction_) {
1651276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray      last_instruction_ = instruction_list.last_instruction_;
1652276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    } else {
1653276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray      cursor->next_->previous_ = instruction_list.last_instruction_;
1654276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    }
1655276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    instruction_list.last_instruction_->next_ = cursor->next_;
1656276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    cursor->next_ = instruction_list.first_instruction_;
1657276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    instruction_list.first_instruction_->previous_ = cursor;
1658276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
1659276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
1660276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1661916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffrayvoid HInstructionList::AddBefore(HInstruction* cursor, const HInstructionList& instruction_list) {
1662916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  DCHECK(Contains(cursor));
1663916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  if (!instruction_list.IsEmpty()) {
1664916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    if (cursor == first_instruction_) {
1665916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray      first_instruction_ = instruction_list.first_instruction_;
1666916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    } else {
1667916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray      cursor->previous_->next_ = instruction_list.first_instruction_;
1668916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    }
1669916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    instruction_list.last_instruction_->next_ = cursor;
1670916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    instruction_list.first_instruction_->previous_ = cursor->previous_;
1671916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    cursor->previous_ = instruction_list.last_instruction_;
1672916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray  }
1673916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray}
1674916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray
1675276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffrayvoid HInstructionList::Add(const HInstructionList& instruction_list) {
167646e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  if (IsEmpty()) {
167746e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil    first_instruction_ = instruction_list.first_instruction_;
167846e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil    last_instruction_ = instruction_list.last_instruction_;
167946e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  } else {
168046e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil    AddAfter(last_instruction_, instruction_list);
168146e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  }
168246e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil}
168346e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil
168404ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil// Should be called on instructions in a dead block in post order. This method
168504ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil// assumes `insn` has been removed from all users with the exception of catch
168604ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil// phis because of missing exceptional edges in the graph. It removes the
168704ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil// instruction from catch phi uses, together with inputs of other catch phis in
168804ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil// the catch block at the same index, as these must be dead too.
168904ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdilstatic void RemoveUsesOfDeadInstruction(HInstruction* insn) {
169004ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil  DCHECK(!insn->HasEnvironmentUses());
169104ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil  while (insn->HasNonEnvironmentUses()) {
1692d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    const HUseListNode<HInstruction*>& use = insn->GetUses().front();
1693d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    size_t use_index = use.GetIndex();
1694d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HBasicBlock* user_block =  use.GetUser()->GetBlock();
1695d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    DCHECK(use.GetUser()->IsPhi() && user_block->IsCatchBlock());
169604ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil    for (HInstructionIterator phi_it(user_block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
169704ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil      phi_it.Current()->AsPhi()->RemoveInputAt(use_index);
169804ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil    }
169904ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil  }
170004ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil}
170104ff4e8463ac68752638d305eeb84b457fd8289cDavid Brazdil
17022d7352ba5311b8f57427b91b7a891e61497373c1David Brazdilvoid HBasicBlock::DisconnectAndDelete() {
17032d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Dominators must be removed after all the blocks they dominate. This way
17042d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // a loop header is removed last, a requirement for correct loop information
17052d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // iteration.
17066058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(dominated_blocks_.empty());
17072d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
17089eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // The following steps gradually remove the block from all its dependants in
17099eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // post order (b/27683071).
17109eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil
17119eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (1) Store a basic block that we'll use in step (5) to find loops to be updated.
17129eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     We need to do this before step (4) which destroys the predecessor list.
17139eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  HBasicBlock* loop_update_start = this;
17149eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  if (IsLoopHeader()) {
17159eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    HLoopInformation* loop_info = GetLoopInformation();
17169eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // All other blocks in this loop should have been removed because the header
17179eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // was their dominator.
17189eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // Note that we do not remove `this` from `loop_info` as it is unreachable.
17199eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    DCHECK(!loop_info->IsIrreducible());
17209eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    DCHECK_EQ(loop_info->GetBlocks().NumSetBits(), 1u);
17219eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    DCHECK_EQ(static_cast<uint32_t>(loop_info->GetBlocks().GetHighestBitSet()), GetBlockId());
17229eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    loop_update_start = loop_info->GetPreHeader();
17239eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  }
17249eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil
17259eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (2) Disconnect the block from its successors and update their phis.
17269eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  for (HBasicBlock* successor : successors_) {
17279eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // Delete this block from the list of predecessors.
17289eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    size_t this_index = successor->GetPredecessorIndexOf(this);
17299eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    successor->predecessors_.erase(successor->predecessors_.begin() + this_index);
17309eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil
17319eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // Check that `successor` has other predecessors, otherwise `this` is the
17329eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // dominator of `successor` which violates the order DCHECKed at the top.
17339eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    DCHECK(!successor->predecessors_.empty());
17349eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil
17359eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // Remove this block's entries in the successor's phis. Skip exceptional
17369eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // successors because catch phi inputs do not correspond to predecessor
17379eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // blocks but throwing instructions. The inputs of the catch phis will be
17389eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // updated in step (3).
17399eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    if (!successor->IsCatchBlock()) {
17409eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      if (successor->predecessors_.size() == 1u) {
17419eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil        // The successor has just one predecessor left. Replace phis with the only
17429eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil        // remaining input.
17439eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil        for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
17449eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil          HPhi* phi = phi_it.Current()->AsPhi();
17459eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil          phi->ReplaceWith(phi->InputAt(1 - this_index));
17469eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil          successor->RemovePhi(phi);
17479eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil        }
17489eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      } else {
17499eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil        for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
17509eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil          phi_it.Current()->AsPhi()->RemoveInputAt(this_index);
17519eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil        }
17529eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      }
17532d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
17542d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
17559eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  successors_.clear();
17569eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil
17579eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (3) Remove instructions and phis. Instructions should have no remaining uses
17589eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     except in catch phis. If an instruction is used by a catch phi at `index`,
17599eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     remove `index`-th input of all phis in the catch block since they are
17609eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     guaranteed dead. Note that we may miss dead inputs this way but the
17619eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     graph will always remain consistent.
17629eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  for (HBackwardInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
17639eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    HInstruction* insn = it.Current();
17649eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    RemoveUsesOfDeadInstruction(insn);
17659eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    RemoveInstruction(insn);
17669eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  }
17679eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  for (HInstructionIterator it(GetPhis()); !it.Done(); it.Advance()) {
17689eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    HPhi* insn = it.Current()->AsPhi();
17699eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    RemoveUsesOfDeadInstruction(insn);
17709eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    RemovePhi(insn);
17719eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  }
177246e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil
17739eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (4) Disconnect the block from its predecessors and update their
17748a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil  //     control-flow instructions.
17756058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* predecessor : predecessors_) {
17769eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    // We should not see any back edges as they would have been removed by step (3).
17779eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    DCHECK(!IsInLoop() || !GetLoopInformation()->IsBackEdge(*predecessor));
17789eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil
17792d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    HInstruction* last_instruction = predecessor->GetLastInstruction();
17808a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil    if (last_instruction->IsTryBoundary() && !IsCatchBlock()) {
17818a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // This block is the only normal-flow successor of the TryBoundary which
17828a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // makes `predecessor` dead. Since DCE removes blocks in post order,
17838a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // exception handlers of this TryBoundary were already visited and any
17848a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // remaining handlers therefore must be live. We remove `predecessor` from
17858a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // their list of predecessors.
17868a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      DCHECK_EQ(last_instruction->AsTryBoundary()->GetNormalFlowSuccessor(), this);
17878a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      while (predecessor->GetSuccessors().size() > 1) {
17888a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil        HBasicBlock* handler = predecessor->GetSuccessors()[1];
17898a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil        DCHECK(handler->IsCatchBlock());
17908a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil        predecessor->RemoveSuccessor(handler);
17918a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil        handler->RemovePredecessor(predecessor);
17928a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      }
17938a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil    }
17948a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil
17952d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    predecessor->RemoveSuccessor(this);
1796fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell    uint32_t num_pred_successors = predecessor->GetSuccessors().size();
1797fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell    if (num_pred_successors == 1u) {
1798fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell      // If we have one successor after removing one, then we must have
17998a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // had an HIf, HPackedSwitch or HTryBoundary, as they have more than one
18008a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // successor. Replace those with a HGoto.
18018a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      DCHECK(last_instruction->IsIf() ||
18028a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil             last_instruction->IsPackedSwitch() ||
18038a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil             (last_instruction->IsTryBoundary() && IsCatchBlock()));
1804fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell      predecessor->RemoveInstruction(last_instruction);
18053ecfd65143d95bd7c6cbe4f58c33af517d3761e0Yevgeny Rouban      predecessor->AddInstruction(new (graph_->GetArena()) HGoto(last_instruction->GetDexPc()));
1806fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell    } else if (num_pred_successors == 0u) {
18072d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      // The predecessor has no remaining successors and therefore must be dead.
18082d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      // We deliberately leave it without a control-flow instruction so that the
1809badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      // GraphChecker fails unless it is not removed during the pass too.
1810fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell      predecessor->RemoveInstruction(last_instruction);
1811fe57faa2e0349418dda38e77ef1c0ac29db75f4dMark Mendell    } else {
18128a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // There are multiple successors left. The removed block might be a successor
18138a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // of a PackedSwitch which will be completely removed (perhaps replaced with
18148a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // a Goto), or we are deleting a catch block from a TryBoundary. In either
18158a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      // case, leave `last_instruction` as is for now.
18168a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil      DCHECK(last_instruction->IsPackedSwitch() ||
18178a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil             (last_instruction->IsTryBoundary() && IsCatchBlock()));
18182d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
181946e2a3915aa68c77426b71e95b9f3658250646b7David Brazdil  }
18206058455d486219994921b63a2d774dc9908415a2Vladimir Marko  predecessors_.clear();
18212d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18229eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (5) Remove the block from all loops it is included in. Skip the inner-most
18239eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     loop if this is the loop header (see definition of `loop_update_start`)
18249eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  //     because the loop header's predecessor list has been destroyed in step (4).
18259eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  for (HLoopInformationOutwardIterator it(*loop_update_start); !it.Done(); it.Advance()) {
18269eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    HLoopInformation* loop_info = it.Current();
18279eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    loop_info->Remove(this);
18289eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil    if (loop_info->IsBackEdge(*this)) {
18299eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      // If this was the last back edge of the loop, we deliberately leave the
18309eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      // loop in an inconsistent state and will fail GraphChecker unless the
18319eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      // entire loop is removed during the pass.
18329eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil      loop_info->RemoveBackEdge(this);
18332d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
18342d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
18358a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil
18369eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (6) Disconnect from the dominator.
18372d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  dominator_->RemoveDominatedBlock(this);
18382d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  SetDominator(nullptr);
18392d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18409eeebf646b118269b3f5bd6fc6c1b0a58c26c6d4David Brazdil  // (7) Delete from the graph, update reverse post order.
18418a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil  graph_->DeleteDeadEmptyBlock(this);
18422d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  SetGraph(nullptr);
1843276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
1844276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1845276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffrayvoid HBasicBlock::MergeWith(HBasicBlock* other) {
18462d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK_EQ(GetGraph(), other->GetGraph());
18476058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(ContainsElement(dominated_blocks_, other));
18486058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK_EQ(GetSingleSuccessor(), other);
18496058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK_EQ(other->GetSinglePredecessor(), this);
1850276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  DCHECK(other->GetPhis().IsEmpty());
1851276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
18522d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Move instructions from `other` to `this`.
18532d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK(EndsWithControlFlowInstruction());
18542d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  RemoveInstruction(GetLastInstruction());
18552d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  instructions_.Add(other->GetInstructions());
18562d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  other->instructions_.SetBlockOfInstructions(this);
18572d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  other->instructions_.Clear();
18582d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18592d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Remove `other` from the loops it is included in.
18602d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  for (HLoopInformationOutwardIterator it(*other); !it.Done(); it.Advance()) {
18612d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    HLoopInformation* loop_info = it.Current();
18622d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    loop_info->Remove(other);
18632d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    if (loop_info->IsBackEdge(*other)) {
1864db216f4d49ea1561a74261c29f1264952232728aNicolas Geoffray      loop_info->ReplaceBackEdge(other, this);
18652d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
18662d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
18672d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18682d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Update links to the successors of `other`.
18696058455d486219994921b63a2d774dc9908415a2Vladimir Marko  successors_.clear();
18706058455d486219994921b63a2d774dc9908415a2Vladimir Marko  while (!other->successors_.empty()) {
1871ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* successor = other->GetSuccessors()[0];
18722d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    successor->ReplacePredecessor(other, this);
18732d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
18742d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18752d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Update the dominator tree.
18766058455d486219994921b63a2d774dc9908415a2Vladimir Marko  RemoveDominatedBlock(other);
18776058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
18786058455d486219994921b63a2d774dc9908415a2Vladimir Marko    dominated_blocks_.push_back(dominated);
18792d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    dominated->SetDominator(this);
18802d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
18816058455d486219994921b63a2d774dc9908415a2Vladimir Marko  other->dominated_blocks_.clear();
18822d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  other->dominator_ = nullptr;
18832d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18842d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Clear the list of predecessors of `other` in preparation of deleting it.
18856058455d486219994921b63a2d774dc9908415a2Vladimir Marko  other->predecessors_.clear();
18862d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18872d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Delete `other` from the graph. The function updates reverse post order.
18888a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil  graph_->DeleteDeadEmptyBlock(other);
18892d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  other->SetGraph(nullptr);
18902d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil}
18912d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
18922d7352ba5311b8f57427b91b7a891e61497373c1David Brazdilvoid HBasicBlock::MergeWithInlined(HBasicBlock* other) {
18932d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK_NE(GetGraph(), other->GetGraph());
18946058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(GetDominatedBlocks().empty());
18956058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(GetSuccessors().empty());
18962d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK(!EndsWithControlFlowInstruction());
18976058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(other->GetSinglePredecessor()->IsEntryBlock());
18982d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK(other->GetPhis().IsEmpty());
18992d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK(!other->IsInLoop());
19002d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
19012d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Move instructions from `other` to `this`.
1902276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  instructions_.Add(other->GetInstructions());
19032d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  other->instructions_.SetBlockOfInstructions(this);
1904276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
19052d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Update links to the successors of `other`.
19066058455d486219994921b63a2d774dc9908415a2Vladimir Marko  successors_.clear();
19076058455d486219994921b63a2d774dc9908415a2Vladimir Marko  while (!other->successors_.empty()) {
1908ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* successor = other->GetSuccessors()[0];
1909276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    successor->ReplacePredecessor(other, this);
1910276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
1911276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
19122d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  // Update the dominator tree.
19136058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
19146058455d486219994921b63a2d774dc9908415a2Vladimir Marko    dominated_blocks_.push_back(dominated);
1915276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    dominated->SetDominator(this);
1916276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
19176058455d486219994921b63a2d774dc9908415a2Vladimir Marko  other->dominated_blocks_.clear();
1918276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  other->dominator_ = nullptr;
1919276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  other->graph_ = nullptr;
1920276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
1921276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
1922276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffrayvoid HBasicBlock::ReplaceWith(HBasicBlock* other) {
19236058455d486219994921b63a2d774dc9908415a2Vladimir Marko  while (!GetPredecessors().empty()) {
1924ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* predecessor = GetPredecessors()[0];
1925276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    predecessor->ReplaceSuccessor(this, other);
1926276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
19276058455d486219994921b63a2d774dc9908415a2Vladimir Marko  while (!GetSuccessors().empty()) {
1928ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* successor = GetSuccessors()[0];
1929276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    successor->ReplacePredecessor(this, other);
1930276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
19316058455d486219994921b63a2d774dc9908415a2Vladimir Marko  for (HBasicBlock* dominated : GetDominatedBlocks()) {
19326058455d486219994921b63a2d774dc9908415a2Vladimir Marko    other->AddDominatedBlock(dominated);
1933276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  }
1934276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  GetDominator()->ReplaceDominatedBlock(this, other);
1935276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  other->SetDominator(GetDominator());
1936276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  dominator_ = nullptr;
1937276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray  graph_ = nullptr;
1938276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray}
1939276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
19408a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdilvoid HGraph::DeleteDeadEmptyBlock(HBasicBlock* block) {
19412d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK_EQ(block->GetGraph(), this);
19426058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(block->GetSuccessors().empty());
19436058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(block->GetPredecessors().empty());
19446058455d486219994921b63a2d774dc9908415a2Vladimir Marko  DCHECK(block->GetDominatedBlocks().empty());
19452d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  DCHECK(block->GetDominator() == nullptr);
19468a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil  DCHECK(block->GetInstructions().IsEmpty());
19478a7c0fe837bb00b02dfcfc678910d81d07fb2136David Brazdil  DCHECK(block->GetPhis().IsEmpty());
19482d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
1949c7af85dad0dc392cfc0b373b0c1cb4b4197c89f4David Brazdil  if (block->IsExitBlock()) {
19507ba9966b76bbf818513018fa1da72c89330fe384Serguei Katkov    SetExitBlock(nullptr);
1951c7af85dad0dc392cfc0b373b0c1cb4b4197c89f4David Brazdil  }
1952c7af85dad0dc392cfc0b373b0c1cb4b4197c89f4David Brazdil
1953fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  RemoveElement(reverse_post_order_, block);
1954fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  blocks_[block->GetBlockId()] = nullptr;
195586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  block->SetGraph(nullptr);
19562d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil}
19572d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
1958a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffrayvoid HGraph::UpdateLoopAndTryInformationOfNewBlock(HBasicBlock* block,
1959a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray                                                   HBasicBlock* reference,
1960a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray                                                   bool replace_if_back_edge) {
1961a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  if (block->IsLoopHeader()) {
1962a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    // Clear the information of which blocks are contained in that loop. Since the
1963a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    // information is stored as a bit vector based on block ids, we have to update
1964a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    // it, as those block ids were specific to the callee graph and we are now adding
1965a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    // these blocks to the caller graph.
1966a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    block->GetLoopInformation()->ClearAllBlocks();
1967a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  }
1968a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray
1969a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  // If not already in a loop, update the loop information.
1970a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  if (!block->IsInLoop()) {
1971a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    block->SetLoopInformation(reference->GetLoopInformation());
1972a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  }
1973a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray
1974a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  // If the block is in a loop, update all its outward loops.
1975a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  HLoopInformation* loop_info = block->GetLoopInformation();
1976a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  if (loop_info != nullptr) {
1977a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    for (HLoopInformationOutwardIterator loop_it(*block);
1978a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray         !loop_it.Done();
1979a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray         loop_it.Advance()) {
1980a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      loop_it.Current()->Add(block);
1981a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    }
1982a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    if (replace_if_back_edge && loop_info->IsBackEdge(*reference)) {
1983a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      loop_info->ReplaceBackEdge(reference, block);
1984a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    }
1985a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  }
1986a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray
1987a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  // Copy TryCatchInformation if `reference` is a try block, not if it is a catch block.
1988a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  TryCatchInformation* try_catch_info = reference->IsTryBlock()
1989a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      ? reference->GetTryCatchInformation()
1990a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      : nullptr;
1991a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  block->SetTryCatchInformation(try_catch_info);
1992a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray}
1993a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray
19942e76830f0b3f23825677436c0633714402715099Calin JuravleHInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
1995c7af85dad0dc392cfc0b373b0c1cb4b4197c89f4David Brazdil  DCHECK(HasExitBlock()) << "Unimplemented scenario";
1996d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  // Update the environments in this graph to have the invoke's environment
1997d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  // as parent.
1998d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  {
1999d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray    HReversePostOrderIterator it(*this);
2000d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray    it.Advance();  // Skip the entry block, we do not need to update the entry's suspend check.
2001d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray    for (; !it.Done(); it.Advance()) {
2002d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      HBasicBlock* block = it.Current();
2003d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      for (HInstructionIterator instr_it(block->GetInstructions());
2004d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray           !instr_it.Done();
2005d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray           instr_it.Advance()) {
2006d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray        HInstruction* current = instr_it.Current();
2007d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray        if (current->NeedsEnvironment()) {
2008dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil          DCHECK(current->HasEnvironment());
2009d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray          current->GetEnvironment()->SetAndCopyParentChain(
2010d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray              outer_graph->GetArena(), invoke->GetEnvironment());
2011d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray        }
2012d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      }
2013d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray    }
2014d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  }
2015d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  outer_graph->UpdateMaximumNumberOfOutVRegs(GetMaximumNumberOfOutVRegs());
2016d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  if (HasBoundsChecks()) {
2017d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray    outer_graph->SetHasBoundsChecks(true);
2018d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray  }
2019d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray
20202e76830f0b3f23825677436c0633714402715099Calin Juravle  HInstruction* return_value = nullptr;
2021fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  if (GetBlocks().size() == 3) {
2022be31ff94d66a0037c445eb57dc82f2a51bb46d9eNicolas Geoffray    // Simple case of an entry block, a body block, and an exit block.
2023be31ff94d66a0037c445eb57dc82f2a51bb46d9eNicolas Geoffray    // Put the body block's instruction into `invoke`'s block.
2024ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* body = GetBlocks()[1];
2025ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    DCHECK(GetBlocks()[0]->IsEntryBlock());
2026ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    DCHECK(GetBlocks()[2]->IsExitBlock());
2027276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    DCHECK(!body->IsExitBlock());
2028788f2f05c3e5b0e5bda247b00e34f0094585546fNicolas Geoffray    DCHECK(!body->IsInLoop());
2029276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    HInstruction* last = body->GetLastInstruction();
2030276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2031916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    // Note that we add instructions before the invoke only to simplify polymorphic inlining.
2032916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    invoke->GetBlock()->instructions_.AddBefore(invoke, body->GetInstructions());
2033276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    body->GetInstructions().SetBlockOfInstructions(invoke->GetBlock());
2034276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2035276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // Replace the invoke with the return value of the inlined graph.
2036276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    if (last->IsReturn()) {
20372e76830f0b3f23825677436c0633714402715099Calin Juravle      return_value = last->InputAt(0);
2038276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    } else {
2039276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray      DCHECK(last->IsReturnVoid());
2040e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray    }
2041e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray
2042276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    invoke->GetBlock()->RemoveInstruction(last);
2043e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  } else {
2044276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // Need to inline multiple blocks. We split `invoke`'s block
2045276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // into two blocks, merge the first block of the inlined graph into
2046be31ff94d66a0037c445eb57dc82f2a51bb46d9eNicolas Geoffray    // the first half, and replace the exit block of the inlined graph
2047276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // with the second half.
2048276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    ArenaAllocator* allocator = outer_graph->GetArena();
2049276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    HBasicBlock* at = invoke->GetBlock();
2050916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    // Note that we split before the invoke only to simplify polymorphic inlining.
2051916cc1d504f10a24f43b384e035fdecbe6a74b4cNicolas Geoffray    HBasicBlock* to = at->SplitBeforeForInlining(invoke);
2052276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2053ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HBasicBlock* first = entry_block_->GetSuccessors()[0];
2054276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    DCHECK(!first->IsInLoop());
20552d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    at->MergeWithInlined(first);
2056276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    exit_block_->ReplaceWith(to);
2057276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2058276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // Update the meta information surrounding blocks:
2059276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // (1) the graph they are now in,
2060276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // (2) the reverse post order of that graph,
2061788f2f05c3e5b0e5bda247b00e34f0094585546fNicolas Geoffray    // (3) their potential loop information, inner and outer,
2062951779839f0d35ed5336f399c8f521fd9a6b7c27David Brazdil    // (4) try block membership.
206359a850ee63a637660599f215901058b059f3a4b4David Brazdil    // Note that we do not need to update catch phi inputs because they
206459a850ee63a637660599f215901058b059f3a4b4David Brazdil    // correspond to the register file of the outer method which the inlinee
206559a850ee63a637660599f215901058b059f3a4b4David Brazdil    // cannot modify.
2066276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2067276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // We don't add the entry block, the exit block, and the first block, which
2068276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // has been merged with `at`.
2069276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    static constexpr int kNumberOfSkippedBlocksInCallee = 3;
2070276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2071276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // We add the `to` block.
2072276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    static constexpr int kNumberOfNewBlocksInCaller = 1;
2073fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko    size_t blocks_added = (reverse_post_order_.size() - kNumberOfSkippedBlocksInCallee)
2074276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray        + kNumberOfNewBlocksInCaller;
2075276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2076276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // Find the location of `at` in the outer graph's reverse post order. The new
2077276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    // blocks will be added after it.
2078fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko    size_t index_of_at = IndexOfElement(outer_graph->reverse_post_order_, at);
2079276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    MakeRoomFor(&outer_graph->reverse_post_order_, blocks_added, index_of_at);
2080276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2081951779839f0d35ed5336f399c8f521fd9a6b7c27David Brazdil    // Do a reverse post order of the blocks in the callee and do (1), (2), (3)
2082951779839f0d35ed5336f399c8f521fd9a6b7c27David Brazdil    // and (4) to the blocks that apply.
2083276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
2084276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray      HBasicBlock* current = it.Current();
2085276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray      if (current != exit_block_ && current != entry_block_ && current != first) {
2086951779839f0d35ed5336f399c8f521fd9a6b7c27David Brazdil        DCHECK(current->GetTryCatchInformation() == nullptr);
2087276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray        DCHECK(current->GetGraph() == this);
2088276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray        current->SetGraph(outer_graph);
2089276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray        outer_graph->AddBlock(current);
2090fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko        outer_graph->reverse_post_order_[++index_of_at] = current;
2091a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray        UpdateLoopAndTryInformationOfNewBlock(current, at,  /* replace_if_back_edge */ false);
2092276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray      }
2093276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    }
2094276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray
2095951779839f0d35ed5336f399c8f521fd9a6b7c27David Brazdil    // Do (1), (2), (3) and (4) to `to`.
2096276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    to->SetGraph(outer_graph);
2097276d9daaedfbff716339f94d55e6eff98b7434c6Nicolas Geoffray    outer_graph->AddBlock(to);
2098fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko    outer_graph->reverse_post_order_[++index_of_at] = to;
2099a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    // Only `to` can become a back edge, as the inlined blocks
2100a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    // are predecessors of `to`.
2101a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray    UpdateLoopAndTryInformationOfNewBlock(to, at, /* replace_if_back_edge */ true);
21027c5367badfe61b96c5836d495d286cee64861579Nicolas Geoffray
21033f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil    // Update all predecessors of the exit block (now the `to` block)
21043f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil    // to not `HReturn` but `HGoto` instead.
21053f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil    bool returns_void = to->GetPredecessors()[0]->GetLastInstruction()->IsReturnVoid();
21063f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil    if (to->GetPredecessors().size() == 1) {
21073f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      HBasicBlock* predecessor = to->GetPredecessors()[0];
21083f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      HInstruction* last = predecessor->GetLastInstruction();
21093f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      if (!returns_void) {
21103f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        return_value = last->InputAt(0);
21113f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      }
21123f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
21133f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      predecessor->RemoveInstruction(last);
21143f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil    } else {
21153f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      if (!returns_void) {
21163f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        // There will be multiple returns.
21173f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        return_value = new (allocator) HPhi(
21183f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil            allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()), to->GetDexPc());
21193f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        to->AddPhi(return_value->AsPhi());
21203f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      }
21213f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      for (HBasicBlock* predecessor : to->GetPredecessors()) {
21223f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        HInstruction* last = predecessor->GetLastInstruction();
21233f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        if (!returns_void) {
21243f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil          DCHECK(last->IsReturn());
21253f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil          return_value->AsPhi()->AddInput(last->InputAt(0));
21263f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        }
21273f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
21283f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil        predecessor->RemoveInstruction(last);
21293f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil      }
21303f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil    }
21313f52306b259caed1c654c4b3fd5b594d5ec8d46cDavid Brazdil  }
213205144f4322eed049f4878015bf1f0381d419b785David Brazdil
213305144f4322eed049f4878015bf1f0381d419b785David Brazdil  // Walk over the entry block and:
213405144f4322eed049f4878015bf1f0381d419b785David Brazdil  // - Move constants from the entry block to the outer_graph's entry block,
213505144f4322eed049f4878015bf1f0381d419b785David Brazdil  // - Replace HParameterValue instructions with their real value.
213605144f4322eed049f4878015bf1f0381d419b785David Brazdil  // - Remove suspend checks, that hold an environment.
213705144f4322eed049f4878015bf1f0381d419b785David Brazdil  // We must do this after the other blocks have been inlined, otherwise ids of
213805144f4322eed049f4878015bf1f0381d419b785David Brazdil  // constants could overlap with the inner graph.
21394c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain  size_t parameter_index = 0;
214005144f4322eed049f4878015bf1f0381d419b785David Brazdil  for (HInstructionIterator it(entry_block_->GetInstructions()); !it.Done(); it.Advance()) {
214105144f4322eed049f4878015bf1f0381d419b785David Brazdil    HInstruction* current = it.Current();
2142214bbcd1d7454197427c13cc082860619357d847Calin Juravle    HInstruction* replacement = nullptr;
214305144f4322eed049f4878015bf1f0381d419b785David Brazdil    if (current->IsNullConstant()) {
2144214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = outer_graph->GetNullConstant(current->GetDexPc());
214505144f4322eed049f4878015bf1f0381d419b785David Brazdil    } else if (current->IsIntConstant()) {
2146214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = outer_graph->GetIntConstant(
2147214bbcd1d7454197427c13cc082860619357d847Calin Juravle          current->AsIntConstant()->GetValue(), current->GetDexPc());
214805144f4322eed049f4878015bf1f0381d419b785David Brazdil    } else if (current->IsLongConstant()) {
2149214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = outer_graph->GetLongConstant(
2150214bbcd1d7454197427c13cc082860619357d847Calin Juravle          current->AsLongConstant()->GetValue(), current->GetDexPc());
2151f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray    } else if (current->IsFloatConstant()) {
2152214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = outer_graph->GetFloatConstant(
2153214bbcd1d7454197427c13cc082860619357d847Calin Juravle          current->AsFloatConstant()->GetValue(), current->GetDexPc());
2154f213e05cef6d38166cfe0cce8f3b0a53225a1b39Nicolas Geoffray    } else if (current->IsDoubleConstant()) {
2155214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = outer_graph->GetDoubleConstant(
2156214bbcd1d7454197427c13cc082860619357d847Calin Juravle          current->AsDoubleConstant()->GetValue(), current->GetDexPc());
215705144f4322eed049f4878015bf1f0381d419b785David Brazdil    } else if (current->IsParameterValue()) {
21584c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain      if (kIsDebugBuild
21594c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain          && invoke->IsInvokeStaticOrDirect()
21604c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain          && invoke->AsInvokeStaticOrDirect()->IsStaticWithExplicitClinitCheck()) {
21614c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain        // Ensure we do not use the last input of `invoke`, as it
21624c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain        // contains a clinit check which is not an actual argument.
21634c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain        size_t last_input_index = invoke->InputCount() - 1;
21644c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain        DCHECK(parameter_index != last_input_index);
21654c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain      }
2166214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = invoke->InputAt(parameter_index++);
216776b1e1799a713a19218de26b171b0aef48a59e98Nicolas Geoffray    } else if (current->IsCurrentMethod()) {
2168214bbcd1d7454197427c13cc082860619357d847Calin Juravle      replacement = outer_graph->GetCurrentMethod();
216905144f4322eed049f4878015bf1f0381d419b785David Brazdil    } else {
217005144f4322eed049f4878015bf1f0381d419b785David Brazdil      DCHECK(current->IsGoto() || current->IsSuspendCheck());
217105144f4322eed049f4878015bf1f0381d419b785David Brazdil      entry_block_->RemoveInstruction(current);
217205144f4322eed049f4878015bf1f0381d419b785David Brazdil    }
2173214bbcd1d7454197427c13cc082860619357d847Calin Juravle    if (replacement != nullptr) {
2174214bbcd1d7454197427c13cc082860619357d847Calin Juravle      current->ReplaceWith(replacement);
2175214bbcd1d7454197427c13cc082860619357d847Calin Juravle      // If the current is the return value then we need to update the latter.
2176214bbcd1d7454197427c13cc082860619357d847Calin Juravle      if (current == return_value) {
2177214bbcd1d7454197427c13cc082860619357d847Calin Juravle        DCHECK_EQ(entry_block_, return_value->GetBlock());
2178214bbcd1d7454197427c13cc082860619357d847Calin Juravle        return_value = replacement;
2179214bbcd1d7454197427c13cc082860619357d847Calin Juravle      }
2180214bbcd1d7454197427c13cc082860619357d847Calin Juravle    }
2181214bbcd1d7454197427c13cc082860619357d847Calin Juravle  }
2182214bbcd1d7454197427c13cc082860619357d847Calin Juravle
21832e76830f0b3f23825677436c0633714402715099Calin Juravle  return return_value;
2184e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray}
2185e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray
21863584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang/*
21873584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang * Loop will be transformed to:
21883584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *       old_pre_header
21893584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *             |
21903584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *          if_block
21913584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *           /    \
21923fc7f357170311689c4c31007a5e168ddea321d5Aart Bik *  true_block   false_block
21933584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *           \    /
21943584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *       new_pre_header
21953584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *             |
21963584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang *           header
21973584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang */
21983584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yangvoid HGraph::TransformLoopHeaderForBCE(HBasicBlock* header) {
21993584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  DCHECK(header->IsLoopHeader());
22003fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  HBasicBlock* old_pre_header = header->GetDominator();
22013584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang
22023fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  // Need extra block to avoid critical edge.
22033584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  HBasicBlock* if_block = new (arena_) HBasicBlock(this, header->GetDexPc());
22043fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  HBasicBlock* true_block = new (arena_) HBasicBlock(this, header->GetDexPc());
22053fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  HBasicBlock* false_block = new (arena_) HBasicBlock(this, header->GetDexPc());
22063584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  HBasicBlock* new_pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
22073584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  AddBlock(if_block);
22083fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  AddBlock(true_block);
22093fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  AddBlock(false_block);
22103584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  AddBlock(new_pre_header);
22113584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang
22123fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  header->ReplacePredecessor(old_pre_header, new_pre_header);
22133fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  old_pre_header->successors_.clear();
22143fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  old_pre_header->dominated_blocks_.clear();
22153fc7f357170311689c4c31007a5e168ddea321d5Aart Bik
22163fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  old_pre_header->AddSuccessor(if_block);
22173fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  if_block->AddSuccessor(true_block);  // True successor
22183fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  if_block->AddSuccessor(false_block);  // False successor
22193fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  true_block->AddSuccessor(new_pre_header);
22203fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  false_block->AddSuccessor(new_pre_header);
22213fc7f357170311689c4c31007a5e168ddea321d5Aart Bik
22223fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  old_pre_header->dominated_blocks_.push_back(if_block);
22233fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  if_block->SetDominator(old_pre_header);
22243fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  if_block->dominated_blocks_.push_back(true_block);
22253fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  true_block->SetDominator(if_block);
22263fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  if_block->dominated_blocks_.push_back(false_block);
22273fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  false_block->SetDominator(if_block);
22286058455d486219994921b63a2d774dc9908415a2Vladimir Marko  if_block->dominated_blocks_.push_back(new_pre_header);
22293584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  new_pre_header->SetDominator(if_block);
22306058455d486219994921b63a2d774dc9908415a2Vladimir Marko  new_pre_header->dominated_blocks_.push_back(header);
22313584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  header->SetDominator(new_pre_header);
22323584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang
22333fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  // Fix reverse post order.
2234fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  size_t index_of_header = IndexOfElement(reverse_post_order_, header);
22353584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang  MakeRoomFor(&reverse_post_order_, 4, index_of_header - 1);
2236fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  reverse_post_order_[index_of_header++] = if_block;
22373fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  reverse_post_order_[index_of_header++] = true_block;
22383fc7f357170311689c4c31007a5e168ddea321d5Aart Bik  reverse_post_order_[index_of_header++] = false_block;
2239fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  reverse_post_order_[index_of_header++] = new_pre_header;
22403584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang
2241a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  // The pre_header can never be a back edge of a loop.
2242a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  DCHECK((old_pre_header->GetLoopInformation() == nullptr) ||
2243a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray         !old_pre_header->GetLoopInformation()->IsBackEdge(*old_pre_header));
2244a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  UpdateLoopAndTryInformationOfNewBlock(
2245a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      if_block, old_pre_header, /* replace_if_back_edge */ false);
2246a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  UpdateLoopAndTryInformationOfNewBlock(
2247a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      true_block, old_pre_header, /* replace_if_back_edge */ false);
2248a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  UpdateLoopAndTryInformationOfNewBlock(
2249a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      false_block, old_pre_header, /* replace_if_back_edge */ false);
2250a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray  UpdateLoopAndTryInformationOfNewBlock(
2251a1d8ddfaf09545f99bc326dff97ab604d4574eb6Nicolas Geoffray      new_pre_header, old_pre_header, /* replace_if_back_edge */ false);
22523584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang}
22533584bce5b1f45e5741d3a6ca24884a36320ecb6bMingyao Yang
2254f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdilstatic void CheckAgainstUpperBound(ReferenceTypeInfo rti, ReferenceTypeInfo upper_bound_rti)
2255f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    SHARED_REQUIRES(Locks::mutator_lock_) {
2256f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (rti.IsValid()) {
2257f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    DCHECK(upper_bound_rti.IsSupertypeOf(rti))
2258f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil        << " upper_bound_rti: " << upper_bound_rti
2259f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil        << " rti: " << rti;
226018401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    DCHECK(!upper_bound_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes() || rti.IsExact())
226118401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray        << " upper_bound_rti: " << upper_bound_rti
226218401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray        << " rti: " << rti;
2263f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  }
2264f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil}
2265f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil
22662e76830f0b3f23825677436c0633714402715099Calin Juravlevoid HInstruction::SetReferenceTypeInfo(ReferenceTypeInfo rti) {
22672e76830f0b3f23825677436c0633714402715099Calin Juravle  if (kIsDebugBuild) {
22682e76830f0b3f23825677436c0633714402715099Calin Juravle    DCHECK_EQ(GetType(), Primitive::kPrimNot);
22692e76830f0b3f23825677436c0633714402715099Calin Juravle    ScopedObjectAccess soa(Thread::Current());
22702e76830f0b3f23825677436c0633714402715099Calin Juravle    DCHECK(rti.IsValid()) << "Invalid RTI for " << DebugName();
22712e76830f0b3f23825677436c0633714402715099Calin Juravle    if (IsBoundType()) {
22722e76830f0b3f23825677436c0633714402715099Calin Juravle      // Having the test here spares us from making the method virtual just for
22732e76830f0b3f23825677436c0633714402715099Calin Juravle      // the sake of a DCHECK.
2274f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil      CheckAgainstUpperBound(rti, AsBoundType()->GetUpperBound());
22752e76830f0b3f23825677436c0633714402715099Calin Juravle    }
22762e76830f0b3f23825677436c0633714402715099Calin Juravle  }
2277a1de9188a05afdecca8cd04ecc4fefbac8b9880fVladimir Marko  reference_type_handle_ = rti.GetTypeHandle();
2278a1de9188a05afdecca8cd04ecc4fefbac8b9880fVladimir Marko  SetPackedFlag<kFlagReferenceTypeIsExact>(rti.IsExact());
22792e76830f0b3f23825677436c0633714402715099Calin Juravle}
22802e76830f0b3f23825677436c0633714402715099Calin Juravle
2281f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdilvoid HBoundType::SetUpperBound(const ReferenceTypeInfo& upper_bound, bool can_be_null) {
2282f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (kIsDebugBuild) {
2283f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    ScopedObjectAccess soa(Thread::Current());
2284f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    DCHECK(upper_bound.IsValid());
2285f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    DCHECK(!upper_bound_.IsValid()) << "Upper bound should only be set once.";
2286f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    CheckAgainstUpperBound(GetReferenceTypeInfo(), upper_bound);
2287f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  }
2288f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  upper_bound_ = upper_bound;
2289a1de9188a05afdecca8cd04ecc4fefbac8b9880fVladimir Marko  SetPackedFlag<kFlagUpperCanBeNull>(can_be_null);
2290f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil}
2291f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil
2292a1de9188a05afdecca8cd04ecc4fefbac8b9880fVladimir MarkoReferenceTypeInfo ReferenceTypeInfo::Create(TypeHandle type_handle, bool is_exact) {
22932e76830f0b3f23825677436c0633714402715099Calin Juravle  if (kIsDebugBuild) {
22942e76830f0b3f23825677436c0633714402715099Calin Juravle    ScopedObjectAccess soa(Thread::Current());
22952e76830f0b3f23825677436c0633714402715099Calin Juravle    DCHECK(IsValidHandle(type_handle));
229618401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    if (!is_exact) {
229718401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray      DCHECK(!type_handle->CannotBeAssignedFromOtherTypes())
229818401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray          << "Callers of ReferenceTypeInfo::Create should ensure is_exact is properly computed";
229918401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    }
23002e76830f0b3f23825677436c0633714402715099Calin Juravle  }
2301a1de9188a05afdecca8cd04ecc4fefbac8b9880fVladimir Marko  return ReferenceTypeInfo(type_handle, is_exact);
23022e76830f0b3f23825677436c0633714402715099Calin Juravle}
23032e76830f0b3f23825677436c0633714402715099Calin Juravle
2304acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravlestd::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs) {
2305acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  ScopedObjectAccess soa(Thread::Current());
2306acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  os << "["
23072e76830f0b3f23825677436c0633714402715099Calin Juravle     << " is_valid=" << rhs.IsValid()
23082e76830f0b3f23825677436c0633714402715099Calin Juravle     << " type=" << (!rhs.IsValid() ? "?" : PrettyClass(rhs.GetTypeHandle().Get()))
2309acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle     << " is_exact=" << rhs.IsExact()
2310acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle     << " ]";
2311acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  return os;
2312acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle}
2313acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
2314c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellbool HInstruction::HasAnyEnvironmentUseBefore(HInstruction* other) {
2315c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // For now, assume that instructions in different blocks may use the
2316c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // environment.
2317c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // TODO: Use the control flow to decide if this is true.
2318c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  if (GetBlock() != other->GetBlock()) {
2319c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell    return true;
2320c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  }
2321c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell
2322c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // We know that we are in the same block. Walk from 'this' to 'other',
2323c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // checking to see if there is any instruction with an environment.
2324c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  HInstruction* current = this;
2325c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  for (; current != other && current != nullptr; current = current->GetNext()) {
2326c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell    // This is a conservative check, as the instruction result may not be in
2327c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell    // the referenced environment.
2328c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell    if (current->HasEnvironment()) {
2329c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell      return true;
2330c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell    }
2331c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  }
2332c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell
2333c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // We should have been called with 'this' before 'other' in the block.
2334c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  // Just confirm this.
2335c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  DCHECK(current != nullptr);
2336c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  return false;
2337c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell}
2338c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell
2339a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayvoid HInvoke::SetIntrinsic(Intrinsics intrinsic,
23405d75afe333f57546786686d9bee16b52f1bbe971Aart Bik                           IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
23415d75afe333f57546786686d9bee16b52f1bbe971Aart Bik                           IntrinsicSideEffects side_effects,
23425d75afe333f57546786686d9bee16b52f1bbe971Aart Bik                           IntrinsicExceptions exceptions) {
2343a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  intrinsic_ = intrinsic;
2344a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  IntrinsicOptimizations opt(this);
2345a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray
23465d75afe333f57546786686d9bee16b52f1bbe971Aart Bik  // Adjust method's side effects from intrinsic table.
23475d75afe333f57546786686d9bee16b52f1bbe971Aart Bik  switch (side_effects) {
23485d75afe333f57546786686d9bee16b52f1bbe971Aart Bik    case kNoSideEffects: SetSideEffects(SideEffects::None()); break;
23495d75afe333f57546786686d9bee16b52f1bbe971Aart Bik    case kReadSideEffects: SetSideEffects(SideEffects::AllReads()); break;
23505d75afe333f57546786686d9bee16b52f1bbe971Aart Bik    case kWriteSideEffects: SetSideEffects(SideEffects::AllWrites()); break;
23515d75afe333f57546786686d9bee16b52f1bbe971Aart Bik    case kAllSideEffects: SetSideEffects(SideEffects::AllExceptGCDependency()); break;
23525d75afe333f57546786686d9bee16b52f1bbe971Aart Bik  }
2353a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray
2354a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray  if (needs_env_or_cache == kNoEnvironmentOrCache) {
2355a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray    opt.SetDoesNotNeedDexCache();
2356a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray    opt.SetDoesNotNeedEnvironment();
2357a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray  } else {
2358a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray    // If we need an environment, that means there will be a call, which can trigger GC.
2359a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray    SetSideEffects(GetSideEffects().Union(SideEffects::CanTriggerGC()));
2360a3eca2d7300f35c66cf4b696d788a8b7ba74eb99Nicolas Geoffray  }
23615d75afe333f57546786686d9bee16b52f1bbe971Aart Bik  // Adjust method's exception status from intrinsic table.
236209e8d5ffe52c738c6a74984b1cbc7ad4bc8f5e2cAart Bik  SetCanThrow(exceptions == kCanThrow);
2363a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}
2364a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray
23656de1938e562b0d06e462512dd806166e754035eaDavid Brazdilbool HNewInstance::IsStringAlloc() const {
23666de1938e562b0d06e462512dd806166e754035eaDavid Brazdil  ScopedObjectAccess soa(Thread::Current());
23676de1938e562b0d06e462512dd806166e754035eaDavid Brazdil  return GetReferenceTypeInfo().IsStringClass();
23686de1938e562b0d06e462512dd806166e754035eaDavid Brazdil}
23696de1938e562b0d06e462512dd806166e754035eaDavid Brazdil
2370a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffraybool HInvoke::NeedsEnvironment() const {
2371a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  if (!IsIntrinsic()) {
2372a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray    return true;
2373a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  }
2374a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  IntrinsicOptimizations opt(*this);
2375a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  return !opt.GetDoesNotNeedEnvironment();
2376a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}
2377a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray
2378dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Markobool HInvokeStaticOrDirect::NeedsDexCacheOfDeclaringClass() const {
2379dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  if (GetMethodLoadKind() != MethodLoadKind::kDexCacheViaMethod) {
2380a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray    return false;
2381a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  }
2382a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  if (!IsIntrinsic()) {
2383a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray    return true;
2384a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  }
2385a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  IntrinsicOptimizations opt(*this);
2386a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray  return !opt.GetDoesNotNeedDexCache();
2387a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}
2388a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray
23890f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Markovoid HInvokeStaticOrDirect::InsertInputAt(size_t index, HInstruction* input) {
23900f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  inputs_.insert(inputs_.begin() + index, HUserRecord<HInstruction*>(input));
23910f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  input->AddUseAt(this, index);
23920f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  // Update indexes in use nodes of inputs that have been pushed further back by the insert().
23930f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  for (size_t i = index + 1u, size = inputs_.size(); i != size; ++i) {
23940f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    DCHECK_EQ(InputRecordAt(i).GetUseNode()->GetIndex(), i - 1u);
23950f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    InputRecordAt(i).GetUseNode()->SetIndex(i);
23960f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  }
23970f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko}
23980f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko
2399b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Markovoid HInvokeStaticOrDirect::RemoveInputAt(size_t index) {
2400b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko  RemoveAsUserOfInput(index);
2401b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko  inputs_.erase(inputs_.begin() + index);
2402b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko  // Update indexes in use nodes of inputs that have been pulled forward by the erase().
2403b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko  for (size_t i = index, e = InputCount(); i < e; ++i) {
2404b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko    DCHECK_EQ(InputRecordAt(i).GetUseNode()->GetIndex(), i + 1u);
2405b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko    InputRecordAt(i).GetUseNode()->SetIndex(i);
2406b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko  }
2407b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko}
2408b554b5a5ae3cdc66969d61be20783a8af816206eVladimir Marko
2409f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Markostd::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs) {
2410f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko  switch (rhs) {
2411f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit:
2412f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      return os << "string_init";
2413f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
2414f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      return os << "recursive";
2415f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
2416f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      return os << "direct";
2417f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup:
2418f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      return os << "direct_fixup";
2419f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative:
2420f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      return os << "dex_cache_pc_relative";
2421f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod:
2422f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      return os << "dex_cache_via_method";
2423f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko    default:
2424f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      LOG(FATAL) << "Unknown MethodLoadKind: " << static_cast<int>(rhs);
2425f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      UNREACHABLE();
2426f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko  }
2427f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko}
2428f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko
2429fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Markostd::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs) {
2430fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  switch (rhs) {
2431fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    case HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit:
2432fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      return os << "explicit";
2433fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    case HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit:
2434fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      return os << "implicit";
2435fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    case HInvokeStaticOrDirect::ClinitCheckRequirement::kNone:
2436fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      return os << "none";
2437fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    default:
2438f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      LOG(FATAL) << "Unknown ClinitCheckRequirement: " << static_cast<int>(rhs);
2439f64242a30c6e05a8e4302a64eab4bcc28297dc9eVladimir Marko      UNREACHABLE();
2440fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
2441fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko}
2442fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
2443cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markobool HLoadString::InstructionDataEquals(HInstruction* other) const {
2444cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  HLoadString* other_load_string = other->AsLoadString();
2445cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  if (string_index_ != other_load_string->string_index_ ||
2446cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      GetPackedFields() != other_load_string->GetPackedFields()) {
2447cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    return false;
2448cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
2449cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  LoadKind load_kind = GetLoadKind();
2450cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  if (HasAddress(load_kind)) {
2451cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    return GetAddress() == other_load_string->GetAddress();
2452cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  } else if (HasStringReference(load_kind)) {
2453cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    return IsSameDexFile(GetDexFile(), other_load_string->GetDexFile());
2454cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  } else {
2455cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    DCHECK(HasDexCacheReference(load_kind)) << load_kind;
2456cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    // If the string indexes and dex files are the same, dex cache element offsets
2457cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    // must also be the same, so we don't need to compare them.
2458cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    return IsSameDexFile(GetDexFile(), other_load_string->GetDexFile());
2459cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
2460cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
2461cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
2462cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markovoid HLoadString::SetLoadKindInternal(LoadKind load_kind) {
2463cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Once sharpened, the load kind should not be changed again.
2464cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  DCHECK_EQ(GetLoadKind(), LoadKind::kDexCacheViaMethod);
2465cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  SetPackedField<LoadKindField>(load_kind);
2466cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
2467cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  if (load_kind != LoadKind::kDexCacheViaMethod) {
2468cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    RemoveAsUserOfInput(0u);
2469cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    SetRawInputAt(0u, nullptr);
2470cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
2471cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  if (!NeedsEnvironment()) {
2472cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    RemoveEnvironment();
2473bf12e4d4209ac4e8fb98b4fd5193208adc7fe3ffVladimir Marko    SetSideEffects(SideEffects::None());
2474cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
2475cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
2476cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
2477cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markostd::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs) {
2478cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  switch (rhs) {
2479cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    case HLoadString::LoadKind::kBootImageLinkTimeAddress:
2480cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return os << "BootImageLinkTimeAddress";
2481cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
2482cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return os << "BootImageLinkTimePcRelative";
2483cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    case HLoadString::LoadKind::kBootImageAddress:
2484cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return os << "BootImageAddress";
2485cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    case HLoadString::LoadKind::kDexCacheAddress:
2486cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return os << "DexCacheAddress";
2487cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    case HLoadString::LoadKind::kDexCachePcRelative:
2488cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return os << "DexCachePcRelative";
2489cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    case HLoadString::LoadKind::kDexCacheViaMethod:
2490cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return os << "DexCacheViaMethod";
2491cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    default:
2492cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      LOG(FATAL) << "Unknown HLoadString::LoadKind: " << static_cast<int>(rhs);
2493cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      UNREACHABLE();
2494cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
2495cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
2496cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
2497c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellvoid HInstruction::RemoveEnvironmentUsers() {
2498d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (const HUseListNode<HEnvironment*>& use : GetEnvUses()) {
2499d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HEnvironment* user = use.GetUser();
2500d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    user->SetRawEnvAt(use.GetIndex(), nullptr);
2501c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell  }
2502d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  env_uses_.clear();
2503c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell}
2504c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell
2505c9b21f83c2eab8bdd16241992193c3049dc68e43Roland Levillain// Returns an instruction with the opposite Boolean value from 'cond'.
2506f652917de5634b30c974c81d35a72871915b352aMark MendellHInstruction* HGraph::InsertOppositeCondition(HInstruction* cond, HInstruction* cursor) {
2507f652917de5634b30c974c81d35a72871915b352aMark Mendell  ArenaAllocator* allocator = GetArena();
2508f652917de5634b30c974c81d35a72871915b352aMark Mendell
2509f652917de5634b30c974c81d35a72871915b352aMark Mendell  if (cond->IsCondition() &&
2510f652917de5634b30c974c81d35a72871915b352aMark Mendell      !Primitive::IsFloatingPointType(cond->InputAt(0)->GetType())) {
2511f652917de5634b30c974c81d35a72871915b352aMark Mendell    // Can't reverse floating point conditions.  We have to use HBooleanNot in that case.
2512f652917de5634b30c974c81d35a72871915b352aMark Mendell    HInstruction* lhs = cond->InputAt(0);
2513f652917de5634b30c974c81d35a72871915b352aMark Mendell    HInstruction* rhs = cond->InputAt(1);
25145c0048565e78ff53fd2b3a2e446c72ea2fffe239David Brazdil    HInstruction* replacement = nullptr;
2515f652917de5634b30c974c81d35a72871915b352aMark Mendell    switch (cond->AsCondition()->GetOppositeCondition()) {  // get *opposite*
2516f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondEQ: replacement = new (allocator) HEqual(lhs, rhs); break;
2517f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondNE: replacement = new (allocator) HNotEqual(lhs, rhs); break;
2518f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondLT: replacement = new (allocator) HLessThan(lhs, rhs); break;
2519f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondLE: replacement = new (allocator) HLessThanOrEqual(lhs, rhs); break;
2520f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondGT: replacement = new (allocator) HGreaterThan(lhs, rhs); break;
2521f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondGE: replacement = new (allocator) HGreaterThanOrEqual(lhs, rhs); break;
2522f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondB:  replacement = new (allocator) HBelow(lhs, rhs); break;
2523f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondBE: replacement = new (allocator) HBelowOrEqual(lhs, rhs); break;
2524f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondA:  replacement = new (allocator) HAbove(lhs, rhs); break;
2525f652917de5634b30c974c81d35a72871915b352aMark Mendell      case kCondAE: replacement = new (allocator) HAboveOrEqual(lhs, rhs); break;
25265c0048565e78ff53fd2b3a2e446c72ea2fffe239David Brazdil      default:
25275c0048565e78ff53fd2b3a2e446c72ea2fffe239David Brazdil        LOG(FATAL) << "Unexpected condition";
25285c0048565e78ff53fd2b3a2e446c72ea2fffe239David Brazdil        UNREACHABLE();
2529f652917de5634b30c974c81d35a72871915b352aMark Mendell    }
2530f652917de5634b30c974c81d35a72871915b352aMark Mendell    cursor->GetBlock()->InsertInstructionBefore(replacement, cursor);
2531f652917de5634b30c974c81d35a72871915b352aMark Mendell    return replacement;
2532f652917de5634b30c974c81d35a72871915b352aMark Mendell  } else if (cond->IsIntConstant()) {
2533f652917de5634b30c974c81d35a72871915b352aMark Mendell    HIntConstant* int_const = cond->AsIntConstant();
25341a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain    if (int_const->IsFalse()) {
2535f652917de5634b30c974c81d35a72871915b352aMark Mendell      return GetIntConstant(1);
2536f652917de5634b30c974c81d35a72871915b352aMark Mendell    } else {
25371a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain      DCHECK(int_const->IsTrue()) << int_const->GetValue();
2538f652917de5634b30c974c81d35a72871915b352aMark Mendell      return GetIntConstant(0);
2539f652917de5634b30c974c81d35a72871915b352aMark Mendell    }
2540f652917de5634b30c974c81d35a72871915b352aMark Mendell  } else {
2541f652917de5634b30c974c81d35a72871915b352aMark Mendell    HInstruction* replacement = new (allocator) HBooleanNot(cond);
2542f652917de5634b30c974c81d35a72871915b352aMark Mendell    cursor->GetBlock()->InsertInstructionBefore(replacement, cursor);
2543f652917de5634b30c974c81d35a72871915b352aMark Mendell    return replacement;
2544f652917de5634b30c974c81d35a72871915b352aMark Mendell  }
2545f652917de5634b30c974c81d35a72871915b352aMark Mendell}
2546f652917de5634b30c974c81d35a72871915b352aMark Mendell
2547c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillainstd::ostream& operator<<(std::ostream& os, const MoveOperands& rhs) {
2548c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain  os << "["
2549c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain     << " source=" << rhs.GetSource()
2550c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain     << " destination=" << rhs.GetDestination()
2551c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain     << " type=" << rhs.GetType()
2552c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain     << " instruction=";
2553c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain  if (rhs.GetInstruction() != nullptr) {
2554c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain    os << rhs.GetInstruction()->DebugName() << ' ' << rhs.GetInstruction()->GetId();
2555c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain  } else {
2556c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain    os << "null";
2557c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain  }
2558c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain  os << " ]";
2559c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain  return os;
2560c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain}
2561c928591f5b2c544751bb3fb26dc614d3c2e67befRoland Levillain
256286503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillainstd::ostream& operator<<(std::ostream& os, TypeCheckKind rhs) {
256386503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain  switch (rhs) {
256486503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kUnresolvedCheck:
256586503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "unresolved_check";
256686503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kExactCheck:
256786503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "exact_check";
256886503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kClassHierarchyCheck:
256986503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "class_hierarchy_check";
257086503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kAbstractClassCheck:
257186503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "abstract_class_check";
257286503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kInterfaceCheck:
257386503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "interface_check";
257486503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kArrayObjectCheck:
257586503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "array_object_check";
257686503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    case TypeCheckKind::kArrayCheck:
257786503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      return os << "array_check";
257886503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain    default:
257986503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      LOG(FATAL) << "Unknown TypeCheckKind: " << static_cast<int>(rhs);
258086503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain      UNREACHABLE();
258186503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain  }
258286503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain}
258386503785cd6414b8692e5c83cadaa2972b6a099bRoland Levillain
2584818f2107e6d2d9e80faac8ae8c92faffa83cbd11Nicolas Geoffray}  // namespace art
2585