1dae34463SAndrew Litteken //===- IROutliner.cpp -- Outline Similar Regions ----------------*- C++ -*-===//
2dae34463SAndrew Litteken //
3dae34463SAndrew Litteken // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dae34463SAndrew Litteken // See https://llvm.org/LICENSE.txt for license information.
5dae34463SAndrew Litteken // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dae34463SAndrew Litteken //
7dae34463SAndrew Litteken //===----------------------------------------------------------------------===//
8dae34463SAndrew Litteken ///
9dae34463SAndrew Litteken /// \file
10dae34463SAndrew Litteken // Implementation for the IROutliner which is used by the IROutliner Pass.
11dae34463SAndrew Litteken //
12dae34463SAndrew Litteken //===----------------------------------------------------------------------===//
13dae34463SAndrew Litteken 
14dae34463SAndrew Litteken #include "llvm/Transforms/IPO/IROutliner.h"
15dae34463SAndrew Litteken #include "llvm/Analysis/IRSimilarityIdentifier.h"
16df4a931cSAndrew Litteken #include "llvm/Analysis/OptimizationRemarkEmitter.h"
17dae34463SAndrew Litteken #include "llvm/Analysis/TargetTransformInfo.h"
18dae34463SAndrew Litteken #include "llvm/IR/Attributes.h"
192c21278eSAndrew Litteken #include "llvm/IR/DIBuilder.h"
20f7d90ad5SAndrew Litteken #include "llvm/IR/DebugInfo.h"
21f7d90ad5SAndrew Litteken #include "llvm/IR/DebugInfoMetadata.h"
22c172f1adSAndrew Litteken #include "llvm/IR/Dominators.h"
232c21278eSAndrew Litteken #include "llvm/IR/Mangler.h"
24dae34463SAndrew Litteken #include "llvm/IR/PassManager.h"
25dae34463SAndrew Litteken #include "llvm/InitializePasses.h"
26dae34463SAndrew Litteken #include "llvm/Pass.h"
27dae34463SAndrew Litteken #include "llvm/Support/CommandLine.h"
28dae34463SAndrew Litteken #include "llvm/Transforms/IPO.h"
29dae34463SAndrew Litteken #include <vector>
30dae34463SAndrew Litteken 
31dae34463SAndrew Litteken #define DEBUG_TYPE "iroutliner"
32dae34463SAndrew Litteken 
33dae34463SAndrew Litteken using namespace llvm;
34dae34463SAndrew Litteken using namespace IRSimilarity;
35dae34463SAndrew Litteken 
3681d3ac0cSAndrew Litteken // A command flag to be used for debugging to exclude branches from similarity
3781d3ac0cSAndrew Litteken // matching and outlining.
38b69fe48cSFangrui Song namespace llvm {
3981d3ac0cSAndrew Litteken extern cl::opt<bool> DisableBranches;
4081d3ac0cSAndrew Litteken 
41f5f377d1SAndrew Litteken // A command flag to be used for debugging to indirect calls from similarity
42f5f377d1SAndrew Litteken // matching and outlining.
43f5f377d1SAndrew Litteken extern cl::opt<bool> DisableIndirectCalls;
443785c1d0SAndrew Litteken 
453785c1d0SAndrew Litteken // A command flag to be used for debugging to exclude intrinsics from similarity
463785c1d0SAndrew Litteken // matching and outlining.
473785c1d0SAndrew Litteken extern cl::opt<bool> DisableIntrinsics;
483785c1d0SAndrew Litteken 
49ba79295cSAndrew Litteken } // namespace llvm
50f5f377d1SAndrew Litteken 
51fe431103SAndrew Litteken // Set to true if the user wants the ir outliner to run on linkonceodr linkage
52fe431103SAndrew Litteken // functions. This is false by default because the linker can dedupe linkonceodr
53fe431103SAndrew Litteken // functions. Since the outliner is confined to a single module (modulo LTO),
54fe431103SAndrew Litteken // this is off by default. It should, however, be the default behavior in
55fe431103SAndrew Litteken // LTO.
56fe431103SAndrew Litteken static cl::opt<bool> EnableLinkOnceODRIROutlining(
57fe431103SAndrew Litteken     "enable-linkonceodr-ir-outlining", cl::Hidden,
58fe431103SAndrew Litteken     cl::desc("Enable the IR outliner on linkonceodr functions"),
59fe431103SAndrew Litteken     cl::init(false));
60fe431103SAndrew Litteken 
616df161a2SAndrew Litteken // This is a debug option to test small pieces of code to ensure that outlining
626df161a2SAndrew Litteken // works correctly.
636df161a2SAndrew Litteken static cl::opt<bool> NoCostModel(
646df161a2SAndrew Litteken     "ir-outlining-no-cost", cl::init(false), cl::ReallyHidden,
656df161a2SAndrew Litteken     cl::desc("Debug option to outline greedily, without restriction that "
666df161a2SAndrew Litteken              "calculated benefit outweighs cost"));
676df161a2SAndrew Litteken 
68dae34463SAndrew Litteken /// The OutlinableGroup holds all the overarching information for outlining
69dae34463SAndrew Litteken /// a set of regions that are structurally similar to one another, such as the
70dae34463SAndrew Litteken /// types of the overall function, the output blocks, the sets of stores needed
71dae34463SAndrew Litteken /// and a list of the different regions. This information is used in the
72dae34463SAndrew Litteken /// deduplication of extracted regions with the same structure.
73dae34463SAndrew Litteken struct OutlinableGroup {
74dae34463SAndrew Litteken   /// The sections that could be outlined
75dae34463SAndrew Litteken   std::vector<OutlinableRegion *> Regions;
76dae34463SAndrew Litteken 
777c6f28a4SAndrew Litteken   /// The argument types for the function created as the overall function to
787c6f28a4SAndrew Litteken   /// replace the extracted function for each region.
797c6f28a4SAndrew Litteken   std::vector<Type *> ArgumentTypes;
807c6f28a4SAndrew Litteken   /// The FunctionType for the overall function.
817c6f28a4SAndrew Litteken   FunctionType *OutlinedFunctionType = nullptr;
827c6f28a4SAndrew Litteken   /// The Function for the collective overall function.
837c6f28a4SAndrew Litteken   Function *OutlinedFunction = nullptr;
847c6f28a4SAndrew Litteken 
85dae34463SAndrew Litteken   /// Flag for whether we should not consider this group of OutlinableRegions
86dae34463SAndrew Litteken   /// for extraction.
87dae34463SAndrew Litteken   bool IgnoreGroup = false;
88c52bcf3aSAndrew Litteken 
89c172f1adSAndrew Litteken   /// The return blocks for the overall function.
90c172f1adSAndrew Litteken   DenseMap<Value *, BasicBlock *> EndBBs;
91c172f1adSAndrew Litteken 
92c172f1adSAndrew Litteken   /// The PHIBlocks with their corresponding return block based on the return
93c172f1adSAndrew Litteken   /// value as the key.
94c172f1adSAndrew Litteken   DenseMap<Value *, BasicBlock *> PHIBlocks;
95e6ae6233SAndrew Litteken 
961e238025SAndrew Litteken   /// A set containing the different GVN store sets needed. Each array contains
971e238025SAndrew Litteken   /// a sorted list of the different values that need to be stored into output
981e238025SAndrew Litteken   /// registers.
991e238025SAndrew Litteken   DenseSet<ArrayRef<unsigned>> OutputGVNCombinations;
1001e238025SAndrew Litteken 
1017c6f28a4SAndrew Litteken   /// Flag for whether the \ref ArgumentTypes have been defined after the
1027c6f28a4SAndrew Litteken   /// extraction of the first region.
1037c6f28a4SAndrew Litteken   bool InputTypesSet = false;
1047c6f28a4SAndrew Litteken 
1057c6f28a4SAndrew Litteken   /// The number of input values in \ref ArgumentTypes.  Anything after this
1067c6f28a4SAndrew Litteken   /// index in ArgumentTypes is an output argument.
1077c6f28a4SAndrew Litteken   unsigned NumAggregateInputs = 0;
1087c6f28a4SAndrew Litteken 
109063af63bSAndrew Litteken   /// The mapping of the canonical numbering of the values in outlined sections
110063af63bSAndrew Litteken   /// to specific arguments.
111063af63bSAndrew Litteken   DenseMap<unsigned, unsigned> CanonicalNumberToAggArg;
112063af63bSAndrew Litteken 
11381d3ac0cSAndrew Litteken   /// The number of branches in the region target a basic block that is outside
11481d3ac0cSAndrew Litteken   /// of the region.
11581d3ac0cSAndrew Litteken   unsigned BranchesToOutside = 0;
11681d3ac0cSAndrew Litteken 
117dcc3e728SAndrew Litteken   /// Tracker counting backwards from the highest unsigned value possible to
118dcc3e728SAndrew Litteken   /// avoid conflicting with the GVNs of assigned values.  We start at -3 since
119dcc3e728SAndrew Litteken   /// -2 and -1 are assigned by the DenseMap.
120dcc3e728SAndrew Litteken   unsigned PHINodeGVNTracker = -3;
121dcc3e728SAndrew Litteken 
122dcc3e728SAndrew Litteken   DenseMap<unsigned,
123dcc3e728SAndrew Litteken            std::pair<std::pair<unsigned, unsigned>, SmallVector<unsigned, 2>>>
124dcc3e728SAndrew Litteken       PHINodeGVNToGVNs;
125dcc3e728SAndrew Litteken   DenseMap<hash_code, unsigned> GVNsToPHINodeGVN;
126dcc3e728SAndrew Litteken 
1276df161a2SAndrew Litteken   /// The number of instructions that will be outlined by extracting \ref
1286df161a2SAndrew Litteken   /// Regions.
129255a5077SDavid Sherwood   InstructionCost Benefit = 0;
1306df161a2SAndrew Litteken   /// The number of added instructions needed for the outlining of the \ref
1316df161a2SAndrew Litteken   /// Regions.
132255a5077SDavid Sherwood   InstructionCost Cost = 0;
1336df161a2SAndrew Litteken 
13430feb930SAndrew Litteken   /// The argument that needs to be marked with the swifterr attribute.  If not
13530feb930SAndrew Litteken   /// needed, there is no value.
13630feb930SAndrew Litteken   Optional<unsigned> SwiftErrorArgument;
13730feb930SAndrew Litteken 
138c52bcf3aSAndrew Litteken   /// For the \ref Regions, we look at every Value.  If it is a constant,
139c52bcf3aSAndrew Litteken   /// we check whether it is the same in Region.
140c52bcf3aSAndrew Litteken   ///
141c52bcf3aSAndrew Litteken   /// \param [in,out] NotSame contains the global value numbers where the
142c52bcf3aSAndrew Litteken   /// constant is not always the same, and must be passed in as an argument.
143c52bcf3aSAndrew Litteken   void findSameConstants(DenseSet<unsigned> &NotSame);
1441e238025SAndrew Litteken 
1451e238025SAndrew Litteken   /// For the regions, look at each set of GVN stores needed and account for
1461e238025SAndrew Litteken   /// each combination.  Add an argument to the argument types if there is
1471e238025SAndrew Litteken   /// more than one combination.
1481e238025SAndrew Litteken   ///
1491e238025SAndrew Litteken   /// \param [in] M - The module we are outlining from.
1501e238025SAndrew Litteken   void collectGVNStoreSets(Module &M);
151dae34463SAndrew Litteken };
152dae34463SAndrew Litteken 
153dae34463SAndrew Litteken /// Move the contents of \p SourceBB to before the last instruction of \p
154dae34463SAndrew Litteken /// TargetBB.
155dae34463SAndrew Litteken /// \param SourceBB - the BasicBlock to pull Instructions from.
156dae34463SAndrew Litteken /// \param TargetBB - the BasicBlock to put Instruction into.
moveBBContents(BasicBlock & SourceBB,BasicBlock & TargetBB)157dae34463SAndrew Litteken static void moveBBContents(BasicBlock &SourceBB, BasicBlock &TargetBB) {
1581b108ab9SKazu Hirata   for (Instruction &I : llvm::make_early_inc_range(SourceBB))
1591b108ab9SKazu Hirata     I.moveBefore(TargetBB, TargetBB.end());
160dae34463SAndrew Litteken }
161dae34463SAndrew Litteken 
162c172f1adSAndrew Litteken /// A function to sort the keys of \p Map, which must be a mapping of constant
163c172f1adSAndrew Litteken /// values to basic blocks and return it in \p SortedKeys
164c172f1adSAndrew Litteken ///
165c172f1adSAndrew Litteken /// \param SortedKeys - The vector the keys will be return in and sorted.
166c172f1adSAndrew Litteken /// \param Map - The DenseMap containing keys to sort.
getSortedConstantKeys(std::vector<Value * > & SortedKeys,DenseMap<Value *,BasicBlock * > & Map)167c172f1adSAndrew Litteken static void getSortedConstantKeys(std::vector<Value *> &SortedKeys,
168c172f1adSAndrew Litteken                                   DenseMap<Value *, BasicBlock *> &Map) {
169c172f1adSAndrew Litteken   for (auto &VtoBB : Map)
170c172f1adSAndrew Litteken     SortedKeys.push_back(VtoBB.first);
171c172f1adSAndrew Litteken 
172c172f1adSAndrew Litteken   stable_sort(SortedKeys, [](const Value *LHS, const Value *RHS) {
173c172f1adSAndrew Litteken     const ConstantInt *LHSC = dyn_cast<ConstantInt>(LHS);
174c172f1adSAndrew Litteken     const ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS);
175c172f1adSAndrew Litteken     assert(RHSC && "Not a constant integer in return value?");
176c172f1adSAndrew Litteken     assert(LHSC && "Not a constant integer in return value?");
177c172f1adSAndrew Litteken 
178c172f1adSAndrew Litteken     return LHSC->getLimitedValue() < RHSC->getLimitedValue();
179c172f1adSAndrew Litteken   });
180c172f1adSAndrew Litteken }
181c172f1adSAndrew Litteken 
findCorrespondingValueIn(const OutlinableRegion & Other,Value * V)1820087bb4aSAndrew Litteken Value *OutlinableRegion::findCorrespondingValueIn(const OutlinableRegion &Other,
1830087bb4aSAndrew Litteken                                                   Value *V) {
1840087bb4aSAndrew Litteken   Optional<unsigned> GVN = Candidate->getGVN(V);
1855413bf1bSKazu Hirata   assert(GVN && "No GVN for incoming value");
1860087bb4aSAndrew Litteken   Optional<unsigned> CanonNum = Candidate->getCanonicalNum(*GVN);
1870087bb4aSAndrew Litteken   Optional<unsigned> FirstGVN = Other.Candidate->fromCanonicalNum(*CanonNum);
1880087bb4aSAndrew Litteken   Optional<Value *> FoundValueOpt = Other.Candidate->fromGVN(*FirstGVN);
189129b531cSKazu Hirata   return FoundValueOpt.value_or(nullptr);
1900087bb4aSAndrew Litteken }
1910087bb4aSAndrew Litteken 
192228cc2c3SAndrew Litteken BasicBlock *
findCorrespondingBlockIn(const OutlinableRegion & Other,BasicBlock * BB)193228cc2c3SAndrew Litteken OutlinableRegion::findCorrespondingBlockIn(const OutlinableRegion &Other,
194228cc2c3SAndrew Litteken                                            BasicBlock *BB) {
195228cc2c3SAndrew Litteken   Instruction *FirstNonPHI = BB->getFirstNonPHI();
196228cc2c3SAndrew Litteken   assert(FirstNonPHI && "block is empty?");
197228cc2c3SAndrew Litteken   Value *CorrespondingVal = findCorrespondingValueIn(Other, FirstNonPHI);
198228cc2c3SAndrew Litteken   if (!CorrespondingVal)
199228cc2c3SAndrew Litteken     return nullptr;
200228cc2c3SAndrew Litteken   BasicBlock *CorrespondingBlock =
201228cc2c3SAndrew Litteken       cast<Instruction>(CorrespondingVal)->getParent();
202228cc2c3SAndrew Litteken   return CorrespondingBlock;
203228cc2c3SAndrew Litteken }
204228cc2c3SAndrew Litteken 
205e8f4e41bSAndrew Litteken /// Rewrite the BranchInsts in the incoming blocks to \p PHIBlock that are found
206e8f4e41bSAndrew Litteken /// in \p Included to branch to BasicBlock \p Replace if they currently branch
207e8f4e41bSAndrew Litteken /// to the BasicBlock \p Find.  This is used to fix up the incoming basic blocks
208e8f4e41bSAndrew Litteken /// when PHINodes are included in outlined regions.
209e8f4e41bSAndrew Litteken ///
210e8f4e41bSAndrew Litteken /// \param PHIBlock - The BasicBlock containing the PHINodes that need to be
211e8f4e41bSAndrew Litteken /// checked.
212e8f4e41bSAndrew Litteken /// \param Find - The successor block to be replaced.
213e8f4e41bSAndrew Litteken /// \param Replace - The new succesor block to branch to.
214e8f4e41bSAndrew Litteken /// \param Included - The set of blocks about to be outlined.
replaceTargetsFromPHINode(BasicBlock * PHIBlock,BasicBlock * Find,BasicBlock * Replace,DenseSet<BasicBlock * > & Included)215e8f4e41bSAndrew Litteken static void replaceTargetsFromPHINode(BasicBlock *PHIBlock, BasicBlock *Find,
216e8f4e41bSAndrew Litteken                                       BasicBlock *Replace,
217e8f4e41bSAndrew Litteken                                       DenseSet<BasicBlock *> &Included) {
218e8f4e41bSAndrew Litteken   for (PHINode &PN : PHIBlock->phis()) {
219e8f4e41bSAndrew Litteken     for (unsigned Idx = 0, PNEnd = PN.getNumIncomingValues(); Idx != PNEnd;
220e8f4e41bSAndrew Litteken          ++Idx) {
221e8f4e41bSAndrew Litteken       // Check if the incoming block is included in the set of blocks being
222e8f4e41bSAndrew Litteken       // outlined.
223e8f4e41bSAndrew Litteken       BasicBlock *Incoming = PN.getIncomingBlock(Idx);
224e8f4e41bSAndrew Litteken       if (!Included.contains(Incoming))
225e8f4e41bSAndrew Litteken         continue;
226e8f4e41bSAndrew Litteken 
227e8f4e41bSAndrew Litteken       BranchInst *BI = dyn_cast<BranchInst>(Incoming->getTerminator());
228e8f4e41bSAndrew Litteken       assert(BI && "Not a branch instruction?");
229e8f4e41bSAndrew Litteken       // Look over the branching instructions into this block to see if we
230e8f4e41bSAndrew Litteken       // used to branch to Find in this outlined block.
231e8f4e41bSAndrew Litteken       for (unsigned Succ = 0, End = BI->getNumSuccessors(); Succ != End;
232e8f4e41bSAndrew Litteken            Succ++) {
233e8f4e41bSAndrew Litteken         // If we have found the block to replace, we do so here.
234e8f4e41bSAndrew Litteken         if (BI->getSuccessor(Succ) != Find)
235e8f4e41bSAndrew Litteken           continue;
236e8f4e41bSAndrew Litteken         BI->setSuccessor(Succ, Replace);
237e8f4e41bSAndrew Litteken       }
238e8f4e41bSAndrew Litteken     }
239e8f4e41bSAndrew Litteken   }
240e8f4e41bSAndrew Litteken }
241e8f4e41bSAndrew Litteken 
242e8f4e41bSAndrew Litteken 
splitCandidate()243dae34463SAndrew Litteken void OutlinableRegion::splitCandidate() {
244dae34463SAndrew Litteken   assert(!CandidateSplit && "Candidate already split!");
245dae34463SAndrew Litteken 
24681d3ac0cSAndrew Litteken   Instruction *BackInst = Candidate->backInstruction();
24781d3ac0cSAndrew Litteken 
24881d3ac0cSAndrew Litteken   Instruction *EndInst = nullptr;
24981d3ac0cSAndrew Litteken   // Check whether the last instruction is a terminator, if it is, we do
25081d3ac0cSAndrew Litteken   // not split on the following instruction. We leave the block as it is.  We
25181d3ac0cSAndrew Litteken   // also check that this is not the last instruction in the Module, otherwise
25281d3ac0cSAndrew Litteken   // the check for whether the current following instruction matches the
25381d3ac0cSAndrew Litteken   // previously recorded instruction will be incorrect.
25481d3ac0cSAndrew Litteken   if (!BackInst->isTerminator() ||
25581d3ac0cSAndrew Litteken       BackInst->getParent() != &BackInst->getFunction()->back()) {
25681d3ac0cSAndrew Litteken     EndInst = Candidate->end()->Inst;
257f564299fSAndrew Litteken     assert(EndInst && "Expected an end instruction?");
25881d3ac0cSAndrew Litteken   }
259f564299fSAndrew Litteken 
260f564299fSAndrew Litteken   // We check if the current instruction following the last instruction in the
261f564299fSAndrew Litteken   // region is the same as the recorded instruction following the last
262f564299fSAndrew Litteken   // instruction. If they do not match, there could be problems in rewriting
263f564299fSAndrew Litteken   // the program after outlining, so we ignore it.
26481d3ac0cSAndrew Litteken   if (!BackInst->isTerminator() &&
26581d3ac0cSAndrew Litteken       EndInst != BackInst->getNextNonDebugInstruction())
266f564299fSAndrew Litteken     return;
267f564299fSAndrew Litteken 
268f564299fSAndrew Litteken   Instruction *StartInst = (*Candidate->begin()).Inst;
269f564299fSAndrew Litteken   assert(StartInst && "Expected a start instruction?");
270dae34463SAndrew Litteken   StartBB = StartInst->getParent();
271dae34463SAndrew Litteken   PrevBB = StartBB;
272dae34463SAndrew Litteken 
273e8f4e41bSAndrew Litteken   DenseSet<BasicBlock *> BBSet;
274e8f4e41bSAndrew Litteken   Candidate->getBasicBlocks(BBSet);
275e8f4e41bSAndrew Litteken 
276e8f4e41bSAndrew Litteken   // We iterate over the instructions in the region, if we find a PHINode, we
277e8f4e41bSAndrew Litteken   // check if there are predecessors outside of the region, if there are,
278e8f4e41bSAndrew Litteken   // we ignore this region since we are unable to handle the severing of the
279e8f4e41bSAndrew Litteken   // phi node right now.
2804e500df8SAndrew Litteken 
2814e500df8SAndrew Litteken   // TODO: Handle extraneous inputs for PHINodes through variable number of
2824e500df8SAndrew Litteken   // inputs, similar to how outputs are handled.
283e8f4e41bSAndrew Litteken   BasicBlock::iterator It = StartInst->getIterator();
2844e500df8SAndrew Litteken   EndBB = BackInst->getParent();
2854e500df8SAndrew Litteken   BasicBlock *IBlock;
286e38f014cSAndrew Litteken   BasicBlock *PHIPredBlock = nullptr;
2874e500df8SAndrew Litteken   bool EndBBTermAndBackInstDifferent = EndBB->getTerminator() != BackInst;
288e8f4e41bSAndrew Litteken   while (PHINode *PN = dyn_cast<PHINode>(&*It)) {
289e8f4e41bSAndrew Litteken     unsigned NumPredsOutsideRegion = 0;
2904e500df8SAndrew Litteken     for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
2914e500df8SAndrew Litteken       if (!BBSet.contains(PN->getIncomingBlock(i))) {
292e38f014cSAndrew Litteken         PHIPredBlock = PN->getIncomingBlock(i);
293e8f4e41bSAndrew Litteken         ++NumPredsOutsideRegion;
2944e500df8SAndrew Litteken         continue;
2954e500df8SAndrew Litteken       }
2964e500df8SAndrew Litteken 
2974e500df8SAndrew Litteken       // We must consider the case there the incoming block to the PHINode is
2984e500df8SAndrew Litteken       // the same as the final block of the OutlinableRegion.  If this is the
2994e500df8SAndrew Litteken       // case, the branch from this block must also be outlined to be valid.
3004e500df8SAndrew Litteken       IBlock = PN->getIncomingBlock(i);
301e38f014cSAndrew Litteken       if (IBlock == EndBB && EndBBTermAndBackInstDifferent) {
302e38f014cSAndrew Litteken         PHIPredBlock = PN->getIncomingBlock(i);
3034e500df8SAndrew Litteken         ++NumPredsOutsideRegion;
3044e500df8SAndrew Litteken       }
305e38f014cSAndrew Litteken     }
306e8f4e41bSAndrew Litteken 
307e8f4e41bSAndrew Litteken     if (NumPredsOutsideRegion > 1)
308e8f4e41bSAndrew Litteken       return;
309e8f4e41bSAndrew Litteken 
310e8f4e41bSAndrew Litteken     It++;
311e8f4e41bSAndrew Litteken   }
312e8f4e41bSAndrew Litteken 
313e8f4e41bSAndrew Litteken   // If the region starts with a PHINode, but is not the initial instruction of
314e8f4e41bSAndrew Litteken   // the BasicBlock, we ignore this region for now.
315e8f4e41bSAndrew Litteken   if (isa<PHINode>(StartInst) && StartInst != &*StartBB->begin())
316e8f4e41bSAndrew Litteken     return;
317e8f4e41bSAndrew Litteken 
318e8f4e41bSAndrew Litteken   // If the region ends with a PHINode, but does not contain all of the phi node
319e8f4e41bSAndrew Litteken   // instructions of the region, we ignore it for now.
3204e500df8SAndrew Litteken   if (isa<PHINode>(BackInst) &&
3214e500df8SAndrew Litteken       BackInst != &*std::prev(EndBB->getFirstInsertionPt()))
322e8f4e41bSAndrew Litteken     return;
323e8f4e41bSAndrew Litteken 
324dae34463SAndrew Litteken   // The basic block gets split like so:
325dae34463SAndrew Litteken   // block:                 block:
326dae34463SAndrew Litteken   //   inst1                  inst1
327dae34463SAndrew Litteken   //   inst2                  inst2
328dae34463SAndrew Litteken   //   region1               br block_to_outline
329dae34463SAndrew Litteken   //   region2              block_to_outline:
330dae34463SAndrew Litteken   //   region3          ->    region1
331dae34463SAndrew Litteken   //   region4                region2
332dae34463SAndrew Litteken   //   inst3                  region3
333dae34463SAndrew Litteken   //   inst4                  region4
334dae34463SAndrew Litteken   //                          br block_after_outline
335dae34463SAndrew Litteken   //                        block_after_outline:
336dae34463SAndrew Litteken   //                          inst3
337dae34463SAndrew Litteken   //                          inst4
338dae34463SAndrew Litteken 
339dae34463SAndrew Litteken   std::string OriginalName = PrevBB->getName().str();
340dae34463SAndrew Litteken 
341dae34463SAndrew Litteken   StartBB = PrevBB->splitBasicBlock(StartInst, OriginalName + "_to_outline");
34281d3ac0cSAndrew Litteken   PrevBB->replaceSuccessorsPhiUsesWith(PrevBB, StartBB);
343e38f014cSAndrew Litteken   // If there was a PHINode with an incoming block outside the region,
344e38f014cSAndrew Litteken   // make sure is correctly updated in the newly split block.
345e38f014cSAndrew Litteken   if (PHIPredBlock)
346e38f014cSAndrew Litteken     PrevBB->replaceSuccessorsPhiUsesWith(PHIPredBlock, PrevBB);
347dae34463SAndrew Litteken 
348dae34463SAndrew Litteken   CandidateSplit = true;
34981d3ac0cSAndrew Litteken   if (!BackInst->isTerminator()) {
35081d3ac0cSAndrew Litteken     EndBB = EndInst->getParent();
35181d3ac0cSAndrew Litteken     FollowBB = EndBB->splitBasicBlock(EndInst, OriginalName + "_after_outline");
35281d3ac0cSAndrew Litteken     EndBB->replaceSuccessorsPhiUsesWith(EndBB, FollowBB);
35381d3ac0cSAndrew Litteken     FollowBB->replaceSuccessorsPhiUsesWith(PrevBB, FollowBB);
354e8f4e41bSAndrew Litteken   } else {
35581d3ac0cSAndrew Litteken     EndBB = BackInst->getParent();
35681d3ac0cSAndrew Litteken     EndsInBranch = true;
35781d3ac0cSAndrew Litteken     FollowBB = nullptr;
358dae34463SAndrew Litteken   }
359dae34463SAndrew Litteken 
360e8f4e41bSAndrew Litteken   // Refind the basic block set.
361e8f4e41bSAndrew Litteken   BBSet.clear();
362e8f4e41bSAndrew Litteken   Candidate->getBasicBlocks(BBSet);
363e8f4e41bSAndrew Litteken   // For the phi nodes in the new starting basic block of the region, we
364e8f4e41bSAndrew Litteken   // reassign the targets of the basic blocks branching instructions.
365e8f4e41bSAndrew Litteken   replaceTargetsFromPHINode(StartBB, PrevBB, StartBB, BBSet);
366e8f4e41bSAndrew Litteken   if (FollowBB)
367e8f4e41bSAndrew Litteken     replaceTargetsFromPHINode(FollowBB, EndBB, FollowBB, BBSet);
368e8f4e41bSAndrew Litteken }
369e8f4e41bSAndrew Litteken 
reattachCandidate()370dae34463SAndrew Litteken void OutlinableRegion::reattachCandidate() {
371dae34463SAndrew Litteken   assert(CandidateSplit && "Candidate is not split!");
372dae34463SAndrew Litteken 
373dae34463SAndrew Litteken   // The basic block gets reattached like so:
374dae34463SAndrew Litteken   // block:                        block:
375dae34463SAndrew Litteken   //   inst1                         inst1
376dae34463SAndrew Litteken   //   inst2                         inst2
377dae34463SAndrew Litteken   //   br block_to_outline           region1
378dae34463SAndrew Litteken   // block_to_outline:        ->     region2
379dae34463SAndrew Litteken   //   region1                       region3
380dae34463SAndrew Litteken   //   region2                       region4
381dae34463SAndrew Litteken   //   region3                       inst3
382dae34463SAndrew Litteken   //   region4                       inst4
383dae34463SAndrew Litteken   //   br block_after_outline
384dae34463SAndrew Litteken   // block_after_outline:
385dae34463SAndrew Litteken   //   inst3
386dae34463SAndrew Litteken   //   inst4
387dae34463SAndrew Litteken   assert(StartBB != nullptr && "StartBB for Candidate is not defined!");
388dae34463SAndrew Litteken 
389dae34463SAndrew Litteken   assert(PrevBB->getTerminator() && "Terminator removed from PrevBB!");
390e38f014cSAndrew Litteken   // Make sure PHINode references to the block we are merging into are
391e38f014cSAndrew Litteken   // updated to be incoming blocks from the predecessor to the current block.
392e38f014cSAndrew Litteken 
393e38f014cSAndrew Litteken   // NOTE: If this is updated such that the outlined block can have more than
394e38f014cSAndrew Litteken   // one incoming block to a PHINode, this logic will have to updated
395e38f014cSAndrew Litteken   // to handle multiple precessors instead.
396e38f014cSAndrew Litteken 
397e38f014cSAndrew Litteken   // We only need to update this if the outlined section contains a PHINode, if
398e38f014cSAndrew Litteken   // it does not, then the incoming block was never changed in the first place.
399e38f014cSAndrew Litteken   // On the other hand, if PrevBB has no predecessors, it means that all
400e38f014cSAndrew Litteken   // incoming blocks to the first block are contained in the region, and there
401e38f014cSAndrew Litteken   // will be nothing to update.
402e38f014cSAndrew Litteken   Instruction *StartInst = (*Candidate->begin()).Inst;
403e38f014cSAndrew Litteken   if (isa<PHINode>(StartInst) && !PrevBB->hasNPredecessors(0)) {
404e38f014cSAndrew Litteken     assert(!PrevBB->hasNPredecessorsOrMore(2) &&
405e38f014cSAndrew Litteken          "PrevBB has more than one predecessor. Should be 0 or 1.");
406e38f014cSAndrew Litteken     BasicBlock *BeforePrevBB = PrevBB->getSinglePredecessor();
407e38f014cSAndrew Litteken     PrevBB->replaceSuccessorsPhiUsesWith(PrevBB, BeforePrevBB);
408e38f014cSAndrew Litteken   }
409dae34463SAndrew Litteken   PrevBB->getTerminator()->eraseFromParent();
410dae34463SAndrew Litteken 
411e8f4e41bSAndrew Litteken   // If we reattaching after outlining, we iterate over the phi nodes to
412e8f4e41bSAndrew Litteken   // the initial block, and reassign the branch instructions of the incoming
413e8f4e41bSAndrew Litteken   // blocks to the block we are remerging into.
414e8f4e41bSAndrew Litteken   if (!ExtractedFunction) {
415e8f4e41bSAndrew Litteken     DenseSet<BasicBlock *> BBSet;
416e8f4e41bSAndrew Litteken     Candidate->getBasicBlocks(BBSet);
417e8f4e41bSAndrew Litteken 
418e8f4e41bSAndrew Litteken     replaceTargetsFromPHINode(StartBB, StartBB, PrevBB, BBSet);
419e8f4e41bSAndrew Litteken     if (!EndsInBranch)
420e8f4e41bSAndrew Litteken       replaceTargetsFromPHINode(FollowBB, FollowBB, EndBB, BBSet);
421e8f4e41bSAndrew Litteken   }
422e8f4e41bSAndrew Litteken 
423dae34463SAndrew Litteken   moveBBContents(*StartBB, *PrevBB);
424dae34463SAndrew Litteken 
425dae34463SAndrew Litteken   BasicBlock *PlacementBB = PrevBB;
426dae34463SAndrew Litteken   if (StartBB != EndBB)
427dae34463SAndrew Litteken     PlacementBB = EndBB;
42881d3ac0cSAndrew Litteken   if (!EndsInBranch && PlacementBB->getUniqueSuccessor() != nullptr) {
42981d3ac0cSAndrew Litteken     assert(FollowBB != nullptr && "FollowBB for Candidate is not defined!");
43081d3ac0cSAndrew Litteken     assert(PlacementBB->getTerminator() && "Terminator removed from EndBB!");
43181d3ac0cSAndrew Litteken     PlacementBB->getTerminator()->eraseFromParent();
432dae34463SAndrew Litteken     moveBBContents(*FollowBB, *PlacementBB);
43381d3ac0cSAndrew Litteken     PlacementBB->replaceSuccessorsPhiUsesWith(FollowBB, PlacementBB);
43481d3ac0cSAndrew Litteken     FollowBB->eraseFromParent();
43581d3ac0cSAndrew Litteken   }
436dae34463SAndrew Litteken 
437dae34463SAndrew Litteken   PrevBB->replaceSuccessorsPhiUsesWith(StartBB, PrevBB);
438dae34463SAndrew Litteken   StartBB->eraseFromParent();
439dae34463SAndrew Litteken 
440dae34463SAndrew Litteken   // Make sure to save changes back to the StartBB.
441dae34463SAndrew Litteken   StartBB = PrevBB;
442dae34463SAndrew Litteken   EndBB = nullptr;
443dae34463SAndrew Litteken   PrevBB = nullptr;
444dae34463SAndrew Litteken   FollowBB = nullptr;
445dae34463SAndrew Litteken 
446dae34463SAndrew Litteken   CandidateSplit = false;
447dae34463SAndrew Litteken }
448dae34463SAndrew Litteken 
449c52bcf3aSAndrew Litteken /// Find whether \p V matches the Constants previously found for the \p GVN.
450c52bcf3aSAndrew Litteken ///
451c52bcf3aSAndrew Litteken /// \param V - The value to check for consistency.
452c52bcf3aSAndrew Litteken /// \param GVN - The global value number assigned to \p V.
453c52bcf3aSAndrew Litteken /// \param GVNToConstant - The mapping of global value number to Constants.
454c52bcf3aSAndrew Litteken /// \returns true if the Value matches the Constant mapped to by V and false if
455c52bcf3aSAndrew Litteken /// it \p V is a Constant but does not match.
456c52bcf3aSAndrew Litteken /// \returns None if \p V is not a Constant.
457c52bcf3aSAndrew Litteken static Optional<bool>
constantMatches(Value * V,unsigned GVN,DenseMap<unsigned,Constant * > & GVNToConstant)458c52bcf3aSAndrew Litteken constantMatches(Value *V, unsigned GVN,
459c52bcf3aSAndrew Litteken                 DenseMap<unsigned, Constant *> &GVNToConstant) {
460c52bcf3aSAndrew Litteken   // See if we have a constants
461c52bcf3aSAndrew Litteken   Constant *CST = dyn_cast<Constant>(V);
462c52bcf3aSAndrew Litteken   if (!CST)
463c52bcf3aSAndrew Litteken     return None;
464c52bcf3aSAndrew Litteken 
465c52bcf3aSAndrew Litteken   // Holds a mapping from a global value number to a Constant.
466c52bcf3aSAndrew Litteken   DenseMap<unsigned, Constant *>::iterator GVNToConstantIt;
467c52bcf3aSAndrew Litteken   bool Inserted;
468c52bcf3aSAndrew Litteken 
469df4a931cSAndrew Litteken 
470c52bcf3aSAndrew Litteken   // If we have a constant, try to make a new entry in the GVNToConstant.
471c52bcf3aSAndrew Litteken   std::tie(GVNToConstantIt, Inserted) =
472c52bcf3aSAndrew Litteken       GVNToConstant.insert(std::make_pair(GVN, CST));
473c52bcf3aSAndrew Litteken   // If it was found and is not equal, it is not the same. We do not
474c52bcf3aSAndrew Litteken   // handle this case yet, and exit early.
475c52bcf3aSAndrew Litteken   if (Inserted || (GVNToConstantIt->second == CST))
476c52bcf3aSAndrew Litteken     return true;
477c52bcf3aSAndrew Litteken 
478c52bcf3aSAndrew Litteken   return false;
479c52bcf3aSAndrew Litteken }
480c52bcf3aSAndrew Litteken 
getBenefit(TargetTransformInfo & TTI)481255a5077SDavid Sherwood InstructionCost OutlinableRegion::getBenefit(TargetTransformInfo &TTI) {
482255a5077SDavid Sherwood   InstructionCost Benefit = 0;
4836df161a2SAndrew Litteken 
4846df161a2SAndrew Litteken   // Estimate the benefit of outlining a specific sections of the program.  We
4856df161a2SAndrew Litteken   // delegate mostly this task to the TargetTransformInfo so that if the target
4866df161a2SAndrew Litteken   // has specific changes, we can have a more accurate estimate.
4876df161a2SAndrew Litteken 
4886df161a2SAndrew Litteken   // However, getInstructionCost delegates the code size calculation for
4896df161a2SAndrew Litteken   // arithmetic instructions to getArithmeticInstrCost in
4906df161a2SAndrew Litteken   // include/Analysis/TargetTransformImpl.h, where it always estimates that the
4916df161a2SAndrew Litteken   // code size for a division and remainder instruction to be equal to 4, and
4926df161a2SAndrew Litteken   // everything else to 1.  This is not an accurate representation of the
4936df161a2SAndrew Litteken   // division instruction for targets that have a native division instruction.
4946df161a2SAndrew Litteken   // To be overly conservative, we only add 1 to the number of instructions for
4956df161a2SAndrew Litteken   // each division instruction.
496c58d4c4bSAndrew Litteken   for (IRInstructionData &ID : *Candidate) {
497c58d4c4bSAndrew Litteken     Instruction *I = ID.Inst;
498c58d4c4bSAndrew Litteken     switch (I->getOpcode()) {
4996df161a2SAndrew Litteken     case Instruction::FDiv:
5006df161a2SAndrew Litteken     case Instruction::FRem:
5016df161a2SAndrew Litteken     case Instruction::SDiv:
5026df161a2SAndrew Litteken     case Instruction::SRem:
5036df161a2SAndrew Litteken     case Instruction::UDiv:
5046df161a2SAndrew Litteken     case Instruction::URem:
5056df161a2SAndrew Litteken       Benefit += 1;
5066df161a2SAndrew Litteken       break;
5076df161a2SAndrew Litteken     default:
508c58d4c4bSAndrew Litteken       Benefit += TTI.getInstructionCost(I, TargetTransformInfo::TCK_CodeSize);
5096df161a2SAndrew Litteken       break;
5106df161a2SAndrew Litteken     }
5116df161a2SAndrew Litteken   }
5126df161a2SAndrew Litteken 
513255a5077SDavid Sherwood   return Benefit;
5146df161a2SAndrew Litteken }
5156df161a2SAndrew Litteken 
516dcc3e728SAndrew Litteken /// Check the \p OutputMappings structure for value \p Input, if it exists
517dcc3e728SAndrew Litteken /// it has been used as an output for outlining, and has been renamed, and we
518dcc3e728SAndrew Litteken /// return the new value, otherwise, we return the same value.
519dcc3e728SAndrew Litteken ///
520dcc3e728SAndrew Litteken /// \param OutputMappings [in] - The mapping of values to their renamed value
521dcc3e728SAndrew Litteken /// after being used as an output for an outlined region.
522dcc3e728SAndrew Litteken /// \param Input [in] - The value to find the remapped value of, if it exists.
523dcc3e728SAndrew Litteken /// \return The remapped value if it has been renamed, and the same value if has
524dcc3e728SAndrew Litteken /// not.
findOutputMapping(const DenseMap<Value *,Value * > OutputMappings,Value * Input)525dcc3e728SAndrew Litteken static Value *findOutputMapping(const DenseMap<Value *, Value *> OutputMappings,
526dcc3e728SAndrew Litteken                                 Value *Input) {
527dcc3e728SAndrew Litteken   DenseMap<Value *, Value *>::const_iterator OutputMapping =
528dcc3e728SAndrew Litteken       OutputMappings.find(Input);
529dcc3e728SAndrew Litteken   if (OutputMapping != OutputMappings.end())
530dcc3e728SAndrew Litteken     return OutputMapping->second;
531dcc3e728SAndrew Litteken   return Input;
532dcc3e728SAndrew Litteken }
533dcc3e728SAndrew Litteken 
5347c6f28a4SAndrew Litteken /// Find whether \p Region matches the global value numbering to Constant
5357c6f28a4SAndrew Litteken /// mapping found so far.
536c52bcf3aSAndrew Litteken ///
537c52bcf3aSAndrew Litteken /// \param Region - The OutlinableRegion we are checking for constants
5387c6f28a4SAndrew Litteken /// \param GVNToConstant - The mapping of global value number to Constants.
539c52bcf3aSAndrew Litteken /// \param NotSame - The set of global value numbers that do not have the same
540c52bcf3aSAndrew Litteken /// constant in each region.
541c52bcf3aSAndrew Litteken /// \returns true if all Constants are the same in every use of a Constant in \p
542c52bcf3aSAndrew Litteken /// Region and false if not
543c52bcf3aSAndrew Litteken static bool
collectRegionsConstants(OutlinableRegion & Region,DenseMap<unsigned,Constant * > & GVNToConstant,DenseSet<unsigned> & NotSame)544c52bcf3aSAndrew Litteken collectRegionsConstants(OutlinableRegion &Region,
545c52bcf3aSAndrew Litteken                         DenseMap<unsigned, Constant *> &GVNToConstant,
546c52bcf3aSAndrew Litteken                         DenseSet<unsigned> &NotSame) {
547b1191c84SAndrew Litteken   bool ConstantsTheSame = true;
548b1191c84SAndrew Litteken 
549c52bcf3aSAndrew Litteken   IRSimilarityCandidate &C = *Region.Candidate;
550c52bcf3aSAndrew Litteken   for (IRInstructionData &ID : C) {
551c52bcf3aSAndrew Litteken 
552c52bcf3aSAndrew Litteken     // Iterate over the operands in an instruction. If the global value number,
553c52bcf3aSAndrew Litteken     // assigned by the IRSimilarityCandidate, has been seen before, we check if
554c52bcf3aSAndrew Litteken     // the the number has been found to be not the same value in each instance.
555c52bcf3aSAndrew Litteken     for (Value *V : ID.OperVals) {
556c52bcf3aSAndrew Litteken       Optional<unsigned> GVNOpt = C.getGVN(V);
557a7938c74SKazu Hirata       assert(GVNOpt && "Expected a GVN for operand?");
558*611ffcf4SKazu Hirata       unsigned GVN = GVNOpt.value();
559c52bcf3aSAndrew Litteken 
560b1191c84SAndrew Litteken       // Check if this global value has been found to not be the same already.
5615c1c39e8SKazu Hirata       if (NotSame.contains(GVN)) {
562c52bcf3aSAndrew Litteken         if (isa<Constant>(V))
563b1191c84SAndrew Litteken           ConstantsTheSame = false;
564c52bcf3aSAndrew Litteken         continue;
565c52bcf3aSAndrew Litteken       }
566c52bcf3aSAndrew Litteken 
567c52bcf3aSAndrew Litteken       // If it has been the same so far, we check the value for if the
568c52bcf3aSAndrew Litteken       // associated Constant value match the previous instances of the same
569c52bcf3aSAndrew Litteken       // global value number.  If the global value does not map to a Constant,
570c52bcf3aSAndrew Litteken       // it is considered to not be the same value.
571c52bcf3aSAndrew Litteken       Optional<bool> ConstantMatches = constantMatches(V, GVN, GVNToConstant);
572a7938c74SKazu Hirata       if (ConstantMatches) {
573*611ffcf4SKazu Hirata         if (ConstantMatches.value())
574c52bcf3aSAndrew Litteken           continue;
575c52bcf3aSAndrew Litteken         else
576b1191c84SAndrew Litteken           ConstantsTheSame = false;
577c52bcf3aSAndrew Litteken       }
578c52bcf3aSAndrew Litteken 
579c52bcf3aSAndrew Litteken       // While this value is a register, it might not have been previously,
580c52bcf3aSAndrew Litteken       // make sure we don't already have a constant mapped to this global value
581c52bcf3aSAndrew Litteken       // number.
582c52bcf3aSAndrew Litteken       if (GVNToConstant.find(GVN) != GVNToConstant.end())
583b1191c84SAndrew Litteken         ConstantsTheSame = false;
584c52bcf3aSAndrew Litteken 
585c52bcf3aSAndrew Litteken       NotSame.insert(GVN);
586c52bcf3aSAndrew Litteken     }
587c52bcf3aSAndrew Litteken   }
588c52bcf3aSAndrew Litteken 
589b1191c84SAndrew Litteken   return ConstantsTheSame;
590c52bcf3aSAndrew Litteken }
591c52bcf3aSAndrew Litteken 
findSameConstants(DenseSet<unsigned> & NotSame)592c52bcf3aSAndrew Litteken void OutlinableGroup::findSameConstants(DenseSet<unsigned> &NotSame) {
593c52bcf3aSAndrew Litteken   DenseMap<unsigned, Constant *> GVNToConstant;
594c52bcf3aSAndrew Litteken 
595c52bcf3aSAndrew Litteken   for (OutlinableRegion *Region : Regions)
596b1191c84SAndrew Litteken     collectRegionsConstants(*Region, GVNToConstant, NotSame);
597c52bcf3aSAndrew Litteken }
598c52bcf3aSAndrew Litteken 
collectGVNStoreSets(Module & M)5991e238025SAndrew Litteken void OutlinableGroup::collectGVNStoreSets(Module &M) {
6001e238025SAndrew Litteken   for (OutlinableRegion *OS : Regions)
6011e238025SAndrew Litteken     OutputGVNCombinations.insert(OS->GVNStores);
6021e238025SAndrew Litteken 
6031e238025SAndrew Litteken   // We are adding an extracted argument to decide between which output path
6041e238025SAndrew Litteken   // to use in the basic block.  It is used in a switch statement and only
6051e238025SAndrew Litteken   // needs to be an integer.
6061e238025SAndrew Litteken   if (OutputGVNCombinations.size() > 1)
6071e238025SAndrew Litteken     ArgumentTypes.push_back(Type::getInt32Ty(M.getContext()));
6081e238025SAndrew Litteken }
6091e238025SAndrew Litteken 
6102c21278eSAndrew Litteken /// Get the subprogram if it exists for one of the outlined regions.
6112c21278eSAndrew Litteken ///
6122c21278eSAndrew Litteken /// \param [in] Group - The set of regions to find a subprogram for.
6132c21278eSAndrew Litteken /// \returns the subprogram if it exists, or nullptr.
getSubprogramOrNull(OutlinableGroup & Group)6142c21278eSAndrew Litteken static DISubprogram *getSubprogramOrNull(OutlinableGroup &Group) {
6152c21278eSAndrew Litteken   for (OutlinableRegion *OS : Group.Regions)
6162c21278eSAndrew Litteken     if (Function *F = OS->Call->getFunction())
6172c21278eSAndrew Litteken       if (DISubprogram *SP = F->getSubprogram())
6182c21278eSAndrew Litteken         return SP;
6192c21278eSAndrew Litteken 
6202c21278eSAndrew Litteken   return nullptr;
6212c21278eSAndrew Litteken }
6222c21278eSAndrew Litteken 
createFunction(Module & M,OutlinableGroup & Group,unsigned FunctionNameSuffix)6237c6f28a4SAndrew Litteken Function *IROutliner::createFunction(Module &M, OutlinableGroup &Group,
6247c6f28a4SAndrew Litteken                                      unsigned FunctionNameSuffix) {
6257c6f28a4SAndrew Litteken   assert(!Group.OutlinedFunction && "Function is already defined!");
6267c6f28a4SAndrew Litteken 
627c172f1adSAndrew Litteken   Type *RetTy = Type::getVoidTy(M.getContext());
628c172f1adSAndrew Litteken   // All extracted functions _should_ have the same return type at this point
629c172f1adSAndrew Litteken   // since the similarity identifier ensures that all branches outside of the
630c172f1adSAndrew Litteken   // region occur in the same place.
631c172f1adSAndrew Litteken 
632c172f1adSAndrew Litteken   // NOTE: Should we ever move to the model that uses a switch at every point
633c172f1adSAndrew Litteken   // needed, meaning that we could branch within the region or out, it is
634c172f1adSAndrew Litteken   // possible that we will need to switch to using the most general case all of
635c172f1adSAndrew Litteken   // the time.
636c172f1adSAndrew Litteken   for (OutlinableRegion *R : Group.Regions) {
637c172f1adSAndrew Litteken     Type *ExtractedFuncType = R->ExtractedFunction->getReturnType();
638c172f1adSAndrew Litteken     if ((RetTy->isVoidTy() && !ExtractedFuncType->isVoidTy()) ||
639c172f1adSAndrew Litteken         (RetTy->isIntegerTy(1) && ExtractedFuncType->isIntegerTy(16)))
640c172f1adSAndrew Litteken       RetTy = ExtractedFuncType;
641c172f1adSAndrew Litteken   }
642c172f1adSAndrew Litteken 
6437c6f28a4SAndrew Litteken   Group.OutlinedFunctionType = FunctionType::get(
644c172f1adSAndrew Litteken       RetTy, Group.ArgumentTypes, false);
6457c6f28a4SAndrew Litteken 
6467c6f28a4SAndrew Litteken   // These functions will only be called from within the same module, so
6477c6f28a4SAndrew Litteken   // we can set an internal linkage.
6487c6f28a4SAndrew Litteken   Group.OutlinedFunction = Function::Create(
6497c6f28a4SAndrew Litteken       Group.OutlinedFunctionType, GlobalValue::InternalLinkage,
6507c6f28a4SAndrew Litteken       "outlined_ir_func_" + std::to_string(FunctionNameSuffix), M);
6517c6f28a4SAndrew Litteken 
65230feb930SAndrew Litteken   // Transfer the swifterr attribute to the correct function parameter.
653a7938c74SKazu Hirata   if (Group.SwiftErrorArgument)
654*611ffcf4SKazu Hirata     Group.OutlinedFunction->addParamAttr(Group.SwiftErrorArgument.value(),
65530feb930SAndrew Litteken                                          Attribute::SwiftError);
65630feb930SAndrew Litteken 
6577c6f28a4SAndrew Litteken   Group.OutlinedFunction->addFnAttr(Attribute::OptimizeForSize);
6587c6f28a4SAndrew Litteken   Group.OutlinedFunction->addFnAttr(Attribute::MinSize);
6597c6f28a4SAndrew Litteken 
6602c21278eSAndrew Litteken   // If there's a DISubprogram associated with this outlined function, then
6612c21278eSAndrew Litteken   // emit debug info for the outlined function.
6622c21278eSAndrew Litteken   if (DISubprogram *SP = getSubprogramOrNull(Group)) {
6632c21278eSAndrew Litteken     Function *F = Group.OutlinedFunction;
6642c21278eSAndrew Litteken     // We have a DISubprogram. Get its DICompileUnit.
6652c21278eSAndrew Litteken     DICompileUnit *CU = SP->getUnit();
6662c21278eSAndrew Litteken     DIBuilder DB(M, true, CU);
6672c21278eSAndrew Litteken     DIFile *Unit = SP->getFile();
6682c21278eSAndrew Litteken     Mangler Mg;
6692c21278eSAndrew Litteken     // Get the mangled name of the function for the linkage name.
6702c21278eSAndrew Litteken     std::string Dummy;
6712c21278eSAndrew Litteken     llvm::raw_string_ostream MangledNameStream(Dummy);
6722c21278eSAndrew Litteken     Mg.getNameWithPrefix(MangledNameStream, F, false);
6732c21278eSAndrew Litteken 
6742c21278eSAndrew Litteken     DISubprogram *OutlinedSP = DB.createFunction(
6752c21278eSAndrew Litteken         Unit /* Context */, F->getName(), MangledNameStream.str(),
6762c21278eSAndrew Litteken         Unit /* File */,
6772c21278eSAndrew Litteken         0 /* Line 0 is reserved for compiler-generated code. */,
6782c21278eSAndrew Litteken         DB.createSubroutineType(DB.getOrCreateTypeArray(None)), /* void type */
6792c21278eSAndrew Litteken         0, /* Line 0 is reserved for compiler-generated code. */
6802c21278eSAndrew Litteken         DINode::DIFlags::FlagArtificial /* Compiler-generated code. */,
6812c21278eSAndrew Litteken         /* Outlined code is optimized code by definition. */
6822c21278eSAndrew Litteken         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
6832c21278eSAndrew Litteken 
6842c21278eSAndrew Litteken     // Don't add any new variables to the subprogram.
6852c21278eSAndrew Litteken     DB.finalizeSubprogram(OutlinedSP);
6862c21278eSAndrew Litteken 
6872c21278eSAndrew Litteken     // Attach subprogram to the function.
6882c21278eSAndrew Litteken     F->setSubprogram(OutlinedSP);
6892c21278eSAndrew Litteken     // We're done with the DIBuilder.
6902c21278eSAndrew Litteken     DB.finalize();
6912c21278eSAndrew Litteken   }
6922c21278eSAndrew Litteken 
6937c6f28a4SAndrew Litteken   return Group.OutlinedFunction;
6947c6f28a4SAndrew Litteken }
6957c6f28a4SAndrew Litteken 
6967c6f28a4SAndrew Litteken /// Move each BasicBlock in \p Old to \p New.
6977c6f28a4SAndrew Litteken ///
6982c21278eSAndrew Litteken /// \param [in] Old - The function to move the basic blocks from.
6997c6f28a4SAndrew Litteken /// \param [in] New - The function to move the basic blocks to.
700c172f1adSAndrew Litteken /// \param [out] NewEnds - The return blocks of the new overall function.
moveFunctionData(Function & Old,Function & New,DenseMap<Value *,BasicBlock * > & NewEnds)701c172f1adSAndrew Litteken static void moveFunctionData(Function &Old, Function &New,
702c172f1adSAndrew Litteken                              DenseMap<Value *, BasicBlock *> &NewEnds) {
70387e53a0aSKazu Hirata   for (BasicBlock &CurrBB : llvm::make_early_inc_range(Old)) {
70487e53a0aSKazu Hirata     CurrBB.removeFromParent();
70587e53a0aSKazu Hirata     CurrBB.insertInto(&New);
70687e53a0aSKazu Hirata     Instruction *I = CurrBB.getTerminator();
707c172f1adSAndrew Litteken 
708c172f1adSAndrew Litteken     // For each block we find a return instruction is, it is a potential exit
709c172f1adSAndrew Litteken     // path for the function.  We keep track of each block based on the return
710c172f1adSAndrew Litteken     // value here.
711c172f1adSAndrew Litteken     if (ReturnInst *RI = dyn_cast<ReturnInst>(I))
71287e53a0aSKazu Hirata       NewEnds.insert(std::make_pair(RI->getReturnValue(), &CurrBB));
7132c21278eSAndrew Litteken 
7142e192ab1SVyacheslav Zakharin     std::vector<Instruction *> DebugInsts;
7152e192ab1SVyacheslav Zakharin 
71687e53a0aSKazu Hirata     for (Instruction &Val : CurrBB) {
7172c21278eSAndrew Litteken       // We must handle the scoping of called functions differently than
7182c21278eSAndrew Litteken       // other outlined instructions.
7192c21278eSAndrew Litteken       if (!isa<CallInst>(&Val)) {
7202c21278eSAndrew Litteken         // Remove the debug information for outlined functions.
7212c21278eSAndrew Litteken         Val.setDebugLoc(DebugLoc());
722f7d90ad5SAndrew Litteken 
723f7d90ad5SAndrew Litteken         // Loop info metadata may contain line locations. Update them to have no
724f7d90ad5SAndrew Litteken         // value in the new subprogram since the outlined code could be from
725f7d90ad5SAndrew Litteken         // several locations.
726f7d90ad5SAndrew Litteken         auto updateLoopInfoLoc = [&New](Metadata *MD) -> Metadata * {
727f7d90ad5SAndrew Litteken           if (DISubprogram *SP = New.getSubprogram())
728f7d90ad5SAndrew Litteken             if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
729f7d90ad5SAndrew Litteken               return DILocation::get(New.getContext(), Loc->getLine(),
730f7d90ad5SAndrew Litteken                                      Loc->getColumn(), SP, nullptr);
731f7d90ad5SAndrew Litteken           return MD;
732f7d90ad5SAndrew Litteken         };
733f7d90ad5SAndrew Litteken         updateLoopMetadataDebugLocations(Val, updateLoopInfoLoc);
7342c21278eSAndrew Litteken         continue;
7352c21278eSAndrew Litteken       }
7362c21278eSAndrew Litteken 
7372c21278eSAndrew Litteken       // From this point we are only handling call instructions.
7382c21278eSAndrew Litteken       CallInst *CI = cast<CallInst>(&Val);
7392c21278eSAndrew Litteken 
7402c21278eSAndrew Litteken       // We add any debug statements here, to be removed after.  Since the
7412c21278eSAndrew Litteken       // instructions originate from many different locations in the program,
7422c21278eSAndrew Litteken       // it will cause incorrect reporting from a debugger if we keep the
7432c21278eSAndrew Litteken       // same debug instructions.
7442c21278eSAndrew Litteken       if (isa<DbgInfoIntrinsic>(CI)) {
7452c21278eSAndrew Litteken         DebugInsts.push_back(&Val);
7462c21278eSAndrew Litteken         continue;
7472c21278eSAndrew Litteken       }
7482c21278eSAndrew Litteken 
7492c21278eSAndrew Litteken       // Edit the scope of called functions inside of outlined functions.
7502c21278eSAndrew Litteken       if (DISubprogram *SP = New.getSubprogram()) {
7512c21278eSAndrew Litteken         DILocation *DI = DILocation::get(New.getContext(), 0, 0, SP);
7522c21278eSAndrew Litteken         Val.setDebugLoc(DI);
7532c21278eSAndrew Litteken       }
7542c21278eSAndrew Litteken     }
7552c21278eSAndrew Litteken 
7562c21278eSAndrew Litteken     for (Instruction *I : DebugInsts)
7572c21278eSAndrew Litteken       I->eraseFromParent();
7587c6f28a4SAndrew Litteken   }
7597c6f28a4SAndrew Litteken }
7607c6f28a4SAndrew Litteken 
761b1191c84SAndrew Litteken /// Find the the constants that will need to be lifted into arguments
762b1191c84SAndrew Litteken /// as they are not the same in each instance of the region.
763b1191c84SAndrew Litteken ///
764b1191c84SAndrew Litteken /// \param [in] C - The IRSimilarityCandidate containing the region we are
765b1191c84SAndrew Litteken /// analyzing.
766b1191c84SAndrew Litteken /// \param [in] NotSame - The set of global value numbers that do not have a
767b1191c84SAndrew Litteken /// single Constant across all OutlinableRegions similar to \p C.
768b1191c84SAndrew Litteken /// \param [out] Inputs - The list containing the global value numbers of the
769b1191c84SAndrew Litteken /// arguments needed for the region of code.
findConstants(IRSimilarityCandidate & C,DenseSet<unsigned> & NotSame,std::vector<unsigned> & Inputs)770b1191c84SAndrew Litteken static void findConstants(IRSimilarityCandidate &C, DenseSet<unsigned> &NotSame,
771b1191c84SAndrew Litteken                           std::vector<unsigned> &Inputs) {
772b1191c84SAndrew Litteken   DenseSet<unsigned> Seen;
773b1191c84SAndrew Litteken   // Iterate over the instructions, and find what constants will need to be
774b1191c84SAndrew Litteken   // extracted into arguments.
775b1191c84SAndrew Litteken   for (IRInstructionDataList::iterator IDIt = C.begin(), EndIDIt = C.end();
776b1191c84SAndrew Litteken        IDIt != EndIDIt; IDIt++) {
777b1191c84SAndrew Litteken     for (Value *V : (*IDIt).OperVals) {
778b1191c84SAndrew Litteken       // Since these are stored before any outlining, they will be in the
779b1191c84SAndrew Litteken       // global value numbering.
7807a47ee51SKazu Hirata       unsigned GVN = *C.getGVN(V);
781897990e6SCraig Topper       if (isa<Constant>(V))
7825c1c39e8SKazu Hirata         if (NotSame.contains(GVN) && !Seen.contains(GVN)) {
783b1191c84SAndrew Litteken           Inputs.push_back(GVN);
784b1191c84SAndrew Litteken           Seen.insert(GVN);
785b1191c84SAndrew Litteken         }
786b1191c84SAndrew Litteken     }
787b1191c84SAndrew Litteken   }
788b1191c84SAndrew Litteken }
789b1191c84SAndrew Litteken 
790b1191c84SAndrew Litteken /// Find the GVN for the inputs that have been found by the CodeExtractor.
791c52bcf3aSAndrew Litteken ///
792c52bcf3aSAndrew Litteken /// \param [in] C - The IRSimilarityCandidate containing the region we are
793c52bcf3aSAndrew Litteken /// analyzing.
794c52bcf3aSAndrew Litteken /// \param [in] CurrentInputs - The set of inputs found by the
795c52bcf3aSAndrew Litteken /// CodeExtractor.
796e6ae6233SAndrew Litteken /// \param [in] OutputMappings - The mapping of values that have been replaced
797e6ae6233SAndrew Litteken /// by a new output value.
79889edda70SSimon Pilgrim /// \param [out] EndInputNumbers - The global value numbers for the extracted
799e6ae6233SAndrew Litteken /// arguments.
mapInputsToGVNs(IRSimilarityCandidate & C,SetVector<Value * > & CurrentInputs,const DenseMap<Value *,Value * > & OutputMappings,std::vector<unsigned> & EndInputNumbers)800c52bcf3aSAndrew Litteken static void mapInputsToGVNs(IRSimilarityCandidate &C,
801c52bcf3aSAndrew Litteken                             SetVector<Value *> &CurrentInputs,
802e6ae6233SAndrew Litteken                             const DenseMap<Value *, Value *> &OutputMappings,
803c52bcf3aSAndrew Litteken                             std::vector<unsigned> &EndInputNumbers) {
804e6ae6233SAndrew Litteken   // Get the Global Value Number for each input.  We check if the Value has been
805e6ae6233SAndrew Litteken   // replaced by a different value at output, and use the original value before
806e6ae6233SAndrew Litteken   // replacement.
807c52bcf3aSAndrew Litteken   for (Value *Input : CurrentInputs) {
808c52bcf3aSAndrew Litteken     assert(Input && "Have a nullptr as an input");
809e6ae6233SAndrew Litteken     if (OutputMappings.find(Input) != OutputMappings.end())
810e6ae6233SAndrew Litteken       Input = OutputMappings.find(Input)->second;
811a7938c74SKazu Hirata     assert(C.getGVN(Input) && "Could not find a numbering for the given input");
812*611ffcf4SKazu Hirata     EndInputNumbers.push_back(C.getGVN(Input).value());
813c52bcf3aSAndrew Litteken   }
814c52bcf3aSAndrew Litteken }
815c52bcf3aSAndrew Litteken 
816e6ae6233SAndrew Litteken /// Find the original value for the \p ArgInput values if any one of them was
817e6ae6233SAndrew Litteken /// replaced during a previous extraction.
818e6ae6233SAndrew Litteken ///
819e6ae6233SAndrew Litteken /// \param [in] ArgInputs - The inputs to be extracted by the code extractor.
820e6ae6233SAndrew Litteken /// \param [in] OutputMappings - The mapping of values that have been replaced
821e6ae6233SAndrew Litteken /// by a new output value.
822e6ae6233SAndrew Litteken /// \param [out] RemappedArgInputs - The remapped values according to
823e6ae6233SAndrew Litteken /// \p OutputMappings that will be extracted.
824e6ae6233SAndrew Litteken static void
remapExtractedInputs(const ArrayRef<Value * > ArgInputs,const DenseMap<Value *,Value * > & OutputMappings,SetVector<Value * > & RemappedArgInputs)825e6ae6233SAndrew Litteken remapExtractedInputs(const ArrayRef<Value *> ArgInputs,
826e6ae6233SAndrew Litteken                      const DenseMap<Value *, Value *> &OutputMappings,
827e6ae6233SAndrew Litteken                      SetVector<Value *> &RemappedArgInputs) {
828e6ae6233SAndrew Litteken   // Get the global value number for each input that will be extracted as an
829e6ae6233SAndrew Litteken   // argument by the code extractor, remapping if needed for reloaded values.
830e6ae6233SAndrew Litteken   for (Value *Input : ArgInputs) {
831e6ae6233SAndrew Litteken     if (OutputMappings.find(Input) != OutputMappings.end())
832e6ae6233SAndrew Litteken       Input = OutputMappings.find(Input)->second;
833e6ae6233SAndrew Litteken     RemappedArgInputs.insert(Input);
834e6ae6233SAndrew Litteken   }
835e6ae6233SAndrew Litteken }
836e6ae6233SAndrew Litteken 
837c52bcf3aSAndrew Litteken /// Find the input GVNs and the output values for a region of Instructions.
838c52bcf3aSAndrew Litteken /// Using the code extractor, we collect the inputs to the extracted function.
839c52bcf3aSAndrew Litteken ///
840b1191c84SAndrew Litteken /// The \p Region can be identified as needing to be ignored in this function.
841c52bcf3aSAndrew Litteken /// It should be checked whether it should be ignored after a call to this
842c52bcf3aSAndrew Litteken /// function.
843c52bcf3aSAndrew Litteken ///
844c52bcf3aSAndrew Litteken /// \param [in,out] Region - The region of code to be analyzed.
8457c6f28a4SAndrew Litteken /// \param [out] InputGVNs - The global value numbers for the extracted
8467c6f28a4SAndrew Litteken /// arguments.
847b1191c84SAndrew Litteken /// \param [in] NotSame - The global value numbers in the region that do not
848b1191c84SAndrew Litteken /// have the same constant value in the regions structurally similar to
849b1191c84SAndrew Litteken /// \p Region.
850e6ae6233SAndrew Litteken /// \param [in] OutputMappings - The mapping of values that have been replaced
851e6ae6233SAndrew Litteken /// by a new output value after extraction.
852c52bcf3aSAndrew Litteken /// \param [out] ArgInputs - The values of the inputs to the extracted function.
853e6ae6233SAndrew Litteken /// \param [out] Outputs - The set of values extracted by the CodeExtractor
854e6ae6233SAndrew Litteken /// as outputs.
getCodeExtractorArguments(OutlinableRegion & Region,std::vector<unsigned> & InputGVNs,DenseSet<unsigned> & NotSame,DenseMap<Value *,Value * > & OutputMappings,SetVector<Value * > & ArgInputs,SetVector<Value * > & Outputs)855e6ae6233SAndrew Litteken static void getCodeExtractorArguments(
856e6ae6233SAndrew Litteken     OutlinableRegion &Region, std::vector<unsigned> &InputGVNs,
857e6ae6233SAndrew Litteken     DenseSet<unsigned> &NotSame, DenseMap<Value *, Value *> &OutputMappings,
858e6ae6233SAndrew Litteken     SetVector<Value *> &ArgInputs, SetVector<Value *> &Outputs) {
859c52bcf3aSAndrew Litteken   IRSimilarityCandidate &C = *Region.Candidate;
860c52bcf3aSAndrew Litteken 
861c52bcf3aSAndrew Litteken   // OverallInputs are the inputs to the region found by the CodeExtractor,
862c52bcf3aSAndrew Litteken   // SinkCands and HoistCands are used by the CodeExtractor to find sunken
863c52bcf3aSAndrew Litteken   // allocas of values whose lifetimes are contained completely within the
864e6ae6233SAndrew Litteken   // outlined region. PremappedInputs are the arguments found by the
865e6ae6233SAndrew Litteken   // CodeExtractor, removing conditions such as sunken allocas, but that
866e6ae6233SAndrew Litteken   // may need to be remapped due to the extracted output values replacing
86705b1a15fSAndrew Litteken   // the original values. We use DummyOutputs for this first run of finding
86805b1a15fSAndrew Litteken   // inputs and outputs since the outputs could change during findAllocas,
86905b1a15fSAndrew Litteken   // the correct set of extracted outputs will be in the final Outputs ValueSet.
87005b1a15fSAndrew Litteken   SetVector<Value *> OverallInputs, PremappedInputs, SinkCands, HoistCands,
87105b1a15fSAndrew Litteken       DummyOutputs;
872c52bcf3aSAndrew Litteken 
873c52bcf3aSAndrew Litteken   // Use the code extractor to get the inputs and outputs, without sunken
874c52bcf3aSAndrew Litteken   // allocas or removing llvm.assumes.
875c52bcf3aSAndrew Litteken   CodeExtractor *CE = Region.CE;
87605b1a15fSAndrew Litteken   CE->findInputsOutputs(OverallInputs, DummyOutputs, SinkCands);
877c52bcf3aSAndrew Litteken   assert(Region.StartBB && "Region must have a start BasicBlock!");
878c52bcf3aSAndrew Litteken   Function *OrigF = Region.StartBB->getParent();
879c52bcf3aSAndrew Litteken   CodeExtractorAnalysisCache CEAC(*OrigF);
880c52bcf3aSAndrew Litteken   BasicBlock *Dummy = nullptr;
881c52bcf3aSAndrew Litteken 
882c52bcf3aSAndrew Litteken   // The region may be ineligible due to VarArgs in the parent function. In this
883c52bcf3aSAndrew Litteken   // case we ignore the region.
884c52bcf3aSAndrew Litteken   if (!CE->isEligible()) {
885c52bcf3aSAndrew Litteken     Region.IgnoreRegion = true;
886c52bcf3aSAndrew Litteken     return;
887c52bcf3aSAndrew Litteken   }
888c52bcf3aSAndrew Litteken 
889c52bcf3aSAndrew Litteken   // Find if any values are going to be sunk into the function when extracted
890c52bcf3aSAndrew Litteken   CE->findAllocas(CEAC, SinkCands, HoistCands, Dummy);
891e6ae6233SAndrew Litteken   CE->findInputsOutputs(PremappedInputs, Outputs, SinkCands);
892c52bcf3aSAndrew Litteken 
893c52bcf3aSAndrew Litteken   // TODO: Support regions with sunken allocas: values whose lifetimes are
894c52bcf3aSAndrew Litteken   // contained completely within the outlined region.  These are not guaranteed
895c52bcf3aSAndrew Litteken   // to be the same in every region, so we must elevate them all to arguments
896c52bcf3aSAndrew Litteken   // when they appear.  If these values are not equal, it means there is some
897c52bcf3aSAndrew Litteken   // Input in OverallInputs that was removed for ArgInputs.
898e6ae6233SAndrew Litteken   if (OverallInputs.size() != PremappedInputs.size()) {
899c52bcf3aSAndrew Litteken     Region.IgnoreRegion = true;
900c52bcf3aSAndrew Litteken     return;
901c52bcf3aSAndrew Litteken   }
902c52bcf3aSAndrew Litteken 
903b1191c84SAndrew Litteken   findConstants(C, NotSame, InputGVNs);
904e6ae6233SAndrew Litteken 
905e6ae6233SAndrew Litteken   mapInputsToGVNs(C, OverallInputs, OutputMappings, InputGVNs);
906e6ae6233SAndrew Litteken 
907e6ae6233SAndrew Litteken   remapExtractedInputs(PremappedInputs.getArrayRef(), OutputMappings,
908e6ae6233SAndrew Litteken                        ArgInputs);
909b1191c84SAndrew Litteken 
910b1191c84SAndrew Litteken   // Sort the GVNs, since we now have constants included in the \ref InputGVNs
911b1191c84SAndrew Litteken   // we need to make sure they are in a deterministic order.
912125ea20dSKazu Hirata   stable_sort(InputGVNs);
913c52bcf3aSAndrew Litteken }
914c52bcf3aSAndrew Litteken 
9157c6f28a4SAndrew Litteken /// Look over the inputs and map each input argument to an argument in the
916b1191c84SAndrew Litteken /// overall function for the OutlinableRegions.  This creates a way to replace
917b1191c84SAndrew Litteken /// the arguments of the extracted function with the arguments of the new
918b1191c84SAndrew Litteken /// overall function.
9197c6f28a4SAndrew Litteken ///
9207c6f28a4SAndrew Litteken /// \param [in,out] Region - The region of code to be analyzed.
92189edda70SSimon Pilgrim /// \param [in] InputGVNs - The global value numbering of the input values
9227c6f28a4SAndrew Litteken /// collected.
9237c6f28a4SAndrew Litteken /// \param [in] ArgInputs - The values of the arguments to the extracted
9247c6f28a4SAndrew Litteken /// function.
9257c6f28a4SAndrew Litteken static void
findExtractedInputToOverallInputMapping(OutlinableRegion & Region,std::vector<unsigned> & InputGVNs,SetVector<Value * > & ArgInputs)9267c6f28a4SAndrew Litteken findExtractedInputToOverallInputMapping(OutlinableRegion &Region,
927e6ae6233SAndrew Litteken                                         std::vector<unsigned> &InputGVNs,
9287c6f28a4SAndrew Litteken                                         SetVector<Value *> &ArgInputs) {
9297c6f28a4SAndrew Litteken 
9307c6f28a4SAndrew Litteken   IRSimilarityCandidate &C = *Region.Candidate;
9317c6f28a4SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
9327c6f28a4SAndrew Litteken 
9337c6f28a4SAndrew Litteken   // This counts the argument number in the overall function.
9347c6f28a4SAndrew Litteken   unsigned TypeIndex = 0;
9357c6f28a4SAndrew Litteken 
9367c6f28a4SAndrew Litteken   // This counts the argument number in the extracted function.
9377c6f28a4SAndrew Litteken   unsigned OriginalIndex = 0;
9387c6f28a4SAndrew Litteken 
9397c6f28a4SAndrew Litteken   // Find the mapping of the extracted arguments to the arguments for the
940b1191c84SAndrew Litteken   // overall function. Since there may be extra arguments in the overall
941b1191c84SAndrew Litteken   // function to account for the extracted constants, we have two different
942b1191c84SAndrew Litteken   // counters as we find extracted arguments, and as we come across overall
943b1191c84SAndrew Litteken   // arguments.
944063af63bSAndrew Litteken 
945063af63bSAndrew Litteken   // Additionally, in our first pass, for the first extracted function,
946063af63bSAndrew Litteken   // we find argument locations for the canonical value numbering.  This
947063af63bSAndrew Litteken   // numbering overrides any discovered location for the extracted code.
9487c6f28a4SAndrew Litteken   for (unsigned InputVal : InputGVNs) {
949063af63bSAndrew Litteken     Optional<unsigned> CanonicalNumberOpt = C.getCanonicalNum(InputVal);
950a7938c74SKazu Hirata     assert(CanonicalNumberOpt && "Canonical number not found?");
951*611ffcf4SKazu Hirata     unsigned CanonicalNumber = CanonicalNumberOpt.value();
952063af63bSAndrew Litteken 
9537c6f28a4SAndrew Litteken     Optional<Value *> InputOpt = C.fromGVN(InputVal);
954a7938c74SKazu Hirata     assert(InputOpt && "Global value number not found?");
955*611ffcf4SKazu Hirata     Value *Input = InputOpt.value();
9567c6f28a4SAndrew Litteken 
957063af63bSAndrew Litteken     DenseMap<unsigned, unsigned>::iterator AggArgIt =
958063af63bSAndrew Litteken         Group.CanonicalNumberToAggArg.find(CanonicalNumber);
959063af63bSAndrew Litteken 
96030feb930SAndrew Litteken     if (!Group.InputTypesSet) {
9617c6f28a4SAndrew Litteken       Group.ArgumentTypes.push_back(Input->getType());
96230feb930SAndrew Litteken       // If the input value has a swifterr attribute, make sure to mark the
96330feb930SAndrew Litteken       // argument in the overall function.
96430feb930SAndrew Litteken       if (Input->isSwiftError()) {
96530feb930SAndrew Litteken         assert(
9660916d96dSKazu Hirata             !Group.SwiftErrorArgument &&
96730feb930SAndrew Litteken             "Argument already marked with swifterr for this OutlinableGroup!");
96830feb930SAndrew Litteken         Group.SwiftErrorArgument = TypeIndex;
96930feb930SAndrew Litteken       }
97030feb930SAndrew Litteken     }
9717c6f28a4SAndrew Litteken 
972b1191c84SAndrew Litteken     // Check if we have a constant. If we do add it to the overall argument
973b1191c84SAndrew Litteken     // number to Constant map for the region, and continue to the next input.
974b1191c84SAndrew Litteken     if (Constant *CST = dyn_cast<Constant>(Input)) {
975063af63bSAndrew Litteken       if (AggArgIt != Group.CanonicalNumberToAggArg.end())
976063af63bSAndrew Litteken         Region.AggArgToConstant.insert(std::make_pair(AggArgIt->second, CST));
977063af63bSAndrew Litteken       else {
978063af63bSAndrew Litteken         Group.CanonicalNumberToAggArg.insert(
979063af63bSAndrew Litteken             std::make_pair(CanonicalNumber, TypeIndex));
980b1191c84SAndrew Litteken         Region.AggArgToConstant.insert(std::make_pair(TypeIndex, CST));
981063af63bSAndrew Litteken       }
982b1191c84SAndrew Litteken       TypeIndex++;
983b1191c84SAndrew Litteken       continue;
984b1191c84SAndrew Litteken     }
985b1191c84SAndrew Litteken 
986b1191c84SAndrew Litteken     // It is not a constant, we create the mapping from extracted argument list
987063af63bSAndrew Litteken     // to the overall argument list, using the canonical location, if it exists.
988d56982b6SMichael Forster     assert(ArgInputs.count(Input) && "Input cannot be found!");
9897c6f28a4SAndrew Litteken 
990063af63bSAndrew Litteken     if (AggArgIt != Group.CanonicalNumberToAggArg.end()) {
991063af63bSAndrew Litteken       if (OriginalIndex != AggArgIt->second)
992063af63bSAndrew Litteken         Region.ChangedArgOrder = true;
993063af63bSAndrew Litteken       Region.ExtractedArgToAgg.insert(
994063af63bSAndrew Litteken           std::make_pair(OriginalIndex, AggArgIt->second));
995063af63bSAndrew Litteken       Region.AggArgToExtracted.insert(
996063af63bSAndrew Litteken           std::make_pair(AggArgIt->second, OriginalIndex));
997063af63bSAndrew Litteken     } else {
998063af63bSAndrew Litteken       Group.CanonicalNumberToAggArg.insert(
999063af63bSAndrew Litteken           std::make_pair(CanonicalNumber, TypeIndex));
10007c6f28a4SAndrew Litteken       Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, TypeIndex));
10017c6f28a4SAndrew Litteken       Region.AggArgToExtracted.insert(std::make_pair(TypeIndex, OriginalIndex));
1002063af63bSAndrew Litteken     }
10037c6f28a4SAndrew Litteken     OriginalIndex++;
10047c6f28a4SAndrew Litteken     TypeIndex++;
10057c6f28a4SAndrew Litteken   }
10067c6f28a4SAndrew Litteken 
1007b1191c84SAndrew Litteken   // If the function type definitions for the OutlinableGroup holding the region
1008b1191c84SAndrew Litteken   // have not been set, set the length of the inputs here.  We should have the
1009b1191c84SAndrew Litteken   // same inputs for all of the different regions contained in the
1010b1191c84SAndrew Litteken   // OutlinableGroup since they are all structurally similar to one another.
10117c6f28a4SAndrew Litteken   if (!Group.InputTypesSet) {
10127c6f28a4SAndrew Litteken     Group.NumAggregateInputs = TypeIndex;
10137c6f28a4SAndrew Litteken     Group.InputTypesSet = true;
10147c6f28a4SAndrew Litteken   }
10157c6f28a4SAndrew Litteken 
10167c6f28a4SAndrew Litteken   Region.NumExtractedInputs = OriginalIndex;
10177c6f28a4SAndrew Litteken }
10187c6f28a4SAndrew Litteken 
1019dcc3e728SAndrew Litteken /// Check if the \p V has any uses outside of the region other than \p PN.
1020dcc3e728SAndrew Litteken ///
1021dcc3e728SAndrew Litteken /// \param V [in] - The value to check.
1022dcc3e728SAndrew Litteken /// \param PHILoc [in] - The location in the PHINode of \p V.
1023dcc3e728SAndrew Litteken /// \param PN [in] - The PHINode using \p V.
1024dcc3e728SAndrew Litteken /// \param Exits [in] - The potential blocks we exit to from the outlined
1025dcc3e728SAndrew Litteken /// region.
1026dcc3e728SAndrew Litteken /// \param BlocksInRegion [in] - The basic blocks contained in the region.
1027dcc3e728SAndrew Litteken /// \returns true if \p V has any use soutside its region other than \p PN.
outputHasNonPHI(Value * V,unsigned PHILoc,PHINode & PN,SmallPtrSet<BasicBlock *,1> & Exits,DenseSet<BasicBlock * > & BlocksInRegion)1028dcc3e728SAndrew Litteken static bool outputHasNonPHI(Value *V, unsigned PHILoc, PHINode &PN,
1029dcc3e728SAndrew Litteken                             SmallPtrSet<BasicBlock *, 1> &Exits,
1030dcc3e728SAndrew Litteken                             DenseSet<BasicBlock *> &BlocksInRegion) {
1031dcc3e728SAndrew Litteken   // We check to see if the value is used by the PHINode from some other
1032dcc3e728SAndrew Litteken   // predecessor not included in the region.  If it is, we make sure
1033dcc3e728SAndrew Litteken   // to keep it as an output.
103485243124SBenjamin Kramer   if (any_of(llvm::seq<unsigned>(0, PN.getNumIncomingValues()),
103585243124SBenjamin Kramer              [PHILoc, &PN, V, &BlocksInRegion](unsigned Idx) {
1036dcc3e728SAndrew Litteken                return (Idx != PHILoc && V == PN.getIncomingValue(Idx) &&
1037dcc3e728SAndrew Litteken                        !BlocksInRegion.contains(PN.getIncomingBlock(Idx)));
1038dcc3e728SAndrew Litteken              }))
1039dcc3e728SAndrew Litteken     return true;
1040dcc3e728SAndrew Litteken 
1041dcc3e728SAndrew Litteken   // Check if the value is used by any other instructions outside the region.
1042dcc3e728SAndrew Litteken   return any_of(V->users(), [&Exits, &BlocksInRegion](User *U) {
1043dcc3e728SAndrew Litteken     Instruction *I = dyn_cast<Instruction>(U);
1044dcc3e728SAndrew Litteken     if (!I)
1045dcc3e728SAndrew Litteken       return false;
1046dcc3e728SAndrew Litteken 
1047dcc3e728SAndrew Litteken     // If the use of the item is inside the region, we skip it.  Uses
1048dcc3e728SAndrew Litteken     // inside the region give us useful information about how the item could be
1049dcc3e728SAndrew Litteken     // used as an output.
1050dcc3e728SAndrew Litteken     BasicBlock *Parent = I->getParent();
1051dcc3e728SAndrew Litteken     if (BlocksInRegion.contains(Parent))
1052dcc3e728SAndrew Litteken       return false;
1053dcc3e728SAndrew Litteken 
1054dcc3e728SAndrew Litteken     // If it's not a PHINode then we definitely know the use matters.  This
1055dcc3e728SAndrew Litteken     // output value will not completely combined with another item in a PHINode
1056dcc3e728SAndrew Litteken     // as it is directly reference by another non-phi instruction
1057dcc3e728SAndrew Litteken     if (!isa<PHINode>(I))
1058dcc3e728SAndrew Litteken       return true;
1059dcc3e728SAndrew Litteken 
1060dcc3e728SAndrew Litteken     // If we have a PHINode outside one of the exit locations, then it
1061dcc3e728SAndrew Litteken     // can be considered an outside use as well.  If there is a PHINode
1062dcc3e728SAndrew Litteken     // contained in the Exit where this values use matters, it will be
1063dcc3e728SAndrew Litteken     // caught when we analyze that PHINode.
1064dcc3e728SAndrew Litteken     if (!Exits.contains(Parent))
1065dcc3e728SAndrew Litteken       return true;
1066dcc3e728SAndrew Litteken 
1067dcc3e728SAndrew Litteken     return false;
1068dcc3e728SAndrew Litteken   });
1069dcc3e728SAndrew Litteken }
1070dcc3e728SAndrew Litteken 
1071dcc3e728SAndrew Litteken /// Test whether \p CurrentExitFromRegion contains any PhiNodes that should be
1072dcc3e728SAndrew Litteken /// considered outputs. A PHINodes is an output when more than one incoming
1073dcc3e728SAndrew Litteken /// value has been marked by the CodeExtractor as an output.
1074dcc3e728SAndrew Litteken ///
1075dcc3e728SAndrew Litteken /// \param CurrentExitFromRegion [in] - The block to analyze.
1076dcc3e728SAndrew Litteken /// \param PotentialExitsFromRegion [in] - The potential exit blocks from the
1077dcc3e728SAndrew Litteken /// region.
1078dcc3e728SAndrew Litteken /// \param RegionBlocks [in] - The basic blocks in the region.
1079dcc3e728SAndrew Litteken /// \param Outputs [in, out] - The existing outputs for the region, we may add
1080dcc3e728SAndrew Litteken /// PHINodes to this as we find that they replace output values.
1081dcc3e728SAndrew Litteken /// \param OutputsReplacedByPHINode [out] - A set containing outputs that are
1082dcc3e728SAndrew Litteken /// totally replaced  by a PHINode.
1083dcc3e728SAndrew Litteken /// \param OutputsWithNonPhiUses [out] - A set containing outputs that are used
1084dcc3e728SAndrew Litteken /// in PHINodes, but have other uses, and should still be considered outputs.
analyzeExitPHIsForOutputUses(BasicBlock * CurrentExitFromRegion,SmallPtrSet<BasicBlock *,1> & PotentialExitsFromRegion,DenseSet<BasicBlock * > & RegionBlocks,SetVector<Value * > & Outputs,DenseSet<Value * > & OutputsReplacedByPHINode,DenseSet<Value * > & OutputsWithNonPhiUses)1085dcc3e728SAndrew Litteken static void analyzeExitPHIsForOutputUses(
1086dcc3e728SAndrew Litteken     BasicBlock *CurrentExitFromRegion,
1087dcc3e728SAndrew Litteken     SmallPtrSet<BasicBlock *, 1> &PotentialExitsFromRegion,
1088dcc3e728SAndrew Litteken     DenseSet<BasicBlock *> &RegionBlocks, SetVector<Value *> &Outputs,
1089dcc3e728SAndrew Litteken     DenseSet<Value *> &OutputsReplacedByPHINode,
1090dcc3e728SAndrew Litteken     DenseSet<Value *> &OutputsWithNonPhiUses) {
1091dcc3e728SAndrew Litteken   for (PHINode &PN : CurrentExitFromRegion->phis()) {
1092dcc3e728SAndrew Litteken     // Find all incoming values from the outlining region.
1093dcc3e728SAndrew Litteken     SmallVector<unsigned, 2> IncomingVals;
1094dcc3e728SAndrew Litteken     for (unsigned I = 0, E = PN.getNumIncomingValues(); I < E; ++I)
1095dcc3e728SAndrew Litteken       if (RegionBlocks.contains(PN.getIncomingBlock(I)))
1096dcc3e728SAndrew Litteken         IncomingVals.push_back(I);
1097dcc3e728SAndrew Litteken 
1098dcc3e728SAndrew Litteken     // Do not process PHI if there are no predecessors from region.
1099dcc3e728SAndrew Litteken     unsigned NumIncomingVals = IncomingVals.size();
1100dcc3e728SAndrew Litteken     if (NumIncomingVals == 0)
1101dcc3e728SAndrew Litteken       continue;
1102dcc3e728SAndrew Litteken 
1103dcc3e728SAndrew Litteken     // If there is one predecessor, we mark it as a value that needs to be kept
1104dcc3e728SAndrew Litteken     // as an output.
1105dcc3e728SAndrew Litteken     if (NumIncomingVals == 1) {
1106dcc3e728SAndrew Litteken       Value *V = PN.getIncomingValue(*IncomingVals.begin());
1107dcc3e728SAndrew Litteken       OutputsWithNonPhiUses.insert(V);
1108dcc3e728SAndrew Litteken       OutputsReplacedByPHINode.erase(V);
1109dcc3e728SAndrew Litteken       continue;
1110dcc3e728SAndrew Litteken     }
1111dcc3e728SAndrew Litteken 
1112dcc3e728SAndrew Litteken     // This PHINode will be used as an output value, so we add it to our list.
1113dcc3e728SAndrew Litteken     Outputs.insert(&PN);
1114dcc3e728SAndrew Litteken 
1115dcc3e728SAndrew Litteken     // Not all of the incoming values should be ignored as other inputs and
1116dcc3e728SAndrew Litteken     // outputs may have uses in outlined region.  If they have other uses
1117dcc3e728SAndrew Litteken     // outside of the single PHINode we should not skip over it.
1118dcc3e728SAndrew Litteken     for (unsigned Idx : IncomingVals) {
1119dcc3e728SAndrew Litteken       Value *V = PN.getIncomingValue(Idx);
1120dcc3e728SAndrew Litteken       if (outputHasNonPHI(V, Idx, PN, PotentialExitsFromRegion, RegionBlocks)) {
1121dcc3e728SAndrew Litteken         OutputsWithNonPhiUses.insert(V);
1122dcc3e728SAndrew Litteken         OutputsReplacedByPHINode.erase(V);
1123dcc3e728SAndrew Litteken         continue;
1124dcc3e728SAndrew Litteken       }
1125dcc3e728SAndrew Litteken       if (!OutputsWithNonPhiUses.contains(V))
1126dcc3e728SAndrew Litteken         OutputsReplacedByPHINode.insert(V);
1127dcc3e728SAndrew Litteken     }
1128dcc3e728SAndrew Litteken   }
1129dcc3e728SAndrew Litteken }
1130dcc3e728SAndrew Litteken 
1131dcc3e728SAndrew Litteken // Represents the type for the unsigned number denoting the output number for
1132dcc3e728SAndrew Litteken // phi node, along with the canonical number for the exit block.
1133dcc3e728SAndrew Litteken using ArgLocWithBBCanon = std::pair<unsigned, unsigned>;
1134dcc3e728SAndrew Litteken // The list of canonical numbers for the incoming values to a PHINode.
1135dcc3e728SAndrew Litteken using CanonList = SmallVector<unsigned, 2>;
1136dcc3e728SAndrew Litteken // The pair type representing the set of canonical values being combined in the
1137dcc3e728SAndrew Litteken // PHINode, along with the location data for the PHINode.
1138dcc3e728SAndrew Litteken using PHINodeData = std::pair<ArgLocWithBBCanon, CanonList>;
1139dcc3e728SAndrew Litteken 
1140dcc3e728SAndrew Litteken /// Encode \p PND as an integer for easy lookup based on the argument location,
1141dcc3e728SAndrew Litteken /// the parent BasicBlock canonical numbering, and the canonical numbering of
1142dcc3e728SAndrew Litteken /// the values stored in the PHINode.
1143dcc3e728SAndrew Litteken ///
1144dcc3e728SAndrew Litteken /// \param PND - The data to hash.
1145dcc3e728SAndrew Litteken /// \returns The hash code of \p PND.
encodePHINodeData(PHINodeData & PND)1146dcc3e728SAndrew Litteken static hash_code encodePHINodeData(PHINodeData &PND) {
1147dcc3e728SAndrew Litteken   return llvm::hash_combine(
1148dcc3e728SAndrew Litteken       llvm::hash_value(PND.first.first), llvm::hash_value(PND.first.second),
1149dcc3e728SAndrew Litteken       llvm::hash_combine_range(PND.second.begin(), PND.second.end()));
1150dcc3e728SAndrew Litteken }
1151dcc3e728SAndrew Litteken 
1152dcc3e728SAndrew Litteken /// Create a special GVN for PHINodes that will be used outside of
1153dcc3e728SAndrew Litteken /// the region.  We create a hash code based on the Canonical number of the
1154dcc3e728SAndrew Litteken /// parent BasicBlock, the canonical numbering of the values stored in the
1155dcc3e728SAndrew Litteken /// PHINode and the aggregate argument location.  This is used to find whether
1156dcc3e728SAndrew Litteken /// this PHINode type has been given a canonical numbering already.  If not, we
1157dcc3e728SAndrew Litteken /// assign it a value and store it for later use.  The value is returned to
1158dcc3e728SAndrew Litteken /// identify different output schemes for the set of regions.
1159dcc3e728SAndrew Litteken ///
1160dcc3e728SAndrew Litteken /// \param Region - The region that \p PN is an output for.
1161dcc3e728SAndrew Litteken /// \param PN - The PHINode we are analyzing.
1162c79ab106SAndrew Litteken /// \param Blocks - The blocks for the region we are analyzing.
1163dcc3e728SAndrew Litteken /// \param AggArgIdx - The argument \p PN will be stored into.
1164dcc3e728SAndrew Litteken /// \returns An optional holding the assigned canonical number, or None if
1165dcc3e728SAndrew Litteken /// there is some attribute of the PHINode blocking it from being used.
getGVNForPHINode(OutlinableRegion & Region,PHINode * PN,DenseSet<BasicBlock * > & Blocks,unsigned AggArgIdx)1166dcc3e728SAndrew Litteken static Optional<unsigned> getGVNForPHINode(OutlinableRegion &Region,
1167c79ab106SAndrew Litteken                                            PHINode *PN,
1168c79ab106SAndrew Litteken                                            DenseSet<BasicBlock *> &Blocks,
1169c79ab106SAndrew Litteken                                            unsigned AggArgIdx) {
1170dcc3e728SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
1171dcc3e728SAndrew Litteken   IRSimilarityCandidate &Cand = *Region.Candidate;
1172dcc3e728SAndrew Litteken   BasicBlock *PHIBB = PN->getParent();
1173dcc3e728SAndrew Litteken   CanonList PHIGVNs;
1174c79ab106SAndrew Litteken   Value *Incoming;
1175c79ab106SAndrew Litteken   BasicBlock *IncomingBlock;
1176c79ab106SAndrew Litteken   for (unsigned Idx = 0, EIdx = PN->getNumIncomingValues(); Idx < EIdx; Idx++) {
1177c79ab106SAndrew Litteken     Incoming = PN->getIncomingValue(Idx);
1178c79ab106SAndrew Litteken     IncomingBlock = PN->getIncomingBlock(Idx);
1179c79ab106SAndrew Litteken     // If we cannot find a GVN, and the incoming block is included in the region
1180c79ab106SAndrew Litteken     // this means that the input to the PHINode is not included in the region we
1181c79ab106SAndrew Litteken     // are trying to analyze, meaning, that if it was outlined, we would be
1182c79ab106SAndrew Litteken     // adding an extra input.  We ignore this case for now, and so ignore the
1183c79ab106SAndrew Litteken     // region.
1184dcc3e728SAndrew Litteken     Optional<unsigned> OGVN = Cand.getGVN(Incoming);
1185e0e687a6SKazu Hirata     if (!OGVN && Blocks.contains(IncomingBlock)) {
1186dcc3e728SAndrew Litteken       Region.IgnoreRegion = true;
1187dcc3e728SAndrew Litteken       return None;
1188dcc3e728SAndrew Litteken     }
1189dcc3e728SAndrew Litteken 
1190c79ab106SAndrew Litteken     // If the incoming block isn't in the region, we don't have to worry about
1191c79ab106SAndrew Litteken     // this incoming value.
1192a838043fSKazu Hirata     if (!Blocks.contains(IncomingBlock))
1193c79ab106SAndrew Litteken       continue;
1194c79ab106SAndrew Litteken 
1195dcc3e728SAndrew Litteken     // Collect the canonical numbers of the values in the PHINode.
11967a47ee51SKazu Hirata     unsigned GVN = *OGVN;
1197dcc3e728SAndrew Litteken     OGVN = Cand.getCanonicalNum(GVN);
11985413bf1bSKazu Hirata     assert(OGVN && "No GVN found for incoming value?");
1199dcc3e728SAndrew Litteken     PHIGVNs.push_back(*OGVN);
1200a919d3d8SAndrew Litteken 
1201a919d3d8SAndrew Litteken     // Find the incoming block and use the canonical numbering as well to define
1202a919d3d8SAndrew Litteken     // the hash for the PHINode.
1203a919d3d8SAndrew Litteken     OGVN = Cand.getGVN(IncomingBlock);
1204a919d3d8SAndrew Litteken 
1205a919d3d8SAndrew Litteken     // If there is no number for the incoming block, it is becaause we have
1206a919d3d8SAndrew Litteken     // split the candidate basic blocks.  So we use the previous block that it
1207a919d3d8SAndrew Litteken     // was split from to find the valid global value numbering for the PHINode.
1208e0e687a6SKazu Hirata     if (!OGVN) {
1209a919d3d8SAndrew Litteken       assert(Cand.getStartBB() == IncomingBlock &&
1210a919d3d8SAndrew Litteken              "Unknown basic block used in exit path PHINode.");
1211a919d3d8SAndrew Litteken 
1212e38f014cSAndrew Litteken       BasicBlock *PrevBlock = nullptr;
1213e38f014cSAndrew Litteken       // Iterate over the predecessors to the incoming block of the
1214e38f014cSAndrew Litteken       // PHINode, when we find a block that is not contained in the region
1215e38f014cSAndrew Litteken       // we know that this is the first block that we split from, and should
1216e38f014cSAndrew Litteken       // have a valid global value numbering.
1217e38f014cSAndrew Litteken       for (BasicBlock *Pred : predecessors(IncomingBlock))
1218e38f014cSAndrew Litteken         if (!Blocks.contains(Pred)) {
1219e38f014cSAndrew Litteken           PrevBlock = Pred;
1220e38f014cSAndrew Litteken           break;
1221e38f014cSAndrew Litteken         }
1222e38f014cSAndrew Litteken       assert(PrevBlock && "Expected a predecessor not in the reigon!");
1223a919d3d8SAndrew Litteken       OGVN = Cand.getGVN(PrevBlock);
1224a919d3d8SAndrew Litteken     }
12257a47ee51SKazu Hirata     GVN = *OGVN;
1226a919d3d8SAndrew Litteken     OGVN = Cand.getCanonicalNum(GVN);
12275413bf1bSKazu Hirata     assert(OGVN && "No GVN found for incoming block?");
1228a919d3d8SAndrew Litteken     PHIGVNs.push_back(*OGVN);
1229dcc3e728SAndrew Litteken   }
1230dcc3e728SAndrew Litteken 
1231dcc3e728SAndrew Litteken   // Now that we have the GVNs for the incoming values, we are going to combine
1232dcc3e728SAndrew Litteken   // them with the GVN of the incoming bock, and the output location of the
1233dcc3e728SAndrew Litteken   // PHINode to generate a hash value representing this instance of the PHINode.
1234dcc3e728SAndrew Litteken   DenseMap<hash_code, unsigned>::iterator GVNToPHIIt;
1235dcc3e728SAndrew Litteken   DenseMap<unsigned, PHINodeData>::iterator PHIToGVNIt;
1236dcc3e728SAndrew Litteken   Optional<unsigned> BBGVN = Cand.getGVN(PHIBB);
1237a7938c74SKazu Hirata   assert(BBGVN && "Could not find GVN for the incoming block!");
1238dcc3e728SAndrew Litteken 
1239*611ffcf4SKazu Hirata   BBGVN = Cand.getCanonicalNum(BBGVN.value());
1240a7938c74SKazu Hirata   assert(BBGVN && "Could not find canonical number for the incoming block!");
1241dcc3e728SAndrew Litteken   // Create a pair of the exit block canonical value, and the aggregate
1242dcc3e728SAndrew Litteken   // argument location, connected to the canonical numbers stored in the
1243dcc3e728SAndrew Litteken   // PHINode.
1244dcc3e728SAndrew Litteken   PHINodeData TemporaryPair =
1245*611ffcf4SKazu Hirata       std::make_pair(std::make_pair(BBGVN.value(), AggArgIdx), PHIGVNs);
1246dcc3e728SAndrew Litteken   hash_code PHINodeDataHash = encodePHINodeData(TemporaryPair);
1247dcc3e728SAndrew Litteken 
1248dcc3e728SAndrew Litteken   // Look for and create a new entry in our connection between canonical
1249dcc3e728SAndrew Litteken   // numbers for PHINodes, and the set of objects we just created.
1250dcc3e728SAndrew Litteken   GVNToPHIIt = Group.GVNsToPHINodeGVN.find(PHINodeDataHash);
1251dcc3e728SAndrew Litteken   if (GVNToPHIIt == Group.GVNsToPHINodeGVN.end()) {
1252dcc3e728SAndrew Litteken     bool Inserted = false;
1253dcc3e728SAndrew Litteken     std::tie(PHIToGVNIt, Inserted) = Group.PHINodeGVNToGVNs.insert(
1254dcc3e728SAndrew Litteken         std::make_pair(Group.PHINodeGVNTracker, TemporaryPair));
1255dcc3e728SAndrew Litteken     std::tie(GVNToPHIIt, Inserted) = Group.GVNsToPHINodeGVN.insert(
1256dcc3e728SAndrew Litteken         std::make_pair(PHINodeDataHash, Group.PHINodeGVNTracker--));
1257dcc3e728SAndrew Litteken   }
1258dcc3e728SAndrew Litteken 
1259dcc3e728SAndrew Litteken   return GVNToPHIIt->second;
1260dcc3e728SAndrew Litteken }
1261dcc3e728SAndrew Litteken 
1262e6ae6233SAndrew Litteken /// Create a mapping of the output arguments for the \p Region to the output
1263e6ae6233SAndrew Litteken /// arguments of the overall outlined function.
1264e6ae6233SAndrew Litteken ///
1265e6ae6233SAndrew Litteken /// \param [in,out] Region - The region of code to be analyzed.
1266e6ae6233SAndrew Litteken /// \param [in] Outputs - The values found by the code extractor.
1267e6ae6233SAndrew Litteken static void
findExtractedOutputToOverallOutputMapping(OutlinableRegion & Region,SetVector<Value * > & Outputs)1268e6ae6233SAndrew Litteken findExtractedOutputToOverallOutputMapping(OutlinableRegion &Region,
126981d3ac0cSAndrew Litteken                                           SetVector<Value *> &Outputs) {
1270e6ae6233SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
1271e6ae6233SAndrew Litteken   IRSimilarityCandidate &C = *Region.Candidate;
1272e6ae6233SAndrew Litteken 
127381d3ac0cSAndrew Litteken   SmallVector<BasicBlock *> BE;
1274dcc3e728SAndrew Litteken   DenseSet<BasicBlock *> BlocksInRegion;
1275dcc3e728SAndrew Litteken   C.getBasicBlocks(BlocksInRegion, BE);
127681d3ac0cSAndrew Litteken 
127781d3ac0cSAndrew Litteken   // Find the exits to the region.
127881d3ac0cSAndrew Litteken   SmallPtrSet<BasicBlock *, 1> Exits;
127981d3ac0cSAndrew Litteken   for (BasicBlock *Block : BE)
128081d3ac0cSAndrew Litteken     for (BasicBlock *Succ : successors(Block))
1281dcc3e728SAndrew Litteken       if (!BlocksInRegion.contains(Succ))
128281d3ac0cSAndrew Litteken         Exits.insert(Succ);
128381d3ac0cSAndrew Litteken 
128481d3ac0cSAndrew Litteken   // After determining which blocks exit to PHINodes, we add these PHINodes to
128581d3ac0cSAndrew Litteken   // the set of outputs to be processed.  We also check the incoming values of
128681d3ac0cSAndrew Litteken   // the PHINodes for whether they should no longer be considered outputs.
1287dcc3e728SAndrew Litteken   DenseSet<Value *> OutputsReplacedByPHINode;
1288dcc3e728SAndrew Litteken   DenseSet<Value *> OutputsWithNonPhiUses;
1289dcc3e728SAndrew Litteken   for (BasicBlock *ExitBB : Exits)
1290dcc3e728SAndrew Litteken     analyzeExitPHIsForOutputUses(ExitBB, Exits, BlocksInRegion, Outputs,
1291dcc3e728SAndrew Litteken                                  OutputsReplacedByPHINode,
1292dcc3e728SAndrew Litteken                                  OutputsWithNonPhiUses);
129381d3ac0cSAndrew Litteken 
1294e6ae6233SAndrew Litteken   // This counts the argument number in the extracted function.
1295e6ae6233SAndrew Litteken   unsigned OriginalIndex = Region.NumExtractedInputs;
1296e6ae6233SAndrew Litteken 
1297e6ae6233SAndrew Litteken   // This counts the argument number in the overall function.
1298e6ae6233SAndrew Litteken   unsigned TypeIndex = Group.NumAggregateInputs;
1299e6ae6233SAndrew Litteken   bool TypeFound;
1300e6ae6233SAndrew Litteken   DenseSet<unsigned> AggArgsUsed;
1301e6ae6233SAndrew Litteken 
1302e6ae6233SAndrew Litteken   // Iterate over the output types and identify if there is an aggregate pointer
1303e6ae6233SAndrew Litteken   // type whose base type matches the current output type. If there is, we mark
1304e6ae6233SAndrew Litteken   // that we will use this output register for this value. If not we add another
1305e6ae6233SAndrew Litteken   // type to the overall argument type list. We also store the GVNs used for
1306e6ae6233SAndrew Litteken   // stores to identify which values will need to be moved into an special
1307e6ae6233SAndrew Litteken   // block that holds the stores to the output registers.
1308e6ae6233SAndrew Litteken   for (Value *Output : Outputs) {
1309e6ae6233SAndrew Litteken     TypeFound = false;
1310e6ae6233SAndrew Litteken     // We can do this since it is a result value, and will have a number
1311e6ae6233SAndrew Litteken     // that is necessarily the same. BUT if in the future, the instructions
1312e6ae6233SAndrew Litteken     // do not have to be in same order, but are functionally the same, we will
1313e6ae6233SAndrew Litteken     // have to use a different scheme, as one-to-one correspondence is not
1314e6ae6233SAndrew Litteken     // guaranteed.
1315e6ae6233SAndrew Litteken     unsigned ArgumentSize = Group.ArgumentTypes.size();
1316e6ae6233SAndrew Litteken 
1317dcc3e728SAndrew Litteken     // If the output is combined in a PHINode, we make sure to skip over it.
1318dcc3e728SAndrew Litteken     if (OutputsReplacedByPHINode.contains(Output))
1319dcc3e728SAndrew Litteken       continue;
1320dcc3e728SAndrew Litteken 
1321dcc3e728SAndrew Litteken     unsigned AggArgIdx = 0;
1322e6ae6233SAndrew Litteken     for (unsigned Jdx = TypeIndex; Jdx < ArgumentSize; Jdx++) {
1323e6ae6233SAndrew Litteken       if (Group.ArgumentTypes[Jdx] != PointerType::getUnqual(Output->getType()))
1324e6ae6233SAndrew Litteken         continue;
1325e6ae6233SAndrew Litteken 
13265c1c39e8SKazu Hirata       if (AggArgsUsed.contains(Jdx))
1327e6ae6233SAndrew Litteken         continue;
1328e6ae6233SAndrew Litteken 
1329e6ae6233SAndrew Litteken       TypeFound = true;
1330e6ae6233SAndrew Litteken       AggArgsUsed.insert(Jdx);
1331e6ae6233SAndrew Litteken       Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, Jdx));
1332e6ae6233SAndrew Litteken       Region.AggArgToExtracted.insert(std::make_pair(Jdx, OriginalIndex));
1333dcc3e728SAndrew Litteken       AggArgIdx = Jdx;
1334e6ae6233SAndrew Litteken       break;
1335e6ae6233SAndrew Litteken     }
1336e6ae6233SAndrew Litteken 
1337e6ae6233SAndrew Litteken     // We were unable to find an unused type in the output type set that matches
1338e6ae6233SAndrew Litteken     // the output, so we add a pointer type to the argument types of the overall
1339e6ae6233SAndrew Litteken     // function to handle this output and create a mapping to it.
1340e6ae6233SAndrew Litteken     if (!TypeFound) {
1341e6ae6233SAndrew Litteken       Group.ArgumentTypes.push_back(PointerType::getUnqual(Output->getType()));
1342dcc3e728SAndrew Litteken       // Mark the new pointer type as the last value in the aggregate argument
1343dcc3e728SAndrew Litteken       // list.
1344dcc3e728SAndrew Litteken       unsigned ArgTypeIdx = Group.ArgumentTypes.size() - 1;
1345dcc3e728SAndrew Litteken       AggArgsUsed.insert(ArgTypeIdx);
1346e6ae6233SAndrew Litteken       Region.ExtractedArgToAgg.insert(
1347dcc3e728SAndrew Litteken           std::make_pair(OriginalIndex, ArgTypeIdx));
1348e6ae6233SAndrew Litteken       Region.AggArgToExtracted.insert(
1349dcc3e728SAndrew Litteken           std::make_pair(ArgTypeIdx, OriginalIndex));
1350dcc3e728SAndrew Litteken       AggArgIdx = ArgTypeIdx;
1351e6ae6233SAndrew Litteken     }
1352e6ae6233SAndrew Litteken 
1353dcc3e728SAndrew Litteken     // TODO: Adapt to the extra input from the PHINode.
1354dcc3e728SAndrew Litteken     PHINode *PN = dyn_cast<PHINode>(Output);
1355dcc3e728SAndrew Litteken 
1356dcc3e728SAndrew Litteken     Optional<unsigned> GVN;
1357dcc3e728SAndrew Litteken     if (PN && !BlocksInRegion.contains(PN->getParent())) {
1358dcc3e728SAndrew Litteken       // Values outside the region can be combined into PHINode when we
1359dcc3e728SAndrew Litteken       // have multiple exits. We collect both of these into a list to identify
1360dcc3e728SAndrew Litteken       // which values are being used in the PHINode. Each list identifies a
1361dcc3e728SAndrew Litteken       // different PHINode, and a different output. We store the PHINode as it's
1362dcc3e728SAndrew Litteken       // own canonical value.  These canonical values are also dependent on the
1363dcc3e728SAndrew Litteken       // output argument it is saved to.
1364dcc3e728SAndrew Litteken 
1365dcc3e728SAndrew Litteken       // If two PHINodes have the same canonical values, but different aggregate
1366dcc3e728SAndrew Litteken       // argument locations, then they will have distinct Canonical Values.
1367c79ab106SAndrew Litteken       GVN = getGVNForPHINode(Region, PN, BlocksInRegion, AggArgIdx);
1368e0e687a6SKazu Hirata       if (!GVN)
1369dcc3e728SAndrew Litteken         return;
1370dcc3e728SAndrew Litteken     } else {
1371dcc3e728SAndrew Litteken       // If we do not have a PHINode we use the global value numbering for the
1372dcc3e728SAndrew Litteken       // output value, to find the canonical number to add to the set of stored
1373dcc3e728SAndrew Litteken       // values.
1374dcc3e728SAndrew Litteken       GVN = C.getGVN(Output);
1375dcc3e728SAndrew Litteken       GVN = C.getCanonicalNum(*GVN);
1376dcc3e728SAndrew Litteken     }
1377dcc3e728SAndrew Litteken 
1378dcc3e728SAndrew Litteken     // Each region has a potentially unique set of outputs.  We save which
1379dcc3e728SAndrew Litteken     // values are output in a list of canonical values so we can differentiate
1380dcc3e728SAndrew Litteken     // among the different store schemes.
1381dcc3e728SAndrew Litteken     Region.GVNStores.push_back(*GVN);
1382dcc3e728SAndrew Litteken 
1383e6ae6233SAndrew Litteken     OriginalIndex++;
1384e6ae6233SAndrew Litteken     TypeIndex++;
1385e6ae6233SAndrew Litteken   }
1386dcc3e728SAndrew Litteken 
1387dcc3e728SAndrew Litteken   // We sort the stored values to make sure that we are not affected by analysis
1388dcc3e728SAndrew Litteken   // order when determining what combination of items were stored.
1389dcc3e728SAndrew Litteken   stable_sort(Region.GVNStores);
1390e6ae6233SAndrew Litteken }
1391e6ae6233SAndrew Litteken 
findAddInputsOutputs(Module & M,OutlinableRegion & Region,DenseSet<unsigned> & NotSame)1392b1191c84SAndrew Litteken void IROutliner::findAddInputsOutputs(Module &M, OutlinableRegion &Region,
1393b1191c84SAndrew Litteken                                       DenseSet<unsigned> &NotSame) {
1394c52bcf3aSAndrew Litteken   std::vector<unsigned> Inputs;
1395e6ae6233SAndrew Litteken   SetVector<Value *> ArgInputs, Outputs;
1396c52bcf3aSAndrew Litteken 
1397e6ae6233SAndrew Litteken   getCodeExtractorArguments(Region, Inputs, NotSame, OutputMappings, ArgInputs,
1398e6ae6233SAndrew Litteken                             Outputs);
1399c52bcf3aSAndrew Litteken 
1400c52bcf3aSAndrew Litteken   if (Region.IgnoreRegion)
1401c52bcf3aSAndrew Litteken     return;
14027c6f28a4SAndrew Litteken 
14037c6f28a4SAndrew Litteken   // Map the inputs found by the CodeExtractor to the arguments found for
14047c6f28a4SAndrew Litteken   // the overall function.
14057c6f28a4SAndrew Litteken   findExtractedInputToOverallInputMapping(Region, Inputs, ArgInputs);
1406e6ae6233SAndrew Litteken 
1407e6ae6233SAndrew Litteken   // Map the outputs found by the CodeExtractor to the arguments found for
1408e6ae6233SAndrew Litteken   // the overall function.
140981d3ac0cSAndrew Litteken   findExtractedOutputToOverallOutputMapping(Region, Outputs);
14107c6f28a4SAndrew Litteken }
14117c6f28a4SAndrew Litteken 
14127c6f28a4SAndrew Litteken /// Replace the extracted function in the Region with a call to the overall
14137c6f28a4SAndrew Litteken /// function constructed from the deduplicated similar regions, replacing and
14147c6f28a4SAndrew Litteken /// remapping the values passed to the extracted function as arguments to the
14157c6f28a4SAndrew Litteken /// new arguments of the overall function.
14167c6f28a4SAndrew Litteken ///
14177c6f28a4SAndrew Litteken /// \param [in] M - The module to outline from.
14187c6f28a4SAndrew Litteken /// \param [in] Region - The regions of extracted code to be replaced with a new
14197c6f28a4SAndrew Litteken /// function.
14207c6f28a4SAndrew Litteken /// \returns a call instruction with the replaced function.
replaceCalledFunction(Module & M,OutlinableRegion & Region)14217c6f28a4SAndrew Litteken CallInst *replaceCalledFunction(Module &M, OutlinableRegion &Region) {
14227c6f28a4SAndrew Litteken   std::vector<Value *> NewCallArgs;
1423b1191c84SAndrew Litteken   DenseMap<unsigned, unsigned>::iterator ArgPair;
14247c6f28a4SAndrew Litteken 
14257c6f28a4SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
14267c6f28a4SAndrew Litteken   CallInst *Call = Region.Call;
14277c6f28a4SAndrew Litteken   assert(Call && "Call to replace is nullptr?");
14287c6f28a4SAndrew Litteken   Function *AggFunc = Group.OutlinedFunction;
14297c6f28a4SAndrew Litteken   assert(AggFunc && "Function to replace with is nullptr?");
14307c6f28a4SAndrew Litteken 
14317c6f28a4SAndrew Litteken   // If the arguments are the same size, there are not values that need to be
1432063af63bSAndrew Litteken   // made into an argument, the argument ordering has not been change, or
1433063af63bSAndrew Litteken   // different output registers to handle.  We can simply replace the called
1434063af63bSAndrew Litteken   // function in this case.
1435063af63bSAndrew Litteken   if (!Region.ChangedArgOrder && AggFunc->arg_size() == Call->arg_size()) {
14367c6f28a4SAndrew Litteken     LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to "
14377c6f28a4SAndrew Litteken                       << *AggFunc << " with same number of arguments\n");
14387c6f28a4SAndrew Litteken     Call->setCalledFunction(AggFunc);
14397c6f28a4SAndrew Litteken     return Call;
14407c6f28a4SAndrew Litteken   }
14417c6f28a4SAndrew Litteken 
1442b1191c84SAndrew Litteken   // We have a different number of arguments than the new function, so
1443b1191c84SAndrew Litteken   // we need to use our previously mappings off extracted argument to overall
1444b1191c84SAndrew Litteken   // function argument, and constants to overall function argument to create the
1445b1191c84SAndrew Litteken   // new argument list.
1446b1191c84SAndrew Litteken   for (unsigned AggArgIdx = 0; AggArgIdx < AggFunc->arg_size(); AggArgIdx++) {
1447b1191c84SAndrew Litteken 
1448e6ae6233SAndrew Litteken     if (AggArgIdx == AggFunc->arg_size() - 1 &&
14491e238025SAndrew Litteken         Group.OutputGVNCombinations.size() > 1) {
1450e6ae6233SAndrew Litteken       // If we are on the last argument, and we need to differentiate between
1451e6ae6233SAndrew Litteken       // output blocks, add an integer to the argument list to determine
1452e6ae6233SAndrew Litteken       // what block to take
1453e6ae6233SAndrew Litteken       LLVM_DEBUG(dbgs() << "Set switch block argument to "
1454e6ae6233SAndrew Litteken                         << Region.OutputBlockNum << "\n");
1455e6ae6233SAndrew Litteken       NewCallArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()),
1456e6ae6233SAndrew Litteken                                              Region.OutputBlockNum));
1457e6ae6233SAndrew Litteken       continue;
1458e6ae6233SAndrew Litteken     }
1459e6ae6233SAndrew Litteken 
1460b1191c84SAndrew Litteken     ArgPair = Region.AggArgToExtracted.find(AggArgIdx);
1461b1191c84SAndrew Litteken     if (ArgPair != Region.AggArgToExtracted.end()) {
1462b1191c84SAndrew Litteken       Value *ArgumentValue = Call->getArgOperand(ArgPair->second);
1463b1191c84SAndrew Litteken       // If we found the mapping from the extracted function to the overall
1464b1191c84SAndrew Litteken       // function, we simply add it to the argument list.  We use the same
1465b1191c84SAndrew Litteken       // value, it just needs to honor the new order of arguments.
1466b1191c84SAndrew Litteken       LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to value "
1467b1191c84SAndrew Litteken                         << *ArgumentValue << "\n");
1468b1191c84SAndrew Litteken       NewCallArgs.push_back(ArgumentValue);
1469b1191c84SAndrew Litteken       continue;
1470b1191c84SAndrew Litteken     }
1471b1191c84SAndrew Litteken 
1472b1191c84SAndrew Litteken     // If it is a constant, we simply add it to the argument list as a value.
1473b1191c84SAndrew Litteken     if (Region.AggArgToConstant.find(AggArgIdx) !=
1474b1191c84SAndrew Litteken         Region.AggArgToConstant.end()) {
1475b1191c84SAndrew Litteken       Constant *CST = Region.AggArgToConstant.find(AggArgIdx)->second;
1476b1191c84SAndrew Litteken       LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to value "
1477b1191c84SAndrew Litteken                         << *CST << "\n");
1478b1191c84SAndrew Litteken       NewCallArgs.push_back(CST);
1479b1191c84SAndrew Litteken       continue;
1480b1191c84SAndrew Litteken     }
1481b1191c84SAndrew Litteken 
1482b1191c84SAndrew Litteken     // Add a nullptr value if the argument is not found in the extracted
1483b1191c84SAndrew Litteken     // function.  If we cannot find a value, it means it is not in use
1484b1191c84SAndrew Litteken     // for the region, so we should not pass anything to it.
1485b1191c84SAndrew Litteken     LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to nullptr\n");
1486b1191c84SAndrew Litteken     NewCallArgs.push_back(ConstantPointerNull::get(
1487b1191c84SAndrew Litteken         static_cast<PointerType *>(AggFunc->getArg(AggArgIdx)->getType())));
1488b1191c84SAndrew Litteken   }
1489b1191c84SAndrew Litteken 
1490b1191c84SAndrew Litteken   LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to "
1491b1191c84SAndrew Litteken                     << *AggFunc << " with new set of arguments\n");
1492b1191c84SAndrew Litteken   // Create the new call instruction and erase the old one.
1493b1191c84SAndrew Litteken   Call = CallInst::Create(AggFunc->getFunctionType(), AggFunc, NewCallArgs, "",
1494b1191c84SAndrew Litteken                           Call);
1495b1191c84SAndrew Litteken 
1496b1191c84SAndrew Litteken   // It is possible that the call to the outlined function is either the first
14971e238025SAndrew Litteken   // instruction is in the new block, the last instruction, or both.  If either
14981e238025SAndrew Litteken   // of these is the case, we need to make sure that we replace the instruction
14991e238025SAndrew Litteken   // in the IRInstructionData struct with the new call.
1500b1191c84SAndrew Litteken   CallInst *OldCall = Region.Call;
1501b1191c84SAndrew Litteken   if (Region.NewFront->Inst == OldCall)
1502b1191c84SAndrew Litteken     Region.NewFront->Inst = Call;
1503b1191c84SAndrew Litteken   if (Region.NewBack->Inst == OldCall)
1504b1191c84SAndrew Litteken     Region.NewBack->Inst = Call;
1505b1191c84SAndrew Litteken 
1506b1191c84SAndrew Litteken   // Transfer any debug information.
1507b1191c84SAndrew Litteken   Call->setDebugLoc(Region.Call->getDebugLoc());
1508c172f1adSAndrew Litteken   // Since our output may determine which branch we go to, we make sure to
1509c172f1adSAndrew Litteken   // propogate this new call value through the module.
1510c172f1adSAndrew Litteken   OldCall->replaceAllUsesWith(Call);
1511b1191c84SAndrew Litteken 
1512b1191c84SAndrew Litteken   // Remove the old instruction.
1513b1191c84SAndrew Litteken   OldCall->eraseFromParent();
1514b1191c84SAndrew Litteken   Region.Call = Call;
1515b1191c84SAndrew Litteken 
151630feb930SAndrew Litteken   // Make sure that the argument in the new function has the SwiftError
151730feb930SAndrew Litteken   // argument.
1518a7938c74SKazu Hirata   if (Group.SwiftErrorArgument)
1519*611ffcf4SKazu Hirata     Call->addParamAttr(Group.SwiftErrorArgument.value(), Attribute::SwiftError);
152030feb930SAndrew Litteken 
1521b1191c84SAndrew Litteken   return Call;
1522b1191c84SAndrew Litteken }
1523b1191c84SAndrew Litteken 
1524dcc3e728SAndrew Litteken /// Find or create a BasicBlock in the outlined function containing PhiBlocks
1525dcc3e728SAndrew Litteken /// for \p RetVal.
1526dcc3e728SAndrew Litteken ///
1527dcc3e728SAndrew Litteken /// \param Group - The OutlinableGroup containing the information about the
1528dcc3e728SAndrew Litteken /// overall outlined function.
1529dcc3e728SAndrew Litteken /// \param RetVal - The return value or exit option that we are currently
1530dcc3e728SAndrew Litteken /// evaluating.
1531dcc3e728SAndrew Litteken /// \returns The found or newly created BasicBlock to contain the needed
1532dcc3e728SAndrew Litteken /// PHINodes to be used as outputs.
findOrCreatePHIBlock(OutlinableGroup & Group,Value * RetVal)1533dcc3e728SAndrew Litteken static BasicBlock *findOrCreatePHIBlock(OutlinableGroup &Group, Value *RetVal) {
1534dcc3e728SAndrew Litteken   DenseMap<Value *, BasicBlock *>::iterator PhiBlockForRetVal,
1535dcc3e728SAndrew Litteken       ReturnBlockForRetVal;
1536dcc3e728SAndrew Litteken   PhiBlockForRetVal = Group.PHIBlocks.find(RetVal);
1537dcc3e728SAndrew Litteken   ReturnBlockForRetVal = Group.EndBBs.find(RetVal);
1538dcc3e728SAndrew Litteken   assert(ReturnBlockForRetVal != Group.EndBBs.end() &&
1539dcc3e728SAndrew Litteken          "Could not find output value!");
1540dcc3e728SAndrew Litteken   BasicBlock *ReturnBB = ReturnBlockForRetVal->second;
1541dcc3e728SAndrew Litteken 
1542dcc3e728SAndrew Litteken   // Find if a PHIBlock exists for this return value already.  If it is
1543dcc3e728SAndrew Litteken   // the first time we are analyzing this, we will not, so we record it.
1544dcc3e728SAndrew Litteken   PhiBlockForRetVal = Group.PHIBlocks.find(RetVal);
1545dcc3e728SAndrew Litteken   if (PhiBlockForRetVal != Group.PHIBlocks.end())
1546dcc3e728SAndrew Litteken     return PhiBlockForRetVal->second;
1547dcc3e728SAndrew Litteken 
1548dcc3e728SAndrew Litteken   // If we did not find a block, we create one, and insert it into the
1549dcc3e728SAndrew Litteken   // overall function and record it.
1550dcc3e728SAndrew Litteken   bool Inserted = false;
1551dcc3e728SAndrew Litteken   BasicBlock *PHIBlock = BasicBlock::Create(ReturnBB->getContext(), "phi_block",
1552dcc3e728SAndrew Litteken                                             ReturnBB->getParent());
1553dcc3e728SAndrew Litteken   std::tie(PhiBlockForRetVal, Inserted) =
1554dcc3e728SAndrew Litteken       Group.PHIBlocks.insert(std::make_pair(RetVal, PHIBlock));
1555dcc3e728SAndrew Litteken 
1556dcc3e728SAndrew Litteken   // We find the predecessors of the return block in the newly created outlined
1557dcc3e728SAndrew Litteken   // function in order to point them to the new PHIBlock rather than the already
1558dcc3e728SAndrew Litteken   // existing return block.
1559dcc3e728SAndrew Litteken   SmallVector<BranchInst *, 2> BranchesToChange;
1560dcc3e728SAndrew Litteken   for (BasicBlock *Pred : predecessors(ReturnBB))
1561dcc3e728SAndrew Litteken     BranchesToChange.push_back(cast<BranchInst>(Pred->getTerminator()));
1562dcc3e728SAndrew Litteken 
1563dcc3e728SAndrew Litteken   // Now we mark the branch instructions found, and change the references of the
1564dcc3e728SAndrew Litteken   // return block to the newly created PHIBlock.
1565dcc3e728SAndrew Litteken   for (BranchInst *BI : BranchesToChange)
1566dcc3e728SAndrew Litteken     for (unsigned Succ = 0, End = BI->getNumSuccessors(); Succ < End; Succ++) {
1567dcc3e728SAndrew Litteken       if (BI->getSuccessor(Succ) != ReturnBB)
1568dcc3e728SAndrew Litteken         continue;
1569dcc3e728SAndrew Litteken       BI->setSuccessor(Succ, PHIBlock);
1570dcc3e728SAndrew Litteken     }
1571dcc3e728SAndrew Litteken 
1572dcc3e728SAndrew Litteken   BranchInst::Create(ReturnBB, PHIBlock);
1573dcc3e728SAndrew Litteken 
1574dcc3e728SAndrew Litteken   return PhiBlockForRetVal->second;
1575dcc3e728SAndrew Litteken }
1576dcc3e728SAndrew Litteken 
1577dcc3e728SAndrew Litteken /// For the function call now representing the \p Region, find the passed value
1578dcc3e728SAndrew Litteken /// to that call that represents Argument \p A at the call location if the
1579dcc3e728SAndrew Litteken /// call has already been replaced with a call to the  overall, aggregate
1580dcc3e728SAndrew Litteken /// function.
1581dcc3e728SAndrew Litteken ///
1582dcc3e728SAndrew Litteken /// \param A - The Argument to get the passed value for.
1583dcc3e728SAndrew Litteken /// \param Region - The extracted Region corresponding to the outlined function.
1584dcc3e728SAndrew Litteken /// \returns The Value representing \p A at the call site.
1585dcc3e728SAndrew Litteken static Value *
getPassedArgumentInAlreadyOutlinedFunction(const Argument * A,const OutlinableRegion & Region)1586dcc3e728SAndrew Litteken getPassedArgumentInAlreadyOutlinedFunction(const Argument *A,
1587dcc3e728SAndrew Litteken                                            const OutlinableRegion &Region) {
1588dcc3e728SAndrew Litteken   // If we don't need to adjust the argument number at all (since the call
1589dcc3e728SAndrew Litteken   // has already been replaced by a call to the overall outlined function)
1590dcc3e728SAndrew Litteken   // we can just get the specified argument.
1591dcc3e728SAndrew Litteken   return Region.Call->getArgOperand(A->getArgNo());
1592dcc3e728SAndrew Litteken }
1593dcc3e728SAndrew Litteken 
1594dcc3e728SAndrew Litteken /// For the function call now representing the \p Region, find the passed value
1595dcc3e728SAndrew Litteken /// to that call that represents Argument \p A at the call location if the
1596dcc3e728SAndrew Litteken /// call has only been replaced by the call to the aggregate function.
1597dcc3e728SAndrew Litteken ///
1598dcc3e728SAndrew Litteken /// \param A - The Argument to get the passed value for.
1599dcc3e728SAndrew Litteken /// \param Region - The extracted Region corresponding to the outlined function.
1600dcc3e728SAndrew Litteken /// \returns The Value representing \p A at the call site.
1601dcc3e728SAndrew Litteken static Value *
getPassedArgumentAndAdjustArgumentLocation(const Argument * A,const OutlinableRegion & Region)1602dcc3e728SAndrew Litteken getPassedArgumentAndAdjustArgumentLocation(const Argument *A,
1603dcc3e728SAndrew Litteken                                            const OutlinableRegion &Region) {
1604dcc3e728SAndrew Litteken   unsigned ArgNum = A->getArgNo();
1605dcc3e728SAndrew Litteken 
1606dcc3e728SAndrew Litteken   // If it is a constant, we can look at our mapping from when we created
1607dcc3e728SAndrew Litteken   // the outputs to figure out what the constant value is.
1608dcc3e728SAndrew Litteken   if (Region.AggArgToConstant.count(ArgNum))
1609dcc3e728SAndrew Litteken     return Region.AggArgToConstant.find(ArgNum)->second;
1610dcc3e728SAndrew Litteken 
1611dcc3e728SAndrew Litteken   // If it is not a constant, and we are not looking at the overall function, we
1612dcc3e728SAndrew Litteken   // need to adjust which argument we are looking at.
1613dcc3e728SAndrew Litteken   ArgNum = Region.AggArgToExtracted.find(ArgNum)->second;
1614dcc3e728SAndrew Litteken   return Region.Call->getArgOperand(ArgNum);
1615dcc3e728SAndrew Litteken }
1616dcc3e728SAndrew Litteken 
1617dcc3e728SAndrew Litteken /// Find the canonical numbering for the incoming Values into the PHINode \p PN.
1618dcc3e728SAndrew Litteken ///
1619dcc3e728SAndrew Litteken /// \param PN [in] - The PHINode that we are finding the canonical numbers for.
1620dcc3e728SAndrew Litteken /// \param Region [in] - The OutlinableRegion containing \p PN.
1621dcc3e728SAndrew Litteken /// \param OutputMappings [in] - The mapping of output values from outlined
1622dcc3e728SAndrew Litteken /// region to their original values.
1623dcc3e728SAndrew Litteken /// \param CanonNums [out] - The canonical numbering for the incoming values to
1624228cc2c3SAndrew Litteken /// \p PN paired with their incoming block.
1625dcc3e728SAndrew Litteken /// \param ReplacedWithOutlinedCall - A flag to use the extracted function call
1626dcc3e728SAndrew Litteken /// of \p Region rather than the overall function's call.
findCanonNumsForPHI(PHINode * PN,OutlinableRegion & Region,const DenseMap<Value *,Value * > & OutputMappings,SmallVector<std::pair<unsigned,BasicBlock * >> & CanonNums,bool ReplacedWithOutlinedCall=true)1627228cc2c3SAndrew Litteken static void findCanonNumsForPHI(
1628228cc2c3SAndrew Litteken     PHINode *PN, OutlinableRegion &Region,
1629dcc3e728SAndrew Litteken     const DenseMap<Value *, Value *> &OutputMappings,
1630228cc2c3SAndrew Litteken     SmallVector<std::pair<unsigned, BasicBlock *>> &CanonNums,
1631dcc3e728SAndrew Litteken     bool ReplacedWithOutlinedCall = true) {
1632dcc3e728SAndrew Litteken   // Iterate over the incoming values.
1633dcc3e728SAndrew Litteken   for (unsigned Idx = 0, EIdx = PN->getNumIncomingValues(); Idx < EIdx; Idx++) {
1634dcc3e728SAndrew Litteken     Value *IVal = PN->getIncomingValue(Idx);
1635228cc2c3SAndrew Litteken     BasicBlock *IBlock = PN->getIncomingBlock(Idx);
1636dcc3e728SAndrew Litteken     // If we have an argument as incoming value, we need to grab the passed
1637dcc3e728SAndrew Litteken     // value from the call itself.
1638dcc3e728SAndrew Litteken     if (Argument *A = dyn_cast<Argument>(IVal)) {
1639dcc3e728SAndrew Litteken       if (ReplacedWithOutlinedCall)
1640dcc3e728SAndrew Litteken         IVal = getPassedArgumentInAlreadyOutlinedFunction(A, Region);
1641dcc3e728SAndrew Litteken       else
1642dcc3e728SAndrew Litteken         IVal = getPassedArgumentAndAdjustArgumentLocation(A, Region);
1643dcc3e728SAndrew Litteken     }
1644dcc3e728SAndrew Litteken 
1645dcc3e728SAndrew Litteken     // Get the original value if it has been replaced by an output value.
1646dcc3e728SAndrew Litteken     IVal = findOutputMapping(OutputMappings, IVal);
1647dcc3e728SAndrew Litteken 
1648dcc3e728SAndrew Litteken     // Find and add the canonical number for the incoming value.
1649dcc3e728SAndrew Litteken     Optional<unsigned> GVN = Region.Candidate->getGVN(IVal);
1650a7938c74SKazu Hirata     assert(GVN && "No GVN for incoming value");
1651dcc3e728SAndrew Litteken     Optional<unsigned> CanonNum = Region.Candidate->getCanonicalNum(*GVN);
1652a7938c74SKazu Hirata     assert(CanonNum && "No Canonical Number for GVN");
1653228cc2c3SAndrew Litteken     CanonNums.push_back(std::make_pair(*CanonNum, IBlock));
1654dcc3e728SAndrew Litteken   }
1655dcc3e728SAndrew Litteken }
1656dcc3e728SAndrew Litteken 
1657dcc3e728SAndrew Litteken /// Find, or add PHINode \p PN to the combined PHINode Block \p OverallPHIBlock
1658dcc3e728SAndrew Litteken /// in order to condense the number of instructions added to the outlined
1659dcc3e728SAndrew Litteken /// function.
1660dcc3e728SAndrew Litteken ///
1661dcc3e728SAndrew Litteken /// \param PN [in] - The PHINode that we are finding the canonical numbers for.
1662dcc3e728SAndrew Litteken /// \param Region [in] - The OutlinableRegion containing \p PN.
1663dcc3e728SAndrew Litteken /// \param OverallPhiBlock [in] - The overall PHIBlock we are trying to find
1664dcc3e728SAndrew Litteken /// \p PN in.
1665dcc3e728SAndrew Litteken /// \param OutputMappings [in] - The mapping of output values from outlined
1666dcc3e728SAndrew Litteken /// region to their original values.
166786f970e5SHirochika Matsumoto /// \param UsedPHIs [in, out] - The PHINodes in the block that have already been
16683c90812fSAndrew Litteken /// matched.
1669dcc3e728SAndrew Litteken /// \return the newly found or created PHINode in \p OverallPhiBlock.
1670dcc3e728SAndrew Litteken static PHINode*
findOrCreatePHIInBlock(PHINode & PN,OutlinableRegion & Region,BasicBlock * OverallPhiBlock,const DenseMap<Value *,Value * > & OutputMappings,DenseSet<PHINode * > & UsedPHIs)1671dcc3e728SAndrew Litteken findOrCreatePHIInBlock(PHINode &PN, OutlinableRegion &Region,
1672dcc3e728SAndrew Litteken                        BasicBlock *OverallPhiBlock,
16733c90812fSAndrew Litteken                        const DenseMap<Value *, Value *> &OutputMappings,
16743c90812fSAndrew Litteken                        DenseSet<PHINode *> &UsedPHIs) {
1675dcc3e728SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
1676dcc3e728SAndrew Litteken 
1677228cc2c3SAndrew Litteken 
1678228cc2c3SAndrew Litteken   // A list of the canonical numbering assigned to each incoming value, paired
1679228cc2c3SAndrew Litteken   // with the incoming block for the PHINode passed into this function.
1680228cc2c3SAndrew Litteken   SmallVector<std::pair<unsigned, BasicBlock *>> PNCanonNums;
1681228cc2c3SAndrew Litteken 
1682dcc3e728SAndrew Litteken   // We have to use the extracted function since we have merged this region into
1683dcc3e728SAndrew Litteken   // the overall function yet.  We make sure to reassign the argument numbering
1684dcc3e728SAndrew Litteken   // since it is possible that the argument ordering is different between the
1685dcc3e728SAndrew Litteken   // functions.
1686dcc3e728SAndrew Litteken   findCanonNumsForPHI(&PN, Region, OutputMappings, PNCanonNums,
1687dcc3e728SAndrew Litteken                       /* ReplacedWithOutlinedCall = */ false);
1688dcc3e728SAndrew Litteken 
1689dcc3e728SAndrew Litteken   OutlinableRegion *FirstRegion = Group.Regions[0];
1690228cc2c3SAndrew Litteken 
1691228cc2c3SAndrew Litteken   // A list of the canonical numbering assigned to each incoming value, paired
1692228cc2c3SAndrew Litteken   // with the incoming block for the PHINode that we are currently comparing
1693228cc2c3SAndrew Litteken   // the passed PHINode to.
1694228cc2c3SAndrew Litteken   SmallVector<std::pair<unsigned, BasicBlock *>> CurrentCanonNums;
1695228cc2c3SAndrew Litteken 
1696dcc3e728SAndrew Litteken   // Find the Canonical Numbering for each PHINode, if it matches, we replace
1697dcc3e728SAndrew Litteken   // the uses of the PHINode we are searching for, with the found PHINode.
1698dcc3e728SAndrew Litteken   for (PHINode &CurrPN : OverallPhiBlock->phis()) {
16993c90812fSAndrew Litteken     // If this PHINode has already been matched to another PHINode to be merged,
17003c90812fSAndrew Litteken     // we skip it.
1701a838043fSKazu Hirata     if (UsedPHIs.contains(&CurrPN))
17023c90812fSAndrew Litteken       continue;
17033c90812fSAndrew Litteken 
1704dcc3e728SAndrew Litteken     CurrentCanonNums.clear();
1705dcc3e728SAndrew Litteken     findCanonNumsForPHI(&CurrPN, *FirstRegion, OutputMappings, CurrentCanonNums,
1706dcc3e728SAndrew Litteken                         /* ReplacedWithOutlinedCall = */ true);
1707228cc2c3SAndrew Litteken 
1708228cc2c3SAndrew Litteken     // If the list of incoming values is not the same length, then they cannot
1709228cc2c3SAndrew Litteken     // match since there is not an analogue for each incoming value.
1710228cc2c3SAndrew Litteken     if (PNCanonNums.size() != CurrentCanonNums.size())
1711228cc2c3SAndrew Litteken       continue;
1712228cc2c3SAndrew Litteken 
1713228cc2c3SAndrew Litteken     bool FoundMatch = true;
1714228cc2c3SAndrew Litteken 
1715228cc2c3SAndrew Litteken     // We compare the canonical value for each incoming value in the passed
1716228cc2c3SAndrew Litteken     // in PHINode to one already present in the outlined region.  If the
1717228cc2c3SAndrew Litteken     // incoming values do not match, then the PHINodes do not match.
1718228cc2c3SAndrew Litteken 
1719228cc2c3SAndrew Litteken     // We also check to make sure that the incoming block matches as well by
1720228cc2c3SAndrew Litteken     // finding the corresponding incoming block in the combined outlined region
1721228cc2c3SAndrew Litteken     // for the current outlined region.
1722228cc2c3SAndrew Litteken     for (unsigned Idx = 0, Edx = PNCanonNums.size(); Idx < Edx; ++Idx) {
1723228cc2c3SAndrew Litteken       std::pair<unsigned, BasicBlock *> ToCompareTo = CurrentCanonNums[Idx];
1724228cc2c3SAndrew Litteken       std::pair<unsigned, BasicBlock *> ToAdd = PNCanonNums[Idx];
1725228cc2c3SAndrew Litteken       if (ToCompareTo.first != ToAdd.first) {
1726228cc2c3SAndrew Litteken         FoundMatch = false;
1727228cc2c3SAndrew Litteken         break;
1728228cc2c3SAndrew Litteken       }
1729228cc2c3SAndrew Litteken 
1730228cc2c3SAndrew Litteken       BasicBlock *CorrespondingBlock =
1731228cc2c3SAndrew Litteken           Region.findCorrespondingBlockIn(*FirstRegion, ToAdd.second);
1732228cc2c3SAndrew Litteken       assert(CorrespondingBlock && "Found block is nullptr");
1733228cc2c3SAndrew Litteken       if (CorrespondingBlock != ToCompareTo.second) {
1734228cc2c3SAndrew Litteken         FoundMatch = false;
1735228cc2c3SAndrew Litteken         break;
1736228cc2c3SAndrew Litteken       }
1737228cc2c3SAndrew Litteken     }
1738228cc2c3SAndrew Litteken 
1739228cc2c3SAndrew Litteken     // If all incoming values and branches matched, then we can merge
1740228cc2c3SAndrew Litteken     // into the found PHINode.
1741228cc2c3SAndrew Litteken     if (FoundMatch) {
17423c90812fSAndrew Litteken       UsedPHIs.insert(&CurrPN);
1743dcc3e728SAndrew Litteken       return &CurrPN;
1744dcc3e728SAndrew Litteken     }
17453c90812fSAndrew Litteken   }
1746dcc3e728SAndrew Litteken 
1747dcc3e728SAndrew Litteken   // If we've made it here, it means we weren't able to replace the PHINode, so
1748dcc3e728SAndrew Litteken   // we must insert it ourselves.
1749dcc3e728SAndrew Litteken   PHINode *NewPN = cast<PHINode>(PN.clone());
1750dcc3e728SAndrew Litteken   NewPN->insertBefore(&*OverallPhiBlock->begin());
1751dcc3e728SAndrew Litteken   for (unsigned Idx = 0, Edx = NewPN->getNumIncomingValues(); Idx < Edx;
1752dcc3e728SAndrew Litteken        Idx++) {
1753dcc3e728SAndrew Litteken     Value *IncomingVal = NewPN->getIncomingValue(Idx);
1754dcc3e728SAndrew Litteken     BasicBlock *IncomingBlock = NewPN->getIncomingBlock(Idx);
1755dcc3e728SAndrew Litteken 
1756dcc3e728SAndrew Litteken     // Find corresponding basic block in the overall function for the incoming
1757dcc3e728SAndrew Litteken     // block.
1758228cc2c3SAndrew Litteken     BasicBlock *BlockToUse =
1759228cc2c3SAndrew Litteken         Region.findCorrespondingBlockIn(*FirstRegion, IncomingBlock);
1760dcc3e728SAndrew Litteken     NewPN->setIncomingBlock(Idx, BlockToUse);
1761dcc3e728SAndrew Litteken 
1762dcc3e728SAndrew Litteken     // If we have an argument we make sure we replace using the argument from
1763dcc3e728SAndrew Litteken     // the correct function.
1764dcc3e728SAndrew Litteken     if (Argument *A = dyn_cast<Argument>(IncomingVal)) {
1765dcc3e728SAndrew Litteken       Value *Val = Group.OutlinedFunction->getArg(A->getArgNo());
1766dcc3e728SAndrew Litteken       NewPN->setIncomingValue(Idx, Val);
1767dcc3e728SAndrew Litteken       continue;
1768dcc3e728SAndrew Litteken     }
1769dcc3e728SAndrew Litteken 
1770dcc3e728SAndrew Litteken     // Find the corresponding value in the overall function.
1771dcc3e728SAndrew Litteken     IncomingVal = findOutputMapping(OutputMappings, IncomingVal);
1772dcc3e728SAndrew Litteken     Value *Val = Region.findCorrespondingValueIn(*FirstRegion, IncomingVal);
1773dcc3e728SAndrew Litteken     assert(Val && "Value is nullptr?");
1774d7c56a07SAndrew Litteken     DenseMap<Value *, Value *>::iterator RemappedIt =
1775d7c56a07SAndrew Litteken         FirstRegion->RemappedArguments.find(Val);
1776d7c56a07SAndrew Litteken     if (RemappedIt != FirstRegion->RemappedArguments.end())
1777d7c56a07SAndrew Litteken       Val = RemappedIt->second;
1778dcc3e728SAndrew Litteken     NewPN->setIncomingValue(Idx, Val);
1779dcc3e728SAndrew Litteken   }
1780dcc3e728SAndrew Litteken   return NewPN;
1781dcc3e728SAndrew Litteken }
1782dcc3e728SAndrew Litteken 
17837c6f28a4SAndrew Litteken // Within an extracted function, replace the argument uses of the extracted
17847c6f28a4SAndrew Litteken // region with the arguments of the function for an OutlinableGroup.
17857c6f28a4SAndrew Litteken //
1786e6ae6233SAndrew Litteken /// \param [in] Region - The region of extracted code to be changed.
178777f6c0bcSSimon Pilgrim /// \param [in,out] OutputBBs - The BasicBlock for the output stores for this
1788e6ae6233SAndrew Litteken /// region.
1789c172f1adSAndrew Litteken /// \param [in] FirstFunction - A flag to indicate whether we are using this
1790c172f1adSAndrew Litteken /// function to define the overall outlined function for all the regions, or
1791c172f1adSAndrew Litteken /// if we are operating on one of the following regions.
1792c172f1adSAndrew Litteken static void
replaceArgumentUses(OutlinableRegion & Region,DenseMap<Value *,BasicBlock * > & OutputBBs,const DenseMap<Value *,Value * > & OutputMappings,bool FirstFunction=false)1793c172f1adSAndrew Litteken replaceArgumentUses(OutlinableRegion &Region,
1794c172f1adSAndrew Litteken                     DenseMap<Value *, BasicBlock *> &OutputBBs,
1795dcc3e728SAndrew Litteken                     const DenseMap<Value *, Value *> &OutputMappings,
1796c172f1adSAndrew Litteken                     bool FirstFunction = false) {
17977c6f28a4SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
17987c6f28a4SAndrew Litteken   assert(Region.ExtractedFunction && "Region has no extracted function?");
17997c6f28a4SAndrew Litteken 
1800c172f1adSAndrew Litteken   Function *DominatingFunction = Region.ExtractedFunction;
1801c172f1adSAndrew Litteken   if (FirstFunction)
1802c172f1adSAndrew Litteken     DominatingFunction = Group.OutlinedFunction;
1803c172f1adSAndrew Litteken   DominatorTree DT(*DominatingFunction);
18043c90812fSAndrew Litteken   DenseSet<PHINode *> UsedPHIs;
1805c172f1adSAndrew Litteken 
18067c6f28a4SAndrew Litteken   for (unsigned ArgIdx = 0; ArgIdx < Region.ExtractedFunction->arg_size();
18077c6f28a4SAndrew Litteken        ArgIdx++) {
18087c6f28a4SAndrew Litteken     assert(Region.ExtractedArgToAgg.find(ArgIdx) !=
18097c6f28a4SAndrew Litteken                Region.ExtractedArgToAgg.end() &&
18107c6f28a4SAndrew Litteken            "No mapping from extracted to outlined?");
18117c6f28a4SAndrew Litteken     unsigned AggArgIdx = Region.ExtractedArgToAgg.find(ArgIdx)->second;
18127c6f28a4SAndrew Litteken     Argument *AggArg = Group.OutlinedFunction->getArg(AggArgIdx);
18137c6f28a4SAndrew Litteken     Argument *Arg = Region.ExtractedFunction->getArg(ArgIdx);
18147c6f28a4SAndrew Litteken     // The argument is an input, so we can simply replace it with the overall
18157c6f28a4SAndrew Litteken     // argument value
1816e6ae6233SAndrew Litteken     if (ArgIdx < Region.NumExtractedInputs) {
18177c6f28a4SAndrew Litteken       LLVM_DEBUG(dbgs() << "Replacing uses of input " << *Arg << " in function "
18187c6f28a4SAndrew Litteken                         << *Region.ExtractedFunction << " with " << *AggArg
18197c6f28a4SAndrew Litteken                         << " in function " << *Group.OutlinedFunction << "\n");
18207c6f28a4SAndrew Litteken       Arg->replaceAllUsesWith(AggArg);
1821d7c56a07SAndrew Litteken       Value *V = Region.Call->getArgOperand(ArgIdx);
1822d7c56a07SAndrew Litteken       Region.RemappedArguments.insert(std::make_pair(V, AggArg));
1823e6ae6233SAndrew Litteken       continue;
1824e6ae6233SAndrew Litteken     }
1825e6ae6233SAndrew Litteken 
1826e6ae6233SAndrew Litteken     // If we are replacing an output, we place the store value in its own
1827e6ae6233SAndrew Litteken     // block inside the overall function before replacing the use of the output
1828e6ae6233SAndrew Litteken     // in the function.
1829e6ae6233SAndrew Litteken     assert(Arg->hasOneUse() && "Output argument can only have one use");
1830e6ae6233SAndrew Litteken     User *InstAsUser = Arg->user_back();
1831e6ae6233SAndrew Litteken     assert(InstAsUser && "User is nullptr!");
1832e6ae6233SAndrew Litteken 
1833e6ae6233SAndrew Litteken     Instruction *I = cast<Instruction>(InstAsUser);
1834c172f1adSAndrew Litteken     BasicBlock *BB = I->getParent();
1835c172f1adSAndrew Litteken     SmallVector<BasicBlock *, 4> Descendants;
1836c172f1adSAndrew Litteken     DT.getDescendants(BB, Descendants);
1837c172f1adSAndrew Litteken     bool EdgeAdded = false;
1838c172f1adSAndrew Litteken     if (Descendants.size() == 0) {
1839c172f1adSAndrew Litteken       EdgeAdded = true;
1840c172f1adSAndrew Litteken       DT.insertEdge(&DominatingFunction->getEntryBlock(), BB);
1841c172f1adSAndrew Litteken       DT.getDescendants(BB, Descendants);
1842c172f1adSAndrew Litteken     }
1843c172f1adSAndrew Litteken 
1844c172f1adSAndrew Litteken     // Iterate over the following blocks, looking for return instructions,
1845c172f1adSAndrew Litteken     // if we find one, find the corresponding output block for the return value
1846c172f1adSAndrew Litteken     // and move our store instruction there.
1847c172f1adSAndrew Litteken     for (BasicBlock *DescendBB : Descendants) {
1848c172f1adSAndrew Litteken       ReturnInst *RI = dyn_cast<ReturnInst>(DescendBB->getTerminator());
1849c172f1adSAndrew Litteken       if (!RI)
1850c172f1adSAndrew Litteken         continue;
1851c172f1adSAndrew Litteken       Value *RetVal = RI->getReturnValue();
1852373b7622SBenjamin Kramer       auto VBBIt = OutputBBs.find(RetVal);
1853c172f1adSAndrew Litteken       assert(VBBIt != OutputBBs.end() && "Could not find output value!");
1854c172f1adSAndrew Litteken 
18550087bb4aSAndrew Litteken       // If this is storing a PHINode, we must make sure it is included in the
18560087bb4aSAndrew Litteken       // overall function.
18570087bb4aSAndrew Litteken       StoreInst *SI = cast<StoreInst>(I);
18580087bb4aSAndrew Litteken 
18590087bb4aSAndrew Litteken       Value *ValueOperand = SI->getValueOperand();
18600087bb4aSAndrew Litteken 
18610087bb4aSAndrew Litteken       StoreInst *NewI = cast<StoreInst>(I->clone());
1862c172f1adSAndrew Litteken       NewI->setDebugLoc(DebugLoc());
1863c172f1adSAndrew Litteken       BasicBlock *OutputBB = VBBIt->second;
1864c172f1adSAndrew Litteken       OutputBB->getInstList().push_back(NewI);
1865e6ae6233SAndrew Litteken       LLVM_DEBUG(dbgs() << "Move store for instruction " << *I << " to "
1866e6ae6233SAndrew Litteken                         << *OutputBB << "\n");
18670087bb4aSAndrew Litteken 
1868dcc3e728SAndrew Litteken       // If this is storing a PHINode, we must make sure it is included in the
1869dcc3e728SAndrew Litteken       // overall function.
1870e8f4e41bSAndrew Litteken       if (!isa<PHINode>(ValueOperand) ||
18710916d96dSKazu Hirata           Region.Candidate->getGVN(ValueOperand).has_value()) {
18720087bb4aSAndrew Litteken         if (FirstFunction)
18730087bb4aSAndrew Litteken           continue;
18740087bb4aSAndrew Litteken         Value *CorrVal =
18750087bb4aSAndrew Litteken             Region.findCorrespondingValueIn(*Group.Regions[0], ValueOperand);
18760087bb4aSAndrew Litteken         assert(CorrVal && "Value is nullptr?");
18770087bb4aSAndrew Litteken         NewI->setOperand(0, CorrVal);
1878dcc3e728SAndrew Litteken         continue;
1879dcc3e728SAndrew Litteken       }
1880dcc3e728SAndrew Litteken       PHINode *PN = cast<PHINode>(SI->getValueOperand());
1881dcc3e728SAndrew Litteken       // If it has a value, it was not split by the code extractor, which
1882dcc3e728SAndrew Litteken       // is what we are looking for.
1883e0e687a6SKazu Hirata       if (Region.Candidate->getGVN(PN))
1884dcc3e728SAndrew Litteken         continue;
1885dcc3e728SAndrew Litteken 
1886dcc3e728SAndrew Litteken       // We record the parent block for the PHINode in the Region so that
1887dcc3e728SAndrew Litteken       // we can exclude it from checks later on.
1888dcc3e728SAndrew Litteken       Region.PHIBlocks.insert(std::make_pair(RetVal, PN->getParent()));
1889dcc3e728SAndrew Litteken 
1890dcc3e728SAndrew Litteken       // If this is the first function, we do not need to worry about mergiing
1891dcc3e728SAndrew Litteken       // this with any other block in the overall outlined function, so we can
1892dcc3e728SAndrew Litteken       // just continue.
1893dcc3e728SAndrew Litteken       if (FirstFunction) {
1894dcc3e728SAndrew Litteken         BasicBlock *PHIBlock = PN->getParent();
1895dcc3e728SAndrew Litteken         Group.PHIBlocks.insert(std::make_pair(RetVal, PHIBlock));
1896dcc3e728SAndrew Litteken         continue;
1897dcc3e728SAndrew Litteken       }
1898dcc3e728SAndrew Litteken 
1899dcc3e728SAndrew Litteken       // We look for the aggregate block that contains the PHINodes leading into
1900dcc3e728SAndrew Litteken       // this exit path. If we can't find one, we create one.
1901dcc3e728SAndrew Litteken       BasicBlock *OverallPhiBlock = findOrCreatePHIBlock(Group, RetVal);
1902dcc3e728SAndrew Litteken 
1903dcc3e728SAndrew Litteken       // For our PHINode, we find the combined canonical numbering, and
1904dcc3e728SAndrew Litteken       // attempt to find a matching PHINode in the overall PHIBlock.  If we
1905dcc3e728SAndrew Litteken       // cannot, we copy the PHINode and move it into this new block.
19063c90812fSAndrew Litteken       PHINode *NewPN = findOrCreatePHIInBlock(*PN, Region, OverallPhiBlock,
19073c90812fSAndrew Litteken                                               OutputMappings, UsedPHIs);
1908dcc3e728SAndrew Litteken       NewI->setOperand(0, NewPN);
1909c172f1adSAndrew Litteken     }
1910e6ae6233SAndrew Litteken 
1911c172f1adSAndrew Litteken     // If we added an edge for basic blocks without a predecessor, we remove it
1912c172f1adSAndrew Litteken     // here.
1913c172f1adSAndrew Litteken     if (EdgeAdded)
1914c172f1adSAndrew Litteken       DT.deleteEdge(&DominatingFunction->getEntryBlock(), BB);
1915c172f1adSAndrew Litteken     I->eraseFromParent();
1916e6ae6233SAndrew Litteken 
1917e6ae6233SAndrew Litteken     LLVM_DEBUG(dbgs() << "Replacing uses of output " << *Arg << " in function "
1918e6ae6233SAndrew Litteken                       << *Region.ExtractedFunction << " with " << *AggArg
1919e6ae6233SAndrew Litteken                       << " in function " << *Group.OutlinedFunction << "\n");
1920e6ae6233SAndrew Litteken     Arg->replaceAllUsesWith(AggArg);
19217c6f28a4SAndrew Litteken   }
19227c6f28a4SAndrew Litteken }
19237c6f28a4SAndrew Litteken 
1924b1191c84SAndrew Litteken /// Within an extracted function, replace the constants that need to be lifted
1925b1191c84SAndrew Litteken /// into arguments with the actual argument.
1926b1191c84SAndrew Litteken ///
1927b1191c84SAndrew Litteken /// \param Region [in] - The region of extracted code to be changed.
replaceConstants(OutlinableRegion & Region)1928b1191c84SAndrew Litteken void replaceConstants(OutlinableRegion &Region) {
1929b1191c84SAndrew Litteken   OutlinableGroup &Group = *Region.Parent;
1930b1191c84SAndrew Litteken   // Iterate over the constants that need to be elevated into arguments
1931b1191c84SAndrew Litteken   for (std::pair<unsigned, Constant *> &Const : Region.AggArgToConstant) {
1932b1191c84SAndrew Litteken     unsigned AggArgIdx = Const.first;
1933b1191c84SAndrew Litteken     Function *OutlinedFunction = Group.OutlinedFunction;
1934b1191c84SAndrew Litteken     assert(OutlinedFunction && "Overall Function is not defined?");
1935b1191c84SAndrew Litteken     Constant *CST = Const.second;
1936b1191c84SAndrew Litteken     Argument *Arg = Group.OutlinedFunction->getArg(AggArgIdx);
1937b1191c84SAndrew Litteken     // Identify the argument it will be elevated to, and replace instances of
1938b1191c84SAndrew Litteken     // that constant in the function.
1939b1191c84SAndrew Litteken 
1940b1191c84SAndrew Litteken     // TODO: If in the future constants do not have one global value number,
1941b1191c84SAndrew Litteken     // i.e. a constant 1 could be mapped to several values, this check will
1942b1191c84SAndrew Litteken     // have to be more strict.  It cannot be using only replaceUsesWithIf.
1943b1191c84SAndrew Litteken 
1944b1191c84SAndrew Litteken     LLVM_DEBUG(dbgs() << "Replacing uses of constant " << *CST
1945b1191c84SAndrew Litteken                       << " in function " << *OutlinedFunction << " with "
1946b1191c84SAndrew Litteken                       << *Arg << "\n");
1947b1191c84SAndrew Litteken     CST->replaceUsesWithIf(Arg, [OutlinedFunction](Use &U) {
1948b1191c84SAndrew Litteken       if (Instruction *I = dyn_cast<Instruction>(U.getUser()))
1949b1191c84SAndrew Litteken         return I->getFunction() == OutlinedFunction;
1950b1191c84SAndrew Litteken       return false;
1951b1191c84SAndrew Litteken     });
1952b1191c84SAndrew Litteken   }
1953b1191c84SAndrew Litteken }
1954b1191c84SAndrew Litteken 
19551e238025SAndrew Litteken /// It is possible that there is a basic block that already performs the same
19561e238025SAndrew Litteken /// stores. This returns a duplicate block, if it exists
19571e238025SAndrew Litteken ///
195877f6c0bcSSimon Pilgrim /// \param OutputBBs [in] the blocks we are looking for a duplicate of.
19591e238025SAndrew Litteken /// \param OutputStoreBBs [in] The existing output blocks.
19601e238025SAndrew Litteken /// \returns an optional value with the number output block if there is a match.
findDuplicateOutputBlock(DenseMap<Value *,BasicBlock * > & OutputBBs,std::vector<DenseMap<Value *,BasicBlock * >> & OutputStoreBBs)1961c172f1adSAndrew Litteken Optional<unsigned> findDuplicateOutputBlock(
1962c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *> &OutputBBs,
1963c172f1adSAndrew Litteken     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
19641e238025SAndrew Litteken 
1965c172f1adSAndrew Litteken   bool Mismatch = false;
19661e238025SAndrew Litteken   unsigned MatchingNum = 0;
1967c172f1adSAndrew Litteken   // We compare the new set output blocks to the other sets of output blocks.
1968c172f1adSAndrew Litteken   // If they are the same number, and have identical instructions, they are
1969c172f1adSAndrew Litteken   // considered to be the same.
1970c172f1adSAndrew Litteken   for (DenseMap<Value *, BasicBlock *> &CompBBs : OutputStoreBBs) {
1971c172f1adSAndrew Litteken     Mismatch = false;
1972c172f1adSAndrew Litteken     for (std::pair<Value *, BasicBlock *> &VToB : CompBBs) {
1973c172f1adSAndrew Litteken       DenseMap<Value *, BasicBlock *>::iterator OutputBBIt =
1974c172f1adSAndrew Litteken           OutputBBs.find(VToB.first);
1975c172f1adSAndrew Litteken       if (OutputBBIt == OutputBBs.end()) {
1976c172f1adSAndrew Litteken         Mismatch = true;
1977c172f1adSAndrew Litteken         break;
19781e238025SAndrew Litteken       }
19791e238025SAndrew Litteken 
1980c172f1adSAndrew Litteken       BasicBlock *CompBB = VToB.second;
1981c172f1adSAndrew Litteken       BasicBlock *OutputBB = OutputBBIt->second;
1982c172f1adSAndrew Litteken       if (CompBB->size() - 1 != OutputBB->size()) {
1983c172f1adSAndrew Litteken         Mismatch = true;
1984c172f1adSAndrew Litteken         break;
1985c172f1adSAndrew Litteken       }
1986c172f1adSAndrew Litteken 
19871e238025SAndrew Litteken       BasicBlock::iterator NIt = OutputBB->begin();
19881e238025SAndrew Litteken       for (Instruction &I : *CompBB) {
19891e238025SAndrew Litteken         if (isa<BranchInst>(&I))
19901e238025SAndrew Litteken           continue;
19911e238025SAndrew Litteken 
19921e238025SAndrew Litteken         if (!I.isIdenticalTo(&(*NIt))) {
1993c172f1adSAndrew Litteken           Mismatch = true;
19941e238025SAndrew Litteken           break;
19951e238025SAndrew Litteken         }
19961e238025SAndrew Litteken 
19971e238025SAndrew Litteken         NIt++;
19981e238025SAndrew Litteken       }
1999c172f1adSAndrew Litteken     }
2000c172f1adSAndrew Litteken 
2001c172f1adSAndrew Litteken     if (!Mismatch)
20021e238025SAndrew Litteken       return MatchingNum;
20031e238025SAndrew Litteken 
20041e238025SAndrew Litteken     MatchingNum++;
20051e238025SAndrew Litteken   }
20061e238025SAndrew Litteken 
20071e238025SAndrew Litteken   return None;
20081e238025SAndrew Litteken }
20091e238025SAndrew Litteken 
2010c172f1adSAndrew Litteken /// Remove empty output blocks from the outlined region.
2011c172f1adSAndrew Litteken ///
2012c172f1adSAndrew Litteken /// \param BlocksToPrune - Mapping of return values output blocks for the \p
2013c172f1adSAndrew Litteken /// Region.
2014c172f1adSAndrew Litteken /// \param Region - The OutlinableRegion we are analyzing.
2015c172f1adSAndrew Litteken static bool
analyzeAndPruneOutputBlocks(DenseMap<Value *,BasicBlock * > & BlocksToPrune,OutlinableRegion & Region)2016c172f1adSAndrew Litteken analyzeAndPruneOutputBlocks(DenseMap<Value *, BasicBlock *> &BlocksToPrune,
2017c172f1adSAndrew Litteken                             OutlinableRegion &Region) {
2018c172f1adSAndrew Litteken   bool AllRemoved = true;
2019c172f1adSAndrew Litteken   Value *RetValueForBB;
2020c172f1adSAndrew Litteken   BasicBlock *NewBB;
2021c172f1adSAndrew Litteken   SmallVector<Value *, 4> ToRemove;
2022c172f1adSAndrew Litteken   // Iterate over the output blocks created in the outlined section.
2023c172f1adSAndrew Litteken   for (std::pair<Value *, BasicBlock *> &VtoBB : BlocksToPrune) {
2024c172f1adSAndrew Litteken     RetValueForBB = VtoBB.first;
2025c172f1adSAndrew Litteken     NewBB = VtoBB.second;
2026c172f1adSAndrew Litteken 
2027c172f1adSAndrew Litteken     // If there are no instructions, we remove it from the module, and also
2028c172f1adSAndrew Litteken     // mark the value for removal from the return value to output block mapping.
2029c172f1adSAndrew Litteken     if (NewBB->size() == 0) {
2030c172f1adSAndrew Litteken       NewBB->eraseFromParent();
2031c172f1adSAndrew Litteken       ToRemove.push_back(RetValueForBB);
2032c172f1adSAndrew Litteken       continue;
2033c172f1adSAndrew Litteken     }
2034c172f1adSAndrew Litteken 
2035c172f1adSAndrew Litteken     // Mark that we could not remove all the blocks since they were not all
2036c172f1adSAndrew Litteken     // empty.
2037c172f1adSAndrew Litteken     AllRemoved = false;
2038c172f1adSAndrew Litteken   }
2039c172f1adSAndrew Litteken 
2040c172f1adSAndrew Litteken   // Remove the return value from the mapping.
2041c172f1adSAndrew Litteken   for (Value *V : ToRemove)
2042c172f1adSAndrew Litteken     BlocksToPrune.erase(V);
2043c172f1adSAndrew Litteken 
2044c172f1adSAndrew Litteken   // Mark the region as having the no output scheme.
2045c172f1adSAndrew Litteken   if (AllRemoved)
2046c172f1adSAndrew Litteken     Region.OutputBlockNum = -1;
2047c172f1adSAndrew Litteken 
2048c172f1adSAndrew Litteken   return AllRemoved;
2049c172f1adSAndrew Litteken }
2050c172f1adSAndrew Litteken 
2051e6ae6233SAndrew Litteken /// For the outlined section, move needed the StoreInsts for the output
2052e6ae6233SAndrew Litteken /// registers into their own block. Then, determine if there is a duplicate
2053e6ae6233SAndrew Litteken /// output block already created.
2054e6ae6233SAndrew Litteken ///
2055e6ae6233SAndrew Litteken /// \param [in] OG - The OutlinableGroup of regions to be outlined.
2056e6ae6233SAndrew Litteken /// \param [in] Region - The OutlinableRegion that is being analyzed.
205777f6c0bcSSimon Pilgrim /// \param [in,out] OutputBBs - the blocks that stores for this region will be
2058e6ae6233SAndrew Litteken /// placed in.
205977f6c0bcSSimon Pilgrim /// \param [in] EndBBs - the final blocks of the extracted function.
2060e6ae6233SAndrew Litteken /// \param [in] OutputMappings - OutputMappings the mapping of values that have
2061e6ae6233SAndrew Litteken /// been replaced by a new output value.
2062e6ae6233SAndrew Litteken /// \param [in,out] OutputStoreBBs - The existing output blocks.
alignOutputBlockWithAggFunc(OutlinableGroup & OG,OutlinableRegion & Region,DenseMap<Value *,BasicBlock * > & OutputBBs,DenseMap<Value *,BasicBlock * > & EndBBs,const DenseMap<Value *,Value * > & OutputMappings,std::vector<DenseMap<Value *,BasicBlock * >> & OutputStoreBBs)2063c172f1adSAndrew Litteken static void alignOutputBlockWithAggFunc(
2064c172f1adSAndrew Litteken     OutlinableGroup &OG, OutlinableRegion &Region,
2065c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *> &OutputBBs,
2066c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *> &EndBBs,
2067e6ae6233SAndrew Litteken     const DenseMap<Value *, Value *> &OutputMappings,
2068c172f1adSAndrew Litteken     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
2069c172f1adSAndrew Litteken   // If none of the output blocks have any instructions, this means that we do
2070c172f1adSAndrew Litteken   // not have to determine if it matches any of the other output schemes, and we
2071c172f1adSAndrew Litteken   // don't have to do anything else.
2072c172f1adSAndrew Litteken   if (analyzeAndPruneOutputBlocks(OutputBBs, Region))
20731e238025SAndrew Litteken     return;
20741e238025SAndrew Litteken 
2075c172f1adSAndrew Litteken   // Determine is there is a duplicate set of blocks.
20761e238025SAndrew Litteken   Optional<unsigned> MatchingBB =
2077c172f1adSAndrew Litteken       findDuplicateOutputBlock(OutputBBs, OutputStoreBBs);
20781e238025SAndrew Litteken 
2079c172f1adSAndrew Litteken   // If there is, we remove the new output blocks.  If it does not,
2080c172f1adSAndrew Litteken   // we add it to our list of sets of output blocks.
2081a7938c74SKazu Hirata   if (MatchingBB) {
20821e238025SAndrew Litteken     LLVM_DEBUG(dbgs() << "Set output block for region in function"
20833b7c3a65SKazu Hirata                       << Region.ExtractedFunction << " to "
2084*611ffcf4SKazu Hirata                       << MatchingBB.value());
20851e238025SAndrew Litteken 
2086*611ffcf4SKazu Hirata     Region.OutputBlockNum = MatchingBB.value();
2087c172f1adSAndrew Litteken     for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs)
2088c172f1adSAndrew Litteken       VtoBB.second->eraseFromParent();
20891e238025SAndrew Litteken     return;
20901e238025SAndrew Litteken   }
20911e238025SAndrew Litteken 
20921e238025SAndrew Litteken   Region.OutputBlockNum = OutputStoreBBs.size();
20931e238025SAndrew Litteken 
2094c172f1adSAndrew Litteken   Value *RetValueForBB;
2095c172f1adSAndrew Litteken   BasicBlock *NewBB;
2096c172f1adSAndrew Litteken   OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
2097c172f1adSAndrew Litteken   for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs) {
2098c172f1adSAndrew Litteken     RetValueForBB = VtoBB.first;
2099c172f1adSAndrew Litteken     NewBB = VtoBB.second;
2100c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *>::iterator VBBIt =
2101c172f1adSAndrew Litteken         EndBBs.find(RetValueForBB);
21021e238025SAndrew Litteken     LLVM_DEBUG(dbgs() << "Create output block for region in"
21031e238025SAndrew Litteken                       << Region.ExtractedFunction << " to "
2104c172f1adSAndrew Litteken                       << *NewBB);
2105c172f1adSAndrew Litteken     BranchInst::Create(VBBIt->second, NewBB);
2106c172f1adSAndrew Litteken     OutputStoreBBs.back().insert(std::make_pair(RetValueForBB, NewBB));
2107c172f1adSAndrew Litteken   }
2108c172f1adSAndrew Litteken }
2109c172f1adSAndrew Litteken 
2110c172f1adSAndrew Litteken /// Takes in a mapping, \p OldMap of ConstantValues to BasicBlocks, sorts keys,
2111c172f1adSAndrew Litteken /// before creating a basic block for each \p NewMap, and inserting into the new
2112c172f1adSAndrew Litteken /// block. Each BasicBlock is named with the scheme "<basename>_<key_idx>".
2113c172f1adSAndrew Litteken ///
2114c172f1adSAndrew Litteken /// \param OldMap [in] - The mapping to base the new mapping off of.
2115c172f1adSAndrew Litteken /// \param NewMap [out] - The output mapping using the keys of \p OldMap.
2116c172f1adSAndrew Litteken /// \param ParentFunc [in] - The function to put the new basic block in.
2117c172f1adSAndrew Litteken /// \param BaseName [in] - The start of the BasicBlock names to be appended to
2118c172f1adSAndrew Litteken /// by an index value.
createAndInsertBasicBlocks(DenseMap<Value *,BasicBlock * > & OldMap,DenseMap<Value *,BasicBlock * > & NewMap,Function * ParentFunc,Twine BaseName)2119c172f1adSAndrew Litteken static void createAndInsertBasicBlocks(DenseMap<Value *, BasicBlock *> &OldMap,
2120c172f1adSAndrew Litteken                                        DenseMap<Value *, BasicBlock *> &NewMap,
2121c172f1adSAndrew Litteken                                        Function *ParentFunc, Twine BaseName) {
2122c172f1adSAndrew Litteken   unsigned Idx = 0;
2123c172f1adSAndrew Litteken   std::vector<Value *> SortedKeys;
2124c172f1adSAndrew Litteken 
2125c172f1adSAndrew Litteken   getSortedConstantKeys(SortedKeys, OldMap);
2126c172f1adSAndrew Litteken 
2127c172f1adSAndrew Litteken   for (Value *RetVal : SortedKeys) {
2128c172f1adSAndrew Litteken     BasicBlock *NewBB = BasicBlock::Create(
2129c172f1adSAndrew Litteken         ParentFunc->getContext(),
2130c172f1adSAndrew Litteken         Twine(BaseName) + Twine("_") + Twine(static_cast<unsigned>(Idx++)),
2131c172f1adSAndrew Litteken         ParentFunc);
2132c172f1adSAndrew Litteken     NewMap.insert(std::make_pair(RetVal, NewBB));
2133c172f1adSAndrew Litteken   }
2134e6ae6233SAndrew Litteken }
2135e6ae6233SAndrew Litteken 
2136e6ae6233SAndrew Litteken /// Create the switch statement for outlined function to differentiate between
2137e6ae6233SAndrew Litteken /// all the output blocks.
2138e6ae6233SAndrew Litteken ///
2139e6ae6233SAndrew Litteken /// For the outlined section, determine if an outlined block already exists that
2140e6ae6233SAndrew Litteken /// matches the needed stores for the extracted section.
2141e6ae6233SAndrew Litteken /// \param [in] M - The module we are outlining from.
2142e6ae6233SAndrew Litteken /// \param [in] OG - The group of regions to be outlined.
214377f6c0bcSSimon Pilgrim /// \param [in] EndBBs - The final blocks of the extracted function.
2144e6ae6233SAndrew Litteken /// \param [in,out] OutputStoreBBs - The existing output blocks.
createSwitchStatement(Module & M,OutlinableGroup & OG,DenseMap<Value *,BasicBlock * > & EndBBs,std::vector<DenseMap<Value *,BasicBlock * >> & OutputStoreBBs)2145c172f1adSAndrew Litteken void createSwitchStatement(
2146c172f1adSAndrew Litteken     Module &M, OutlinableGroup &OG, DenseMap<Value *, BasicBlock *> &EndBBs,
2147c172f1adSAndrew Litteken     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
21481e238025SAndrew Litteken   // We only need the switch statement if there is more than one store
2149dcc3e728SAndrew Litteken   // combination, or there is more than one set of output blocks.  The first
2150dcc3e728SAndrew Litteken   // will occur when we store different sets of values for two different
2151dcc3e728SAndrew Litteken   // regions.  The second will occur when we have two outputs that are combined
2152dcc3e728SAndrew Litteken   // in a PHINode outside of the region in one outlined instance, and are used
2153dcc3e728SAndrew Litteken   // seaparately in another. This will create the same set of OutputGVNs, but
2154dcc3e728SAndrew Litteken   // will generate two different output schemes.
21551e238025SAndrew Litteken   if (OG.OutputGVNCombinations.size() > 1) {
2156e6ae6233SAndrew Litteken     Function *AggFunc = OG.OutlinedFunction;
2157c172f1adSAndrew Litteken     // Create a final block for each different return block.
2158c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *> ReturnBBs;
2159c172f1adSAndrew Litteken     createAndInsertBasicBlocks(OG.EndBBs, ReturnBBs, AggFunc, "final_block");
2160c172f1adSAndrew Litteken 
2161c172f1adSAndrew Litteken     for (std::pair<Value *, BasicBlock *> &RetBlockPair : ReturnBBs) {
2162c172f1adSAndrew Litteken       std::pair<Value *, BasicBlock *> &OutputBlock =
2163c172f1adSAndrew Litteken           *OG.EndBBs.find(RetBlockPair.first);
2164c172f1adSAndrew Litteken       BasicBlock *ReturnBlock = RetBlockPair.second;
2165c172f1adSAndrew Litteken       BasicBlock *EndBB = OutputBlock.second;
2166e6ae6233SAndrew Litteken       Instruction *Term = EndBB->getTerminator();
2167c172f1adSAndrew Litteken       // Move the return value to the final block instead of the original exit
2168c172f1adSAndrew Litteken       // stub.
2169e6ae6233SAndrew Litteken       Term->moveBefore(*ReturnBlock, ReturnBlock->end());
2170c172f1adSAndrew Litteken       // Put the switch statement in the old end basic block for the function
2171c172f1adSAndrew Litteken       // with a fall through to the new return block.
2172e6ae6233SAndrew Litteken       LLVM_DEBUG(dbgs() << "Create switch statement in " << *AggFunc << " for "
2173e6ae6233SAndrew Litteken                         << OutputStoreBBs.size() << "\n");
2174e6ae6233SAndrew Litteken       SwitchInst *SwitchI =
21751e238025SAndrew Litteken           SwitchInst::Create(AggFunc->getArg(AggFunc->arg_size() - 1),
21761e238025SAndrew Litteken                              ReturnBlock, OutputStoreBBs.size(), EndBB);
2177e6ae6233SAndrew Litteken 
2178e6ae6233SAndrew Litteken       unsigned Idx = 0;
2179c172f1adSAndrew Litteken       for (DenseMap<Value *, BasicBlock *> &OutputStoreBB : OutputStoreBBs) {
2180c172f1adSAndrew Litteken         DenseMap<Value *, BasicBlock *>::iterator OSBBIt =
2181c172f1adSAndrew Litteken             OutputStoreBB.find(OutputBlock.first);
2182c172f1adSAndrew Litteken 
2183c172f1adSAndrew Litteken         if (OSBBIt == OutputStoreBB.end())
2184c172f1adSAndrew Litteken           continue;
2185c172f1adSAndrew Litteken 
2186c172f1adSAndrew Litteken         BasicBlock *BB = OSBBIt->second;
2187c172f1adSAndrew Litteken         SwitchI->addCase(
2188c172f1adSAndrew Litteken             ConstantInt::get(Type::getInt32Ty(M.getContext()), Idx), BB);
2189e6ae6233SAndrew Litteken         Term = BB->getTerminator();
2190e6ae6233SAndrew Litteken         Term->setSuccessor(0, ReturnBlock);
2191e6ae6233SAndrew Litteken         Idx++;
2192e6ae6233SAndrew Litteken       }
2193c172f1adSAndrew Litteken     }
21941e238025SAndrew Litteken     return;
21951e238025SAndrew Litteken   }
21961e238025SAndrew Litteken 
2197dcc3e728SAndrew Litteken   assert(OutputStoreBBs.size() < 2 && "Different store sets not handled!");
2198dcc3e728SAndrew Litteken 
2199c172f1adSAndrew Litteken   // If there needs to be stores, move them from the output blocks to their
2200dcc3e728SAndrew Litteken   // corresponding ending block.  We do not check that the OutputGVNCombinations
2201dcc3e728SAndrew Litteken   // is equal to 1 here since that could just been the case where there are 0
2202dcc3e728SAndrew Litteken   // outputs. Instead, we check whether there is more than one set of output
2203dcc3e728SAndrew Litteken   // blocks since this is the only case where we would have to move the
2204dcc3e728SAndrew Litteken   // stores, and erase the extraneous blocks.
22051e238025SAndrew Litteken   if (OutputStoreBBs.size() == 1) {
22061e238025SAndrew Litteken     LLVM_DEBUG(dbgs() << "Move store instructions to the end block in "
22071e238025SAndrew Litteken                       << *OG.OutlinedFunction << "\n");
2208c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *> OutputBlocks = OutputStoreBBs[0];
2209c172f1adSAndrew Litteken     for (std::pair<Value *, BasicBlock *> &VBPair : OutputBlocks) {
2210c172f1adSAndrew Litteken       DenseMap<Value *, BasicBlock *>::iterator EndBBIt =
2211c172f1adSAndrew Litteken           EndBBs.find(VBPair.first);
2212c172f1adSAndrew Litteken       assert(EndBBIt != EndBBs.end() && "Could not find end block");
2213c172f1adSAndrew Litteken       BasicBlock *EndBB = EndBBIt->second;
2214c172f1adSAndrew Litteken       BasicBlock *OutputBB = VBPair.second;
2215c172f1adSAndrew Litteken       Instruction *Term = OutputBB->getTerminator();
22161e238025SAndrew Litteken       Term->eraseFromParent();
22171e238025SAndrew Litteken       Term = EndBB->getTerminator();
2218c172f1adSAndrew Litteken       moveBBContents(*OutputBB, *EndBB);
22191e238025SAndrew Litteken       Term->moveBefore(*EndBB, EndBB->end());
2220c172f1adSAndrew Litteken       OutputBB->eraseFromParent();
2221c172f1adSAndrew Litteken     }
22221e238025SAndrew Litteken   }
2223e6ae6233SAndrew Litteken }
2224e6ae6233SAndrew Litteken 
22257c6f28a4SAndrew Litteken /// Fill the new function that will serve as the replacement function for all of
22267c6f28a4SAndrew Litteken /// the extracted regions of a certain structure from the first region in the
22277c6f28a4SAndrew Litteken /// list of regions.  Replace this first region's extracted function with the
22287c6f28a4SAndrew Litteken /// new overall function.
22297c6f28a4SAndrew Litteken ///
2230e6ae6233SAndrew Litteken /// \param [in] M - The module we are outlining from.
2231e6ae6233SAndrew Litteken /// \param [in] CurrentGroup - The group of regions to be outlined.
2232e6ae6233SAndrew Litteken /// \param [in,out] OutputStoreBBs - The output blocks for each different
2233e6ae6233SAndrew Litteken /// set of stores needed for the different functions.
2234e6ae6233SAndrew Litteken /// \param [in,out] FuncsToRemove - Extracted functions to erase from module
22357c6f28a4SAndrew Litteken /// once outlining is complete.
2236dcc3e728SAndrew Litteken /// \param [in] OutputMappings - Extracted functions to erase from module
2237dcc3e728SAndrew Litteken /// once outlining is complete.
fillOverallFunction(Module & M,OutlinableGroup & CurrentGroup,std::vector<DenseMap<Value *,BasicBlock * >> & OutputStoreBBs,std::vector<Function * > & FuncsToRemove,const DenseMap<Value *,Value * > & OutputMappings)2238c172f1adSAndrew Litteken static void fillOverallFunction(
2239c172f1adSAndrew Litteken     Module &M, OutlinableGroup &CurrentGroup,
2240c172f1adSAndrew Litteken     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs,
2241dcc3e728SAndrew Litteken     std::vector<Function *> &FuncsToRemove,
2242dcc3e728SAndrew Litteken     const DenseMap<Value *, Value *> &OutputMappings) {
22437c6f28a4SAndrew Litteken   OutlinableRegion *CurrentOS = CurrentGroup.Regions[0];
22447c6f28a4SAndrew Litteken 
2245e6ae6233SAndrew Litteken   // Move first extracted function's instructions into new function.
22467c6f28a4SAndrew Litteken   LLVM_DEBUG(dbgs() << "Move instructions from "
22477c6f28a4SAndrew Litteken                     << *CurrentOS->ExtractedFunction << " to instruction "
22487c6f28a4SAndrew Litteken                     << *CurrentGroup.OutlinedFunction << "\n");
2249c172f1adSAndrew Litteken   moveFunctionData(*CurrentOS->ExtractedFunction,
2250c172f1adSAndrew Litteken                    *CurrentGroup.OutlinedFunction, CurrentGroup.EndBBs);
22517c6f28a4SAndrew Litteken 
2252e6ae6233SAndrew Litteken   // Transfer the attributes from the function to the new function.
225380ea2bb5SArthur Eubanks   for (Attribute A : CurrentOS->ExtractedFunction->getAttributes().getFnAttrs())
22547c6f28a4SAndrew Litteken     CurrentGroup.OutlinedFunction->addFnAttr(A);
22557c6f28a4SAndrew Litteken 
2256c172f1adSAndrew Litteken   // Create a new set of output blocks for the first extracted function.
2257c172f1adSAndrew Litteken   DenseMap<Value *, BasicBlock *> NewBBs;
2258c172f1adSAndrew Litteken   createAndInsertBasicBlocks(CurrentGroup.EndBBs, NewBBs,
2259c172f1adSAndrew Litteken                              CurrentGroup.OutlinedFunction, "output_block_0");
2260e6ae6233SAndrew Litteken   CurrentOS->OutputBlockNum = 0;
2261e6ae6233SAndrew Litteken 
2262dcc3e728SAndrew Litteken   replaceArgumentUses(*CurrentOS, NewBBs, OutputMappings, true);
2263b1191c84SAndrew Litteken   replaceConstants(*CurrentOS);
22647c6f28a4SAndrew Litteken 
2265c172f1adSAndrew Litteken   // We first identify if any output blocks are empty, if they are we remove
2266c172f1adSAndrew Litteken   // them. We then create a branch instruction to the basic block to the return
2267c172f1adSAndrew Litteken   // block for the function for each non empty output block.
2268c172f1adSAndrew Litteken   if (!analyzeAndPruneOutputBlocks(NewBBs, *CurrentOS)) {
2269c172f1adSAndrew Litteken     OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
2270c172f1adSAndrew Litteken     for (std::pair<Value *, BasicBlock *> &VToBB : NewBBs) {
2271c172f1adSAndrew Litteken       DenseMap<Value *, BasicBlock *>::iterator VBBIt =
2272c172f1adSAndrew Litteken           CurrentGroup.EndBBs.find(VToBB.first);
2273c172f1adSAndrew Litteken       BasicBlock *EndBB = VBBIt->second;
2274c172f1adSAndrew Litteken       BranchInst::Create(EndBB, VToBB.second);
2275c172f1adSAndrew Litteken       OutputStoreBBs.back().insert(VToBB);
2276c172f1adSAndrew Litteken     }
22771e238025SAndrew Litteken   }
2278e6ae6233SAndrew Litteken 
22797c6f28a4SAndrew Litteken   // Replace the call to the extracted function with the outlined function.
22807c6f28a4SAndrew Litteken   CurrentOS->Call = replaceCalledFunction(M, *CurrentOS);
22817c6f28a4SAndrew Litteken 
2282e6ae6233SAndrew Litteken   // We only delete the extracted functions at the end since we may need to
22837c6f28a4SAndrew Litteken   // reference instructions contained in them for mapping purposes.
22847c6f28a4SAndrew Litteken   FuncsToRemove.push_back(CurrentOS->ExtractedFunction);
22857c6f28a4SAndrew Litteken }
22867c6f28a4SAndrew Litteken 
deduplicateExtractedSections(Module & M,OutlinableGroup & CurrentGroup,std::vector<Function * > & FuncsToRemove,unsigned & OutlinedFunctionNum)22877c6f28a4SAndrew Litteken void IROutliner::deduplicateExtractedSections(
22887c6f28a4SAndrew Litteken     Module &M, OutlinableGroup &CurrentGroup,
22897c6f28a4SAndrew Litteken     std::vector<Function *> &FuncsToRemove, unsigned &OutlinedFunctionNum) {
22907c6f28a4SAndrew Litteken   createFunction(M, CurrentGroup, OutlinedFunctionNum);
22917c6f28a4SAndrew Litteken 
2292c172f1adSAndrew Litteken   std::vector<DenseMap<Value *, BasicBlock *>> OutputStoreBBs;
22937c6f28a4SAndrew Litteken 
22947c6f28a4SAndrew Litteken   OutlinableRegion *CurrentOS;
22957c6f28a4SAndrew Litteken 
2296dcc3e728SAndrew Litteken   fillOverallFunction(M, CurrentGroup, OutputStoreBBs, FuncsToRemove,
2297dcc3e728SAndrew Litteken                       OutputMappings);
22987c6f28a4SAndrew Litteken 
2299c172f1adSAndrew Litteken   std::vector<Value *> SortedKeys;
23007c6f28a4SAndrew Litteken   for (unsigned Idx = 1; Idx < CurrentGroup.Regions.size(); Idx++) {
23017c6f28a4SAndrew Litteken     CurrentOS = CurrentGroup.Regions[Idx];
23021a9eb19aSAndrew Litteken     AttributeFuncs::mergeAttributesForOutlining(*CurrentGroup.OutlinedFunction,
23031a9eb19aSAndrew Litteken                                                *CurrentOS->ExtractedFunction);
23047c6f28a4SAndrew Litteken 
2305c172f1adSAndrew Litteken     // Create a set of BasicBlocks, one for each return block, to hold the
2306c172f1adSAndrew Litteken     // needed store instructions.
2307c172f1adSAndrew Litteken     DenseMap<Value *, BasicBlock *> NewBBs;
2308c172f1adSAndrew Litteken     createAndInsertBasicBlocks(
2309c172f1adSAndrew Litteken         CurrentGroup.EndBBs, NewBBs, CurrentGroup.OutlinedFunction,
2310c172f1adSAndrew Litteken         "output_block_" + Twine(static_cast<unsigned>(Idx)));
2311dcc3e728SAndrew Litteken     replaceArgumentUses(*CurrentOS, NewBBs, OutputMappings);
2312c172f1adSAndrew Litteken     alignOutputBlockWithAggFunc(CurrentGroup, *CurrentOS, NewBBs,
2313c172f1adSAndrew Litteken                                 CurrentGroup.EndBBs, OutputMappings,
2314e6ae6233SAndrew Litteken                                 OutputStoreBBs);
2315e6ae6233SAndrew Litteken 
23167c6f28a4SAndrew Litteken     CurrentOS->Call = replaceCalledFunction(M, *CurrentOS);
23177c6f28a4SAndrew Litteken     FuncsToRemove.push_back(CurrentOS->ExtractedFunction);
23187c6f28a4SAndrew Litteken   }
23197c6f28a4SAndrew Litteken 
2320e6ae6233SAndrew Litteken   // Create a switch statement to handle the different output schemes.
2321c172f1adSAndrew Litteken   createSwitchStatement(M, CurrentGroup, CurrentGroup.EndBBs, OutputStoreBBs);
2322e6ae6233SAndrew Litteken 
23237c6f28a4SAndrew Litteken   OutlinedFunctionNum++;
2324c52bcf3aSAndrew Litteken }
2325c52bcf3aSAndrew Litteken 
2326bd4b1b5fSAndrew Litteken /// Checks that the next instruction in the InstructionDataList matches the
2327bd4b1b5fSAndrew Litteken /// next instruction in the module.  If they do not, there could be the
2328bd4b1b5fSAndrew Litteken /// possibility that extra code has been inserted, and we must ignore it.
2329bd4b1b5fSAndrew Litteken ///
2330bd4b1b5fSAndrew Litteken /// \param ID - The IRInstructionData to check the next instruction of.
2331bd4b1b5fSAndrew Litteken /// \returns true if the InstructionDataList and actual instruction match.
nextIRInstructionDataMatchesNextInst(IRInstructionData & ID)2332bd4b1b5fSAndrew Litteken static bool nextIRInstructionDataMatchesNextInst(IRInstructionData &ID) {
2333bd4b1b5fSAndrew Litteken   // We check if there is a discrepancy between the InstructionDataList
2334bd4b1b5fSAndrew Litteken   // and the actual next instruction in the module.  If there is, it means
2335bd4b1b5fSAndrew Litteken   // that an extra instruction was added, likely by the CodeExtractor.
2336bd4b1b5fSAndrew Litteken 
2337bd4b1b5fSAndrew Litteken   // Since we do not have any similarity data about this particular
2338bd4b1b5fSAndrew Litteken   // instruction, we cannot confidently outline it, and must discard this
2339bd4b1b5fSAndrew Litteken   // candidate.
2340bd4b1b5fSAndrew Litteken   IRInstructionDataList::iterator NextIDIt = std::next(ID.getIterator());
2341bd4b1b5fSAndrew Litteken   Instruction *NextIDLInst = NextIDIt->Inst;
2342bd4b1b5fSAndrew Litteken   Instruction *NextModuleInst = nullptr;
2343bd4b1b5fSAndrew Litteken   if (!ID.Inst->isTerminator())
2344bd4b1b5fSAndrew Litteken     NextModuleInst = ID.Inst->getNextNonDebugInstruction();
2345bd4b1b5fSAndrew Litteken   else if (NextIDLInst != nullptr)
2346bd4b1b5fSAndrew Litteken     NextModuleInst =
2347bd4b1b5fSAndrew Litteken         &*NextIDIt->Inst->getParent()->instructionsWithoutDebug().begin();
2348bd4b1b5fSAndrew Litteken 
2349bd4b1b5fSAndrew Litteken   if (NextIDLInst && NextIDLInst != NextModuleInst)
2350bd4b1b5fSAndrew Litteken     return false;
2351bd4b1b5fSAndrew Litteken 
2352bd4b1b5fSAndrew Litteken   return true;
2353bd4b1b5fSAndrew Litteken }
2354bd4b1b5fSAndrew Litteken 
isCompatibleWithAlreadyOutlinedCode(const OutlinableRegion & Region)2355c58d4c4bSAndrew Litteken bool IROutliner::isCompatibleWithAlreadyOutlinedCode(
2356c58d4c4bSAndrew Litteken     const OutlinableRegion &Region) {
2357c58d4c4bSAndrew Litteken   IRSimilarityCandidate *IRSC = Region.Candidate;
2358c58d4c4bSAndrew Litteken   unsigned StartIdx = IRSC->getStartIdx();
2359c58d4c4bSAndrew Litteken   unsigned EndIdx = IRSC->getEndIdx();
2360c58d4c4bSAndrew Litteken 
2361c58d4c4bSAndrew Litteken   // A check to make sure that we are not about to attempt to outline something
2362c58d4c4bSAndrew Litteken   // that has already been outlined.
2363c58d4c4bSAndrew Litteken   for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2364c58d4c4bSAndrew Litteken     if (Outlined.contains(Idx))
2365c58d4c4bSAndrew Litteken       return false;
2366c58d4c4bSAndrew Litteken 
2367c58d4c4bSAndrew Litteken   // We check if the recorded instruction matches the actual next instruction,
2368c58d4c4bSAndrew Litteken   // if it does not, we fix it in the InstructionDataList.
236981d3ac0cSAndrew Litteken   if (!Region.Candidate->backInstruction()->isTerminator()) {
237081d3ac0cSAndrew Litteken     Instruction *NewEndInst =
2371c58d4c4bSAndrew Litteken         Region.Candidate->backInstruction()->getNextNonDebugInstruction();
237281d3ac0cSAndrew Litteken     assert(NewEndInst && "Next instruction is a nullptr?");
237381d3ac0cSAndrew Litteken     if (Region.Candidate->end()->Inst != NewEndInst) {
2374c58d4c4bSAndrew Litteken       IRInstructionDataList *IDL = Region.Candidate->front()->IDL;
2375c58d4c4bSAndrew Litteken       IRInstructionData *NewEndIRID = new (InstDataAllocator.Allocate())
237681d3ac0cSAndrew Litteken           IRInstructionData(*NewEndInst,
237781d3ac0cSAndrew Litteken                             InstructionClassifier.visit(*NewEndInst), *IDL);
2378c58d4c4bSAndrew Litteken 
2379c58d4c4bSAndrew Litteken       // Insert the first IRInstructionData of the new region after the
2380c58d4c4bSAndrew Litteken       // last IRInstructionData of the IRSimilarityCandidate.
2381c58d4c4bSAndrew Litteken       IDL->insert(Region.Candidate->end(), *NewEndIRID);
2382c58d4c4bSAndrew Litteken     }
238381d3ac0cSAndrew Litteken   }
2384c58d4c4bSAndrew Litteken 
2385c58d4c4bSAndrew Litteken   return none_of(*IRSC, [this](IRInstructionData &ID) {
2386bd4b1b5fSAndrew Litteken     if (!nextIRInstructionDataMatchesNextInst(ID))
2387c58d4c4bSAndrew Litteken       return true;
2388bd4b1b5fSAndrew Litteken 
2389bd4b1b5fSAndrew Litteken     return !this->InstructionClassifier.visit(ID.Inst);
2390c58d4c4bSAndrew Litteken   });
2391c58d4c4bSAndrew Litteken }
2392c58d4c4bSAndrew Litteken 
pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> & CandidateVec,OutlinableGroup & CurrentGroup)2393dae34463SAndrew Litteken void IROutliner::pruneIncompatibleRegions(
2394dae34463SAndrew Litteken     std::vector<IRSimilarityCandidate> &CandidateVec,
2395dae34463SAndrew Litteken     OutlinableGroup &CurrentGroup) {
2396dae34463SAndrew Litteken   bool PreviouslyOutlined;
2397dae34463SAndrew Litteken 
2398dae34463SAndrew Litteken   // Sort from beginning to end, so the IRSimilarityCandidates are in order.
2399dae34463SAndrew Litteken   stable_sort(CandidateVec, [](const IRSimilarityCandidate &LHS,
2400dae34463SAndrew Litteken                                const IRSimilarityCandidate &RHS) {
2401dae34463SAndrew Litteken     return LHS.getStartIdx() < RHS.getStartIdx();
2402dae34463SAndrew Litteken   });
2403dae34463SAndrew Litteken 
240481d3ac0cSAndrew Litteken   IRSimilarityCandidate &FirstCandidate = CandidateVec[0];
240581d3ac0cSAndrew Litteken   // Since outlining a call and a branch instruction will be the same as only
240681d3ac0cSAndrew Litteken   // outlinining a call instruction, we ignore it as a space saving.
240781d3ac0cSAndrew Litteken   if (FirstCandidate.getLength() == 2) {
240881d3ac0cSAndrew Litteken     if (isa<CallInst>(FirstCandidate.front()->Inst) &&
240981d3ac0cSAndrew Litteken         isa<BranchInst>(FirstCandidate.back()->Inst))
241081d3ac0cSAndrew Litteken       return;
241181d3ac0cSAndrew Litteken   }
241281d3ac0cSAndrew Litteken 
2413dae34463SAndrew Litteken   unsigned CurrentEndIdx = 0;
2414dae34463SAndrew Litteken   for (IRSimilarityCandidate &IRSC : CandidateVec) {
2415dae34463SAndrew Litteken     PreviouslyOutlined = false;
2416dae34463SAndrew Litteken     unsigned StartIdx = IRSC.getStartIdx();
2417dae34463SAndrew Litteken     unsigned EndIdx = IRSC.getEndIdx();
2418dae34463SAndrew Litteken 
2419dae34463SAndrew Litteken     for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
242056edfcadSKazu Hirata       if (Outlined.contains(Idx)) {
2421dae34463SAndrew Litteken         PreviouslyOutlined = true;
2422dae34463SAndrew Litteken         break;
2423dae34463SAndrew Litteken       }
2424dae34463SAndrew Litteken 
2425dae34463SAndrew Litteken     if (PreviouslyOutlined)
2426dae34463SAndrew Litteken       continue;
2427dae34463SAndrew Litteken 
242881d3ac0cSAndrew Litteken     // Check over the instructions, and if the basic block has its address
242981d3ac0cSAndrew Litteken     // taken for use somewhere else, we do not outline that block.
243081d3ac0cSAndrew Litteken     bool BBHasAddressTaken = any_of(IRSC, [](IRInstructionData &ID){
243181d3ac0cSAndrew Litteken       return ID.Inst->getParent()->hasAddressTaken();
243281d3ac0cSAndrew Litteken     });
243381d3ac0cSAndrew Litteken 
243481d3ac0cSAndrew Litteken     if (BBHasAddressTaken)
2435dae34463SAndrew Litteken       continue;
2436dae34463SAndrew Litteken 
243738e8880eSAndrew Litteken     if (IRSC.getFunction()->hasOptNone())
243838e8880eSAndrew Litteken       continue;
243938e8880eSAndrew Litteken 
2440fe431103SAndrew Litteken     if (IRSC.front()->Inst->getFunction()->hasLinkOnceODRLinkage() &&
2441fe431103SAndrew Litteken         !OutlineFromLinkODRs)
2442fe431103SAndrew Litteken       continue;
2443fe431103SAndrew Litteken 
2444dae34463SAndrew Litteken     // Greedily prune out any regions that will overlap with already chosen
2445dae34463SAndrew Litteken     // regions.
2446dae34463SAndrew Litteken     if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
2447dae34463SAndrew Litteken       continue;
2448dae34463SAndrew Litteken 
2449cea80760SAndrew Litteken     bool BadInst = any_of(IRSC, [this](IRInstructionData &ID) {
2450bd4b1b5fSAndrew Litteken       if (!nextIRInstructionDataMatchesNextInst(ID))
245105b1a15fSAndrew Litteken         return true;
2452bd4b1b5fSAndrew Litteken 
2453cea80760SAndrew Litteken       return !this->InstructionClassifier.visit(ID.Inst);
2454cea80760SAndrew Litteken     });
2455cea80760SAndrew Litteken 
2456cea80760SAndrew Litteken     if (BadInst)
2457cea80760SAndrew Litteken       continue;
2458cea80760SAndrew Litteken 
2459dae34463SAndrew Litteken     OutlinableRegion *OS = new (RegionAllocator.Allocate())
2460dae34463SAndrew Litteken         OutlinableRegion(IRSC, CurrentGroup);
2461dae34463SAndrew Litteken     CurrentGroup.Regions.push_back(OS);
2462dae34463SAndrew Litteken 
2463dae34463SAndrew Litteken     CurrentEndIdx = EndIdx;
2464dae34463SAndrew Litteken   }
2465dae34463SAndrew Litteken }
2466dae34463SAndrew Litteken 
2467255a5077SDavid Sherwood InstructionCost
findBenefitFromAllRegions(OutlinableGroup & CurrentGroup)2468255a5077SDavid Sherwood IROutliner::findBenefitFromAllRegions(OutlinableGroup &CurrentGroup) {
2469255a5077SDavid Sherwood   InstructionCost RegionBenefit = 0;
24706df161a2SAndrew Litteken   for (OutlinableRegion *Region : CurrentGroup.Regions) {
24716df161a2SAndrew Litteken     TargetTransformInfo &TTI = getTTI(*Region->StartBB->getParent());
24726df161a2SAndrew Litteken     // We add the number of instructions in the region to the benefit as an
24736df161a2SAndrew Litteken     // estimate as to how much will be removed.
24746df161a2SAndrew Litteken     RegionBenefit += Region->getBenefit(TTI);
24756df161a2SAndrew Litteken     LLVM_DEBUG(dbgs() << "Adding: " << RegionBenefit
24766df161a2SAndrew Litteken                       << " saved instructions to overfall benefit.\n");
24776df161a2SAndrew Litteken   }
24786df161a2SAndrew Litteken 
24796df161a2SAndrew Litteken   return RegionBenefit;
24806df161a2SAndrew Litteken }
24816df161a2SAndrew Litteken 
2482dcc3e728SAndrew Litteken /// For the \p OutputCanon number passed in find the value represented by this
2483dcc3e728SAndrew Litteken /// canonical number. If it is from a PHINode, we pick the first incoming
2484dcc3e728SAndrew Litteken /// value and return that Value instead.
2485dcc3e728SAndrew Litteken ///
2486dcc3e728SAndrew Litteken /// \param Region - The OutlinableRegion to get the Value from.
2487dcc3e728SAndrew Litteken /// \param OutputCanon - The canonical number to find the Value from.
2488dcc3e728SAndrew Litteken /// \returns The Value represented by a canonical number \p OutputCanon in \p
2489dcc3e728SAndrew Litteken /// Region.
findOutputValueInRegion(OutlinableRegion & Region,unsigned OutputCanon)2490dcc3e728SAndrew Litteken static Value *findOutputValueInRegion(OutlinableRegion &Region,
2491dcc3e728SAndrew Litteken                                       unsigned OutputCanon) {
2492dcc3e728SAndrew Litteken   OutlinableGroup &CurrentGroup = *Region.Parent;
2493dcc3e728SAndrew Litteken   // If the value is greater than the value in the tracker, we have a
2494dcc3e728SAndrew Litteken   // PHINode and will instead use one of the incoming values to find the
2495dcc3e728SAndrew Litteken   // type.
2496dcc3e728SAndrew Litteken   if (OutputCanon > CurrentGroup.PHINodeGVNTracker) {
2497dcc3e728SAndrew Litteken     auto It = CurrentGroup.PHINodeGVNToGVNs.find(OutputCanon);
2498dcc3e728SAndrew Litteken     assert(It != CurrentGroup.PHINodeGVNToGVNs.end() &&
2499dcc3e728SAndrew Litteken            "Could not find GVN set for PHINode number!");
2500dcc3e728SAndrew Litteken     assert(It->second.second.size() > 0 && "PHINode does not have any values!");
2501dcc3e728SAndrew Litteken     OutputCanon = *It->second.second.begin();
2502dcc3e728SAndrew Litteken   }
2503dcc3e728SAndrew Litteken   Optional<unsigned> OGVN = Region.Candidate->fromCanonicalNum(OutputCanon);
2504a7938c74SKazu Hirata   assert(OGVN && "Could not find GVN for Canonical Number?");
2505dcc3e728SAndrew Litteken   Optional<Value *> OV = Region.Candidate->fromGVN(*OGVN);
2506a7938c74SKazu Hirata   assert(OV && "Could not find value for GVN?");
2507dcc3e728SAndrew Litteken   return *OV;
2508dcc3e728SAndrew Litteken }
2509dcc3e728SAndrew Litteken 
2510255a5077SDavid Sherwood InstructionCost
findCostOutputReloads(OutlinableGroup & CurrentGroup)2511255a5077SDavid Sherwood IROutliner::findCostOutputReloads(OutlinableGroup &CurrentGroup) {
2512255a5077SDavid Sherwood   InstructionCost OverallCost = 0;
25136df161a2SAndrew Litteken   for (OutlinableRegion *Region : CurrentGroup.Regions) {
25146df161a2SAndrew Litteken     TargetTransformInfo &TTI = getTTI(*Region->StartBB->getParent());
25156df161a2SAndrew Litteken 
25166df161a2SAndrew Litteken     // Each output incurs a load after the call, so we add that to the cost.
2517dcc3e728SAndrew Litteken     for (unsigned OutputCanon : Region->GVNStores) {
2518dcc3e728SAndrew Litteken       Value *V = findOutputValueInRegion(*Region, OutputCanon);
2519255a5077SDavid Sherwood       InstructionCost LoadCost =
25206df161a2SAndrew Litteken           TTI.getMemoryOpCost(Instruction::Load, V->getType(), Align(1), 0,
25216df161a2SAndrew Litteken                               TargetTransformInfo::TCK_CodeSize);
25226df161a2SAndrew Litteken 
25236df161a2SAndrew Litteken       LLVM_DEBUG(dbgs() << "Adding: " << LoadCost
25246df161a2SAndrew Litteken                         << " instructions to cost for output of type "
25256df161a2SAndrew Litteken                         << *V->getType() << "\n");
25266df161a2SAndrew Litteken       OverallCost += LoadCost;
25276df161a2SAndrew Litteken     }
25286df161a2SAndrew Litteken   }
25296df161a2SAndrew Litteken 
25306df161a2SAndrew Litteken   return OverallCost;
25316df161a2SAndrew Litteken }
25326df161a2SAndrew Litteken 
25336df161a2SAndrew Litteken /// Find the extra instructions needed to handle any output values for the
25346df161a2SAndrew Litteken /// region.
25356df161a2SAndrew Litteken ///
25366df161a2SAndrew Litteken /// \param [in] M - The Module to outline from.
25376df161a2SAndrew Litteken /// \param [in] CurrentGroup - The collection of OutlinableRegions to analyze.
25386df161a2SAndrew Litteken /// \param [in] TTI - The TargetTransformInfo used to collect information for
25396df161a2SAndrew Litteken /// new instruction costs.
25406df161a2SAndrew Litteken /// \returns the additional cost to handle the outputs.
findCostForOutputBlocks(Module & M,OutlinableGroup & CurrentGroup,TargetTransformInfo & TTI)2541255a5077SDavid Sherwood static InstructionCost findCostForOutputBlocks(Module &M,
25426df161a2SAndrew Litteken                                                OutlinableGroup &CurrentGroup,
25436df161a2SAndrew Litteken                                                TargetTransformInfo &TTI) {
2544255a5077SDavid Sherwood   InstructionCost OutputCost = 0;
254581d3ac0cSAndrew Litteken   unsigned NumOutputBranches = 0;
254681d3ac0cSAndrew Litteken 
2547dcc3e728SAndrew Litteken   OutlinableRegion &FirstRegion = *CurrentGroup.Regions[0];
254881d3ac0cSAndrew Litteken   IRSimilarityCandidate &Candidate = *CurrentGroup.Regions[0]->Candidate;
254981d3ac0cSAndrew Litteken   DenseSet<BasicBlock *> CandidateBlocks;
255081d3ac0cSAndrew Litteken   Candidate.getBasicBlocks(CandidateBlocks);
255181d3ac0cSAndrew Litteken 
255281d3ac0cSAndrew Litteken   // Count the number of different output branches that point to blocks outside
255381d3ac0cSAndrew Litteken   // of the region.
255481d3ac0cSAndrew Litteken   DenseSet<BasicBlock *> FoundBlocks;
255581d3ac0cSAndrew Litteken   for (IRInstructionData &ID : Candidate) {
255681d3ac0cSAndrew Litteken     if (!isa<BranchInst>(ID.Inst))
255781d3ac0cSAndrew Litteken       continue;
255881d3ac0cSAndrew Litteken 
255981d3ac0cSAndrew Litteken     for (Value *V : ID.OperVals) {
256081d3ac0cSAndrew Litteken       BasicBlock *BB = static_cast<BasicBlock *>(V);
2561f8b5be64SKazu Hirata       if (!CandidateBlocks.contains(BB) && FoundBlocks.insert(BB).second)
256281d3ac0cSAndrew Litteken         NumOutputBranches++;
256381d3ac0cSAndrew Litteken     }
256481d3ac0cSAndrew Litteken   }
256581d3ac0cSAndrew Litteken 
256681d3ac0cSAndrew Litteken   CurrentGroup.BranchesToOutside = NumOutputBranches;
25676df161a2SAndrew Litteken 
25686df161a2SAndrew Litteken   for (const ArrayRef<unsigned> &OutputUse :
25696df161a2SAndrew Litteken        CurrentGroup.OutputGVNCombinations) {
2570dcc3e728SAndrew Litteken     for (unsigned OutputCanon : OutputUse) {
2571dcc3e728SAndrew Litteken       Value *V = findOutputValueInRegion(FirstRegion, OutputCanon);
2572255a5077SDavid Sherwood       InstructionCost StoreCost =
25736df161a2SAndrew Litteken           TTI.getMemoryOpCost(Instruction::Load, V->getType(), Align(1), 0,
25746df161a2SAndrew Litteken                               TargetTransformInfo::TCK_CodeSize);
25756df161a2SAndrew Litteken 
25766df161a2SAndrew Litteken       // An instruction cost is added for each store set that needs to occur for
25776df161a2SAndrew Litteken       // various output combinations inside the function, plus a branch to
25786df161a2SAndrew Litteken       // return to the exit block.
25796df161a2SAndrew Litteken       LLVM_DEBUG(dbgs() << "Adding: " << StoreCost
25806df161a2SAndrew Litteken                         << " instructions to cost for output of type "
25816df161a2SAndrew Litteken                         << *V->getType() << "\n");
258281d3ac0cSAndrew Litteken       OutputCost += StoreCost * NumOutputBranches;
25836df161a2SAndrew Litteken     }
25846df161a2SAndrew Litteken 
2585255a5077SDavid Sherwood     InstructionCost BranchCost =
25866df161a2SAndrew Litteken         TTI.getCFInstrCost(Instruction::Br, TargetTransformInfo::TCK_CodeSize);
25876df161a2SAndrew Litteken     LLVM_DEBUG(dbgs() << "Adding " << BranchCost << " to the current cost for"
25886df161a2SAndrew Litteken                       << " a branch instruction\n");
258981d3ac0cSAndrew Litteken     OutputCost += BranchCost * NumOutputBranches;
25906df161a2SAndrew Litteken   }
25916df161a2SAndrew Litteken 
25926df161a2SAndrew Litteken   // If there is more than one output scheme, we must have a comparison and
25936df161a2SAndrew Litteken   // branch for each different item in the switch statement.
25946df161a2SAndrew Litteken   if (CurrentGroup.OutputGVNCombinations.size() > 1) {
2595255a5077SDavid Sherwood     InstructionCost ComparisonCost = TTI.getCmpSelInstrCost(
25966df161a2SAndrew Litteken         Instruction::ICmp, Type::getInt32Ty(M.getContext()),
25976df161a2SAndrew Litteken         Type::getInt32Ty(M.getContext()), CmpInst::BAD_ICMP_PREDICATE,
25986df161a2SAndrew Litteken         TargetTransformInfo::TCK_CodeSize);
2599255a5077SDavid Sherwood     InstructionCost BranchCost =
26006df161a2SAndrew Litteken         TTI.getCFInstrCost(Instruction::Br, TargetTransformInfo::TCK_CodeSize);
26016df161a2SAndrew Litteken 
26026df161a2SAndrew Litteken     unsigned DifferentBlocks = CurrentGroup.OutputGVNCombinations.size();
2603255a5077SDavid Sherwood     InstructionCost TotalCost = ComparisonCost * BranchCost * DifferentBlocks;
26046df161a2SAndrew Litteken 
26056df161a2SAndrew Litteken     LLVM_DEBUG(dbgs() << "Adding: " << TotalCost
26066df161a2SAndrew Litteken                       << " instructions for each switch case for each different"
26076df161a2SAndrew Litteken                       << " output path in a function\n");
260881d3ac0cSAndrew Litteken     OutputCost += TotalCost * NumOutputBranches;
26096df161a2SAndrew Litteken   }
26106df161a2SAndrew Litteken 
26116df161a2SAndrew Litteken   return OutputCost;
26126df161a2SAndrew Litteken }
26136df161a2SAndrew Litteken 
findCostBenefit(Module & M,OutlinableGroup & CurrentGroup)26146df161a2SAndrew Litteken void IROutliner::findCostBenefit(Module &M, OutlinableGroup &CurrentGroup) {
2615255a5077SDavid Sherwood   InstructionCost RegionBenefit = findBenefitFromAllRegions(CurrentGroup);
26166df161a2SAndrew Litteken   CurrentGroup.Benefit += RegionBenefit;
26176df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Current Benefit: " << CurrentGroup.Benefit << "\n");
26186df161a2SAndrew Litteken 
2619255a5077SDavid Sherwood   InstructionCost OutputReloadCost = findCostOutputReloads(CurrentGroup);
26206df161a2SAndrew Litteken   CurrentGroup.Cost += OutputReloadCost;
26216df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
26226df161a2SAndrew Litteken 
2623255a5077SDavid Sherwood   InstructionCost AverageRegionBenefit =
2624255a5077SDavid Sherwood       RegionBenefit / CurrentGroup.Regions.size();
26256df161a2SAndrew Litteken   unsigned OverallArgumentNum = CurrentGroup.ArgumentTypes.size();
26266df161a2SAndrew Litteken   unsigned NumRegions = CurrentGroup.Regions.size();
26276df161a2SAndrew Litteken   TargetTransformInfo &TTI =
26286df161a2SAndrew Litteken       getTTI(*CurrentGroup.Regions[0]->Candidate->getFunction());
26296df161a2SAndrew Litteken 
26306df161a2SAndrew Litteken   // We add one region to the cost once, to account for the instructions added
26316df161a2SAndrew Litteken   // inside of the newly created function.
26326df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Adding: " << AverageRegionBenefit
26336df161a2SAndrew Litteken                     << " instructions to cost for body of new function.\n");
26346df161a2SAndrew Litteken   CurrentGroup.Cost += AverageRegionBenefit;
26356df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
26366df161a2SAndrew Litteken 
26376df161a2SAndrew Litteken   // For each argument, we must add an instruction for loading the argument
26386df161a2SAndrew Litteken   // out of the register and into a value inside of the newly outlined function.
26396df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Adding: " << OverallArgumentNum
26406df161a2SAndrew Litteken                     << " instructions to cost for each argument in the new"
26416df161a2SAndrew Litteken                     << " function.\n");
264205e6ac4eSAndrew Litteken   CurrentGroup.Cost +=
26435c951623SAndrew Litteken       OverallArgumentNum * TargetTransformInfo::TCC_Basic;
26446df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
26456df161a2SAndrew Litteken 
26466df161a2SAndrew Litteken   // Each argument needs to either be loaded into a register or onto the stack.
26476df161a2SAndrew Litteken   // Some arguments will only be loaded into the stack once the argument
26486df161a2SAndrew Litteken   // registers are filled.
26496df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Adding: " << OverallArgumentNum
26506df161a2SAndrew Litteken                     << " instructions to cost for each argument in the new"
26516df161a2SAndrew Litteken                     << " function " << NumRegions << " times for the "
26526df161a2SAndrew Litteken                     << "needed argument handling at the call site.\n");
26536df161a2SAndrew Litteken   CurrentGroup.Cost +=
26545c951623SAndrew Litteken       2 * OverallArgumentNum * TargetTransformInfo::TCC_Basic * NumRegions;
26556df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
26566df161a2SAndrew Litteken 
26576df161a2SAndrew Litteken   CurrentGroup.Cost += findCostForOutputBlocks(M, CurrentGroup, TTI);
26586df161a2SAndrew Litteken   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
26596df161a2SAndrew Litteken }
26606df161a2SAndrew Litteken 
updateOutputMapping(OutlinableRegion & Region,ArrayRef<Value * > Outputs,LoadInst * LI)2661e6ae6233SAndrew Litteken void IROutliner::updateOutputMapping(OutlinableRegion &Region,
2662e6ae6233SAndrew Litteken                                      ArrayRef<Value *> Outputs,
2663e6ae6233SAndrew Litteken                                      LoadInst *LI) {
2664e6ae6233SAndrew Litteken   // For and load instructions following the call
2665e6ae6233SAndrew Litteken   Value *Operand = LI->getPointerOperand();
2666e6ae6233SAndrew Litteken   Optional<unsigned> OutputIdx = None;
2667e6ae6233SAndrew Litteken   // Find if the operand it is an output register.
2668e6ae6233SAndrew Litteken   for (unsigned ArgIdx = Region.NumExtractedInputs;
2669e6ae6233SAndrew Litteken        ArgIdx < Region.Call->arg_size(); ArgIdx++) {
2670e6ae6233SAndrew Litteken     if (Operand == Region.Call->getArgOperand(ArgIdx)) {
2671e6ae6233SAndrew Litteken       OutputIdx = ArgIdx - Region.NumExtractedInputs;
2672e6ae6233SAndrew Litteken       break;
2673e6ae6233SAndrew Litteken     }
2674e6ae6233SAndrew Litteken   }
2675e6ae6233SAndrew Litteken 
2676e6ae6233SAndrew Litteken   // If we found an output register, place a mapping of the new value
2677e6ae6233SAndrew Litteken   // to the original in the mapping.
2678e0e687a6SKazu Hirata   if (!OutputIdx)
2679e6ae6233SAndrew Litteken     return;
2680e6ae6233SAndrew Litteken 
2681*611ffcf4SKazu Hirata   if (OutputMappings.find(Outputs[OutputIdx.value()]) == OutputMappings.end()) {
2682e6ae6233SAndrew Litteken     LLVM_DEBUG(dbgs() << "Mapping extracted output " << *LI << " to "
2683*611ffcf4SKazu Hirata                       << *Outputs[OutputIdx.value()] << "\n");
2684*611ffcf4SKazu Hirata     OutputMappings.insert(std::make_pair(LI, Outputs[OutputIdx.value()]));
2685e6ae6233SAndrew Litteken   } else {
2686*611ffcf4SKazu Hirata     Value *Orig = OutputMappings.find(Outputs[OutputIdx.value()])->second;
2687e6ae6233SAndrew Litteken     LLVM_DEBUG(dbgs() << "Mapping extracted output " << *Orig << " to "
2688*611ffcf4SKazu Hirata                       << *Outputs[OutputIdx.value()] << "\n");
2689e6ae6233SAndrew Litteken     OutputMappings.insert(std::make_pair(LI, Orig));
2690e6ae6233SAndrew Litteken   }
2691e6ae6233SAndrew Litteken }
2692e6ae6233SAndrew Litteken 
extractSection(OutlinableRegion & Region)2693dae34463SAndrew Litteken bool IROutliner::extractSection(OutlinableRegion &Region) {
2694e6ae6233SAndrew Litteken   SetVector<Value *> ArgInputs, Outputs, SinkCands;
2695e6ae6233SAndrew Litteken   assert(Region.StartBB && "StartBB for the OutlinableRegion is nullptr!");
269681d3ac0cSAndrew Litteken   BasicBlock *InitialStart = Region.StartBB;
2697dae34463SAndrew Litteken   Function *OrigF = Region.StartBB->getParent();
2698dae34463SAndrew Litteken   CodeExtractorAnalysisCache CEAC(*OrigF);
269981d3ac0cSAndrew Litteken   Region.ExtractedFunction =
270081d3ac0cSAndrew Litteken       Region.CE->extractCodeRegion(CEAC, ArgInputs, Outputs);
2701dae34463SAndrew Litteken 
2702dae34463SAndrew Litteken   // If the extraction was successful, find the BasicBlock, and reassign the
2703dae34463SAndrew Litteken   // OutlinableRegion blocks
2704dae34463SAndrew Litteken   if (!Region.ExtractedFunction) {
2705dae34463SAndrew Litteken     LLVM_DEBUG(dbgs() << "CodeExtractor failed to outline " << Region.StartBB
2706dae34463SAndrew Litteken                       << "\n");
2707dae34463SAndrew Litteken     Region.reattachCandidate();
2708dae34463SAndrew Litteken     return false;
2709dae34463SAndrew Litteken   }
2710dae34463SAndrew Litteken 
271181d3ac0cSAndrew Litteken   // Get the block containing the called branch, and reassign the blocks as
271281d3ac0cSAndrew Litteken   // necessary.  If the original block still exists, it is because we ended on
271381d3ac0cSAndrew Litteken   // a branch instruction, and so we move the contents into the block before
271481d3ac0cSAndrew Litteken   // and assign the previous block correctly.
271581d3ac0cSAndrew Litteken   User *InstAsUser = Region.ExtractedFunction->user_back();
271681d3ac0cSAndrew Litteken   BasicBlock *RewrittenBB = cast<Instruction>(InstAsUser)->getParent();
271781d3ac0cSAndrew Litteken   Region.PrevBB = RewrittenBB->getSinglePredecessor();
271881d3ac0cSAndrew Litteken   assert(Region.PrevBB && "PrevBB is nullptr?");
271981d3ac0cSAndrew Litteken   if (Region.PrevBB == InitialStart) {
272081d3ac0cSAndrew Litteken     BasicBlock *NewPrev = InitialStart->getSinglePredecessor();
272181d3ac0cSAndrew Litteken     Instruction *BI = NewPrev->getTerminator();
272281d3ac0cSAndrew Litteken     BI->eraseFromParent();
272381d3ac0cSAndrew Litteken     moveBBContents(*InitialStart, *NewPrev);
272481d3ac0cSAndrew Litteken     Region.PrevBB = NewPrev;
272581d3ac0cSAndrew Litteken     InitialStart->eraseFromParent();
272681d3ac0cSAndrew Litteken   }
272781d3ac0cSAndrew Litteken 
2728dae34463SAndrew Litteken   Region.StartBB = RewrittenBB;
2729dae34463SAndrew Litteken   Region.EndBB = RewrittenBB;
2730dae34463SAndrew Litteken 
2731dae34463SAndrew Litteken   // The sequences of outlinable regions has now changed.  We must fix the
2732dae34463SAndrew Litteken   // IRInstructionDataList for consistency.  Although they may not be illegal
2733dae34463SAndrew Litteken   // instructions, they should not be compared with anything else as they
2734dae34463SAndrew Litteken   // should not be outlined in this round.  So marking these as illegal is
2735dae34463SAndrew Litteken   // allowed.
2736dae34463SAndrew Litteken   IRInstructionDataList *IDL = Region.Candidate->front()->IDL;
2737cea80760SAndrew Litteken   Instruction *BeginRewritten = &*RewrittenBB->begin();
2738cea80760SAndrew Litteken   Instruction *EndRewritten = &*RewrittenBB->begin();
2739cea80760SAndrew Litteken   Region.NewFront = new (InstDataAllocator.Allocate()) IRInstructionData(
2740cea80760SAndrew Litteken       *BeginRewritten, InstructionClassifier.visit(*BeginRewritten), *IDL);
2741cea80760SAndrew Litteken   Region.NewBack = new (InstDataAllocator.Allocate()) IRInstructionData(
2742cea80760SAndrew Litteken       *EndRewritten, InstructionClassifier.visit(*EndRewritten), *IDL);
2743dae34463SAndrew Litteken 
2744dae34463SAndrew Litteken   // Insert the first IRInstructionData of the new region in front of the
2745dae34463SAndrew Litteken   // first IRInstructionData of the IRSimilarityCandidate.
2746dae34463SAndrew Litteken   IDL->insert(Region.Candidate->begin(), *Region.NewFront);
2747dae34463SAndrew Litteken   // Insert the first IRInstructionData of the new region after the
2748dae34463SAndrew Litteken   // last IRInstructionData of the IRSimilarityCandidate.
2749dae34463SAndrew Litteken   IDL->insert(Region.Candidate->end(), *Region.NewBack);
2750dae34463SAndrew Litteken   // Remove the IRInstructionData from the IRSimilarityCandidate.
2751dae34463SAndrew Litteken   IDL->erase(Region.Candidate->begin(), std::prev(Region.Candidate->end()));
2752dae34463SAndrew Litteken 
2753dae34463SAndrew Litteken   assert(RewrittenBB != nullptr &&
2754dae34463SAndrew Litteken          "Could not find a predecessor after extraction!");
2755dae34463SAndrew Litteken 
2756dae34463SAndrew Litteken   // Iterate over the new set of instructions to find the new call
2757dae34463SAndrew Litteken   // instruction.
2758dae34463SAndrew Litteken   for (Instruction &I : *RewrittenBB)
2759e6ae6233SAndrew Litteken     if (CallInst *CI = dyn_cast<CallInst>(&I)) {
2760e6ae6233SAndrew Litteken       if (Region.ExtractedFunction == CI->getCalledFunction())
2761dae34463SAndrew Litteken         Region.Call = CI;
2762e6ae6233SAndrew Litteken     } else if (LoadInst *LI = dyn_cast<LoadInst>(&I))
2763e6ae6233SAndrew Litteken       updateOutputMapping(Region, Outputs.getArrayRef(), LI);
2764dae34463SAndrew Litteken   Region.reattachCandidate();
2765dae34463SAndrew Litteken   return true;
2766dae34463SAndrew Litteken }
2767dae34463SAndrew Litteken 
doOutline(Module & M)2768dae34463SAndrew Litteken unsigned IROutliner::doOutline(Module &M) {
2769e6ae6233SAndrew Litteken   // Find the possible similarity sections.
277081d3ac0cSAndrew Litteken   InstructionClassifier.EnableBranches = !DisableBranches;
2771f5f377d1SAndrew Litteken   InstructionClassifier.EnableIndirectCalls = !DisableIndirectCalls;
27723785c1d0SAndrew Litteken   InstructionClassifier.EnableIntrinsics = !DisableIntrinsics;
27733785c1d0SAndrew Litteken 
2774dae34463SAndrew Litteken   IRSimilarityIdentifier &Identifier = getIRSI(M);
2775dae34463SAndrew Litteken   SimilarityGroupList &SimilarityCandidates = *Identifier.getSimilarity();
2776dae34463SAndrew Litteken 
2777dae34463SAndrew Litteken   // Sort them by size of extracted sections
2778dae34463SAndrew Litteken   unsigned OutlinedFunctionNum = 0;
2779dae34463SAndrew Litteken   // If we only have one SimilarityGroup in SimilarityCandidates, we do not have
2780dae34463SAndrew Litteken   // to sort them by the potential number of instructions to be outlined
2781dae34463SAndrew Litteken   if (SimilarityCandidates.size() > 1)
2782dae34463SAndrew Litteken     llvm::stable_sort(SimilarityCandidates,
2783dae34463SAndrew Litteken                       [](const std::vector<IRSimilarityCandidate> &LHS,
2784dae34463SAndrew Litteken                          const std::vector<IRSimilarityCandidate> &RHS) {
2785dae34463SAndrew Litteken                         return LHS[0].getLength() * LHS.size() >
2786dae34463SAndrew Litteken                                RHS[0].getLength() * RHS.size();
2787dae34463SAndrew Litteken                       });
2788c58d4c4bSAndrew Litteken   // Creating OutlinableGroups for each SimilarityCandidate to be used in
2789c58d4c4bSAndrew Litteken   // each of the following for loops to avoid making an allocator.
2790c58d4c4bSAndrew Litteken   std::vector<OutlinableGroup> PotentialGroups(SimilarityCandidates.size());
2791dae34463SAndrew Litteken 
2792c52bcf3aSAndrew Litteken   DenseSet<unsigned> NotSame;
2793c58d4c4bSAndrew Litteken   std::vector<OutlinableGroup *> NegativeCostGroups;
2794c58d4c4bSAndrew Litteken   std::vector<OutlinableRegion *> OutlinedRegions;
2795dae34463SAndrew Litteken   // Iterate over the possible sets of similarity.
2796c58d4c4bSAndrew Litteken   unsigned PotentialGroupIdx = 0;
2797dae34463SAndrew Litteken   for (SimilarityGroup &CandidateVec : SimilarityCandidates) {
2798c58d4c4bSAndrew Litteken     OutlinableGroup &CurrentGroup = PotentialGroups[PotentialGroupIdx++];
2799dae34463SAndrew Litteken 
2800dae34463SAndrew Litteken     // Remove entries that were previously outlined
2801dae34463SAndrew Litteken     pruneIncompatibleRegions(CandidateVec, CurrentGroup);
2802dae34463SAndrew Litteken 
2803dae34463SAndrew Litteken     // We pruned the number of regions to 0 to 1, meaning that it's not worth
2804dae34463SAndrew Litteken     // trying to outlined since there is no compatible similar instance of this
2805dae34463SAndrew Litteken     // code.
2806dae34463SAndrew Litteken     if (CurrentGroup.Regions.size() < 2)
2807dae34463SAndrew Litteken       continue;
2808dae34463SAndrew Litteken 
2809c52bcf3aSAndrew Litteken     // Determine if there are any values that are the same constant throughout
2810c52bcf3aSAndrew Litteken     // each section in the set.
2811c52bcf3aSAndrew Litteken     NotSame.clear();
2812c52bcf3aSAndrew Litteken     CurrentGroup.findSameConstants(NotSame);
2813c52bcf3aSAndrew Litteken 
2814c52bcf3aSAndrew Litteken     if (CurrentGroup.IgnoreGroup)
2815c52bcf3aSAndrew Litteken       continue;
2816c52bcf3aSAndrew Litteken 
2817c52bcf3aSAndrew Litteken     // Create a CodeExtractor for each outlinable region. Identify inputs and
2818c52bcf3aSAndrew Litteken     // outputs for each section using the code extractor and create the argument
2819c52bcf3aSAndrew Litteken     // types for the Aggregate Outlining Function.
2820c58d4c4bSAndrew Litteken     OutlinedRegions.clear();
2821dae34463SAndrew Litteken     for (OutlinableRegion *OS : CurrentGroup.Regions) {
2822dae34463SAndrew Litteken       // Break the outlinable region out of its parent BasicBlock into its own
2823dae34463SAndrew Litteken       // BasicBlocks (see function implementation).
2824dae34463SAndrew Litteken       OS->splitCandidate();
2825f564299fSAndrew Litteken 
2826f564299fSAndrew Litteken       // There's a chance that when the region is split, extra instructions are
2827f564299fSAndrew Litteken       // added to the region. This makes the region no longer viable
2828f564299fSAndrew Litteken       // to be split, so we ignore it for outlining.
2829f564299fSAndrew Litteken       if (!OS->CandidateSplit)
2830f564299fSAndrew Litteken         continue;
2831f564299fSAndrew Litteken 
283281d3ac0cSAndrew Litteken       SmallVector<BasicBlock *> BE;
2833dcc3e728SAndrew Litteken       DenseSet<BasicBlock *> BlocksInRegion;
2834dcc3e728SAndrew Litteken       OS->Candidate->getBasicBlocks(BlocksInRegion, BE);
2835dae34463SAndrew Litteken       OS->CE = new (ExtractorAllocator.Allocate())
2836dae34463SAndrew Litteken           CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false,
283787ec6f41SWilliam S. Moses                         false, nullptr, "outlined");
2838b1191c84SAndrew Litteken       findAddInputsOutputs(M, *OS, NotSame);
2839c52bcf3aSAndrew Litteken       if (!OS->IgnoreRegion)
2840c52bcf3aSAndrew Litteken         OutlinedRegions.push_back(OS);
2841c58d4c4bSAndrew Litteken 
2842c58d4c4bSAndrew Litteken       // We recombine the blocks together now that we have gathered all the
2843c58d4c4bSAndrew Litteken       // needed information.
2844c52bcf3aSAndrew Litteken       OS->reattachCandidate();
2845dae34463SAndrew Litteken     }
2846dae34463SAndrew Litteken 
2847c52bcf3aSAndrew Litteken     CurrentGroup.Regions = std::move(OutlinedRegions);
2848c52bcf3aSAndrew Litteken 
2849e6ae6233SAndrew Litteken     if (CurrentGroup.Regions.empty())
2850e6ae6233SAndrew Litteken       continue;
2851e6ae6233SAndrew Litteken 
28521e238025SAndrew Litteken     CurrentGroup.collectGVNStoreSets(M);
2853e6ae6233SAndrew Litteken 
28546df161a2SAndrew Litteken     if (CostModel)
28556df161a2SAndrew Litteken       findCostBenefit(M, CurrentGroup);
28566df161a2SAndrew Litteken 
2857c58d4c4bSAndrew Litteken     // If we are adhering to the cost model, skip those groups where the cost
2858c58d4c4bSAndrew Litteken     // outweighs the benefits.
28596df161a2SAndrew Litteken     if (CurrentGroup.Cost >= CurrentGroup.Benefit && CostModel) {
2860c58d4c4bSAndrew Litteken       OptimizationRemarkEmitter &ORE =
2861c58d4c4bSAndrew Litteken           getORE(*CurrentGroup.Regions[0]->Candidate->getFunction());
2862df4a931cSAndrew Litteken       ORE.emit([&]() {
2863df4a931cSAndrew Litteken         IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate;
2864df4a931cSAndrew Litteken         OptimizationRemarkMissed R(DEBUG_TYPE, "WouldNotDecreaseSize",
2865df4a931cSAndrew Litteken                                    C->frontInstruction());
2866df4a931cSAndrew Litteken         R << "did not outline "
2867df4a931cSAndrew Litteken           << ore::NV(std::to_string(CurrentGroup.Regions.size()))
2868df4a931cSAndrew Litteken           << " regions due to estimated increase of "
2869df4a931cSAndrew Litteken           << ore::NV("InstructionIncrease",
2870255a5077SDavid Sherwood                      CurrentGroup.Cost - CurrentGroup.Benefit)
2871df4a931cSAndrew Litteken           << " instructions at locations ";
2872df4a931cSAndrew Litteken         interleave(
2873df4a931cSAndrew Litteken             CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(),
2874df4a931cSAndrew Litteken             [&R](OutlinableRegion *Region) {
2875df4a931cSAndrew Litteken               R << ore::NV(
2876df4a931cSAndrew Litteken                   "DebugLoc",
2877df4a931cSAndrew Litteken                   Region->Candidate->frontInstruction()->getDebugLoc());
2878df4a931cSAndrew Litteken             },
2879df4a931cSAndrew Litteken             [&R]() { R << " "; });
2880df4a931cSAndrew Litteken         return R;
2881df4a931cSAndrew Litteken       });
28826df161a2SAndrew Litteken       continue;
28836df161a2SAndrew Litteken     }
28846df161a2SAndrew Litteken 
2885c58d4c4bSAndrew Litteken     NegativeCostGroups.push_back(&CurrentGroup);
2886c58d4c4bSAndrew Litteken   }
2887c58d4c4bSAndrew Litteken 
2888c58d4c4bSAndrew Litteken   ExtractorAllocator.DestroyAll();
2889c58d4c4bSAndrew Litteken 
2890c58d4c4bSAndrew Litteken   if (NegativeCostGroups.size() > 1)
2891c58d4c4bSAndrew Litteken     stable_sort(NegativeCostGroups,
2892c58d4c4bSAndrew Litteken                 [](const OutlinableGroup *LHS, const OutlinableGroup *RHS) {
2893c58d4c4bSAndrew Litteken                   return LHS->Benefit - LHS->Cost > RHS->Benefit - RHS->Cost;
2894c58d4c4bSAndrew Litteken                 });
2895c58d4c4bSAndrew Litteken 
2896c58d4c4bSAndrew Litteken   std::vector<Function *> FuncsToRemove;
2897c58d4c4bSAndrew Litteken   for (OutlinableGroup *CG : NegativeCostGroups) {
2898c58d4c4bSAndrew Litteken     OutlinableGroup &CurrentGroup = *CG;
2899c58d4c4bSAndrew Litteken 
2900c58d4c4bSAndrew Litteken     OutlinedRegions.clear();
2901c58d4c4bSAndrew Litteken     for (OutlinableRegion *Region : CurrentGroup.Regions) {
2902c58d4c4bSAndrew Litteken       // We check whether our region is compatible with what has already been
2903c58d4c4bSAndrew Litteken       // outlined, and whether we need to ignore this item.
2904c58d4c4bSAndrew Litteken       if (!isCompatibleWithAlreadyOutlinedCode(*Region))
2905c58d4c4bSAndrew Litteken         continue;
2906c58d4c4bSAndrew Litteken       OutlinedRegions.push_back(Region);
2907c58d4c4bSAndrew Litteken     }
2908c58d4c4bSAndrew Litteken 
2909c58d4c4bSAndrew Litteken     if (OutlinedRegions.size() < 2)
2910c58d4c4bSAndrew Litteken       continue;
2911c58d4c4bSAndrew Litteken 
2912c58d4c4bSAndrew Litteken     // Reestimate the cost and benefit of the OutlinableGroup. Continue only if
2913c58d4c4bSAndrew Litteken     // we are still outlining enough regions to make up for the added cost.
2914c58d4c4bSAndrew Litteken     CurrentGroup.Regions = std::move(OutlinedRegions);
2915c58d4c4bSAndrew Litteken     if (CostModel) {
2916c58d4c4bSAndrew Litteken       CurrentGroup.Benefit = 0;
2917c58d4c4bSAndrew Litteken       CurrentGroup.Cost = 0;
2918c58d4c4bSAndrew Litteken       findCostBenefit(M, CurrentGroup);
2919c58d4c4bSAndrew Litteken       if (CurrentGroup.Cost >= CurrentGroup.Benefit)
2920c58d4c4bSAndrew Litteken         continue;
2921c58d4c4bSAndrew Litteken     }
2922c58d4c4bSAndrew Litteken     OutlinedRegions.clear();
2923c58d4c4bSAndrew Litteken     for (OutlinableRegion *Region : CurrentGroup.Regions) {
2924c58d4c4bSAndrew Litteken       Region->splitCandidate();
2925c58d4c4bSAndrew Litteken       if (!Region->CandidateSplit)
2926c58d4c4bSAndrew Litteken         continue;
2927c58d4c4bSAndrew Litteken       OutlinedRegions.push_back(Region);
2928c58d4c4bSAndrew Litteken     }
2929c58d4c4bSAndrew Litteken 
2930c58d4c4bSAndrew Litteken     CurrentGroup.Regions = std::move(OutlinedRegions);
2931c58d4c4bSAndrew Litteken     if (CurrentGroup.Regions.size() < 2) {
2932c58d4c4bSAndrew Litteken       for (OutlinableRegion *R : CurrentGroup.Regions)
2933c58d4c4bSAndrew Litteken         R->reattachCandidate();
2934c58d4c4bSAndrew Litteken       continue;
2935c58d4c4bSAndrew Litteken     }
2936c58d4c4bSAndrew Litteken 
29376df161a2SAndrew Litteken     LLVM_DEBUG(dbgs() << "Outlining regions with cost " << CurrentGroup.Cost
29386df161a2SAndrew Litteken                       << " and benefit " << CurrentGroup.Benefit << "\n");
29396df161a2SAndrew Litteken 
2940c52bcf3aSAndrew Litteken     // Create functions out of all the sections, and mark them as outlined.
2941c52bcf3aSAndrew Litteken     OutlinedRegions.clear();
2942dae34463SAndrew Litteken     for (OutlinableRegion *OS : CurrentGroup.Regions) {
294381d3ac0cSAndrew Litteken       SmallVector<BasicBlock *> BE;
2944dcc3e728SAndrew Litteken       DenseSet<BasicBlock *> BlocksInRegion;
2945dcc3e728SAndrew Litteken       OS->Candidate->getBasicBlocks(BlocksInRegion, BE);
2946c58d4c4bSAndrew Litteken       OS->CE = new (ExtractorAllocator.Allocate())
2947c58d4c4bSAndrew Litteken           CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false,
294887ec6f41SWilliam S. Moses                         false, nullptr, "outlined");
2949dae34463SAndrew Litteken       bool FunctionOutlined = extractSection(*OS);
2950dae34463SAndrew Litteken       if (FunctionOutlined) {
2951dae34463SAndrew Litteken         unsigned StartIdx = OS->Candidate->getStartIdx();
2952dae34463SAndrew Litteken         unsigned EndIdx = OS->Candidate->getEndIdx();
2953dae34463SAndrew Litteken         for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2954dae34463SAndrew Litteken           Outlined.insert(Idx);
2955dae34463SAndrew Litteken 
2956dae34463SAndrew Litteken         OutlinedRegions.push_back(OS);
2957dae34463SAndrew Litteken       }
2958dae34463SAndrew Litteken     }
2959dae34463SAndrew Litteken 
2960df4a931cSAndrew Litteken     LLVM_DEBUG(dbgs() << "Outlined " << OutlinedRegions.size()
2961df4a931cSAndrew Litteken                       << " with benefit " << CurrentGroup.Benefit
2962df4a931cSAndrew Litteken                       << " and cost " << CurrentGroup.Cost << "\n");
2963df4a931cSAndrew Litteken 
2964dae34463SAndrew Litteken     CurrentGroup.Regions = std::move(OutlinedRegions);
29657c6f28a4SAndrew Litteken 
29667c6f28a4SAndrew Litteken     if (CurrentGroup.Regions.empty())
29677c6f28a4SAndrew Litteken       continue;
29687c6f28a4SAndrew Litteken 
2969df4a931cSAndrew Litteken     OptimizationRemarkEmitter &ORE =
2970df4a931cSAndrew Litteken         getORE(*CurrentGroup.Regions[0]->Call->getFunction());
2971df4a931cSAndrew Litteken     ORE.emit([&]() {
2972df4a931cSAndrew Litteken       IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate;
2973df4a931cSAndrew Litteken       OptimizationRemark R(DEBUG_TYPE, "Outlined", C->front()->Inst);
2974df4a931cSAndrew Litteken       R << "outlined " << ore::NV(std::to_string(CurrentGroup.Regions.size()))
2975df4a931cSAndrew Litteken         << " regions with decrease of "
2976255a5077SDavid Sherwood         << ore::NV("Benefit", CurrentGroup.Benefit - CurrentGroup.Cost)
2977df4a931cSAndrew Litteken         << " instructions at locations ";
2978df4a931cSAndrew Litteken       interleave(
2979df4a931cSAndrew Litteken           CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(),
2980df4a931cSAndrew Litteken           [&R](OutlinableRegion *Region) {
2981df4a931cSAndrew Litteken             R << ore::NV("DebugLoc",
2982df4a931cSAndrew Litteken                          Region->Candidate->frontInstruction()->getDebugLoc());
2983df4a931cSAndrew Litteken           },
2984df4a931cSAndrew Litteken           [&R]() { R << " "; });
2985df4a931cSAndrew Litteken       return R;
2986df4a931cSAndrew Litteken     });
2987df4a931cSAndrew Litteken 
29887c6f28a4SAndrew Litteken     deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove,
29897c6f28a4SAndrew Litteken                                  OutlinedFunctionNum);
2990dae34463SAndrew Litteken   }
2991dae34463SAndrew Litteken 
29927c6f28a4SAndrew Litteken   for (Function *F : FuncsToRemove)
29937c6f28a4SAndrew Litteken     F->eraseFromParent();
29947c6f28a4SAndrew Litteken 
2995dae34463SAndrew Litteken   return OutlinedFunctionNum;
2996dae34463SAndrew Litteken }
2997dae34463SAndrew Litteken 
run(Module & M)29986df161a2SAndrew Litteken bool IROutliner::run(Module &M) {
29996df161a2SAndrew Litteken   CostModel = !NoCostModel;
3000fe431103SAndrew Litteken   OutlineFromLinkODRs = EnableLinkOnceODRIROutlining;
30016df161a2SAndrew Litteken 
30026df161a2SAndrew Litteken   return doOutline(M) > 0;
30036df161a2SAndrew Litteken }
3004dae34463SAndrew Litteken 
3005dae34463SAndrew Litteken // Pass Manager Boilerplate
30069b8b1645SBenjamin Kramer namespace {
3007dae34463SAndrew Litteken class IROutlinerLegacyPass : public ModulePass {
3008dae34463SAndrew Litteken public:
3009dae34463SAndrew Litteken   static char ID;
IROutlinerLegacyPass()3010dae34463SAndrew Litteken   IROutlinerLegacyPass() : ModulePass(ID) {
3011dae34463SAndrew Litteken     initializeIROutlinerLegacyPassPass(*PassRegistry::getPassRegistry());
3012dae34463SAndrew Litteken   }
3013dae34463SAndrew Litteken 
getAnalysisUsage(AnalysisUsage & AU) const3014dae34463SAndrew Litteken   void getAnalysisUsage(AnalysisUsage &AU) const override {
3015df4a931cSAndrew Litteken     AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
3016dae34463SAndrew Litteken     AU.addRequired<TargetTransformInfoWrapperPass>();
3017dae34463SAndrew Litteken     AU.addRequired<IRSimilarityIdentifierWrapperPass>();
3018dae34463SAndrew Litteken   }
3019dae34463SAndrew Litteken 
3020dae34463SAndrew Litteken   bool runOnModule(Module &M) override;
3021dae34463SAndrew Litteken };
30229b8b1645SBenjamin Kramer } // namespace
3023dae34463SAndrew Litteken 
runOnModule(Module & M)3024dae34463SAndrew Litteken bool IROutlinerLegacyPass::runOnModule(Module &M) {
3025dae34463SAndrew Litteken   if (skipModule(M))
3026dae34463SAndrew Litteken     return false;
3027dae34463SAndrew Litteken 
3028df4a931cSAndrew Litteken   std::unique_ptr<OptimizationRemarkEmitter> ORE;
3029df4a931cSAndrew Litteken   auto GORE = [&ORE](Function &F) -> OptimizationRemarkEmitter & {
3030df4a931cSAndrew Litteken     ORE.reset(new OptimizationRemarkEmitter(&F));
3031bce1bf0eSKazu Hirata     return *ORE;
3032df4a931cSAndrew Litteken   };
3033df4a931cSAndrew Litteken 
3034dae34463SAndrew Litteken   auto GTTI = [this](Function &F) -> TargetTransformInfo & {
3035dae34463SAndrew Litteken     return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
3036dae34463SAndrew Litteken   };
3037dae34463SAndrew Litteken 
3038dae34463SAndrew Litteken   auto GIRSI = [this](Module &) -> IRSimilarityIdentifier & {
3039dae34463SAndrew Litteken     return this->getAnalysis<IRSimilarityIdentifierWrapperPass>().getIRSI();
3040dae34463SAndrew Litteken   };
3041dae34463SAndrew Litteken 
3042df4a931cSAndrew Litteken   return IROutliner(GTTI, GIRSI, GORE).run(M);
3043dae34463SAndrew Litteken }
3044dae34463SAndrew Litteken 
run(Module & M,ModuleAnalysisManager & AM)3045dae34463SAndrew Litteken PreservedAnalyses IROutlinerPass::run(Module &M, ModuleAnalysisManager &AM) {
3046dae34463SAndrew Litteken   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
3047dae34463SAndrew Litteken 
3048dae34463SAndrew Litteken   std::function<TargetTransformInfo &(Function &)> GTTI =
3049dae34463SAndrew Litteken       [&FAM](Function &F) -> TargetTransformInfo & {
3050dae34463SAndrew Litteken     return FAM.getResult<TargetIRAnalysis>(F);
3051dae34463SAndrew Litteken   };
3052dae34463SAndrew Litteken 
3053dae34463SAndrew Litteken   std::function<IRSimilarityIdentifier &(Module &)> GIRSI =
3054dae34463SAndrew Litteken       [&AM](Module &M) -> IRSimilarityIdentifier & {
3055dae34463SAndrew Litteken     return AM.getResult<IRSimilarityAnalysis>(M);
3056dae34463SAndrew Litteken   };
3057dae34463SAndrew Litteken 
3058df4a931cSAndrew Litteken   std::unique_ptr<OptimizationRemarkEmitter> ORE;
3059df4a931cSAndrew Litteken   std::function<OptimizationRemarkEmitter &(Function &)> GORE =
3060df4a931cSAndrew Litteken       [&ORE](Function &F) -> OptimizationRemarkEmitter & {
3061df4a931cSAndrew Litteken     ORE.reset(new OptimizationRemarkEmitter(&F));
3062bce1bf0eSKazu Hirata     return *ORE;
3063df4a931cSAndrew Litteken   };
3064df4a931cSAndrew Litteken 
3065df4a931cSAndrew Litteken   if (IROutliner(GTTI, GIRSI, GORE).run(M))
3066dae34463SAndrew Litteken     return PreservedAnalyses::none();
3067dae34463SAndrew Litteken   return PreservedAnalyses::all();
3068dae34463SAndrew Litteken }
3069dae34463SAndrew Litteken 
3070dae34463SAndrew Litteken char IROutlinerLegacyPass::ID = 0;
3071dae34463SAndrew Litteken INITIALIZE_PASS_BEGIN(IROutlinerLegacyPass, "iroutliner", "IR Outliner", false,
3072dae34463SAndrew Litteken                       false)
INITIALIZE_PASS_DEPENDENCY(IRSimilarityIdentifierWrapperPass)3073dae34463SAndrew Litteken INITIALIZE_PASS_DEPENDENCY(IRSimilarityIdentifierWrapperPass)
3074df4a931cSAndrew Litteken INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
3075dae34463SAndrew Litteken INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
3076dae34463SAndrew Litteken INITIALIZE_PASS_END(IROutlinerLegacyPass, "iroutliner", "IR Outliner", false,
3077dae34463SAndrew Litteken                     false)
3078dae34463SAndrew Litteken 
3079dae34463SAndrew Litteken ModulePass *llvm::createIROutlinerPass() { return new IROutlinerLegacyPass(); }
3080