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