blob: 989970fb49d8a1c4db83bf79990cf3e45ed75c26 [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "nodes.h"
Calin Juravle77520bc2015-01-12 18:45:46 +000018
Mark Mendelle82549b2015-05-06 10:55:34 -040019#include "code_generator.h"
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010020#include "ssa_builder.h"
David Brazdila4b8c212015-05-07 09:59:30 +010021#include "base/bit_vector-inl.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010022#include "base/bit_utils.h"
Vladimir Marko1f8695c2015-09-24 13:11:31 +010023#include "base/stl_util.h"
David Brazdilbaf89b82015-09-15 11:36:54 +010024#include "mirror/class-inl.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000025#include "scoped_thread_state_change.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000026
27namespace art {
28
29void HGraph::AddBlock(HBasicBlock* block) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010030 block->SetBlockId(blocks_.size());
31 blocks_.push_back(block);
Nicolas Geoffray818f2102014-02-18 16:43:35 +000032}
33
Nicolas Geoffray804d0932014-05-02 08:46:00 +010034void HGraph::FindBackEdges(ArenaBitVector* visited) {
Vladimir Marko1f8695c2015-09-24 13:11:31 +010035 // "visited" must be empty on entry, it's an output argument for all visited (i.e. live) blocks.
36 DCHECK_EQ(visited->GetHighestBitSet(), -1);
37
38 // Nodes that we're currently visiting, indexed by block id.
Vladimir Markofa6b93c2015-09-15 10:15:55 +010039 ArenaBitVector visiting(arena_, blocks_.size(), false);
Vladimir Marko1f8695c2015-09-24 13:11:31 +010040 // Number of successors visited from a given node, indexed by block id.
41 ArenaVector<size_t> successors_visited(blocks_.size(), 0u, arena_->Adapter());
42 // Stack of nodes that we're currently visiting (same as marked in "visiting" above).
43 ArenaVector<HBasicBlock*> worklist(arena_->Adapter());
44 constexpr size_t kDefaultWorklistSize = 8;
45 worklist.reserve(kDefaultWorklistSize);
46 visited->SetBit(entry_block_->GetBlockId());
47 visiting.SetBit(entry_block_->GetBlockId());
48 worklist.push_back(entry_block_);
49
50 while (!worklist.empty()) {
51 HBasicBlock* current = worklist.back();
52 uint32_t current_id = current->GetBlockId();
53 if (successors_visited[current_id] == current->GetSuccessors().size()) {
54 visiting.ClearBit(current_id);
55 worklist.pop_back();
56 } else {
57 DCHECK_LT(successors_visited[current_id], current->GetSuccessors().size());
58 HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++];
59 uint32_t successor_id = successor->GetBlockId();
60 if (visiting.IsBitSet(successor_id)) {
61 DCHECK(ContainsElement(worklist, successor));
62 successor->AddBackEdge(current);
63 } else if (!visited->IsBitSet(successor_id)) {
64 visited->SetBit(successor_id);
65 visiting.SetBit(successor_id);
66 worklist.push_back(successor);
67 }
68 }
69 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000070}
71
Roland Levillainfc600dc2014-12-02 17:16:31 +000072static void RemoveAsUser(HInstruction* instruction) {
73 for (size_t i = 0; i < instruction->InputCount(); i++) {
David Brazdil1abb4192015-02-17 18:33:36 +000074 instruction->RemoveAsUserOfInput(i);
Roland Levillainfc600dc2014-12-02 17:16:31 +000075 }
76
Nicolas Geoffray0a23d742015-05-07 11:57:35 +010077 for (HEnvironment* environment = instruction->GetEnvironment();
78 environment != nullptr;
79 environment = environment->GetParent()) {
Roland Levillainfc600dc2014-12-02 17:16:31 +000080 for (size_t i = 0, e = environment->Size(); i < e; ++i) {
David Brazdil1abb4192015-02-17 18:33:36 +000081 if (environment->GetInstructionAt(i) != nullptr) {
82 environment->RemoveAsUserOfInput(i);
Roland Levillainfc600dc2014-12-02 17:16:31 +000083 }
84 }
85 }
86}
87
88void HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010089 for (size_t i = 0; i < blocks_.size(); ++i) {
Roland Levillainfc600dc2014-12-02 17:16:31 +000090 if (!visited.IsBitSet(i)) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010091 HBasicBlock* block = GetBlock(i);
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010092 DCHECK(block->GetPhis().IsEmpty()) << "Phis are not inserted at this stage";
Roland Levillainfc600dc2014-12-02 17:16:31 +000093 for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
94 RemoveAsUser(it.Current());
95 }
96 }
97 }
98}
99
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100100void HGraph::RemoveDeadBlocks(const ArenaBitVector& visited) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100101 for (size_t i = 0; i < blocks_.size(); ++i) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000102 if (!visited.IsBitSet(i)) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100103 HBasicBlock* block = GetBlock(i);
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100104 // We only need to update the successor, which might be live.
Vladimir Marko60584552015-09-03 13:35:12 +0000105 for (HBasicBlock* successor : block->GetSuccessors()) {
106 successor->RemovePredecessor(block);
David Brazdil1abb4192015-02-17 18:33:36 +0000107 }
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100108 // Remove the block from the list of blocks, so that further analyses
109 // never see it.
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100110 blocks_[i] = nullptr;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000111 }
112 }
113}
114
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000115void HGraph::BuildDominatorTree() {
David Brazdilffee3d32015-07-06 11:48:53 +0100116 // (1) Simplify the CFG so that catch blocks have only exceptional incoming
117 // edges. This invariant simplifies building SSA form because Phis cannot
118 // collect both normal- and exceptional-flow values at the same time.
119 SimplifyCatchBlocks();
120
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100121 ArenaBitVector visited(arena_, blocks_.size(), false);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000122
David Brazdilffee3d32015-07-06 11:48:53 +0100123 // (2) Find the back edges in the graph doing a DFS traversal.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000124 FindBackEdges(&visited);
125
David Brazdilffee3d32015-07-06 11:48:53 +0100126 // (3) Remove instructions and phis from blocks not visited during
Roland Levillainfc600dc2014-12-02 17:16:31 +0000127 // the initial DFS as users from other instructions, so that
128 // users can be safely removed before uses later.
129 RemoveInstructionsAsUsersFromDeadBlocks(visited);
130
David Brazdilffee3d32015-07-06 11:48:53 +0100131 // (4) Remove blocks not visited during the initial DFS.
Roland Levillainfc600dc2014-12-02 17:16:31 +0000132 // Step (4) requires dead blocks to be removed from the
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000133 // predecessors list of live blocks.
134 RemoveDeadBlocks(visited);
135
David Brazdilffee3d32015-07-06 11:48:53 +0100136 // (5) Simplify the CFG now, so that we don't need to recompute
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100137 // dominators and the reverse post order.
138 SimplifyCFG();
139
David Brazdilffee3d32015-07-06 11:48:53 +0100140 // (6) Compute the dominance information and the reverse post order.
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100141 ComputeDominanceInformation();
142}
143
144void HGraph::ClearDominanceInformation() {
145 for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
146 it.Current()->ClearDominanceInformation();
147 }
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100148 reverse_post_order_.clear();
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100149}
150
151void HBasicBlock::ClearDominanceInformation() {
Vladimir Marko60584552015-09-03 13:35:12 +0000152 dominated_blocks_.clear();
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100153 dominator_ = nullptr;
154}
155
156void HGraph::ComputeDominanceInformation() {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100157 DCHECK(reverse_post_order_.empty());
158 reverse_post_order_.reserve(blocks_.size());
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100159 reverse_post_order_.push_back(entry_block_);
Vladimir Markod76d1392015-09-23 16:07:14 +0100160
161 // Number of visits of a given node, indexed by block id.
162 ArenaVector<size_t> visits(blocks_.size(), 0u, arena_->Adapter());
163 // Number of successors visited from a given node, indexed by block id.
164 ArenaVector<size_t> successors_visited(blocks_.size(), 0u, arena_->Adapter());
165 // Nodes for which we need to visit successors.
166 ArenaVector<HBasicBlock*> worklist(arena_->Adapter());
167 constexpr size_t kDefaultWorklistSize = 8;
168 worklist.reserve(kDefaultWorklistSize);
169 worklist.push_back(entry_block_);
170
171 while (!worklist.empty()) {
172 HBasicBlock* current = worklist.back();
173 uint32_t current_id = current->GetBlockId();
174 if (successors_visited[current_id] == current->GetSuccessors().size()) {
175 worklist.pop_back();
176 } else {
177 DCHECK_LT(successors_visited[current_id], current->GetSuccessors().size());
178 HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++];
179
180 if (successor->GetDominator() == nullptr) {
181 successor->SetDominator(current);
182 } else {
183 successor->SetDominator(FindCommonDominator(successor->GetDominator(), current));
184 }
185
186 // Once all the forward edges have been visited, we know the immediate
187 // dominator of the block. We can then start visiting its successors.
188 DCHECK_LT(successor->GetBlockId(), visits.size());
189 if (++visits[successor->GetBlockId()] ==
190 successor->GetPredecessors().size() - successor->NumberOfBackEdges()) {
191 successor->GetDominator()->AddDominatedBlock(successor);
192 reverse_post_order_.push_back(successor);
193 worklist.push_back(successor);
194 }
195 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000196 }
197}
198
199HBasicBlock* HGraph::FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100200 ArenaBitVector visited(arena_, blocks_.size(), false);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000201 // Walk the dominator tree of the first block and mark the visited blocks.
202 while (first != nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000203 visited.SetBit(first->GetBlockId());
204 first = first->GetDominator();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000205 }
206 // Walk the dominator tree of the second block until a marked block is found.
207 while (second != nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000208 if (visited.IsBitSet(second->GetBlockId())) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000209 return second;
210 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000211 second = second->GetDominator();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000212 }
213 LOG(ERROR) << "Could not find common dominator";
214 return nullptr;
215}
216
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000217void HGraph::TransformToSsa() {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100218 DCHECK(!reverse_post_order_.empty());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100219 SsaBuilder ssa_builder(this);
220 ssa_builder.BuildSsa();
221}
222
David Brazdilfc6a86a2015-06-26 10:33:45 +0000223HBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) {
David Brazdil3e187382015-06-26 09:59:52 +0000224 HBasicBlock* new_block = new (arena_) HBasicBlock(this, successor->GetDexPc());
225 AddBlock(new_block);
David Brazdil3e187382015-06-26 09:59:52 +0000226 // Use `InsertBetween` to ensure the predecessor index and successor index of
227 // `block` and `successor` are preserved.
228 new_block->InsertBetween(block, successor);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000229 return new_block;
230}
231
232void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) {
233 // Insert a new node between `block` and `successor` to split the
234 // critical edge.
235 HBasicBlock* new_block = SplitEdge(block, successor);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600236 new_block->AddInstruction(new (arena_) HGoto(successor->GetDexPc()));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100237 if (successor->IsLoopHeader()) {
238 // If we split at a back edge boundary, make the new block the back edge.
239 HLoopInformation* info = successor->GetLoopInformation();
David Brazdil46e2a392015-03-16 17:31:52 +0000240 if (info->IsBackEdge(*block)) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100241 info->RemoveBackEdge(block);
242 info->AddBackEdge(new_block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100243 }
244 }
245}
246
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100247void HGraph::SimplifyLoop(HBasicBlock* header) {
248 HLoopInformation* info = header->GetLoopInformation();
249
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100250 // Make sure the loop has only one pre header. This simplifies SSA building by having
251 // to just look at the pre header to know which locals are initialized at entry of the
252 // loop.
Vladimir Marko60584552015-09-03 13:35:12 +0000253 size_t number_of_incomings = header->GetPredecessors().size() - info->NumberOfBackEdges();
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100254 if (number_of_incomings != 1) {
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100255 HBasicBlock* pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100256 AddBlock(pre_header);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600257 pre_header->AddInstruction(new (arena_) HGoto(header->GetDexPc()));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100258
Vladimir Marko60584552015-09-03 13:35:12 +0000259 for (size_t pred = 0; pred < header->GetPredecessors().size(); ++pred) {
260 HBasicBlock* predecessor = header->GetPredecessor(pred);
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100261 if (!info->IsBackEdge(*predecessor)) {
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100262 predecessor->ReplaceSuccessor(header, pre_header);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100263 pred--;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100264 }
265 }
266 pre_header->AddSuccessor(header);
267 }
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100268
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100269 // Make sure the first predecessor of a loop header is the incoming block.
Vladimir Marko60584552015-09-03 13:35:12 +0000270 if (info->IsBackEdge(*header->GetPredecessor(0))) {
271 HBasicBlock* to_swap = header->GetPredecessor(0);
272 for (size_t pred = 1, e = header->GetPredecessors().size(); pred < e; ++pred) {
273 HBasicBlock* predecessor = header->GetPredecessor(pred);
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100274 if (!info->IsBackEdge(*predecessor)) {
Vladimir Marko60584552015-09-03 13:35:12 +0000275 header->predecessors_[pred] = to_swap;
276 header->predecessors_[0] = predecessor;
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100277 break;
278 }
279 }
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100280 }
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100281
282 // Place the suspend check at the beginning of the header, so that live registers
283 // will be known when allocating registers. Note that code generation can still
284 // generate the suspend check at the back edge, but needs to be careful with
285 // loop phi spill slots (which are not written to at back edge).
286 HInstruction* first_instruction = header->GetFirstInstruction();
287 if (!first_instruction->IsSuspendCheck()) {
288 HSuspendCheck* check = new (arena_) HSuspendCheck(header->GetDexPc());
289 header->InsertInstructionBefore(check, first_instruction);
290 first_instruction = check;
291 }
292 info->SetSuspendCheck(first_instruction->AsSuspendCheck());
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100293}
294
David Brazdilffee3d32015-07-06 11:48:53 +0100295static bool CheckIfPredecessorAtIsExceptional(const HBasicBlock& block, size_t pred_idx) {
Vladimir Marko60584552015-09-03 13:35:12 +0000296 HBasicBlock* predecessor = block.GetPredecessor(pred_idx);
David Brazdilffee3d32015-07-06 11:48:53 +0100297 if (!predecessor->EndsWithTryBoundary()) {
298 // Only edges from HTryBoundary can be exceptional.
299 return false;
300 }
301 HTryBoundary* try_boundary = predecessor->GetLastInstruction()->AsTryBoundary();
302 if (try_boundary->GetNormalFlowSuccessor() == &block) {
303 // This block is the normal-flow successor of `try_boundary`, but it could
304 // also be one of its exception handlers if catch blocks have not been
305 // simplified yet. Predecessors are unordered, so we will consider the first
306 // occurrence to be the normal edge and a possible second occurrence to be
307 // the exceptional edge.
308 return !block.IsFirstIndexOfPredecessor(predecessor, pred_idx);
309 } else {
310 // This is not the normal-flow successor of `try_boundary`, hence it must be
311 // one of its exception handlers.
312 DCHECK(try_boundary->HasExceptionHandler(block));
313 return true;
314 }
315}
316
317void HGraph::SimplifyCatchBlocks() {
Vladimir Markob7d8e8c2015-09-17 15:47:05 +0100318 // NOTE: We're appending new blocks inside the loop, so we need to use index because iterators
319 // can be invalidated. We remember the initial size to avoid iterating over the new blocks.
320 for (size_t block_id = 0u, end = blocks_.size(); block_id != end; ++block_id) {
321 HBasicBlock* catch_block = blocks_[block_id];
David Brazdilffee3d32015-07-06 11:48:53 +0100322 if (!catch_block->IsCatchBlock()) {
323 continue;
324 }
325
326 bool exceptional_predecessors_only = true;
Vladimir Marko60584552015-09-03 13:35:12 +0000327 for (size_t j = 0; j < catch_block->GetPredecessors().size(); ++j) {
David Brazdilffee3d32015-07-06 11:48:53 +0100328 if (!CheckIfPredecessorAtIsExceptional(*catch_block, j)) {
329 exceptional_predecessors_only = false;
330 break;
331 }
332 }
333
334 if (!exceptional_predecessors_only) {
335 // Catch block has normal-flow predecessors and needs to be simplified.
336 // Splitting the block before its first instruction moves all its
337 // instructions into `normal_block` and links the two blocks with a Goto.
338 // Afterwards, incoming normal-flow edges are re-linked to `normal_block`,
339 // leaving `catch_block` with the exceptional edges only.
340 // Note that catch blocks with normal-flow predecessors cannot begin with
341 // a MOVE_EXCEPTION instruction, as guaranteed by the verifier.
342 DCHECK(!catch_block->GetFirstInstruction()->IsLoadException());
343 HBasicBlock* normal_block = catch_block->SplitBefore(catch_block->GetFirstInstruction());
Vladimir Marko60584552015-09-03 13:35:12 +0000344 for (size_t j = 0; j < catch_block->GetPredecessors().size(); ++j) {
David Brazdilffee3d32015-07-06 11:48:53 +0100345 if (!CheckIfPredecessorAtIsExceptional(*catch_block, j)) {
Vladimir Marko60584552015-09-03 13:35:12 +0000346 catch_block->GetPredecessor(j)->ReplaceSuccessor(catch_block, normal_block);
David Brazdilffee3d32015-07-06 11:48:53 +0100347 --j;
348 }
349 }
350 }
351 }
352}
353
354void HGraph::ComputeTryBlockInformation() {
355 // Iterate in reverse post order to propagate try membership information from
356 // predecessors to their successors.
357 for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
358 HBasicBlock* block = it.Current();
359 if (block->IsEntryBlock() || block->IsCatchBlock()) {
360 // Catch blocks after simplification have only exceptional predecessors
361 // and hence are never in tries.
362 continue;
363 }
364
365 // Infer try membership from the first predecessor. Having simplified loops,
366 // the first predecessor can never be a back edge and therefore it must have
367 // been visited already and had its try membership set.
Vladimir Marko60584552015-09-03 13:35:12 +0000368 HBasicBlock* first_predecessor = block->GetPredecessor(0);
David Brazdilffee3d32015-07-06 11:48:53 +0100369 DCHECK(!block->IsLoopHeader() || !block->GetLoopInformation()->IsBackEdge(*first_predecessor));
David Brazdilec16f792015-08-19 15:04:01 +0100370 const HTryBoundary* try_entry = first_predecessor->ComputeTryEntryOfSuccessors();
371 if (try_entry != nullptr) {
372 block->SetTryCatchInformation(new (arena_) TryCatchInformation(*try_entry));
373 }
David Brazdilffee3d32015-07-06 11:48:53 +0100374 }
375}
376
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100377void HGraph::SimplifyCFG() {
378 // Simplify the CFG for future analysis, and code generation:
379 // (1): Split critical edges.
380 // (2): Simplify loops by having only one back edge, and one preheader.
Vladimir Markob7d8e8c2015-09-17 15:47:05 +0100381 // NOTE: We're appending new blocks inside the loop, so we need to use index because iterators
382 // can be invalidated. We remember the initial size to avoid iterating over the new blocks.
383 for (size_t block_id = 0u, end = blocks_.size(); block_id != end; ++block_id) {
384 HBasicBlock* block = blocks_[block_id];
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100385 if (block == nullptr) continue;
David Brazdilffee3d32015-07-06 11:48:53 +0100386 if (block->NumberOfNormalSuccessors() > 1) {
Vladimir Marko60584552015-09-03 13:35:12 +0000387 for (size_t j = 0; j < block->GetSuccessors().size(); ++j) {
388 HBasicBlock* successor = block->GetSuccessor(j);
David Brazdilffee3d32015-07-06 11:48:53 +0100389 DCHECK(!successor->IsCatchBlock());
Vladimir Marko60584552015-09-03 13:35:12 +0000390 if (successor->GetPredecessors().size() > 1) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100391 SplitCriticalEdge(block, successor);
392 --j;
393 }
394 }
395 }
396 if (block->IsLoopHeader()) {
397 SimplifyLoop(block);
398 }
399 }
400}
401
Nicolas Geoffrayf5370122014-12-02 11:51:19 +0000402bool HGraph::AnalyzeNaturalLoops() const {
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100403 // Order does not matter.
404 for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
405 HBasicBlock* block = it.Current();
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100406 if (block->IsLoopHeader()) {
David Brazdilffee3d32015-07-06 11:48:53 +0100407 if (block->IsCatchBlock()) {
408 // TODO: Dealing with exceptional back edges could be tricky because
409 // they only approximate the real control flow. Bail out for now.
410 return false;
411 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100412 HLoopInformation* info = block->GetLoopInformation();
413 if (!info->Populate()) {
414 // Abort if the loop is non natural. We currently bailout in such cases.
415 return false;
416 }
417 }
418 }
419 return true;
420}
421
David Brazdil8d5b8b22015-03-24 10:51:52 +0000422void HGraph::InsertConstant(HConstant* constant) {
423 // New constants are inserted before the final control-flow instruction
424 // of the graph, or at its end if called from the graph builder.
425 if (entry_block_->EndsWithControlFlowInstruction()) {
426 entry_block_->InsertInstructionBefore(constant, entry_block_->GetLastInstruction());
David Brazdil46e2a392015-03-16 17:31:52 +0000427 } else {
David Brazdil8d5b8b22015-03-24 10:51:52 +0000428 entry_block_->AddInstruction(constant);
David Brazdil46e2a392015-03-16 17:31:52 +0000429 }
430}
431
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600432HNullConstant* HGraph::GetNullConstant(uint32_t dex_pc) {
Nicolas Geoffray18e68732015-06-17 23:09:05 +0100433 // For simplicity, don't bother reviving the cached null constant if it is
434 // not null and not in a block. Otherwise, we need to clear the instruction
435 // id and/or any invariants the graph is assuming when adding new instructions.
436 if ((cached_null_constant_ == nullptr) || (cached_null_constant_->GetBlock() == nullptr)) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600437 cached_null_constant_ = new (arena_) HNullConstant(dex_pc);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000438 InsertConstant(cached_null_constant_);
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000439 }
440 return cached_null_constant_;
441}
442
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100443HCurrentMethod* HGraph::GetCurrentMethod() {
Nicolas Geoffrayf78848f2015-06-17 11:57:56 +0100444 // For simplicity, don't bother reviving the cached current method if it is
445 // not null and not in a block. Otherwise, we need to clear the instruction
446 // id and/or any invariants the graph is assuming when adding new instructions.
447 if ((cached_current_method_ == nullptr) || (cached_current_method_->GetBlock() == nullptr)) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700448 cached_current_method_ = new (arena_) HCurrentMethod(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600449 Is64BitInstructionSet(instruction_set_) ? Primitive::kPrimLong : Primitive::kPrimInt,
450 entry_block_->GetDexPc());
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100451 if (entry_block_->GetFirstInstruction() == nullptr) {
452 entry_block_->AddInstruction(cached_current_method_);
453 } else {
454 entry_block_->InsertInstructionBefore(
455 cached_current_method_, entry_block_->GetFirstInstruction());
456 }
457 }
458 return cached_current_method_;
459}
460
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600461HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc) {
David Brazdil8d5b8b22015-03-24 10:51:52 +0000462 switch (type) {
463 case Primitive::Type::kPrimBoolean:
464 DCHECK(IsUint<1>(value));
465 FALLTHROUGH_INTENDED;
466 case Primitive::Type::kPrimByte:
467 case Primitive::Type::kPrimChar:
468 case Primitive::Type::kPrimShort:
469 case Primitive::Type::kPrimInt:
470 DCHECK(IsInt(Primitive::ComponentSize(type) * kBitsPerByte, value));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600471 return GetIntConstant(static_cast<int32_t>(value), dex_pc);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000472
473 case Primitive::Type::kPrimLong:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600474 return GetLongConstant(value, dex_pc);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000475
476 default:
477 LOG(FATAL) << "Unsupported constant type";
478 UNREACHABLE();
David Brazdil46e2a392015-03-16 17:31:52 +0000479 }
David Brazdil46e2a392015-03-16 17:31:52 +0000480}
481
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000482void HGraph::CacheFloatConstant(HFloatConstant* constant) {
483 int32_t value = bit_cast<int32_t, float>(constant->GetValue());
484 DCHECK(cached_float_constants_.find(value) == cached_float_constants_.end());
485 cached_float_constants_.Overwrite(value, constant);
486}
487
488void HGraph::CacheDoubleConstant(HDoubleConstant* constant) {
489 int64_t value = bit_cast<int64_t, double>(constant->GetValue());
490 DCHECK(cached_double_constants_.find(value) == cached_double_constants_.end());
491 cached_double_constants_.Overwrite(value, constant);
492}
493
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000494void HLoopInformation::Add(HBasicBlock* block) {
495 blocks_.SetBit(block->GetBlockId());
496}
497
David Brazdil46e2a392015-03-16 17:31:52 +0000498void HLoopInformation::Remove(HBasicBlock* block) {
499 blocks_.ClearBit(block->GetBlockId());
500}
501
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100502void HLoopInformation::PopulateRecursive(HBasicBlock* block) {
503 if (blocks_.IsBitSet(block->GetBlockId())) {
504 return;
505 }
506
507 blocks_.SetBit(block->GetBlockId());
508 block->SetInLoop(this);
Vladimir Marko60584552015-09-03 13:35:12 +0000509 for (HBasicBlock* predecessor : block->GetPredecessors()) {
510 PopulateRecursive(predecessor);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100511 }
512}
513
514bool HLoopInformation::Populate() {
David Brazdila4b8c212015-05-07 09:59:30 +0100515 DCHECK_EQ(blocks_.NumSetBits(), 0u) << "Loop information has already been populated";
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100516 for (HBasicBlock* back_edge : GetBackEdges()) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100517 DCHECK(back_edge->GetDominator() != nullptr);
518 if (!header_->Dominates(back_edge)) {
519 // This loop is not natural. Do not bother going further.
520 return false;
521 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100522
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100523 // Populate this loop: starting with the back edge, recursively add predecessors
524 // that are not already part of that loop. Set the header as part of the loop
525 // to end the recursion.
526 // This is a recursive implementation of the algorithm described in
527 // "Advanced Compiler Design & Implementation" (Muchnick) p192.
528 blocks_.SetBit(header_->GetBlockId());
529 PopulateRecursive(back_edge);
530 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100531 return true;
532}
533
David Brazdila4b8c212015-05-07 09:59:30 +0100534void HLoopInformation::Update() {
535 HGraph* graph = header_->GetGraph();
536 for (uint32_t id : blocks_.Indexes()) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100537 HBasicBlock* block = graph->GetBlock(id);
David Brazdila4b8c212015-05-07 09:59:30 +0100538 // Reset loop information of non-header blocks inside the loop, except
539 // members of inner nested loops because those should already have been
540 // updated by their own LoopInformation.
541 if (block->GetLoopInformation() == this && block != header_) {
542 block->SetLoopInformation(nullptr);
543 }
544 }
545 blocks_.ClearAllBits();
546
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100547 if (back_edges_.empty()) {
David Brazdila4b8c212015-05-07 09:59:30 +0100548 // The loop has been dismantled, delete its suspend check and remove info
549 // from the header.
550 DCHECK(HasSuspendCheck());
551 header_->RemoveInstruction(suspend_check_);
552 header_->SetLoopInformation(nullptr);
553 header_ = nullptr;
554 suspend_check_ = nullptr;
555 } else {
556 if (kIsDebugBuild) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100557 for (HBasicBlock* back_edge : back_edges_) {
558 DCHECK(header_->Dominates(back_edge));
David Brazdila4b8c212015-05-07 09:59:30 +0100559 }
560 }
561 // This loop still has reachable back edges. Repopulate the list of blocks.
562 bool populate_successful = Populate();
563 DCHECK(populate_successful);
564 }
565}
566
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100567HBasicBlock* HLoopInformation::GetPreHeader() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100568 return header_->GetDominator();
569}
570
571bool HLoopInformation::Contains(const HBasicBlock& block) const {
572 return blocks_.IsBitSet(block.GetBlockId());
573}
574
575bool HLoopInformation::IsIn(const HLoopInformation& other) const {
576 return other.blocks_.IsBitSet(header_->GetBlockId());
577}
578
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100579size_t HLoopInformation::GetLifetimeEnd() const {
580 size_t last_position = 0;
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100581 for (HBasicBlock* back_edge : GetBackEdges()) {
582 last_position = std::max(back_edge->GetLifetimeEnd(), last_position);
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100583 }
584 return last_position;
585}
586
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100587bool HBasicBlock::Dominates(HBasicBlock* other) const {
588 // Walk up the dominator tree from `other`, to find out if `this`
589 // is an ancestor.
590 HBasicBlock* current = other;
591 while (current != nullptr) {
592 if (current == this) {
593 return true;
594 }
595 current = current->GetDominator();
596 }
597 return false;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100598}
599
Nicolas Geoffray191c4b12014-10-07 14:14:27 +0100600static void UpdateInputsUsers(HInstruction* instruction) {
601 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
602 instruction->InputAt(i)->AddUseAt(instruction, i);
603 }
604 // Environment should be created later.
605 DCHECK(!instruction->HasEnvironment());
606}
607
Roland Levillainccc07a92014-09-16 14:48:16 +0100608void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial,
609 HInstruction* replacement) {
610 DCHECK(initial->GetBlock() == this);
611 InsertInstructionBefore(replacement, initial);
612 initial->ReplaceWith(replacement);
613 RemoveInstruction(initial);
614}
615
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100616static void Add(HInstructionList* instruction_list,
617 HBasicBlock* block,
618 HInstruction* instruction) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000619 DCHECK(instruction->GetBlock() == nullptr);
Nicolas Geoffray43c86422014-03-18 11:58:24 +0000620 DCHECK_EQ(instruction->GetId(), -1);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100621 instruction->SetBlock(block);
622 instruction->SetId(block->GetGraph()->GetNextInstructionId());
Nicolas Geoffray191c4b12014-10-07 14:14:27 +0100623 UpdateInputsUsers(instruction);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100624 instruction_list->AddInstruction(instruction);
625}
626
627void HBasicBlock::AddInstruction(HInstruction* instruction) {
628 Add(&instructions_, this, instruction);
629}
630
631void HBasicBlock::AddPhi(HPhi* phi) {
632 Add(&phis_, this, phi);
633}
634
David Brazdilc3d743f2015-04-22 13:40:50 +0100635void HBasicBlock::InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor) {
636 DCHECK(!cursor->IsPhi());
637 DCHECK(!instruction->IsPhi());
638 DCHECK_EQ(instruction->GetId(), -1);
639 DCHECK_NE(cursor->GetId(), -1);
640 DCHECK_EQ(cursor->GetBlock(), this);
641 DCHECK(!instruction->IsControlFlow());
642 instruction->SetBlock(this);
643 instruction->SetId(GetGraph()->GetNextInstructionId());
644 UpdateInputsUsers(instruction);
645 instructions_.InsertInstructionBefore(instruction, cursor);
646}
647
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100648void HBasicBlock::InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor) {
649 DCHECK(!cursor->IsPhi());
650 DCHECK(!instruction->IsPhi());
651 DCHECK_EQ(instruction->GetId(), -1);
652 DCHECK_NE(cursor->GetId(), -1);
653 DCHECK_EQ(cursor->GetBlock(), this);
654 DCHECK(!instruction->IsControlFlow());
655 DCHECK(!cursor->IsControlFlow());
656 instruction->SetBlock(this);
657 instruction->SetId(GetGraph()->GetNextInstructionId());
658 UpdateInputsUsers(instruction);
659 instructions_.InsertInstructionAfter(instruction, cursor);
660}
661
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100662void HBasicBlock::InsertPhiAfter(HPhi* phi, HPhi* cursor) {
663 DCHECK_EQ(phi->GetId(), -1);
664 DCHECK_NE(cursor->GetId(), -1);
665 DCHECK_EQ(cursor->GetBlock(), this);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100666 phi->SetBlock(this);
667 phi->SetId(GetGraph()->GetNextInstructionId());
668 UpdateInputsUsers(phi);
David Brazdilc3d743f2015-04-22 13:40:50 +0100669 phis_.InsertInstructionAfter(phi, cursor);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100670}
671
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100672static void Remove(HInstructionList* instruction_list,
673 HBasicBlock* block,
David Brazdil1abb4192015-02-17 18:33:36 +0000674 HInstruction* instruction,
675 bool ensure_safety) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100676 DCHECK_EQ(block, instruction->GetBlock());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100677 instruction->SetBlock(nullptr);
678 instruction_list->RemoveInstruction(instruction);
David Brazdil1abb4192015-02-17 18:33:36 +0000679 if (ensure_safety) {
680 DCHECK(instruction->GetUses().IsEmpty());
681 DCHECK(instruction->GetEnvUses().IsEmpty());
682 RemoveAsUser(instruction);
683 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100684}
685
David Brazdil1abb4192015-02-17 18:33:36 +0000686void HBasicBlock::RemoveInstruction(HInstruction* instruction, bool ensure_safety) {
David Brazdilc7508e92015-04-27 13:28:57 +0100687 DCHECK(!instruction->IsPhi());
David Brazdil1abb4192015-02-17 18:33:36 +0000688 Remove(&instructions_, this, instruction, ensure_safety);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100689}
690
David Brazdil1abb4192015-02-17 18:33:36 +0000691void HBasicBlock::RemovePhi(HPhi* phi, bool ensure_safety) {
692 Remove(&phis_, this, phi, ensure_safety);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100693}
694
David Brazdilc7508e92015-04-27 13:28:57 +0100695void HBasicBlock::RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety) {
696 if (instruction->IsPhi()) {
697 RemovePhi(instruction->AsPhi(), ensure_safety);
698 } else {
699 RemoveInstruction(instruction, ensure_safety);
700 }
701}
702
Vladimir Marko71bf8092015-09-15 15:33:14 +0100703void HEnvironment::CopyFrom(const ArenaVector<HInstruction*>& locals) {
704 for (size_t i = 0; i < locals.size(); i++) {
705 HInstruction* instruction = locals[i];
Nicolas Geoffray8c0c91a2015-05-07 11:46:05 +0100706 SetRawEnvAt(i, instruction);
707 if (instruction != nullptr) {
708 instruction->AddEnvUseAt(this, i);
709 }
710 }
711}
712
David Brazdiled596192015-01-23 10:39:45 +0000713void HEnvironment::CopyFrom(HEnvironment* env) {
714 for (size_t i = 0; i < env->Size(); i++) {
715 HInstruction* instruction = env->GetInstructionAt(i);
716 SetRawEnvAt(i, instruction);
717 if (instruction != nullptr) {
718 instruction->AddEnvUseAt(this, i);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100719 }
David Brazdiled596192015-01-23 10:39:45 +0000720 }
721}
722
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700723void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
724 HBasicBlock* loop_header) {
725 DCHECK(loop_header->IsLoopHeader());
726 for (size_t i = 0; i < env->Size(); i++) {
727 HInstruction* instruction = env->GetInstructionAt(i);
728 SetRawEnvAt(i, instruction);
729 if (instruction == nullptr) {
730 continue;
731 }
732 if (instruction->IsLoopHeaderPhi() && (instruction->GetBlock() == loop_header)) {
733 // At the end of the loop pre-header, the corresponding value for instruction
734 // is the first input of the phi.
735 HInstruction* initial = instruction->AsPhi()->InputAt(0);
736 DCHECK(initial->GetBlock()->Dominates(loop_header));
737 SetRawEnvAt(i, initial);
738 initial->AddEnvUseAt(this, i);
739 } else {
740 instruction->AddEnvUseAt(this, i);
741 }
742 }
743}
744
David Brazdil1abb4192015-02-17 18:33:36 +0000745void HEnvironment::RemoveAsUserOfInput(size_t index) const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100746 DCHECK_LT(index, Size());
747 const HUserRecord<HEnvironment*>& user_record = vregs_[index];
David Brazdil1abb4192015-02-17 18:33:36 +0000748 user_record.GetInstruction()->RemoveEnvironmentUser(user_record.GetUseNode());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100749}
750
Calin Juravle77520bc2015-01-12 18:45:46 +0000751HInstruction* HInstruction::GetNextDisregardingMoves() const {
752 HInstruction* next = GetNext();
753 while (next != nullptr && next->IsParallelMove()) {
754 next = next->GetNext();
755 }
756 return next;
757}
758
759HInstruction* HInstruction::GetPreviousDisregardingMoves() const {
760 HInstruction* previous = GetPrevious();
761 while (previous != nullptr && previous->IsParallelMove()) {
762 previous = previous->GetPrevious();
763 }
764 return previous;
765}
766
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100767void HInstructionList::AddInstruction(HInstruction* instruction) {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000768 if (first_instruction_ == nullptr) {
769 DCHECK(last_instruction_ == nullptr);
770 first_instruction_ = last_instruction_ = instruction;
771 } else {
772 last_instruction_->next_ = instruction;
773 instruction->previous_ = last_instruction_;
774 last_instruction_ = instruction;
775 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000776}
777
David Brazdilc3d743f2015-04-22 13:40:50 +0100778void HInstructionList::InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor) {
779 DCHECK(Contains(cursor));
780 if (cursor == first_instruction_) {
781 cursor->previous_ = instruction;
782 instruction->next_ = cursor;
783 first_instruction_ = instruction;
784 } else {
785 instruction->previous_ = cursor->previous_;
786 instruction->next_ = cursor;
787 cursor->previous_ = instruction;
788 instruction->previous_->next_ = instruction;
789 }
790}
791
792void HInstructionList::InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor) {
793 DCHECK(Contains(cursor));
794 if (cursor == last_instruction_) {
795 cursor->next_ = instruction;
796 instruction->previous_ = cursor;
797 last_instruction_ = instruction;
798 } else {
799 instruction->next_ = cursor->next_;
800 instruction->previous_ = cursor;
801 cursor->next_ = instruction;
802 instruction->next_->previous_ = instruction;
803 }
804}
805
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100806void HInstructionList::RemoveInstruction(HInstruction* instruction) {
807 if (instruction->previous_ != nullptr) {
808 instruction->previous_->next_ = instruction->next_;
809 }
810 if (instruction->next_ != nullptr) {
811 instruction->next_->previous_ = instruction->previous_;
812 }
813 if (instruction == first_instruction_) {
814 first_instruction_ = instruction->next_;
815 }
816 if (instruction == last_instruction_) {
817 last_instruction_ = instruction->previous_;
818 }
819}
820
Roland Levillain6b469232014-09-25 10:10:38 +0100821bool HInstructionList::Contains(HInstruction* instruction) const {
822 for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
823 if (it.Current() == instruction) {
824 return true;
825 }
826 }
827 return false;
828}
829
Roland Levillainccc07a92014-09-16 14:48:16 +0100830bool HInstructionList::FoundBefore(const HInstruction* instruction1,
831 const HInstruction* instruction2) const {
832 DCHECK_EQ(instruction1->GetBlock(), instruction2->GetBlock());
833 for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
834 if (it.Current() == instruction1) {
835 return true;
836 }
837 if (it.Current() == instruction2) {
838 return false;
839 }
840 }
841 LOG(FATAL) << "Did not find an order between two instructions of the same block.";
842 return true;
843}
844
Roland Levillain6c82d402014-10-13 16:10:27 +0100845bool HInstruction::StrictlyDominates(HInstruction* other_instruction) const {
846 if (other_instruction == this) {
847 // An instruction does not strictly dominate itself.
848 return false;
849 }
Roland Levillainccc07a92014-09-16 14:48:16 +0100850 HBasicBlock* block = GetBlock();
851 HBasicBlock* other_block = other_instruction->GetBlock();
852 if (block != other_block) {
853 return GetBlock()->Dominates(other_instruction->GetBlock());
854 } else {
855 // If both instructions are in the same block, ensure this
856 // instruction comes before `other_instruction`.
857 if (IsPhi()) {
858 if (!other_instruction->IsPhi()) {
859 // Phis appear before non phi-instructions so this instruction
860 // dominates `other_instruction`.
861 return true;
862 } else {
863 // There is no order among phis.
864 LOG(FATAL) << "There is no dominance between phis of a same block.";
865 return false;
866 }
867 } else {
868 // `this` is not a phi.
869 if (other_instruction->IsPhi()) {
870 // Phis appear before non phi-instructions so this instruction
871 // does not dominate `other_instruction`.
872 return false;
873 } else {
874 // Check whether this instruction comes before
875 // `other_instruction` in the instruction list.
876 return block->GetInstructions().FoundBefore(this, other_instruction);
877 }
878 }
879 }
880}
881
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100882void HInstruction::ReplaceWith(HInstruction* other) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100883 DCHECK(other != nullptr);
David Brazdiled596192015-01-23 10:39:45 +0000884 for (HUseIterator<HInstruction*> it(GetUses()); !it.Done(); it.Advance()) {
885 HUseListNode<HInstruction*>* current = it.Current();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100886 HInstruction* user = current->GetUser();
887 size_t input_index = current->GetIndex();
888 user->SetRawInputAt(input_index, other);
889 other->AddUseAt(user, input_index);
890 }
891
David Brazdiled596192015-01-23 10:39:45 +0000892 for (HUseIterator<HEnvironment*> it(GetEnvUses()); !it.Done(); it.Advance()) {
893 HUseListNode<HEnvironment*>* current = it.Current();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100894 HEnvironment* user = current->GetUser();
895 size_t input_index = current->GetIndex();
896 user->SetRawEnvAt(input_index, other);
897 other->AddEnvUseAt(user, input_index);
898 }
899
David Brazdiled596192015-01-23 10:39:45 +0000900 uses_.Clear();
901 env_uses_.Clear();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100902}
903
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100904void HInstruction::ReplaceInput(HInstruction* replacement, size_t index) {
David Brazdil1abb4192015-02-17 18:33:36 +0000905 RemoveAsUserOfInput(index);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100906 SetRawInputAt(index, replacement);
907 replacement->AddUseAt(this, index);
908}
909
Nicolas Geoffray39468442014-09-02 15:17:15 +0100910size_t HInstruction::EnvironmentSize() const {
911 return HasEnvironment() ? environment_->Size() : 0;
912}
913
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100914void HPhi::AddInput(HInstruction* input) {
915 DCHECK(input->GetBlock() != nullptr);
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100916 inputs_.push_back(HUserRecord<HInstruction*>(input));
917 input->AddUseAt(this, inputs_.size() - 1);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100918}
919
David Brazdil2d7352b2015-04-20 14:52:42 +0100920void HPhi::RemoveInputAt(size_t index) {
921 RemoveAsUserOfInput(index);
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100922 inputs_.erase(inputs_.begin() + index);
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +0100923 for (size_t i = index, e = InputCount(); i < e; ++i) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100924 DCHECK_EQ(InputRecordAt(i).GetUseNode()->GetIndex(), i + 1u);
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +0100925 InputRecordAt(i).GetUseNode()->SetIndex(i);
926 }
David Brazdil2d7352b2015-04-20 14:52:42 +0100927}
928
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100929#define DEFINE_ACCEPT(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000930void H##name::Accept(HGraphVisitor* visitor) { \
931 visitor->Visit##name(this); \
932}
933
934FOR_EACH_INSTRUCTION(DEFINE_ACCEPT)
935
936#undef DEFINE_ACCEPT
937
938void HGraphVisitor::VisitInsertionOrder() {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100939 const ArenaVector<HBasicBlock*>& blocks = graph_->GetBlocks();
940 for (HBasicBlock* block : blocks) {
David Brazdil46e2a392015-03-16 17:31:52 +0000941 if (block != nullptr) {
942 VisitBasicBlock(block);
943 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000944 }
945}
946
Roland Levillain633021e2014-10-01 14:12:25 +0100947void HGraphVisitor::VisitReversePostOrder() {
948 for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
949 VisitBasicBlock(it.Current());
950 }
951}
952
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000953void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) {
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100954 for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100955 it.Current()->Accept(this);
956 }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100957 for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000958 it.Current()->Accept(this);
959 }
960}
961
Mark Mendelle82549b2015-05-06 10:55:34 -0400962HConstant* HTypeConversion::TryStaticEvaluation() const {
963 HGraph* graph = GetBlock()->GetGraph();
964 if (GetInput()->IsIntConstant()) {
965 int32_t value = GetInput()->AsIntConstant()->GetValue();
966 switch (GetResultType()) {
967 case Primitive::kPrimLong:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600968 return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400969 case Primitive::kPrimFloat:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600970 return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400971 case Primitive::kPrimDouble:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600972 return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400973 default:
974 return nullptr;
975 }
976 } else if (GetInput()->IsLongConstant()) {
977 int64_t value = GetInput()->AsLongConstant()->GetValue();
978 switch (GetResultType()) {
979 case Primitive::kPrimInt:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600980 return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400981 case Primitive::kPrimFloat:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600982 return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400983 case Primitive::kPrimDouble:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600984 return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400985 default:
986 return nullptr;
987 }
988 } else if (GetInput()->IsFloatConstant()) {
989 float value = GetInput()->AsFloatConstant()->GetValue();
990 switch (GetResultType()) {
991 case Primitive::kPrimInt:
992 if (std::isnan(value))
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600993 return graph->GetIntConstant(0, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400994 if (value >= kPrimIntMax)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600995 return graph->GetIntConstant(kPrimIntMax, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400996 if (value <= kPrimIntMin)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600997 return graph->GetIntConstant(kPrimIntMin, GetDexPc());
998 return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -0400999 case Primitive::kPrimLong:
1000 if (std::isnan(value))
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001001 return graph->GetLongConstant(0, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001002 if (value >= kPrimLongMax)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001003 return graph->GetLongConstant(kPrimLongMax, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001004 if (value <= kPrimLongMin)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001005 return graph->GetLongConstant(kPrimLongMin, GetDexPc());
1006 return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001007 case Primitive::kPrimDouble:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001008 return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001009 default:
1010 return nullptr;
1011 }
1012 } else if (GetInput()->IsDoubleConstant()) {
1013 double value = GetInput()->AsDoubleConstant()->GetValue();
1014 switch (GetResultType()) {
1015 case Primitive::kPrimInt:
1016 if (std::isnan(value))
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001017 return graph->GetIntConstant(0, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001018 if (value >= kPrimIntMax)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001019 return graph->GetIntConstant(kPrimIntMax, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001020 if (value <= kPrimLongMin)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001021 return graph->GetIntConstant(kPrimIntMin, GetDexPc());
1022 return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001023 case Primitive::kPrimLong:
1024 if (std::isnan(value))
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001025 return graph->GetLongConstant(0, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001026 if (value >= kPrimLongMax)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001027 return graph->GetLongConstant(kPrimLongMax, GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001028 if (value <= kPrimLongMin)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001029 return graph->GetLongConstant(kPrimLongMin, GetDexPc());
1030 return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001031 case Primitive::kPrimFloat:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001032 return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
Mark Mendelle82549b2015-05-06 10:55:34 -04001033 default:
1034 return nullptr;
1035 }
1036 }
1037 return nullptr;
1038}
1039
Roland Levillain9240d6a2014-10-20 16:47:04 +01001040HConstant* HUnaryOperation::TryStaticEvaluation() const {
1041 if (GetInput()->IsIntConstant()) {
Roland Levillain9867bc72015-08-05 10:21:34 +01001042 return Evaluate(GetInput()->AsIntConstant());
Roland Levillain9240d6a2014-10-20 16:47:04 +01001043 } else if (GetInput()->IsLongConstant()) {
Roland Levillain9867bc72015-08-05 10:21:34 +01001044 return Evaluate(GetInput()->AsLongConstant());
Roland Levillain9240d6a2014-10-20 16:47:04 +01001045 }
1046 return nullptr;
1047}
1048
1049HConstant* HBinaryOperation::TryStaticEvaluation() const {
Roland Levillain9867bc72015-08-05 10:21:34 +01001050 if (GetLeft()->IsIntConstant()) {
1051 if (GetRight()->IsIntConstant()) {
1052 return Evaluate(GetLeft()->AsIntConstant(), GetRight()->AsIntConstant());
1053 } else if (GetRight()->IsLongConstant()) {
1054 return Evaluate(GetLeft()->AsIntConstant(), GetRight()->AsLongConstant());
1055 }
1056 } else if (GetLeft()->IsLongConstant()) {
1057 if (GetRight()->IsIntConstant()) {
1058 return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsIntConstant());
1059 } else if (GetRight()->IsLongConstant()) {
1060 return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsLongConstant());
Nicolas Geoffray9ee66182015-01-16 12:35:40 +00001061 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001062 }
1063 return nullptr;
1064}
Dave Allison20dfc792014-06-16 20:44:29 -07001065
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001066HConstant* HBinaryOperation::GetConstantRight() const {
1067 if (GetRight()->IsConstant()) {
1068 return GetRight()->AsConstant();
1069 } else if (IsCommutative() && GetLeft()->IsConstant()) {
1070 return GetLeft()->AsConstant();
1071 } else {
1072 return nullptr;
1073 }
1074}
1075
1076// If `GetConstantRight()` returns one of the input, this returns the other
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001077// one. Otherwise it returns null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001078HInstruction* HBinaryOperation::GetLeastConstantLeft() const {
1079 HInstruction* most_constant_right = GetConstantRight();
1080 if (most_constant_right == nullptr) {
1081 return nullptr;
1082 } else if (most_constant_right == GetLeft()) {
1083 return GetRight();
1084 } else {
1085 return GetLeft();
1086 }
1087}
1088
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001089bool HCondition::IsBeforeWhenDisregardMoves(HInstruction* instruction) const {
1090 return this == instruction->GetPreviousDisregardingMoves();
Nicolas Geoffray18efde52014-09-22 15:51:11 +01001091}
1092
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001093bool HInstruction::Equals(HInstruction* other) const {
1094 if (!InstructionTypeEquals(other)) return false;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001095 DCHECK_EQ(GetKind(), other->GetKind());
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001096 if (!InstructionDataEquals(other)) return false;
1097 if (GetType() != other->GetType()) return false;
1098 if (InputCount() != other->InputCount()) return false;
1099
1100 for (size_t i = 0, e = InputCount(); i < e; ++i) {
1101 if (InputAt(i) != other->InputAt(i)) return false;
1102 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001103 DCHECK_EQ(ComputeHashCode(), other->ComputeHashCode());
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001104 return true;
1105}
1106
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001107std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs) {
1108#define DECLARE_CASE(type, super) case HInstruction::k##type: os << #type; break;
1109 switch (rhs) {
1110 FOR_EACH_INSTRUCTION(DECLARE_CASE)
1111 default:
1112 os << "Unknown instruction kind " << static_cast<int>(rhs);
1113 break;
1114 }
1115#undef DECLARE_CASE
1116 return os;
1117}
1118
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001119void HInstruction::MoveBefore(HInstruction* cursor) {
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001120 next_->previous_ = previous_;
1121 if (previous_ != nullptr) {
1122 previous_->next_ = next_;
1123 }
1124 if (block_->instructions_.first_instruction_ == this) {
1125 block_->instructions_.first_instruction_ = next_;
1126 }
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001127 DCHECK_NE(block_->instructions_.last_instruction_, this);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001128
1129 previous_ = cursor->previous_;
1130 if (previous_ != nullptr) {
1131 previous_->next_ = this;
1132 }
1133 next_ = cursor;
1134 cursor->previous_ = this;
1135 block_ = cursor->block_;
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001136
1137 if (block_->instructions_.first_instruction_ == cursor) {
1138 block_->instructions_.first_instruction_ = this;
1139 }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001140}
1141
David Brazdilfc6a86a2015-06-26 10:33:45 +00001142HBasicBlock* HBasicBlock::SplitBefore(HInstruction* cursor) {
1143 DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented";
1144 DCHECK_EQ(cursor->GetBlock(), this);
1145
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001146 HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(),
1147 cursor->GetDexPc());
David Brazdilfc6a86a2015-06-26 10:33:45 +00001148 new_block->instructions_.first_instruction_ = cursor;
1149 new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
1150 instructions_.last_instruction_ = cursor->previous_;
1151 if (cursor->previous_ == nullptr) {
1152 instructions_.first_instruction_ = nullptr;
1153 } else {
1154 cursor->previous_->next_ = nullptr;
1155 cursor->previous_ = nullptr;
1156 }
1157
1158 new_block->instructions_.SetBlockOfInstructions(new_block);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001159 AddInstruction(new (GetGraph()->GetArena()) HGoto(new_block->GetDexPc()));
David Brazdilfc6a86a2015-06-26 10:33:45 +00001160
Vladimir Marko60584552015-09-03 13:35:12 +00001161 for (HBasicBlock* successor : GetSuccessors()) {
1162 new_block->successors_.push_back(successor);
1163 successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
David Brazdilfc6a86a2015-06-26 10:33:45 +00001164 }
Vladimir Marko60584552015-09-03 13:35:12 +00001165 successors_.clear();
David Brazdilfc6a86a2015-06-26 10:33:45 +00001166 AddSuccessor(new_block);
1167
David Brazdil56e1acc2015-06-30 15:41:36 +01001168 GetGraph()->AddBlock(new_block);
David Brazdilfc6a86a2015-06-26 10:33:45 +00001169 return new_block;
1170}
1171
David Brazdild7558da2015-09-22 13:04:14 +01001172HBasicBlock* HBasicBlock::CreateImmediateDominator() {
1173 DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented";
1174 DCHECK(!IsCatchBlock()) << "Support for updating try/catch information not implemented.";
1175
1176 HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
1177
1178 for (HBasicBlock* predecessor : GetPredecessors()) {
1179 new_block->predecessors_.push_back(predecessor);
1180 predecessor->successors_[predecessor->GetSuccessorIndexOf(this)] = new_block;
1181 }
1182 predecessors_.clear();
1183 AddPredecessor(new_block);
1184
1185 GetGraph()->AddBlock(new_block);
1186 return new_block;
1187}
1188
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001189HBasicBlock* HBasicBlock::SplitAfter(HInstruction* cursor) {
1190 DCHECK(!cursor->IsControlFlow());
1191 DCHECK_NE(instructions_.last_instruction_, cursor);
1192 DCHECK_EQ(cursor->GetBlock(), this);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001193
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001194 HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
1195 new_block->instructions_.first_instruction_ = cursor->GetNext();
1196 new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
1197 cursor->next_->previous_ = nullptr;
1198 cursor->next_ = nullptr;
1199 instructions_.last_instruction_ = cursor;
1200
1201 new_block->instructions_.SetBlockOfInstructions(new_block);
Vladimir Marko60584552015-09-03 13:35:12 +00001202 for (HBasicBlock* successor : GetSuccessors()) {
1203 new_block->successors_.push_back(successor);
1204 successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001205 }
Vladimir Marko60584552015-09-03 13:35:12 +00001206 successors_.clear();
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001207
Vladimir Marko60584552015-09-03 13:35:12 +00001208 for (HBasicBlock* dominated : GetDominatedBlocks()) {
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001209 dominated->dominator_ = new_block;
Vladimir Marko60584552015-09-03 13:35:12 +00001210 new_block->dominated_blocks_.push_back(dominated);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001211 }
Vladimir Marko60584552015-09-03 13:35:12 +00001212 dominated_blocks_.clear();
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001213 return new_block;
1214}
1215
David Brazdilec16f792015-08-19 15:04:01 +01001216const HTryBoundary* HBasicBlock::ComputeTryEntryOfSuccessors() const {
David Brazdilffee3d32015-07-06 11:48:53 +01001217 if (EndsWithTryBoundary()) {
1218 HTryBoundary* try_boundary = GetLastInstruction()->AsTryBoundary();
1219 if (try_boundary->IsEntry()) {
David Brazdilec16f792015-08-19 15:04:01 +01001220 DCHECK(!IsTryBlock());
David Brazdilffee3d32015-07-06 11:48:53 +01001221 return try_boundary;
1222 } else {
David Brazdilec16f792015-08-19 15:04:01 +01001223 DCHECK(IsTryBlock());
1224 DCHECK(try_catch_information_->GetTryEntry().HasSameExceptionHandlersAs(*try_boundary));
David Brazdilffee3d32015-07-06 11:48:53 +01001225 return nullptr;
1226 }
David Brazdilec16f792015-08-19 15:04:01 +01001227 } else if (IsTryBlock()) {
1228 return &try_catch_information_->GetTryEntry();
David Brazdilffee3d32015-07-06 11:48:53 +01001229 } else {
David Brazdilec16f792015-08-19 15:04:01 +01001230 return nullptr;
David Brazdilffee3d32015-07-06 11:48:53 +01001231 }
David Brazdilfc6a86a2015-06-26 10:33:45 +00001232}
1233
David Brazdild7558da2015-09-22 13:04:14 +01001234bool HBasicBlock::HasThrowingInstructions() const {
1235 for (HInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
1236 if (it.Current()->CanThrow()) {
1237 return true;
1238 }
1239 }
1240 return false;
1241}
1242
David Brazdilfc6a86a2015-06-26 10:33:45 +00001243static bool HasOnlyOneInstruction(const HBasicBlock& block) {
1244 return block.GetPhis().IsEmpty()
1245 && !block.GetInstructions().IsEmpty()
1246 && block.GetFirstInstruction() == block.GetLastInstruction();
1247}
1248
David Brazdil46e2a392015-03-16 17:31:52 +00001249bool HBasicBlock::IsSingleGoto() const {
David Brazdilfc6a86a2015-06-26 10:33:45 +00001250 return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsGoto();
1251}
1252
1253bool HBasicBlock::IsSingleTryBoundary() const {
1254 return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsTryBoundary();
David Brazdil46e2a392015-03-16 17:31:52 +00001255}
1256
David Brazdil8d5b8b22015-03-24 10:51:52 +00001257bool HBasicBlock::EndsWithControlFlowInstruction() const {
1258 return !GetInstructions().IsEmpty() && GetLastInstruction()->IsControlFlow();
1259}
1260
David Brazdilb2bd1c52015-03-25 11:17:37 +00001261bool HBasicBlock::EndsWithIf() const {
1262 return !GetInstructions().IsEmpty() && GetLastInstruction()->IsIf();
1263}
1264
David Brazdilffee3d32015-07-06 11:48:53 +01001265bool HBasicBlock::EndsWithTryBoundary() const {
1266 return !GetInstructions().IsEmpty() && GetLastInstruction()->IsTryBoundary();
1267}
1268
David Brazdilb2bd1c52015-03-25 11:17:37 +00001269bool HBasicBlock::HasSinglePhi() const {
1270 return !GetPhis().IsEmpty() && GetFirstPhi()->GetNext() == nullptr;
1271}
1272
David Brazdilffee3d32015-07-06 11:48:53 +01001273bool HTryBoundary::HasSameExceptionHandlersAs(const HTryBoundary& other) const {
Vladimir Marko60584552015-09-03 13:35:12 +00001274 if (GetBlock()->GetSuccessors().size() != other.GetBlock()->GetSuccessors().size()) {
David Brazdilffee3d32015-07-06 11:48:53 +01001275 return false;
1276 }
1277
David Brazdilb618ade2015-07-29 10:31:29 +01001278 // Exception handlers need to be stored in the same order.
1279 for (HExceptionHandlerIterator it1(*this), it2(other);
1280 !it1.Done();
1281 it1.Advance(), it2.Advance()) {
1282 DCHECK(!it2.Done());
1283 if (it1.Current() != it2.Current()) {
David Brazdilffee3d32015-07-06 11:48:53 +01001284 return false;
1285 }
1286 }
1287 return true;
1288}
1289
David Brazdil2d7352b2015-04-20 14:52:42 +01001290size_t HInstructionList::CountSize() const {
1291 size_t size = 0;
1292 HInstruction* current = first_instruction_;
1293 for (; current != nullptr; current = current->GetNext()) {
1294 size++;
1295 }
1296 return size;
1297}
1298
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001299void HInstructionList::SetBlockOfInstructions(HBasicBlock* block) const {
1300 for (HInstruction* current = first_instruction_;
1301 current != nullptr;
1302 current = current->GetNext()) {
1303 current->SetBlock(block);
1304 }
1305}
1306
1307void HInstructionList::AddAfter(HInstruction* cursor, const HInstructionList& instruction_list) {
1308 DCHECK(Contains(cursor));
1309 if (!instruction_list.IsEmpty()) {
1310 if (cursor == last_instruction_) {
1311 last_instruction_ = instruction_list.last_instruction_;
1312 } else {
1313 cursor->next_->previous_ = instruction_list.last_instruction_;
1314 }
1315 instruction_list.last_instruction_->next_ = cursor->next_;
1316 cursor->next_ = instruction_list.first_instruction_;
1317 instruction_list.first_instruction_->previous_ = cursor;
1318 }
1319}
1320
1321void HInstructionList::Add(const HInstructionList& instruction_list) {
David Brazdil46e2a392015-03-16 17:31:52 +00001322 if (IsEmpty()) {
1323 first_instruction_ = instruction_list.first_instruction_;
1324 last_instruction_ = instruction_list.last_instruction_;
1325 } else {
1326 AddAfter(last_instruction_, instruction_list);
1327 }
1328}
1329
David Brazdil2d7352b2015-04-20 14:52:42 +01001330void HBasicBlock::DisconnectAndDelete() {
1331 // Dominators must be removed after all the blocks they dominate. This way
1332 // a loop header is removed last, a requirement for correct loop information
1333 // iteration.
Vladimir Marko60584552015-09-03 13:35:12 +00001334 DCHECK(dominated_blocks_.empty());
David Brazdil46e2a392015-03-16 17:31:52 +00001335
David Brazdil2d7352b2015-04-20 14:52:42 +01001336 // Remove the block from all loops it is included in.
1337 for (HLoopInformationOutwardIterator it(*this); !it.Done(); it.Advance()) {
1338 HLoopInformation* loop_info = it.Current();
1339 loop_info->Remove(this);
1340 if (loop_info->IsBackEdge(*this)) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001341 // If this was the last back edge of the loop, we deliberately leave the
1342 // loop in an inconsistent state and will fail SSAChecker unless the
1343 // entire loop is removed during the pass.
David Brazdil2d7352b2015-04-20 14:52:42 +01001344 loop_info->RemoveBackEdge(this);
1345 }
1346 }
1347
1348 // Disconnect the block from its predecessors and update their control-flow
1349 // instructions.
Vladimir Marko60584552015-09-03 13:35:12 +00001350 for (HBasicBlock* predecessor : predecessors_) {
David Brazdil2d7352b2015-04-20 14:52:42 +01001351 HInstruction* last_instruction = predecessor->GetLastInstruction();
David Brazdil2d7352b2015-04-20 14:52:42 +01001352 predecessor->RemoveSuccessor(this);
Mark Mendellfe57faa2015-09-18 09:26:15 -04001353 uint32_t num_pred_successors = predecessor->GetSuccessors().size();
1354 if (num_pred_successors == 1u) {
1355 // If we have one successor after removing one, then we must have
1356 // had an HIf or HPackedSwitch, as they have more than one successor.
1357 // Replace those with a HGoto.
1358 DCHECK(last_instruction->IsIf() || last_instruction->IsPackedSwitch());
1359 predecessor->RemoveInstruction(last_instruction);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001360 predecessor->AddInstruction(new (graph_->GetArena()) HGoto(last_instruction->GetDexPc()));
Mark Mendellfe57faa2015-09-18 09:26:15 -04001361 } else if (num_pred_successors == 0u) {
David Brazdil2d7352b2015-04-20 14:52:42 +01001362 // The predecessor has no remaining successors and therefore must be dead.
1363 // We deliberately leave it without a control-flow instruction so that the
1364 // SSAChecker fails unless it is not removed during the pass too.
Mark Mendellfe57faa2015-09-18 09:26:15 -04001365 predecessor->RemoveInstruction(last_instruction);
1366 } else {
1367 // There are multiple successors left. This must come from a HPackedSwitch
1368 // and we are in the middle of removing the HPackedSwitch. Like above, leave
1369 // this alone, and the SSAChecker will fail if it is not removed as well.
1370 DCHECK(last_instruction->IsPackedSwitch());
David Brazdil2d7352b2015-04-20 14:52:42 +01001371 }
David Brazdil46e2a392015-03-16 17:31:52 +00001372 }
Vladimir Marko60584552015-09-03 13:35:12 +00001373 predecessors_.clear();
David Brazdil2d7352b2015-04-20 14:52:42 +01001374
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +01001375 // Disconnect the block from its successors and update their phis.
Vladimir Marko60584552015-09-03 13:35:12 +00001376 for (HBasicBlock* successor : successors_) {
David Brazdil2d7352b2015-04-20 14:52:42 +01001377 // Delete this block from the list of predecessors.
1378 size_t this_index = successor->GetPredecessorIndexOf(this);
Vladimir Marko60584552015-09-03 13:35:12 +00001379 successor->predecessors_.erase(successor->predecessors_.begin() + this_index);
David Brazdil2d7352b2015-04-20 14:52:42 +01001380
1381 // Check that `successor` has other predecessors, otherwise `this` is the
1382 // dominator of `successor` which violates the order DCHECKed at the top.
Vladimir Marko60584552015-09-03 13:35:12 +00001383 DCHECK(!successor->predecessors_.empty());
David Brazdil2d7352b2015-04-20 14:52:42 +01001384
David Brazdil2d7352b2015-04-20 14:52:42 +01001385 // Remove this block's entries in the successor's phis.
Vladimir Marko60584552015-09-03 13:35:12 +00001386 if (successor->predecessors_.size() == 1u) {
David Brazdil2d7352b2015-04-20 14:52:42 +01001387 // The successor has just one predecessor left. Replace phis with the only
1388 // remaining input.
1389 for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
1390 HPhi* phi = phi_it.Current()->AsPhi();
1391 phi->ReplaceWith(phi->InputAt(1 - this_index));
1392 successor->RemovePhi(phi);
1393 }
1394 } else {
1395 for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
1396 phi_it.Current()->AsPhi()->RemoveInputAt(this_index);
1397 }
1398 }
1399 }
Vladimir Marko60584552015-09-03 13:35:12 +00001400 successors_.clear();
David Brazdil2d7352b2015-04-20 14:52:42 +01001401
1402 // Disconnect from the dominator.
1403 dominator_->RemoveDominatedBlock(this);
1404 SetDominator(nullptr);
1405
1406 // Delete from the graph. The function safely deletes remaining instructions
1407 // and updates the reverse post order.
1408 graph_->DeleteDeadBlock(this);
1409 SetGraph(nullptr);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001410}
1411
1412void HBasicBlock::MergeWith(HBasicBlock* other) {
David Brazdil2d7352b2015-04-20 14:52:42 +01001413 DCHECK_EQ(GetGraph(), other->GetGraph());
Vladimir Marko60584552015-09-03 13:35:12 +00001414 DCHECK(ContainsElement(dominated_blocks_, other));
1415 DCHECK_EQ(GetSingleSuccessor(), other);
1416 DCHECK_EQ(other->GetSinglePredecessor(), this);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001417 DCHECK(other->GetPhis().IsEmpty());
1418
David Brazdil2d7352b2015-04-20 14:52:42 +01001419 // Move instructions from `other` to `this`.
1420 DCHECK(EndsWithControlFlowInstruction());
1421 RemoveInstruction(GetLastInstruction());
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001422 instructions_.Add(other->GetInstructions());
David Brazdil2d7352b2015-04-20 14:52:42 +01001423 other->instructions_.SetBlockOfInstructions(this);
1424 other->instructions_.Clear();
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001425
David Brazdil2d7352b2015-04-20 14:52:42 +01001426 // Remove `other` from the loops it is included in.
1427 for (HLoopInformationOutwardIterator it(*other); !it.Done(); it.Advance()) {
1428 HLoopInformation* loop_info = it.Current();
1429 loop_info->Remove(other);
1430 if (loop_info->IsBackEdge(*other)) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001431 loop_info->ReplaceBackEdge(other, this);
David Brazdil2d7352b2015-04-20 14:52:42 +01001432 }
1433 }
1434
1435 // Update links to the successors of `other`.
Vladimir Marko60584552015-09-03 13:35:12 +00001436 successors_.clear();
1437 while (!other->successors_.empty()) {
1438 HBasicBlock* successor = other->GetSuccessor(0);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001439 successor->ReplacePredecessor(other, this);
1440 }
1441
David Brazdil2d7352b2015-04-20 14:52:42 +01001442 // Update the dominator tree.
Vladimir Marko60584552015-09-03 13:35:12 +00001443 RemoveDominatedBlock(other);
1444 for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
1445 dominated_blocks_.push_back(dominated);
David Brazdil2d7352b2015-04-20 14:52:42 +01001446 dominated->SetDominator(this);
1447 }
Vladimir Marko60584552015-09-03 13:35:12 +00001448 other->dominated_blocks_.clear();
David Brazdil2d7352b2015-04-20 14:52:42 +01001449 other->dominator_ = nullptr;
1450
1451 // Clear the list of predecessors of `other` in preparation of deleting it.
Vladimir Marko60584552015-09-03 13:35:12 +00001452 other->predecessors_.clear();
David Brazdil2d7352b2015-04-20 14:52:42 +01001453
1454 // Delete `other` from the graph. The function updates reverse post order.
1455 graph_->DeleteDeadBlock(other);
1456 other->SetGraph(nullptr);
1457}
1458
1459void HBasicBlock::MergeWithInlined(HBasicBlock* other) {
1460 DCHECK_NE(GetGraph(), other->GetGraph());
Vladimir Marko60584552015-09-03 13:35:12 +00001461 DCHECK(GetDominatedBlocks().empty());
1462 DCHECK(GetSuccessors().empty());
David Brazdil2d7352b2015-04-20 14:52:42 +01001463 DCHECK(!EndsWithControlFlowInstruction());
Vladimir Marko60584552015-09-03 13:35:12 +00001464 DCHECK(other->GetSinglePredecessor()->IsEntryBlock());
David Brazdil2d7352b2015-04-20 14:52:42 +01001465 DCHECK(other->GetPhis().IsEmpty());
1466 DCHECK(!other->IsInLoop());
1467
1468 // Move instructions from `other` to `this`.
1469 instructions_.Add(other->GetInstructions());
1470 other->instructions_.SetBlockOfInstructions(this);
1471
1472 // Update links to the successors of `other`.
Vladimir Marko60584552015-09-03 13:35:12 +00001473 successors_.clear();
1474 while (!other->successors_.empty()) {
1475 HBasicBlock* successor = other->GetSuccessor(0);
David Brazdil2d7352b2015-04-20 14:52:42 +01001476 successor->ReplacePredecessor(other, this);
1477 }
1478
1479 // Update the dominator tree.
Vladimir Marko60584552015-09-03 13:35:12 +00001480 for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
1481 dominated_blocks_.push_back(dominated);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001482 dominated->SetDominator(this);
1483 }
Vladimir Marko60584552015-09-03 13:35:12 +00001484 other->dominated_blocks_.clear();
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001485 other->dominator_ = nullptr;
1486 other->graph_ = nullptr;
1487}
1488
1489void HBasicBlock::ReplaceWith(HBasicBlock* other) {
Vladimir Marko60584552015-09-03 13:35:12 +00001490 while (!GetPredecessors().empty()) {
1491 HBasicBlock* predecessor = GetPredecessor(0);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001492 predecessor->ReplaceSuccessor(this, other);
1493 }
Vladimir Marko60584552015-09-03 13:35:12 +00001494 while (!GetSuccessors().empty()) {
1495 HBasicBlock* successor = GetSuccessor(0);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001496 successor->ReplacePredecessor(this, other);
1497 }
Vladimir Marko60584552015-09-03 13:35:12 +00001498 for (HBasicBlock* dominated : GetDominatedBlocks()) {
1499 other->AddDominatedBlock(dominated);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001500 }
1501 GetDominator()->ReplaceDominatedBlock(this, other);
1502 other->SetDominator(GetDominator());
1503 dominator_ = nullptr;
1504 graph_ = nullptr;
1505}
1506
1507// Create space in `blocks` for adding `number_of_new_blocks` entries
1508// starting at location `at`. Blocks after `at` are moved accordingly.
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001509static void MakeRoomFor(ArenaVector<HBasicBlock*>* blocks,
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001510 size_t number_of_new_blocks,
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001511 size_t after) {
1512 DCHECK_LT(after, blocks->size());
1513 size_t old_size = blocks->size();
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001514 size_t new_size = old_size + number_of_new_blocks;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001515 blocks->resize(new_size);
1516 std::copy_backward(blocks->begin() + after + 1u, blocks->begin() + old_size, blocks->end());
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001517}
1518
David Brazdil2d7352b2015-04-20 14:52:42 +01001519void HGraph::DeleteDeadBlock(HBasicBlock* block) {
1520 DCHECK_EQ(block->GetGraph(), this);
Vladimir Marko60584552015-09-03 13:35:12 +00001521 DCHECK(block->GetSuccessors().empty());
1522 DCHECK(block->GetPredecessors().empty());
1523 DCHECK(block->GetDominatedBlocks().empty());
David Brazdil2d7352b2015-04-20 14:52:42 +01001524 DCHECK(block->GetDominator() == nullptr);
1525
1526 for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
1527 block->RemoveInstruction(it.Current());
1528 }
1529 for (HBackwardInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
1530 block->RemovePhi(it.Current()->AsPhi());
1531 }
1532
David Brazdilc7af85d2015-05-26 12:05:55 +01001533 if (block->IsExitBlock()) {
1534 exit_block_ = nullptr;
1535 }
1536
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001537 RemoveElement(reverse_post_order_, block);
1538 blocks_[block->GetBlockId()] = nullptr;
David Brazdil2d7352b2015-04-20 14:52:42 +01001539}
1540
Calin Juravle2e768302015-07-28 14:41:11 +00001541HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
David Brazdilc7af85d2015-05-26 12:05:55 +01001542 DCHECK(HasExitBlock()) << "Unimplemented scenario";
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001543 // Update the environments in this graph to have the invoke's environment
1544 // as parent.
1545 {
1546 HReversePostOrderIterator it(*this);
1547 it.Advance(); // Skip the entry block, we do not need to update the entry's suspend check.
1548 for (; !it.Done(); it.Advance()) {
1549 HBasicBlock* block = it.Current();
1550 for (HInstructionIterator instr_it(block->GetInstructions());
1551 !instr_it.Done();
1552 instr_it.Advance()) {
1553 HInstruction* current = instr_it.Current();
1554 if (current->NeedsEnvironment()) {
1555 current->GetEnvironment()->SetAndCopyParentChain(
1556 outer_graph->GetArena(), invoke->GetEnvironment());
1557 }
1558 }
1559 }
1560 }
1561 outer_graph->UpdateMaximumNumberOfOutVRegs(GetMaximumNumberOfOutVRegs());
1562 if (HasBoundsChecks()) {
1563 outer_graph->SetHasBoundsChecks(true);
1564 }
1565
Calin Juravle2e768302015-07-28 14:41:11 +00001566 HInstruction* return_value = nullptr;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001567 if (GetBlocks().size() == 3) {
Nicolas Geoffraybe31ff92015-02-04 14:52:20 +00001568 // Simple case of an entry block, a body block, and an exit block.
1569 // Put the body block's instruction into `invoke`'s block.
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001570 HBasicBlock* body = GetBlock(1);
1571 DCHECK(GetBlock(0)->IsEntryBlock());
1572 DCHECK(GetBlock(2)->IsExitBlock());
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001573 DCHECK(!body->IsExitBlock());
1574 HInstruction* last = body->GetLastInstruction();
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001575
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001576 invoke->GetBlock()->instructions_.AddAfter(invoke, body->GetInstructions());
1577 body->GetInstructions().SetBlockOfInstructions(invoke->GetBlock());
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001578
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001579 // Replace the invoke with the return value of the inlined graph.
1580 if (last->IsReturn()) {
Calin Juravle2e768302015-07-28 14:41:11 +00001581 return_value = last->InputAt(0);
1582 invoke->ReplaceWith(return_value);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001583 } else {
1584 DCHECK(last->IsReturnVoid());
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001585 }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001586
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001587 invoke->GetBlock()->RemoveInstruction(last);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001588 } else {
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001589 // Need to inline multiple blocks. We split `invoke`'s block
1590 // into two blocks, merge the first block of the inlined graph into
Nicolas Geoffraybe31ff92015-02-04 14:52:20 +00001591 // the first half, and replace the exit block of the inlined graph
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001592 // with the second half.
1593 ArenaAllocator* allocator = outer_graph->GetArena();
1594 HBasicBlock* at = invoke->GetBlock();
1595 HBasicBlock* to = at->SplitAfter(invoke);
1596
Vladimir Marko60584552015-09-03 13:35:12 +00001597 HBasicBlock* first = entry_block_->GetSuccessor(0);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001598 DCHECK(!first->IsInLoop());
David Brazdil2d7352b2015-04-20 14:52:42 +01001599 at->MergeWithInlined(first);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001600 exit_block_->ReplaceWith(to);
1601
1602 // Update all predecessors of the exit block (now the `to` block)
Nicolas Geoffray817bce72015-02-24 13:35:38 +00001603 // to not `HReturn` but `HGoto` instead.
Vladimir Marko60584552015-09-03 13:35:12 +00001604 bool returns_void = to->GetPredecessor(0)->GetLastInstruction()->IsReturnVoid();
1605 if (to->GetPredecessors().size() == 1) {
1606 HBasicBlock* predecessor = to->GetPredecessor(0);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001607 HInstruction* last = predecessor->GetLastInstruction();
Nicolas Geoffray817bce72015-02-24 13:35:38 +00001608 if (!returns_void) {
1609 return_value = last->InputAt(0);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001610 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001611 predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001612 predecessor->RemoveInstruction(last);
Nicolas Geoffray817bce72015-02-24 13:35:38 +00001613 } else {
1614 if (!returns_void) {
1615 // There will be multiple returns.
Nicolas Geoffray4f1a3842015-03-12 10:34:11 +00001616 return_value = new (allocator) HPhi(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001617 allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()), to->GetDexPc());
Nicolas Geoffray817bce72015-02-24 13:35:38 +00001618 to->AddPhi(return_value->AsPhi());
1619 }
Vladimir Marko60584552015-09-03 13:35:12 +00001620 for (HBasicBlock* predecessor : to->GetPredecessors()) {
Nicolas Geoffray817bce72015-02-24 13:35:38 +00001621 HInstruction* last = predecessor->GetLastInstruction();
1622 if (!returns_void) {
1623 return_value->AsPhi()->AddInput(last->InputAt(0));
1624 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001625 predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
Nicolas Geoffray817bce72015-02-24 13:35:38 +00001626 predecessor->RemoveInstruction(last);
1627 }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001628 }
1629
1630 if (return_value != nullptr) {
1631 invoke->ReplaceWith(return_value);
1632 }
1633
1634 // Update the meta information surrounding blocks:
1635 // (1) the graph they are now in,
1636 // (2) the reverse post order of that graph,
1637 // (3) the potential loop information they are now in.
1638
1639 // We don't add the entry block, the exit block, and the first block, which
1640 // has been merged with `at`.
1641 static constexpr int kNumberOfSkippedBlocksInCallee = 3;
1642
1643 // We add the `to` block.
1644 static constexpr int kNumberOfNewBlocksInCaller = 1;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001645 size_t blocks_added = (reverse_post_order_.size() - kNumberOfSkippedBlocksInCallee)
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001646 + kNumberOfNewBlocksInCaller;
1647
1648 // Find the location of `at` in the outer graph's reverse post order. The new
1649 // blocks will be added after it.
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001650 size_t index_of_at = IndexOfElement(outer_graph->reverse_post_order_, at);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001651 MakeRoomFor(&outer_graph->reverse_post_order_, blocks_added, index_of_at);
1652
1653 // Do a reverse post order of the blocks in the callee and do (1), (2),
1654 // and (3) to the blocks that apply.
1655 HLoopInformation* info = at->GetLoopInformation();
1656 for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
1657 HBasicBlock* current = it.Current();
1658 if (current != exit_block_ && current != entry_block_ && current != first) {
1659 DCHECK(!current->IsInLoop());
1660 DCHECK(current->GetGraph() == this);
1661 current->SetGraph(outer_graph);
1662 outer_graph->AddBlock(current);
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001663 outer_graph->reverse_post_order_[++index_of_at] = current;
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001664 if (info != nullptr) {
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001665 current->SetLoopInformation(info);
David Brazdil7d275372015-04-21 16:36:35 +01001666 for (HLoopInformationOutwardIterator loop_it(*at); !loop_it.Done(); loop_it.Advance()) {
1667 loop_it.Current()->Add(current);
1668 }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001669 }
1670 }
1671 }
1672
1673 // Do (1), (2), and (3) to `to`.
1674 to->SetGraph(outer_graph);
1675 outer_graph->AddBlock(to);
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001676 outer_graph->reverse_post_order_[++index_of_at] = to;
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001677 if (info != nullptr) {
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001678 to->SetLoopInformation(info);
David Brazdil7d275372015-04-21 16:36:35 +01001679 for (HLoopInformationOutwardIterator loop_it(*at); !loop_it.Done(); loop_it.Advance()) {
1680 loop_it.Current()->Add(to);
1681 }
David Brazdil46e2a392015-03-16 17:31:52 +00001682 if (info->IsBackEdge(*at)) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001683 // Only `to` can become a back edge, as the inlined blocks
1684 // are predecessors of `to`.
1685 info->ReplaceBackEdge(at, to);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001686 }
1687 }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001688 }
Nicolas Geoffray7c5367b2014-12-17 10:13:46 +00001689
David Brazdil05144f42015-04-16 15:18:00 +01001690 // Update the next instruction id of the outer graph, so that instructions
1691 // added later get bigger ids than those in the inner graph.
1692 outer_graph->SetCurrentInstructionId(GetNextInstructionId());
1693
1694 // Walk over the entry block and:
1695 // - Move constants from the entry block to the outer_graph's entry block,
1696 // - Replace HParameterValue instructions with their real value.
1697 // - Remove suspend checks, that hold an environment.
1698 // We must do this after the other blocks have been inlined, otherwise ids of
1699 // constants could overlap with the inner graph.
Roland Levillain4c0eb422015-04-24 16:43:49 +01001700 size_t parameter_index = 0;
David Brazdil05144f42015-04-16 15:18:00 +01001701 for (HInstructionIterator it(entry_block_->GetInstructions()); !it.Done(); it.Advance()) {
1702 HInstruction* current = it.Current();
1703 if (current->IsNullConstant()) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001704 current->ReplaceWith(outer_graph->GetNullConstant(current->GetDexPc()));
David Brazdil05144f42015-04-16 15:18:00 +01001705 } else if (current->IsIntConstant()) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001706 current->ReplaceWith(outer_graph->GetIntConstant(
1707 current->AsIntConstant()->GetValue(), current->GetDexPc()));
David Brazdil05144f42015-04-16 15:18:00 +01001708 } else if (current->IsLongConstant()) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001709 current->ReplaceWith(outer_graph->GetLongConstant(
1710 current->AsLongConstant()->GetValue(), current->GetDexPc()));
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00001711 } else if (current->IsFloatConstant()) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001712 current->ReplaceWith(outer_graph->GetFloatConstant(
1713 current->AsFloatConstant()->GetValue(), current->GetDexPc()));
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00001714 } else if (current->IsDoubleConstant()) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001715 current->ReplaceWith(outer_graph->GetDoubleConstant(
1716 current->AsDoubleConstant()->GetValue(), current->GetDexPc()));
David Brazdil05144f42015-04-16 15:18:00 +01001717 } else if (current->IsParameterValue()) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01001718 if (kIsDebugBuild
1719 && invoke->IsInvokeStaticOrDirect()
1720 && invoke->AsInvokeStaticOrDirect()->IsStaticWithExplicitClinitCheck()) {
1721 // Ensure we do not use the last input of `invoke`, as it
1722 // contains a clinit check which is not an actual argument.
1723 size_t last_input_index = invoke->InputCount() - 1;
1724 DCHECK(parameter_index != last_input_index);
1725 }
David Brazdil05144f42015-04-16 15:18:00 +01001726 current->ReplaceWith(invoke->InputAt(parameter_index++));
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001727 } else if (current->IsCurrentMethod()) {
1728 current->ReplaceWith(outer_graph->GetCurrentMethod());
David Brazdil05144f42015-04-16 15:18:00 +01001729 } else {
1730 DCHECK(current->IsGoto() || current->IsSuspendCheck());
1731 entry_block_->RemoveInstruction(current);
1732 }
1733 }
1734
Nicolas Geoffray7c5367b2014-12-17 10:13:46 +00001735 // Finally remove the invoke from the caller.
1736 invoke->GetBlock()->RemoveInstruction(invoke);
Calin Juravle2e768302015-07-28 14:41:11 +00001737
1738 return return_value;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001739}
1740
Mingyao Yang3584bce2015-05-19 16:01:59 -07001741/*
1742 * Loop will be transformed to:
1743 * old_pre_header
1744 * |
1745 * if_block
1746 * / \
1747 * dummy_block deopt_block
1748 * \ /
1749 * new_pre_header
1750 * |
1751 * header
1752 */
1753void HGraph::TransformLoopHeaderForBCE(HBasicBlock* header) {
1754 DCHECK(header->IsLoopHeader());
1755 HBasicBlock* pre_header = header->GetDominator();
1756
1757 // Need this to avoid critical edge.
1758 HBasicBlock* if_block = new (arena_) HBasicBlock(this, header->GetDexPc());
1759 // Need this to avoid critical edge.
1760 HBasicBlock* dummy_block = new (arena_) HBasicBlock(this, header->GetDexPc());
1761 HBasicBlock* deopt_block = new (arena_) HBasicBlock(this, header->GetDexPc());
1762 HBasicBlock* new_pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
1763 AddBlock(if_block);
1764 AddBlock(dummy_block);
1765 AddBlock(deopt_block);
1766 AddBlock(new_pre_header);
1767
1768 header->ReplacePredecessor(pre_header, new_pre_header);
Vladimir Marko60584552015-09-03 13:35:12 +00001769 pre_header->successors_.clear();
1770 pre_header->dominated_blocks_.clear();
Mingyao Yang3584bce2015-05-19 16:01:59 -07001771
1772 pre_header->AddSuccessor(if_block);
1773 if_block->AddSuccessor(dummy_block); // True successor
1774 if_block->AddSuccessor(deopt_block); // False successor
1775 dummy_block->AddSuccessor(new_pre_header);
1776 deopt_block->AddSuccessor(new_pre_header);
1777
Vladimir Marko60584552015-09-03 13:35:12 +00001778 pre_header->dominated_blocks_.push_back(if_block);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001779 if_block->SetDominator(pre_header);
Vladimir Marko60584552015-09-03 13:35:12 +00001780 if_block->dominated_blocks_.push_back(dummy_block);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001781 dummy_block->SetDominator(if_block);
Vladimir Marko60584552015-09-03 13:35:12 +00001782 if_block->dominated_blocks_.push_back(deopt_block);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001783 deopt_block->SetDominator(if_block);
Vladimir Marko60584552015-09-03 13:35:12 +00001784 if_block->dominated_blocks_.push_back(new_pre_header);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001785 new_pre_header->SetDominator(if_block);
Vladimir Marko60584552015-09-03 13:35:12 +00001786 new_pre_header->dominated_blocks_.push_back(header);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001787 header->SetDominator(new_pre_header);
1788
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001789 size_t index_of_header = IndexOfElement(reverse_post_order_, header);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001790 MakeRoomFor(&reverse_post_order_, 4, index_of_header - 1);
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001791 reverse_post_order_[index_of_header++] = if_block;
1792 reverse_post_order_[index_of_header++] = dummy_block;
1793 reverse_post_order_[index_of_header++] = deopt_block;
1794 reverse_post_order_[index_of_header++] = new_pre_header;
Mingyao Yang3584bce2015-05-19 16:01:59 -07001795
1796 HLoopInformation* info = pre_header->GetLoopInformation();
1797 if (info != nullptr) {
1798 if_block->SetLoopInformation(info);
1799 dummy_block->SetLoopInformation(info);
1800 deopt_block->SetLoopInformation(info);
1801 new_pre_header->SetLoopInformation(info);
1802 for (HLoopInformationOutwardIterator loop_it(*pre_header);
1803 !loop_it.Done();
1804 loop_it.Advance()) {
1805 loop_it.Current()->Add(if_block);
1806 loop_it.Current()->Add(dummy_block);
1807 loop_it.Current()->Add(deopt_block);
1808 loop_it.Current()->Add(new_pre_header);
1809 }
1810 }
1811}
1812
Calin Juravle2e768302015-07-28 14:41:11 +00001813void HInstruction::SetReferenceTypeInfo(ReferenceTypeInfo rti) {
1814 if (kIsDebugBuild) {
1815 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1816 ScopedObjectAccess soa(Thread::Current());
1817 DCHECK(rti.IsValid()) << "Invalid RTI for " << DebugName();
1818 if (IsBoundType()) {
1819 // Having the test here spares us from making the method virtual just for
1820 // the sake of a DCHECK.
1821 ReferenceTypeInfo upper_bound_rti = AsBoundType()->GetUpperBound();
1822 DCHECK(upper_bound_rti.IsSupertypeOf(rti))
1823 << " upper_bound_rti: " << upper_bound_rti
1824 << " rti: " << rti;
David Brazdilbaf89b82015-09-15 11:36:54 +01001825 DCHECK(!upper_bound_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes() || rti.IsExact());
Calin Juravle2e768302015-07-28 14:41:11 +00001826 }
1827 }
1828 reference_type_info_ = rti;
1829}
1830
1831ReferenceTypeInfo::ReferenceTypeInfo() : type_handle_(TypeHandle()), is_exact_(false) {}
1832
1833ReferenceTypeInfo::ReferenceTypeInfo(TypeHandle type_handle, bool is_exact)
1834 : type_handle_(type_handle), is_exact_(is_exact) {
1835 if (kIsDebugBuild) {
1836 ScopedObjectAccess soa(Thread::Current());
1837 DCHECK(IsValidHandle(type_handle));
1838 }
1839}
1840
Calin Juravleacf735c2015-02-12 15:25:22 +00001841std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs) {
1842 ScopedObjectAccess soa(Thread::Current());
1843 os << "["
Calin Juravle2e768302015-07-28 14:41:11 +00001844 << " is_valid=" << rhs.IsValid()
1845 << " type=" << (!rhs.IsValid() ? "?" : PrettyClass(rhs.GetTypeHandle().Get()))
Calin Juravleacf735c2015-02-12 15:25:22 +00001846 << " is_exact=" << rhs.IsExact()
1847 << " ]";
1848 return os;
1849}
1850
Mark Mendellc4701932015-04-10 13:18:51 -04001851bool HInstruction::HasAnyEnvironmentUseBefore(HInstruction* other) {
1852 // For now, assume that instructions in different blocks may use the
1853 // environment.
1854 // TODO: Use the control flow to decide if this is true.
1855 if (GetBlock() != other->GetBlock()) {
1856 return true;
1857 }
1858
1859 // We know that we are in the same block. Walk from 'this' to 'other',
1860 // checking to see if there is any instruction with an environment.
1861 HInstruction* current = this;
1862 for (; current != other && current != nullptr; current = current->GetNext()) {
1863 // This is a conservative check, as the instruction result may not be in
1864 // the referenced environment.
1865 if (current->HasEnvironment()) {
1866 return true;
1867 }
1868 }
1869
1870 // We should have been called with 'this' before 'other' in the block.
1871 // Just confirm this.
1872 DCHECK(current != nullptr);
1873 return false;
1874}
1875
1876void HInstruction::RemoveEnvironmentUsers() {
1877 for (HUseIterator<HEnvironment*> use_it(GetEnvUses()); !use_it.Done(); use_it.Advance()) {
1878 HUseListNode<HEnvironment*>* user_node = use_it.Current();
1879 HEnvironment* user = user_node->GetUser();
1880 user->SetRawEnvAt(user_node->GetIndex(), nullptr);
1881 }
1882 env_uses_.Clear();
1883}
1884
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001885} // namespace art