xref: /aosp_15_r20/art/compiler/optimizing/superblock_cloner.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_SUPERBLOCK_CLONER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_SUPERBLOCK_CLONER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/arena_bit_vector.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/bit_vector-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
24*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker class InductionVarRange;
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker static const bool kSuperblockClonerLogging = false;
31*795d594fSAndroid Build Coastguard Worker static const bool kSuperblockClonerVerify = false;
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker // Represents an edge between two HBasicBlocks.
34*795d594fSAndroid Build Coastguard Worker //
35*795d594fSAndroid Build Coastguard Worker // Note: objects of this class are small - pass them by value.
36*795d594fSAndroid Build Coastguard Worker class HEdge : public ArenaObject<kArenaAllocSuperblockCloner> {
37*795d594fSAndroid Build Coastguard Worker  public:
HEdge(HBasicBlock * from,HBasicBlock * to)38*795d594fSAndroid Build Coastguard Worker   HEdge(HBasicBlock* from, HBasicBlock* to) : from_(from->GetBlockId()), to_(to->GetBlockId()) {
39*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(to_, kInvalidBlockId);
40*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(from_, kInvalidBlockId);
41*795d594fSAndroid Build Coastguard Worker   }
HEdge(uint32_t from,uint32_t to)42*795d594fSAndroid Build Coastguard Worker   HEdge(uint32_t from, uint32_t to) : from_(from), to_(to) {
43*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(to_, kInvalidBlockId);
44*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(from_, kInvalidBlockId);
45*795d594fSAndroid Build Coastguard Worker   }
HEdge()46*795d594fSAndroid Build Coastguard Worker   HEdge() : from_(kInvalidBlockId), to_(kInvalidBlockId) {}
47*795d594fSAndroid Build Coastguard Worker 
GetFrom()48*795d594fSAndroid Build Coastguard Worker   uint32_t GetFrom() const { return from_; }
GetTo()49*795d594fSAndroid Build Coastguard Worker   uint32_t GetTo() const { return to_; }
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker   bool operator==(const HEdge& other) const {
52*795d594fSAndroid Build Coastguard Worker     return this->from_ == other.from_ && this->to_ == other.to_;
53*795d594fSAndroid Build Coastguard Worker   }
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker   bool operator!=(const HEdge& other) const { return !operator==(other); }
56*795d594fSAndroid Build Coastguard Worker   void Dump(std::ostream& stream) const;
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker   // Returns whether an edge represents a valid edge in CF graph: whether the from_ block
59*795d594fSAndroid Build Coastguard Worker   // has to_ block as a successor.
IsValid()60*795d594fSAndroid Build Coastguard Worker   bool IsValid() const { return from_ != kInvalidBlockId && to_ != kInvalidBlockId; }
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker  private:
63*795d594fSAndroid Build Coastguard Worker   // Predecessor block id.
64*795d594fSAndroid Build Coastguard Worker   uint32_t from_;
65*795d594fSAndroid Build Coastguard Worker   // Successor block id.
66*795d594fSAndroid Build Coastguard Worker   uint32_t to_;
67*795d594fSAndroid Build Coastguard Worker };
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker // Returns whether a HEdge edge corresponds to an existing edge in the graph.
IsEdgeValid(HEdge edge,HGraph * graph)70*795d594fSAndroid Build Coastguard Worker inline bool IsEdgeValid(HEdge edge, HGraph* graph) {
71*795d594fSAndroid Build Coastguard Worker   if (!edge.IsValid()) {
72*795d594fSAndroid Build Coastguard Worker     return false;
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker   uint32_t from = edge.GetFrom();
75*795d594fSAndroid Build Coastguard Worker   uint32_t to = edge.GetTo();
76*795d594fSAndroid Build Coastguard Worker   if (from >= graph->GetBlocks().size() || to >= graph->GetBlocks().size()) {
77*795d594fSAndroid Build Coastguard Worker     return false;
78*795d594fSAndroid Build Coastguard Worker   }
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   HBasicBlock* block_from = graph->GetBlocks()[from];
81*795d594fSAndroid Build Coastguard Worker   HBasicBlock* block_to = graph->GetBlocks()[to];
82*795d594fSAndroid Build Coastguard Worker   if (block_from == nullptr || block_to == nullptr) {
83*795d594fSAndroid Build Coastguard Worker     return false;
84*795d594fSAndroid Build Coastguard Worker   }
85*795d594fSAndroid Build Coastguard Worker 
86*795d594fSAndroid Build Coastguard Worker   return block_from->HasSuccessor(block_to, 0);
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker // SuperblockCloner provides a feature of cloning subgraphs in a smart, high level way without
90*795d594fSAndroid Build Coastguard Worker // fine grain manipulation with IR; data flow and graph properties are resolved/adjusted
91*795d594fSAndroid Build Coastguard Worker // automatically. The clone transformation is defined by specifying a set of basic blocks to copy
92*795d594fSAndroid Build Coastguard Worker // and a set of rules how to treat edges, remap their successors. By using this approach such
93*795d594fSAndroid Build Coastguard Worker // optimizations as Branch Target Expansion, Loop Peeling, Loop Unrolling, Loop Versioning can be
94*795d594fSAndroid Build Coastguard Worker // implemented.
95*795d594fSAndroid Build Coastguard Worker //
96*795d594fSAndroid Build Coastguard Worker // The idea of the transformation is based on "Superblock cloning" technique described in the book
97*795d594fSAndroid Build Coastguard Worker // "Engineering a Compiler. Second Edition", Keith D. Cooper, Linda Torczon, Rice University
98*795d594fSAndroid Build Coastguard Worker // Houston, Texas. 2nd edition, Morgan Kaufmann. The original paper is "The Superblock: An Efective
99*795d594fSAndroid Build Coastguard Worker // Technique for VLIW and Superscalar Compilation" by Hwu, W.M.W., Mahlke, S.A., Chen, W.Y. et al.
100*795d594fSAndroid Build Coastguard Worker // J Supercomput (1993) 7: 229. doi:10.1007/BF01205185.
101*795d594fSAndroid Build Coastguard Worker //
102*795d594fSAndroid Build Coastguard Worker // There are two states of the IR graph: original graph (before the transformation) and
103*795d594fSAndroid Build Coastguard Worker // copy graph (after).
104*795d594fSAndroid Build Coastguard Worker //
105*795d594fSAndroid Build Coastguard Worker // Before the transformation:
106*795d594fSAndroid Build Coastguard Worker // Defining a set of basic block to copy (orig_bb_set) partitions all of the edges in the original
107*795d594fSAndroid Build Coastguard Worker // graph into 4 categories/sets (use the following notation for edges: "(pred, succ)",
108*795d594fSAndroid Build Coastguard Worker // where pred, succ - basic blocks):
109*795d594fSAndroid Build Coastguard Worker //  - internal - pred, succ are members of ‘orig_bb_set’.
110*795d594fSAndroid Build Coastguard Worker //  - outside  - pred, succ are not members of ‘orig_bb_set’.
111*795d594fSAndroid Build Coastguard Worker //  - incoming - pred is not a member of ‘orig_bb_set’, succ is.
112*795d594fSAndroid Build Coastguard Worker //  - outgoing - pred is a member of ‘orig_bb_set’, succ is not.
113*795d594fSAndroid Build Coastguard Worker //
114*795d594fSAndroid Build Coastguard Worker // Transformation:
115*795d594fSAndroid Build Coastguard Worker //
116*795d594fSAndroid Build Coastguard Worker // 1. Initial cloning:
117*795d594fSAndroid Build Coastguard Worker //   1.1. For each ‘orig_block’ in orig_bb_set create a copy ‘copy_block’; these new blocks
118*795d594fSAndroid Build Coastguard Worker //        form ‘copy_bb_set’.
119*795d594fSAndroid Build Coastguard Worker //   1.2. For each edge (X, Y) from internal set create an edge (X_1, Y_1) where X_1, Y_1 are the
120*795d594fSAndroid Build Coastguard Worker //        copies of X, Y basic blocks correspondingly; these new edges form ‘copy_internal’ edge
121*795d594fSAndroid Build Coastguard Worker //        set.
122*795d594fSAndroid Build Coastguard Worker //   1.3. For each edge (X, Y) from outgoing set create an edge (X_1, Y_1) where X_1, Y_1 are the
123*795d594fSAndroid Build Coastguard Worker //        copies of X, Y basic blocks correspondingly; these new edges form ‘copy_outgoing’ edge
124*795d594fSAndroid Build Coastguard Worker //        set.
125*795d594fSAndroid Build Coastguard Worker // 2. Successors remapping.
126*795d594fSAndroid Build Coastguard Worker //   2.1. 'remap_orig_internal’ - set of edges (X, Y) from ‘orig_bb_set’ whose successors should
127*795d594fSAndroid Build Coastguard Worker //        be remapped to copy nodes: ((X, Y) will be transformed into (X, Y_1)).
128*795d594fSAndroid Build Coastguard Worker //   2.2. ‘remap_copy_internal’ - set of edges (X_1, Y_1) from ‘copy_bb_set’ whose successors
129*795d594fSAndroid Build Coastguard Worker //        should be remapped to copy nodes: (X_1, Y_1) will be transformed into (X_1, Y)).
130*795d594fSAndroid Build Coastguard Worker //   2.3. 'remap_incoming’ - set of edges (X, Y) from the ‘incoming’ edge set in the original graph
131*795d594fSAndroid Build Coastguard Worker //        whose successors should be remapped to copies nodes: ((X, Y) will be transformed into
132*795d594fSAndroid Build Coastguard Worker //        (X, Y_1)).
133*795d594fSAndroid Build Coastguard Worker // 3. Adjust control flow structures and relations (dominance, reverse post order, loops, etc).
134*795d594fSAndroid Build Coastguard Worker // 4. Fix/resolve data flow.
135*795d594fSAndroid Build Coastguard Worker // 5. Do cleanups e.g. critical edges splitting.
136*795d594fSAndroid Build Coastguard Worker //
137*795d594fSAndroid Build Coastguard Worker class SuperblockCloner : public ValueObject {
138*795d594fSAndroid Build Coastguard Worker  public:
139*795d594fSAndroid Build Coastguard Worker   // TODO: Investigate optimal types for the containers.
140*795d594fSAndroid Build Coastguard Worker   using HBasicBlockMap = ArenaSafeMap<HBasicBlock*, HBasicBlock*>;
141*795d594fSAndroid Build Coastguard Worker   using HInstructionMap = ArenaSafeMap<HInstruction*, HInstruction*>;
142*795d594fSAndroid Build Coastguard Worker   using HBasicBlockSet = ArenaBitVector;
143*795d594fSAndroid Build Coastguard Worker   using HEdgeSet = ArenaHashSet<HEdge>;
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   SuperblockCloner(HGraph* graph,
146*795d594fSAndroid Build Coastguard Worker                    const HBasicBlockSet* orig_bb_set,
147*795d594fSAndroid Build Coastguard Worker                    HBasicBlockMap* bb_map,
148*795d594fSAndroid Build Coastguard Worker                    HInstructionMap* hir_map,
149*795d594fSAndroid Build Coastguard Worker                    InductionVarRange* induction_range);
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker   // Sets edge successor remapping info specified by corresponding edge sets.
152*795d594fSAndroid Build Coastguard Worker   void SetSuccessorRemappingInfo(const HEdgeSet* remap_orig_internal,
153*795d594fSAndroid Build Coastguard Worker                                  const HEdgeSet* remap_copy_internal,
154*795d594fSAndroid Build Coastguard Worker                                  const HEdgeSet* remap_incoming);
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker   // Returns whether the specified subgraph is copyable.
157*795d594fSAndroid Build Coastguard Worker   // TODO: Start from small range of graph patterns then extend it.
158*795d594fSAndroid Build Coastguard Worker   bool IsSubgraphClonable() const;
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   // Returns whether selected subgraph satisfies the criteria for fast data flow resolution
161*795d594fSAndroid Build Coastguard Worker   // when iterative DF algorithm is not required and dominators/instructions inputs can be
162*795d594fSAndroid Build Coastguard Worker   // trivially adjusted.
163*795d594fSAndroid Build Coastguard Worker   //
164*795d594fSAndroid Build Coastguard Worker   // TODO: formally describe the criteria.
165*795d594fSAndroid Build Coastguard Worker   //
166*795d594fSAndroid Build Coastguard Worker   // Loop peeling, unrolling and versioning satisfy the criteria.
167*795d594fSAndroid Build Coastguard Worker   bool IsFastCase() const;
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker   // Runs the copy algorithm according to the description.
170*795d594fSAndroid Build Coastguard Worker   void Run();
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker   // Cleans up the graph after transformation: splits critical edges, recalculates control flow
173*795d594fSAndroid Build Coastguard Worker   // information (back-edges, dominators, loop info, etc), eliminates redundant phis.
174*795d594fSAndroid Build Coastguard Worker   void CleanUp();
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker   // Returns a clone of a basic block (orig_block).
177*795d594fSAndroid Build Coastguard Worker   //
178*795d594fSAndroid Build Coastguard Worker   //  - The copy block will have no successors/predecessors; they should be set up manually.
179*795d594fSAndroid Build Coastguard Worker   //  - For each instruction in the orig_block a copy is created and inserted into the copy block;
180*795d594fSAndroid Build Coastguard Worker   //    this correspondence is recorded in the map (old instruction, new instruction).
181*795d594fSAndroid Build Coastguard Worker   //  - Graph HIR is not valid after this transformation: all of the HIRs have their inputs the
182*795d594fSAndroid Build Coastguard Worker   //    same, as in the original block, PHIs do not reflect a correct correspondence between the
183*795d594fSAndroid Build Coastguard Worker   //    value and predecessors (as the copy block has no predecessors by now), etc.
184*795d594fSAndroid Build Coastguard Worker   HBasicBlock* CloneBasicBlock(const HBasicBlock* orig_block);
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker   // Creates a clone for each basic blocks in orig_bb_set adding corresponding entries into bb_map_
187*795d594fSAndroid Build Coastguard Worker   // and hir_map_.
188*795d594fSAndroid Build Coastguard Worker   void CloneBasicBlocks();
189*795d594fSAndroid Build Coastguard Worker 
GetInstrCopy(HInstruction * orig_instr)190*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInstrCopy(HInstruction* orig_instr) const {
191*795d594fSAndroid Build Coastguard Worker     auto copy_input_iter = hir_map_->find(orig_instr);
192*795d594fSAndroid Build Coastguard Worker     DCHECK(copy_input_iter != hir_map_->end());
193*795d594fSAndroid Build Coastguard Worker     return copy_input_iter->second;
194*795d594fSAndroid Build Coastguard Worker   }
195*795d594fSAndroid Build Coastguard Worker 
GetBlockCopy(HBasicBlock * orig_block)196*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetBlockCopy(HBasicBlock* orig_block) const {
197*795d594fSAndroid Build Coastguard Worker     HBasicBlock* block = bb_map_->Get(orig_block);
198*795d594fSAndroid Build Coastguard Worker     DCHECK(block != nullptr);
199*795d594fSAndroid Build Coastguard Worker     return block;
200*795d594fSAndroid Build Coastguard Worker   }
201*795d594fSAndroid Build Coastguard Worker 
GetInstrOrig(HInstruction * copy_instr)202*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInstrOrig(HInstruction* copy_instr) const {
203*795d594fSAndroid Build Coastguard Worker     for (auto it : *hir_map_) {
204*795d594fSAndroid Build Coastguard Worker       if (it.second == copy_instr) {
205*795d594fSAndroid Build Coastguard Worker         return it.first;
206*795d594fSAndroid Build Coastguard Worker       }
207*795d594fSAndroid Build Coastguard Worker     }
208*795d594fSAndroid Build Coastguard Worker     return nullptr;
209*795d594fSAndroid Build Coastguard Worker   }
210*795d594fSAndroid Build Coastguard Worker 
IsInOrigBBSet(uint32_t block_id)211*795d594fSAndroid Build Coastguard Worker   bool IsInOrigBBSet(uint32_t block_id) const {
212*795d594fSAndroid Build Coastguard Worker     return orig_bb_set_.IsBitSet(block_id);
213*795d594fSAndroid Build Coastguard Worker   }
214*795d594fSAndroid Build Coastguard Worker 
IsInOrigBBSet(const HBasicBlock * block)215*795d594fSAndroid Build Coastguard Worker   bool IsInOrigBBSet(const HBasicBlock* block) const {
216*795d594fSAndroid Build Coastguard Worker     return IsInOrigBBSet(block->GetBlockId());
217*795d594fSAndroid Build Coastguard Worker   }
218*795d594fSAndroid Build Coastguard Worker 
219*795d594fSAndroid Build Coastguard Worker   // Returns the area (the most outer loop) in the graph for which control flow (back edges, loops,
220*795d594fSAndroid Build Coastguard Worker   // dominators) needs to be adjusted.
GetRegionToBeAdjusted()221*795d594fSAndroid Build Coastguard Worker   HLoopInformation* GetRegionToBeAdjusted() const {
222*795d594fSAndroid Build Coastguard Worker     return outer_loop_;
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker  private:
226*795d594fSAndroid Build Coastguard Worker   // Fills the 'exits' vector with the subgraph exits.
227*795d594fSAndroid Build Coastguard Worker   void SearchForSubgraphExits(ArenaVector<HBasicBlock*>* exits) const;
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker   // Finds and records information about the area in the graph for which control flow (back edges,
230*795d594fSAndroid Build Coastguard Worker   // loops, dominators) needs to be adjusted.
231*795d594fSAndroid Build Coastguard Worker   void FindAndSetLocalAreaForAdjustments();
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   // Remaps edges' successors according to the info specified in the edges sets.
234*795d594fSAndroid Build Coastguard Worker   //
235*795d594fSAndroid Build Coastguard Worker   // Only edge successors/predecessors and phis' input records (to have a correspondence between
236*795d594fSAndroid Build Coastguard Worker   // a phi input record (not value) and a block's predecessor) are adjusted at this stage: neither
237*795d594fSAndroid Build Coastguard Worker   // phis' nor instructions' inputs values are resolved.
238*795d594fSAndroid Build Coastguard Worker   void RemapEdgesSuccessors();
239*795d594fSAndroid Build Coastguard Worker 
240*795d594fSAndroid Build Coastguard Worker   // Adjusts control flow (back edges, loops, dominators) for the local area defined by
241*795d594fSAndroid Build Coastguard Worker   // FindAndSetLocalAreaForAdjustments.
242*795d594fSAndroid Build Coastguard Worker   void AdjustControlFlowInfo();
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker   // Resolves Data Flow - adjusts phis' and instructions' inputs in order to have a valid graph in
245*795d594fSAndroid Build Coastguard Worker   // the SSA form.
246*795d594fSAndroid Build Coastguard Worker   void ResolveDataFlow();
247*795d594fSAndroid Build Coastguard Worker 
248*795d594fSAndroid Build Coastguard Worker   //
249*795d594fSAndroid Build Coastguard Worker   // Helpers for live-outs processing and Subgraph-closed SSA.
250*795d594fSAndroid Build Coastguard Worker   //
251*795d594fSAndroid Build Coastguard Worker   //  - live-outs - values which are defined inside the subgraph and have uses outside.
252*795d594fSAndroid Build Coastguard Worker   //  - Subgraph-closed SSA - SSA form for which all the values defined inside the subgraph
253*795d594fSAndroid Build Coastguard Worker   //    have no outside uses except for the phi-nodes in the subgraph exits.
254*795d594fSAndroid Build Coastguard Worker   //
255*795d594fSAndroid Build Coastguard Worker   // Note: now if the subgraph has live-outs it is only clonable if it has a single exit; this
256*795d594fSAndroid Build Coastguard Worker   // makes the subgraph-closed SSA form construction much easier.
257*795d594fSAndroid Build Coastguard Worker   //
258*795d594fSAndroid Build Coastguard Worker   // TODO: Support subgraphs with live-outs and multiple exits.
259*795d594fSAndroid Build Coastguard Worker   //
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker   // For each live-out value 'val' in the region puts a record <val, val> into the map.
262*795d594fSAndroid Build Coastguard Worker   // Returns whether all of the instructions in the subgraph are clonable.
263*795d594fSAndroid Build Coastguard Worker   bool CollectLiveOutsAndCheckClonable(HInstructionMap* live_outs_) const;
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker   // Constructs Subgraph-closed SSA; precondition - a subgraph has a single exit.
266*795d594fSAndroid Build Coastguard Worker   //
267*795d594fSAndroid Build Coastguard Worker   // For each live-out 'val' in 'live_outs_' map inserts a HPhi 'phi' into the exit node, updates
268*795d594fSAndroid Build Coastguard Worker   // the record in the map to <val, phi> and replaces all outside uses with this phi.
269*795d594fSAndroid Build Coastguard Worker   void ConstructSubgraphClosedSSA();
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker   // Fixes the data flow for the live-out 'val' by adding a 'copy_val' input to the corresponding
272*795d594fSAndroid Build Coastguard Worker   // (<val, phi>) phi after the cloning is done.
273*795d594fSAndroid Build Coastguard Worker   void FixSubgraphClosedSSAAfterCloning();
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   //
276*795d594fSAndroid Build Coastguard Worker   // Helpers for CloneBasicBlock.
277*795d594fSAndroid Build Coastguard Worker   //
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   // Adjusts copy instruction's inputs: if the input of the original instruction is defined in the
280*795d594fSAndroid Build Coastguard Worker   // orig_bb_set, replaces it with a corresponding copy otherwise leaves it the same as original.
281*795d594fSAndroid Build Coastguard Worker   void ReplaceInputsWithCopies(HInstruction* copy_instr);
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker   // Recursively clones the environment for the copy instruction. If the input of the original
284*795d594fSAndroid Build Coastguard Worker   // environment is defined in the orig_bb_set, replaces it with a corresponding copy otherwise
285*795d594fSAndroid Build Coastguard Worker   // leaves it the same as original.
286*795d594fSAndroid Build Coastguard Worker   void DeepCloneEnvironmentWithRemapping(HInstruction* copy_instr, const HEnvironment* orig_env);
287*795d594fSAndroid Build Coastguard Worker 
288*795d594fSAndroid Build Coastguard Worker   //
289*795d594fSAndroid Build Coastguard Worker   // Helpers for RemapEdgesSuccessors.
290*795d594fSAndroid Build Coastguard Worker   //
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker   // Remaps incoming or original internal edge to its copy, adjusts the phi inputs in orig_succ and
293*795d594fSAndroid Build Coastguard Worker   // copy_succ.
294*795d594fSAndroid Build Coastguard Worker   void RemapOrigInternalOrIncomingEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker   // Adds copy internal edge (from copy_block to copy_succ), updates phis in the copy_succ.
297*795d594fSAndroid Build Coastguard Worker   void AddCopyInternalEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);
298*795d594fSAndroid Build Coastguard Worker 
299*795d594fSAndroid Build Coastguard Worker   // Remaps copy internal edge to its origin, adjusts the phi inputs in orig_succ.
300*795d594fSAndroid Build Coastguard Worker   void RemapCopyInternalEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);
301*795d594fSAndroid Build Coastguard Worker 
302*795d594fSAndroid Build Coastguard Worker   // Checks whether the edges remapping info corresponds to the subgraph versioning case:
303*795d594fSAndroid Build Coastguard Worker   //  - none of the incoming edges are to be remapped (they are being duplicated).
304*795d594fSAndroid Build Coastguard Worker   //  - none of the internal edges are to be remapped.
305*795d594fSAndroid Build Coastguard Worker   bool IsRemapInfoForVersioning() const;
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker   // Processes incoming edges for subgraph versioning case: for each incoming edge (X, Y) adds
308*795d594fSAndroid Build Coastguard Worker   // an edge (X, Y_1) where Y_1 = Copy(Y) and add corresponding phi input to copy phi.
309*795d594fSAndroid Build Coastguard Worker   //
310*795d594fSAndroid Build Coastguard Worker   // Note: such node X will now have two successors, its unconditional branch instruction
311*795d594fSAndroid Build Coastguard Worker   // will be invalid and should be adjusted to some conditional branch by the client code.
312*795d594fSAndroid Build Coastguard Worker   void CopyIncomingEdgesForVersioning();
313*795d594fSAndroid Build Coastguard Worker 
314*795d594fSAndroid Build Coastguard Worker   //
315*795d594fSAndroid Build Coastguard Worker   // Local versions of control flow calculation/adjustment routines.
316*795d594fSAndroid Build Coastguard Worker   //
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker   void FindBackEdgesLocal(HBasicBlock* entry_block, ArenaBitVector* local_set);
319*795d594fSAndroid Build Coastguard Worker   void RecalculateBackEdgesInfo(ArenaBitVector* outer_loop_bb_set);
320*795d594fSAndroid Build Coastguard Worker   GraphAnalysisResult AnalyzeLoopsLocally(ArenaBitVector* outer_loop_bb_set);
321*795d594fSAndroid Build Coastguard Worker   void CleanUpControlFlow();
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker   //
324*795d594fSAndroid Build Coastguard Worker   // Helpers for ResolveDataFlow
325*795d594fSAndroid Build Coastguard Worker   //
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   // Resolves the inputs of the phi.
328*795d594fSAndroid Build Coastguard Worker   void ResolvePhi(HPhi* phi);
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker   // Update induction range after when fixing SSA.
331*795d594fSAndroid Build Coastguard Worker   void UpdateInductionRangeInfoOf(
332*795d594fSAndroid Build Coastguard Worker       HInstruction* user, HInstruction* old_instruction, HInstruction* replacement);
333*795d594fSAndroid Build Coastguard Worker 
334*795d594fSAndroid Build Coastguard Worker   //
335*795d594fSAndroid Build Coastguard Worker   // Debug and logging methods.
336*795d594fSAndroid Build Coastguard Worker   //
337*795d594fSAndroid Build Coastguard Worker   void CheckInstructionInputsRemapping(HInstruction* orig_instr);
338*795d594fSAndroid Build Coastguard Worker   bool CheckRemappingInfoIsValid();
339*795d594fSAndroid Build Coastguard Worker   void VerifyGraph();
340*795d594fSAndroid Build Coastguard Worker   void DumpInputSets();
341*795d594fSAndroid Build Coastguard Worker 
GetBlockById(uint32_t block_id)342*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetBlockById(uint32_t block_id) const {
343*795d594fSAndroid Build Coastguard Worker     DCHECK(block_id < graph_->GetBlocks().size());
344*795d594fSAndroid Build Coastguard Worker     HBasicBlock* block = graph_->GetBlocks()[block_id];
345*795d594fSAndroid Build Coastguard Worker     DCHECK(block != nullptr);
346*795d594fSAndroid Build Coastguard Worker     return block;
347*795d594fSAndroid Build Coastguard Worker   }
348*795d594fSAndroid Build Coastguard Worker 
349*795d594fSAndroid Build Coastguard Worker   HGraph* const graph_;
350*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* const arena_;
351*795d594fSAndroid Build Coastguard Worker 
352*795d594fSAndroid Build Coastguard Worker   // Set of basic block in the original graph to be copied.
353*795d594fSAndroid Build Coastguard Worker   HBasicBlockSet orig_bb_set_;
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker   // Sets of edges which require successors remapping.
356*795d594fSAndroid Build Coastguard Worker   const HEdgeSet* remap_orig_internal_;
357*795d594fSAndroid Build Coastguard Worker   const HEdgeSet* remap_copy_internal_;
358*795d594fSAndroid Build Coastguard Worker   const HEdgeSet* remap_incoming_;
359*795d594fSAndroid Build Coastguard Worker 
360*795d594fSAndroid Build Coastguard Worker   // Correspondence map for blocks: (original block, copy block).
361*795d594fSAndroid Build Coastguard Worker   HBasicBlockMap* bb_map_;
362*795d594fSAndroid Build Coastguard Worker   // Correspondence map for instructions: (original HInstruction, copy HInstruction).
363*795d594fSAndroid Build Coastguard Worker   HInstructionMap* hir_map_;
364*795d594fSAndroid Build Coastguard Worker   // As a result of cloning, the induction range analysis information can be invalidated
365*795d594fSAndroid Build Coastguard Worker   // and must be updated. If not null, the cloner updates it for changed instructions.
366*795d594fSAndroid Build Coastguard Worker   InductionVarRange* induction_range_;
367*795d594fSAndroid Build Coastguard Worker   // Area in the graph for which control flow (back edges, loops, dominators) needs to be adjusted.
368*795d594fSAndroid Build Coastguard Worker   HLoopInformation* outer_loop_;
369*795d594fSAndroid Build Coastguard Worker   HBasicBlockSet outer_loop_bb_set_;
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker   HInstructionMap live_outs_;
372*795d594fSAndroid Build Coastguard Worker 
373*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(SuperblockClonerTest, AdjustControlFlowInfo);
374*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(SuperblockClonerTest, IsGraphConnected);
375*795d594fSAndroid Build Coastguard Worker 
376*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(SuperblockCloner);
377*795d594fSAndroid Build Coastguard Worker };
378*795d594fSAndroid Build Coastguard Worker 
379*795d594fSAndroid Build Coastguard Worker // Helper class to perform loop peeling/unrolling/versioning.
380*795d594fSAndroid Build Coastguard Worker //
381*795d594fSAndroid Build Coastguard Worker // This helper should be used when correspondence map between original and copied
382*795d594fSAndroid Build Coastguard Worker // basic blocks/instructions are demanded.
383*795d594fSAndroid Build Coastguard Worker class LoopClonerHelper : public ValueObject {
384*795d594fSAndroid Build Coastguard Worker  public:
LoopClonerHelper(HLoopInformation * info,SuperblockCloner::HBasicBlockMap * bb_map,SuperblockCloner::HInstructionMap * hir_map,InductionVarRange * induction_range)385*795d594fSAndroid Build Coastguard Worker   LoopClonerHelper(HLoopInformation* info,
386*795d594fSAndroid Build Coastguard Worker                    SuperblockCloner::HBasicBlockMap* bb_map,
387*795d594fSAndroid Build Coastguard Worker                    SuperblockCloner::HInstructionMap* hir_map,
388*795d594fSAndroid Build Coastguard Worker                    InductionVarRange* induction_range) :
389*795d594fSAndroid Build Coastguard Worker       loop_info_(info),
390*795d594fSAndroid Build Coastguard Worker       cloner_(info->GetHeader()->GetGraph(), &info->GetBlocks(), bb_map, hir_map, induction_range) {
391*795d594fSAndroid Build Coastguard Worker     // For now do transformations only for natural loops.
392*795d594fSAndroid Build Coastguard Worker     DCHECK(!info->IsIrreducible());
393*795d594fSAndroid Build Coastguard Worker   }
394*795d594fSAndroid Build Coastguard Worker 
395*795d594fSAndroid Build Coastguard Worker   // Returns whether the loop can be peeled/unrolled (static function).
396*795d594fSAndroid Build Coastguard Worker   static bool IsLoopClonable(HLoopInformation* loop_info);
397*795d594fSAndroid Build Coastguard Worker 
398*795d594fSAndroid Build Coastguard Worker   // Returns whether the loop can be peeled/unrolled.
IsLoopClonable()399*795d594fSAndroid Build Coastguard Worker   bool IsLoopClonable() const { return cloner_.IsSubgraphClonable(); }
400*795d594fSAndroid Build Coastguard Worker 
401*795d594fSAndroid Build Coastguard Worker   // Perform loop peeling.
402*795d594fSAndroid Build Coastguard Worker   //
403*795d594fSAndroid Build Coastguard Worker   // Control flow of an example (ignoring critical edges splitting).
404*795d594fSAndroid Build Coastguard Worker   //
405*795d594fSAndroid Build Coastguard Worker   //       Before                    After
406*795d594fSAndroid Build Coastguard Worker   //
407*795d594fSAndroid Build Coastguard Worker   //         |B|                      |B|
408*795d594fSAndroid Build Coastguard Worker   //          |                        |
409*795d594fSAndroid Build Coastguard Worker   //          v                        v
410*795d594fSAndroid Build Coastguard Worker   //         |1|                      |1|
411*795d594fSAndroid Build Coastguard Worker   //          |                        |
412*795d594fSAndroid Build Coastguard Worker   //          v                        v
413*795d594fSAndroid Build Coastguard Worker   //         |2|<-\                  |2A|
414*795d594fSAndroid Build Coastguard Worker   //         / \  /                   / \
415*795d594fSAndroid Build Coastguard Worker   //        v   v/                   /   v
416*795d594fSAndroid Build Coastguard Worker   //       |4|  |3|                 /   |3A|
417*795d594fSAndroid Build Coastguard Worker   //        |                      /     /
418*795d594fSAndroid Build Coastguard Worker   //        v                     |     v
419*795d594fSAndroid Build Coastguard Worker   //       |E|                     \   |2|<-\
420*795d594fSAndroid Build Coastguard Worker   //                                \ / \   /
421*795d594fSAndroid Build Coastguard Worker   //                                 v   v /
422*795d594fSAndroid Build Coastguard Worker   //                                |4|  |3|
423*795d594fSAndroid Build Coastguard Worker   //                                 |
424*795d594fSAndroid Build Coastguard Worker   //                                 v
425*795d594fSAndroid Build Coastguard Worker   //                                |E|
DoPeeling()426*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoPeeling() {
427*795d594fSAndroid Build Coastguard Worker     return DoLoopTransformationImpl(TransformationKind::kPeeling);
428*795d594fSAndroid Build Coastguard Worker   }
429*795d594fSAndroid Build Coastguard Worker 
430*795d594fSAndroid Build Coastguard Worker   // Perform loop unrolling.
431*795d594fSAndroid Build Coastguard Worker   //
432*795d594fSAndroid Build Coastguard Worker   // Control flow of an example (ignoring critical edges splitting).
433*795d594fSAndroid Build Coastguard Worker   //
434*795d594fSAndroid Build Coastguard Worker   //       Before                    After
435*795d594fSAndroid Build Coastguard Worker   //
436*795d594fSAndroid Build Coastguard Worker   //         |B|                      |B|
437*795d594fSAndroid Build Coastguard Worker   //          |                        |
438*795d594fSAndroid Build Coastguard Worker   //          v                        v
439*795d594fSAndroid Build Coastguard Worker   //         |1|                      |1|
440*795d594fSAndroid Build Coastguard Worker   //          |                        |
441*795d594fSAndroid Build Coastguard Worker   //          v                        v
442*795d594fSAndroid Build Coastguard Worker   //         |2|<-\                   |2A|<-\
443*795d594fSAndroid Build Coastguard Worker   //         / \  /                   / \    \
444*795d594fSAndroid Build Coastguard Worker   //        v   v/                   /   v    \
445*795d594fSAndroid Build Coastguard Worker   //       |4|  |3|                 /   |3A|   |
446*795d594fSAndroid Build Coastguard Worker   //        |                      /     /    /
447*795d594fSAndroid Build Coastguard Worker   //        v                     |     v    /
448*795d594fSAndroid Build Coastguard Worker   //       |E|                     \   |2|  /
449*795d594fSAndroid Build Coastguard Worker   //                                \ / \  /
450*795d594fSAndroid Build Coastguard Worker   //                                 v   v/
451*795d594fSAndroid Build Coastguard Worker   //                                |4| |3|
452*795d594fSAndroid Build Coastguard Worker   //                                 |
453*795d594fSAndroid Build Coastguard Worker   //                                 v
454*795d594fSAndroid Build Coastguard Worker   //                                |E|
DoUnrolling()455*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoUnrolling() {
456*795d594fSAndroid Build Coastguard Worker     return DoLoopTransformationImpl(TransformationKind::kUnrolling);
457*795d594fSAndroid Build Coastguard Worker   }
458*795d594fSAndroid Build Coastguard Worker 
459*795d594fSAndroid Build Coastguard Worker   // Perform loop versioning.
460*795d594fSAndroid Build Coastguard Worker   //
461*795d594fSAndroid Build Coastguard Worker   // Control flow of an example (ignoring critical edges splitting).
462*795d594fSAndroid Build Coastguard Worker   //
463*795d594fSAndroid Build Coastguard Worker   //       Before                    After
464*795d594fSAndroid Build Coastguard Worker   //
465*795d594fSAndroid Build Coastguard Worker   //         |B|                      |B|
466*795d594fSAndroid Build Coastguard Worker   //          |                        |
467*795d594fSAndroid Build Coastguard Worker   //          v                        v
468*795d594fSAndroid Build Coastguard Worker   //         |1|                      |1|_________
469*795d594fSAndroid Build Coastguard Worker   //          |                        |          |
470*795d594fSAndroid Build Coastguard Worker   //          v                        v          v
471*795d594fSAndroid Build Coastguard Worker   //         |2|<-\                   |2|<-\     |2A|<-\
472*795d594fSAndroid Build Coastguard Worker   //         / \  /                   / \  /     /  \  /
473*795d594fSAndroid Build Coastguard Worker   //        v   v/                   |   v/      |   v/
474*795d594fSAndroid Build Coastguard Worker   //        |   |3|                  |  |3|      | |3A|
475*795d594fSAndroid Build Coastguard Worker   //        |                        | __________|
476*795d594fSAndroid Build Coastguard Worker   //        |                        ||
477*795d594fSAndroid Build Coastguard Worker   //        v                        vv
478*795d594fSAndroid Build Coastguard Worker   //       |4|                       |4|
479*795d594fSAndroid Build Coastguard Worker   //        |                         |
480*795d594fSAndroid Build Coastguard Worker   //        v                         v
481*795d594fSAndroid Build Coastguard Worker   //       |E|                       |E|
DoVersioning()482*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoVersioning() {
483*795d594fSAndroid Build Coastguard Worker     return DoLoopTransformationImpl(TransformationKind::kVersioning);
484*795d594fSAndroid Build Coastguard Worker   }
485*795d594fSAndroid Build Coastguard Worker 
GetRegionToBeAdjusted()486*795d594fSAndroid Build Coastguard Worker   HLoopInformation* GetRegionToBeAdjusted() const { return cloner_.GetRegionToBeAdjusted(); }
487*795d594fSAndroid Build Coastguard Worker 
488*795d594fSAndroid Build Coastguard Worker  protected:
489*795d594fSAndroid Build Coastguard Worker   enum class TransformationKind {
490*795d594fSAndroid Build Coastguard Worker     kPeeling,
491*795d594fSAndroid Build Coastguard Worker     kUnrolling,
492*795d594fSAndroid Build Coastguard Worker     kVersioning,
493*795d594fSAndroid Build Coastguard Worker   };
494*795d594fSAndroid Build Coastguard Worker 
495*795d594fSAndroid Build Coastguard Worker   // Applies a specific loop transformation to the loop.
496*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoLoopTransformationImpl(TransformationKind transformation);
497*795d594fSAndroid Build Coastguard Worker 
498*795d594fSAndroid Build Coastguard Worker  private:
499*795d594fSAndroid Build Coastguard Worker   HLoopInformation* loop_info_;
500*795d594fSAndroid Build Coastguard Worker   SuperblockCloner cloner_;
501*795d594fSAndroid Build Coastguard Worker 
502*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(LoopClonerHelper);
503*795d594fSAndroid Build Coastguard Worker };
504*795d594fSAndroid Build Coastguard Worker 
505*795d594fSAndroid Build Coastguard Worker // Helper class to perform loop peeling/unrolling/versioning.
506*795d594fSAndroid Build Coastguard Worker //
507*795d594fSAndroid Build Coastguard Worker // This helper should be used when there is no need to get correspondence information between
508*795d594fSAndroid Build Coastguard Worker // original and copied basic blocks/instructions.
509*795d594fSAndroid Build Coastguard Worker class LoopClonerSimpleHelper : public ValueObject {
510*795d594fSAndroid Build Coastguard Worker  public:
511*795d594fSAndroid Build Coastguard Worker   LoopClonerSimpleHelper(HLoopInformation* info, InductionVarRange* induction_range);
IsLoopClonable()512*795d594fSAndroid Build Coastguard Worker   bool IsLoopClonable() const { return helper_.IsLoopClonable(); }
DoPeeling()513*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoPeeling() { return helper_.DoPeeling(); }
DoUnrolling()514*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoUnrolling() { return helper_.DoUnrolling(); }
DoVersioning()515*795d594fSAndroid Build Coastguard Worker   HBasicBlock* DoVersioning() { return helper_.DoVersioning(); }
GetRegionToBeAdjusted()516*795d594fSAndroid Build Coastguard Worker   HLoopInformation* GetRegionToBeAdjusted() const { return helper_.GetRegionToBeAdjusted(); }
517*795d594fSAndroid Build Coastguard Worker 
GetBasicBlockMap()518*795d594fSAndroid Build Coastguard Worker   const SuperblockCloner::HBasicBlockMap* GetBasicBlockMap() const { return &bb_map_; }
GetInstructionMap()519*795d594fSAndroid Build Coastguard Worker   const SuperblockCloner::HInstructionMap* GetInstructionMap() const { return &hir_map_; }
520*795d594fSAndroid Build Coastguard Worker 
521*795d594fSAndroid Build Coastguard Worker  private:
522*795d594fSAndroid Build Coastguard Worker   SuperblockCloner::HBasicBlockMap bb_map_;
523*795d594fSAndroid Build Coastguard Worker   SuperblockCloner::HInstructionMap hir_map_;
524*795d594fSAndroid Build Coastguard Worker   LoopClonerHelper helper_;
525*795d594fSAndroid Build Coastguard Worker 
526*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(LoopClonerSimpleHelper);
527*795d594fSAndroid Build Coastguard Worker };
528*795d594fSAndroid Build Coastguard Worker 
529*795d594fSAndroid Build Coastguard Worker // Collects edge remapping info for loop peeling/unrolling for the loop specified by loop info.
530*795d594fSAndroid Build Coastguard Worker void CollectRemappingInfoForPeelUnroll(bool to_unroll,
531*795d594fSAndroid Build Coastguard Worker                                        HLoopInformation* loop_info,
532*795d594fSAndroid Build Coastguard Worker                                        SuperblockCloner::HEdgeSet* remap_orig_internal,
533*795d594fSAndroid Build Coastguard Worker                                        SuperblockCloner::HEdgeSet* remap_copy_internal,
534*795d594fSAndroid Build Coastguard Worker                                        SuperblockCloner::HEdgeSet* remap_incoming);
535*795d594fSAndroid Build Coastguard Worker 
536*795d594fSAndroid Build Coastguard Worker // Returns whether blocks from 'work_set' are reachable from the rest of the graph.
537*795d594fSAndroid Build Coastguard Worker //
538*795d594fSAndroid Build Coastguard Worker // Returns whether such a set 'outer_entries' of basic blocks exists that:
539*795d594fSAndroid Build Coastguard Worker // - each block from 'outer_entries' is not from 'work_set'.
540*795d594fSAndroid Build Coastguard Worker // - each block from 'work_set' is reachable from at least one block from 'outer_entries'.
541*795d594fSAndroid Build Coastguard Worker //
542*795d594fSAndroid Build Coastguard Worker // After the function returns work_set contains only blocks from the original 'work_set'
543*795d594fSAndroid Build Coastguard Worker // which are unreachable from the rest of the graph.
544*795d594fSAndroid Build Coastguard Worker bool IsSubgraphConnected(SuperblockCloner::HBasicBlockSet* work_set, HGraph* graph);
545*795d594fSAndroid Build Coastguard Worker 
546*795d594fSAndroid Build Coastguard Worker // Returns a common predecessor of loop1 and loop2 in the loop tree or nullptr if it is the whole
547*795d594fSAndroid Build Coastguard Worker // graph.
548*795d594fSAndroid Build Coastguard Worker HLoopInformation* FindCommonLoop(HLoopInformation* loop1, HLoopInformation* loop2);
549*795d594fSAndroid Build Coastguard Worker }  // namespace art
550*795d594fSAndroid Build Coastguard Worker 
551*795d594fSAndroid Build Coastguard Worker namespace std {
552*795d594fSAndroid Build Coastguard Worker 
553*795d594fSAndroid Build Coastguard Worker template <>
554*795d594fSAndroid Build Coastguard Worker struct hash<art::HEdge> {
555*795d594fSAndroid Build Coastguard Worker   size_t operator()(art::HEdge const& x) const noexcept  {
556*795d594fSAndroid Build Coastguard Worker     // Use Cantor pairing function as the hash function.
557*795d594fSAndroid Build Coastguard Worker     size_t a = x.GetFrom();
558*795d594fSAndroid Build Coastguard Worker     size_t b = x.GetTo();
559*795d594fSAndroid Build Coastguard Worker     return (a + b) * (a + b + 1) / 2 + b;
560*795d594fSAndroid Build Coastguard Worker   }
561*795d594fSAndroid Build Coastguard Worker };
562*795d594fSAndroid Build Coastguard Worker ostream& operator<<(ostream& os, const art::HEdge& e);
563*795d594fSAndroid Build Coastguard Worker 
564*795d594fSAndroid Build Coastguard Worker }  // namespace std
565*795d594fSAndroid Build Coastguard Worker 
566*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_SUPERBLOCK_CLONER_H_
567