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