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