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