xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/IPO/IROutliner.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1e8d8bef9SDimitry Andric //===- IROutliner.cpp -- Outline Similar Regions ----------------*- C++ -*-===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric ///
9e8d8bef9SDimitry Andric /// \file
10e8d8bef9SDimitry Andric // Implementation for the IROutliner which is used by the IROutliner Pass.
11e8d8bef9SDimitry Andric //
12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
13e8d8bef9SDimitry Andric 
14e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/IROutliner.h"
15e8d8bef9SDimitry Andric #include "llvm/Analysis/IRSimilarityIdentifier.h"
16e8d8bef9SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
17e8d8bef9SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
18e8d8bef9SDimitry Andric #include "llvm/IR/Attributes.h"
19fe6060f1SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
20fe6060f1SDimitry Andric #include "llvm/IR/DIBuilder.h"
21*349cc55cSDimitry Andric #include "llvm/IR/Dominators.h"
22fe6060f1SDimitry Andric #include "llvm/IR/Mangler.h"
23e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h"
24e8d8bef9SDimitry Andric #include "llvm/InitializePasses.h"
25e8d8bef9SDimitry Andric #include "llvm/Pass.h"
26e8d8bef9SDimitry Andric #include "llvm/Support/CommandLine.h"
27e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO.h"
28e8d8bef9SDimitry Andric #include <map>
29e8d8bef9SDimitry Andric #include <set>
30e8d8bef9SDimitry Andric #include <vector>
31e8d8bef9SDimitry Andric 
32e8d8bef9SDimitry Andric #define DEBUG_TYPE "iroutliner"
33e8d8bef9SDimitry Andric 
34e8d8bef9SDimitry Andric using namespace llvm;
35e8d8bef9SDimitry Andric using namespace IRSimilarity;
36e8d8bef9SDimitry Andric 
37*349cc55cSDimitry Andric // A command flag to be used for debugging to exclude branches from similarity
38*349cc55cSDimitry Andric // matching and outlining.
39*349cc55cSDimitry Andric extern cl::opt<bool> DisableBranches;
40*349cc55cSDimitry Andric 
41e8d8bef9SDimitry Andric // Set to true if the user wants the ir outliner to run on linkonceodr linkage
42e8d8bef9SDimitry Andric // functions. This is false by default because the linker can dedupe linkonceodr
43e8d8bef9SDimitry Andric // functions. Since the outliner is confined to a single module (modulo LTO),
44e8d8bef9SDimitry Andric // this is off by default. It should, however, be the default behavior in
45e8d8bef9SDimitry Andric // LTO.
46e8d8bef9SDimitry Andric static cl::opt<bool> EnableLinkOnceODRIROutlining(
47e8d8bef9SDimitry Andric     "enable-linkonceodr-ir-outlining", cl::Hidden,
48e8d8bef9SDimitry Andric     cl::desc("Enable the IR outliner on linkonceodr functions"),
49e8d8bef9SDimitry Andric     cl::init(false));
50e8d8bef9SDimitry Andric 
51e8d8bef9SDimitry Andric // This is a debug option to test small pieces of code to ensure that outlining
52e8d8bef9SDimitry Andric // works correctly.
53e8d8bef9SDimitry Andric static cl::opt<bool> NoCostModel(
54e8d8bef9SDimitry Andric     "ir-outlining-no-cost", cl::init(false), cl::ReallyHidden,
55e8d8bef9SDimitry Andric     cl::desc("Debug option to outline greedily, without restriction that "
56e8d8bef9SDimitry Andric              "calculated benefit outweighs cost"));
57e8d8bef9SDimitry Andric 
58e8d8bef9SDimitry Andric /// The OutlinableGroup holds all the overarching information for outlining
59e8d8bef9SDimitry Andric /// a set of regions that are structurally similar to one another, such as the
60e8d8bef9SDimitry Andric /// types of the overall function, the output blocks, the sets of stores needed
61e8d8bef9SDimitry Andric /// and a list of the different regions. This information is used in the
62e8d8bef9SDimitry Andric /// deduplication of extracted regions with the same structure.
63e8d8bef9SDimitry Andric struct OutlinableGroup {
64e8d8bef9SDimitry Andric   /// The sections that could be outlined
65e8d8bef9SDimitry Andric   std::vector<OutlinableRegion *> Regions;
66e8d8bef9SDimitry Andric 
67e8d8bef9SDimitry Andric   /// The argument types for the function created as the overall function to
68e8d8bef9SDimitry Andric   /// replace the extracted function for each region.
69e8d8bef9SDimitry Andric   std::vector<Type *> ArgumentTypes;
70e8d8bef9SDimitry Andric   /// The FunctionType for the overall function.
71e8d8bef9SDimitry Andric   FunctionType *OutlinedFunctionType = nullptr;
72e8d8bef9SDimitry Andric   /// The Function for the collective overall function.
73e8d8bef9SDimitry Andric   Function *OutlinedFunction = nullptr;
74e8d8bef9SDimitry Andric 
75e8d8bef9SDimitry Andric   /// Flag for whether we should not consider this group of OutlinableRegions
76e8d8bef9SDimitry Andric   /// for extraction.
77e8d8bef9SDimitry Andric   bool IgnoreGroup = false;
78e8d8bef9SDimitry Andric 
79*349cc55cSDimitry Andric   /// The return blocks for the overall function.
80*349cc55cSDimitry Andric   DenseMap<Value *, BasicBlock *> EndBBs;
81*349cc55cSDimitry Andric 
82*349cc55cSDimitry Andric   /// The PHIBlocks with their corresponding return block based on the return
83*349cc55cSDimitry Andric   /// value as the key.
84*349cc55cSDimitry Andric   DenseMap<Value *, BasicBlock *> PHIBlocks;
85e8d8bef9SDimitry Andric 
86e8d8bef9SDimitry Andric   /// A set containing the different GVN store sets needed. Each array contains
87e8d8bef9SDimitry Andric   /// a sorted list of the different values that need to be stored into output
88e8d8bef9SDimitry Andric   /// registers.
89e8d8bef9SDimitry Andric   DenseSet<ArrayRef<unsigned>> OutputGVNCombinations;
90e8d8bef9SDimitry Andric 
91e8d8bef9SDimitry Andric   /// Flag for whether the \ref ArgumentTypes have been defined after the
92e8d8bef9SDimitry Andric   /// extraction of the first region.
93e8d8bef9SDimitry Andric   bool InputTypesSet = false;
94e8d8bef9SDimitry Andric 
95e8d8bef9SDimitry Andric   /// The number of input values in \ref ArgumentTypes.  Anything after this
96e8d8bef9SDimitry Andric   /// index in ArgumentTypes is an output argument.
97e8d8bef9SDimitry Andric   unsigned NumAggregateInputs = 0;
98e8d8bef9SDimitry Andric 
99*349cc55cSDimitry Andric   /// The mapping of the canonical numbering of the values in outlined sections
100*349cc55cSDimitry Andric   /// to specific arguments.
101*349cc55cSDimitry Andric   DenseMap<unsigned, unsigned> CanonicalNumberToAggArg;
102*349cc55cSDimitry Andric 
103*349cc55cSDimitry Andric   /// The number of branches in the region target a basic block that is outside
104*349cc55cSDimitry Andric   /// of the region.
105*349cc55cSDimitry Andric   unsigned BranchesToOutside = 0;
106*349cc55cSDimitry Andric 
107e8d8bef9SDimitry Andric   /// The number of instructions that will be outlined by extracting \ref
108e8d8bef9SDimitry Andric   /// Regions.
109e8d8bef9SDimitry Andric   InstructionCost Benefit = 0;
110e8d8bef9SDimitry Andric   /// The number of added instructions needed for the outlining of the \ref
111e8d8bef9SDimitry Andric   /// Regions.
112e8d8bef9SDimitry Andric   InstructionCost Cost = 0;
113e8d8bef9SDimitry Andric 
114e8d8bef9SDimitry Andric   /// The argument that needs to be marked with the swifterr attribute.  If not
115e8d8bef9SDimitry Andric   /// needed, there is no value.
116e8d8bef9SDimitry Andric   Optional<unsigned> SwiftErrorArgument;
117e8d8bef9SDimitry Andric 
118e8d8bef9SDimitry Andric   /// For the \ref Regions, we look at every Value.  If it is a constant,
119e8d8bef9SDimitry Andric   /// we check whether it is the same in Region.
120e8d8bef9SDimitry Andric   ///
121e8d8bef9SDimitry Andric   /// \param [in,out] NotSame contains the global value numbers where the
122e8d8bef9SDimitry Andric   /// constant is not always the same, and must be passed in as an argument.
123e8d8bef9SDimitry Andric   void findSameConstants(DenseSet<unsigned> &NotSame);
124e8d8bef9SDimitry Andric 
125e8d8bef9SDimitry Andric   /// For the regions, look at each set of GVN stores needed and account for
126e8d8bef9SDimitry Andric   /// each combination.  Add an argument to the argument types if there is
127e8d8bef9SDimitry Andric   /// more than one combination.
128e8d8bef9SDimitry Andric   ///
129e8d8bef9SDimitry Andric   /// \param [in] M - The module we are outlining from.
130e8d8bef9SDimitry Andric   void collectGVNStoreSets(Module &M);
131e8d8bef9SDimitry Andric };
132e8d8bef9SDimitry Andric 
133e8d8bef9SDimitry Andric /// Move the contents of \p SourceBB to before the last instruction of \p
134e8d8bef9SDimitry Andric /// TargetBB.
135e8d8bef9SDimitry Andric /// \param SourceBB - the BasicBlock to pull Instructions from.
136e8d8bef9SDimitry Andric /// \param TargetBB - the BasicBlock to put Instruction into.
137e8d8bef9SDimitry Andric static void moveBBContents(BasicBlock &SourceBB, BasicBlock &TargetBB) {
138*349cc55cSDimitry Andric   for (Instruction &I : llvm::make_early_inc_range(SourceBB))
139*349cc55cSDimitry Andric     I.moveBefore(TargetBB, TargetBB.end());
140e8d8bef9SDimitry Andric }
141*349cc55cSDimitry Andric 
142*349cc55cSDimitry Andric /// A function to sort the keys of \p Map, which must be a mapping of constant
143*349cc55cSDimitry Andric /// values to basic blocks and return it in \p SortedKeys
144*349cc55cSDimitry Andric ///
145*349cc55cSDimitry Andric /// \param SortedKeys - The vector the keys will be return in and sorted.
146*349cc55cSDimitry Andric /// \param Map - The DenseMap containing keys to sort.
147*349cc55cSDimitry Andric static void getSortedConstantKeys(std::vector<Value *> &SortedKeys,
148*349cc55cSDimitry Andric                                   DenseMap<Value *, BasicBlock *> &Map) {
149*349cc55cSDimitry Andric   for (auto &VtoBB : Map)
150*349cc55cSDimitry Andric     SortedKeys.push_back(VtoBB.first);
151*349cc55cSDimitry Andric 
152*349cc55cSDimitry Andric   stable_sort(SortedKeys, [](const Value *LHS, const Value *RHS) {
153*349cc55cSDimitry Andric     const ConstantInt *LHSC = dyn_cast<ConstantInt>(LHS);
154*349cc55cSDimitry Andric     const ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS);
155*349cc55cSDimitry Andric     assert(RHSC && "Not a constant integer in return value?");
156*349cc55cSDimitry Andric     assert(LHSC && "Not a constant integer in return value?");
157*349cc55cSDimitry Andric 
158*349cc55cSDimitry Andric     return LHSC->getLimitedValue() < RHSC->getLimitedValue();
159*349cc55cSDimitry Andric   });
160*349cc55cSDimitry Andric }
161*349cc55cSDimitry Andric 
162*349cc55cSDimitry Andric Value *OutlinableRegion::findCorrespondingValueIn(const OutlinableRegion &Other,
163*349cc55cSDimitry Andric                                                   Value *V) {
164*349cc55cSDimitry Andric   Optional<unsigned> GVN = Candidate->getGVN(V);
165*349cc55cSDimitry Andric   assert(GVN.hasValue() && "No GVN for incoming value");
166*349cc55cSDimitry Andric   Optional<unsigned> CanonNum = Candidate->getCanonicalNum(*GVN);
167*349cc55cSDimitry Andric   Optional<unsigned> FirstGVN = Other.Candidate->fromCanonicalNum(*CanonNum);
168*349cc55cSDimitry Andric   Optional<Value *> FoundValueOpt = Other.Candidate->fromGVN(*FirstGVN);
169*349cc55cSDimitry Andric   return FoundValueOpt.getValueOr(nullptr);
170e8d8bef9SDimitry Andric }
171e8d8bef9SDimitry Andric 
172e8d8bef9SDimitry Andric void OutlinableRegion::splitCandidate() {
173e8d8bef9SDimitry Andric   assert(!CandidateSplit && "Candidate already split!");
174e8d8bef9SDimitry Andric 
175*349cc55cSDimitry Andric   Instruction *BackInst = Candidate->backInstruction();
176*349cc55cSDimitry Andric 
177*349cc55cSDimitry Andric   Instruction *EndInst = nullptr;
178*349cc55cSDimitry Andric   // Check whether the last instruction is a terminator, if it is, we do
179*349cc55cSDimitry Andric   // not split on the following instruction. We leave the block as it is.  We
180*349cc55cSDimitry Andric   // also check that this is not the last instruction in the Module, otherwise
181*349cc55cSDimitry Andric   // the check for whether the current following instruction matches the
182*349cc55cSDimitry Andric   // previously recorded instruction will be incorrect.
183*349cc55cSDimitry Andric   if (!BackInst->isTerminator() ||
184*349cc55cSDimitry Andric       BackInst->getParent() != &BackInst->getFunction()->back()) {
185*349cc55cSDimitry Andric     EndInst = Candidate->end()->Inst;
186*349cc55cSDimitry Andric     assert(EndInst && "Expected an end instruction?");
187*349cc55cSDimitry Andric   }
188*349cc55cSDimitry Andric 
189*349cc55cSDimitry Andric   // We check if the current instruction following the last instruction in the
190*349cc55cSDimitry Andric   // region is the same as the recorded instruction following the last
191*349cc55cSDimitry Andric   // instruction. If they do not match, there could be problems in rewriting
192*349cc55cSDimitry Andric   // the program after outlining, so we ignore it.
193*349cc55cSDimitry Andric   if (!BackInst->isTerminator() &&
194*349cc55cSDimitry Andric       EndInst != BackInst->getNextNonDebugInstruction())
195*349cc55cSDimitry Andric     return;
196*349cc55cSDimitry Andric 
197e8d8bef9SDimitry Andric   Instruction *StartInst = (*Candidate->begin()).Inst;
198*349cc55cSDimitry Andric   assert(StartInst && "Expected a start instruction?");
199e8d8bef9SDimitry Andric   StartBB = StartInst->getParent();
200e8d8bef9SDimitry Andric   PrevBB = StartBB;
201e8d8bef9SDimitry Andric 
202e8d8bef9SDimitry Andric   // The basic block gets split like so:
203e8d8bef9SDimitry Andric   // block:                 block:
204e8d8bef9SDimitry Andric   //   inst1                  inst1
205e8d8bef9SDimitry Andric   //   inst2                  inst2
206e8d8bef9SDimitry Andric   //   region1               br block_to_outline
207e8d8bef9SDimitry Andric   //   region2              block_to_outline:
208e8d8bef9SDimitry Andric   //   region3          ->    region1
209e8d8bef9SDimitry Andric   //   region4                region2
210e8d8bef9SDimitry Andric   //   inst3                  region3
211e8d8bef9SDimitry Andric   //   inst4                  region4
212e8d8bef9SDimitry Andric   //                          br block_after_outline
213e8d8bef9SDimitry Andric   //                        block_after_outline:
214e8d8bef9SDimitry Andric   //                          inst3
215e8d8bef9SDimitry Andric   //                          inst4
216e8d8bef9SDimitry Andric 
217e8d8bef9SDimitry Andric   std::string OriginalName = PrevBB->getName().str();
218e8d8bef9SDimitry Andric 
219e8d8bef9SDimitry Andric   StartBB = PrevBB->splitBasicBlock(StartInst, OriginalName + "_to_outline");
220*349cc55cSDimitry Andric   PrevBB->replaceSuccessorsPhiUsesWith(PrevBB, StartBB);
221e8d8bef9SDimitry Andric 
222e8d8bef9SDimitry Andric   CandidateSplit = true;
223*349cc55cSDimitry Andric   if (!BackInst->isTerminator()) {
224*349cc55cSDimitry Andric     EndBB = EndInst->getParent();
225*349cc55cSDimitry Andric     FollowBB = EndBB->splitBasicBlock(EndInst, OriginalName + "_after_outline");
226*349cc55cSDimitry Andric     EndBB->replaceSuccessorsPhiUsesWith(EndBB, FollowBB);
227*349cc55cSDimitry Andric     FollowBB->replaceSuccessorsPhiUsesWith(PrevBB, FollowBB);
228*349cc55cSDimitry Andric     return;
229*349cc55cSDimitry Andric   }
230*349cc55cSDimitry Andric 
231*349cc55cSDimitry Andric   EndBB = BackInst->getParent();
232*349cc55cSDimitry Andric   EndsInBranch = true;
233*349cc55cSDimitry Andric   FollowBB = nullptr;
234e8d8bef9SDimitry Andric }
235e8d8bef9SDimitry Andric 
236e8d8bef9SDimitry Andric void OutlinableRegion::reattachCandidate() {
237e8d8bef9SDimitry Andric   assert(CandidateSplit && "Candidate is not split!");
238e8d8bef9SDimitry Andric 
239e8d8bef9SDimitry Andric   // The basic block gets reattached like so:
240e8d8bef9SDimitry Andric   // block:                        block:
241e8d8bef9SDimitry Andric   //   inst1                         inst1
242e8d8bef9SDimitry Andric   //   inst2                         inst2
243e8d8bef9SDimitry Andric   //   br block_to_outline           region1
244e8d8bef9SDimitry Andric   // block_to_outline:        ->     region2
245e8d8bef9SDimitry Andric   //   region1                       region3
246e8d8bef9SDimitry Andric   //   region2                       region4
247e8d8bef9SDimitry Andric   //   region3                       inst3
248e8d8bef9SDimitry Andric   //   region4                       inst4
249e8d8bef9SDimitry Andric   //   br block_after_outline
250e8d8bef9SDimitry Andric   // block_after_outline:
251e8d8bef9SDimitry Andric   //   inst3
252e8d8bef9SDimitry Andric   //   inst4
253e8d8bef9SDimitry Andric   assert(StartBB != nullptr && "StartBB for Candidate is not defined!");
254e8d8bef9SDimitry Andric 
255e8d8bef9SDimitry Andric   // StartBB should only have one predecessor since we put an unconditional
256e8d8bef9SDimitry Andric   // branch at the end of PrevBB when we split the BasicBlock.
257e8d8bef9SDimitry Andric   PrevBB = StartBB->getSinglePredecessor();
258e8d8bef9SDimitry Andric   assert(PrevBB != nullptr &&
259e8d8bef9SDimitry Andric          "No Predecessor for the region start basic block!");
260e8d8bef9SDimitry Andric 
261e8d8bef9SDimitry Andric   assert(PrevBB->getTerminator() && "Terminator removed from PrevBB!");
262e8d8bef9SDimitry Andric   PrevBB->getTerminator()->eraseFromParent();
263e8d8bef9SDimitry Andric 
264e8d8bef9SDimitry Andric   moveBBContents(*StartBB, *PrevBB);
265e8d8bef9SDimitry Andric 
266e8d8bef9SDimitry Andric   BasicBlock *PlacementBB = PrevBB;
267e8d8bef9SDimitry Andric   if (StartBB != EndBB)
268e8d8bef9SDimitry Andric     PlacementBB = EndBB;
269*349cc55cSDimitry Andric   if (!EndsInBranch && PlacementBB->getUniqueSuccessor() != nullptr) {
270*349cc55cSDimitry Andric     assert(FollowBB != nullptr && "FollowBB for Candidate is not defined!");
271*349cc55cSDimitry Andric     assert(PlacementBB->getTerminator() && "Terminator removed from EndBB!");
272*349cc55cSDimitry Andric     PlacementBB->getTerminator()->eraseFromParent();
273e8d8bef9SDimitry Andric     moveBBContents(*FollowBB, *PlacementBB);
274*349cc55cSDimitry Andric     PlacementBB->replaceSuccessorsPhiUsesWith(FollowBB, PlacementBB);
275*349cc55cSDimitry Andric     FollowBB->eraseFromParent();
276*349cc55cSDimitry Andric   }
277e8d8bef9SDimitry Andric 
278e8d8bef9SDimitry Andric   PrevBB->replaceSuccessorsPhiUsesWith(StartBB, PrevBB);
279e8d8bef9SDimitry Andric   StartBB->eraseFromParent();
280e8d8bef9SDimitry Andric 
281e8d8bef9SDimitry Andric   // Make sure to save changes back to the StartBB.
282e8d8bef9SDimitry Andric   StartBB = PrevBB;
283e8d8bef9SDimitry Andric   EndBB = nullptr;
284e8d8bef9SDimitry Andric   PrevBB = nullptr;
285e8d8bef9SDimitry Andric   FollowBB = nullptr;
286e8d8bef9SDimitry Andric 
287e8d8bef9SDimitry Andric   CandidateSplit = false;
288e8d8bef9SDimitry Andric }
289e8d8bef9SDimitry Andric 
290e8d8bef9SDimitry Andric /// Find whether \p V matches the Constants previously found for the \p GVN.
291e8d8bef9SDimitry Andric ///
292e8d8bef9SDimitry Andric /// \param V - The value to check for consistency.
293e8d8bef9SDimitry Andric /// \param GVN - The global value number assigned to \p V.
294e8d8bef9SDimitry Andric /// \param GVNToConstant - The mapping of global value number to Constants.
295e8d8bef9SDimitry Andric /// \returns true if the Value matches the Constant mapped to by V and false if
296e8d8bef9SDimitry Andric /// it \p V is a Constant but does not match.
297e8d8bef9SDimitry Andric /// \returns None if \p V is not a Constant.
298e8d8bef9SDimitry Andric static Optional<bool>
299e8d8bef9SDimitry Andric constantMatches(Value *V, unsigned GVN,
300e8d8bef9SDimitry Andric                 DenseMap<unsigned, Constant *> &GVNToConstant) {
301e8d8bef9SDimitry Andric   // See if we have a constants
302e8d8bef9SDimitry Andric   Constant *CST = dyn_cast<Constant>(V);
303e8d8bef9SDimitry Andric   if (!CST)
304e8d8bef9SDimitry Andric     return None;
305e8d8bef9SDimitry Andric 
306e8d8bef9SDimitry Andric   // Holds a mapping from a global value number to a Constant.
307e8d8bef9SDimitry Andric   DenseMap<unsigned, Constant *>::iterator GVNToConstantIt;
308e8d8bef9SDimitry Andric   bool Inserted;
309e8d8bef9SDimitry Andric 
310e8d8bef9SDimitry Andric 
311e8d8bef9SDimitry Andric   // If we have a constant, try to make a new entry in the GVNToConstant.
312e8d8bef9SDimitry Andric   std::tie(GVNToConstantIt, Inserted) =
313e8d8bef9SDimitry Andric       GVNToConstant.insert(std::make_pair(GVN, CST));
314e8d8bef9SDimitry Andric   // If it was found and is not equal, it is not the same. We do not
315e8d8bef9SDimitry Andric   // handle this case yet, and exit early.
316e8d8bef9SDimitry Andric   if (Inserted || (GVNToConstantIt->second == CST))
317e8d8bef9SDimitry Andric     return true;
318e8d8bef9SDimitry Andric 
319e8d8bef9SDimitry Andric   return false;
320e8d8bef9SDimitry Andric }
321e8d8bef9SDimitry Andric 
322e8d8bef9SDimitry Andric InstructionCost OutlinableRegion::getBenefit(TargetTransformInfo &TTI) {
323e8d8bef9SDimitry Andric   InstructionCost Benefit = 0;
324e8d8bef9SDimitry Andric 
325e8d8bef9SDimitry Andric   // Estimate the benefit of outlining a specific sections of the program.  We
326e8d8bef9SDimitry Andric   // delegate mostly this task to the TargetTransformInfo so that if the target
327e8d8bef9SDimitry Andric   // has specific changes, we can have a more accurate estimate.
328e8d8bef9SDimitry Andric 
329e8d8bef9SDimitry Andric   // However, getInstructionCost delegates the code size calculation for
330e8d8bef9SDimitry Andric   // arithmetic instructions to getArithmeticInstrCost in
331e8d8bef9SDimitry Andric   // include/Analysis/TargetTransformImpl.h, where it always estimates that the
332e8d8bef9SDimitry Andric   // code size for a division and remainder instruction to be equal to 4, and
333e8d8bef9SDimitry Andric   // everything else to 1.  This is not an accurate representation of the
334e8d8bef9SDimitry Andric   // division instruction for targets that have a native division instruction.
335e8d8bef9SDimitry Andric   // To be overly conservative, we only add 1 to the number of instructions for
336e8d8bef9SDimitry Andric   // each division instruction.
337*349cc55cSDimitry Andric   for (IRInstructionData &ID : *Candidate) {
338*349cc55cSDimitry Andric     Instruction *I = ID.Inst;
339*349cc55cSDimitry Andric     switch (I->getOpcode()) {
340e8d8bef9SDimitry Andric     case Instruction::FDiv:
341e8d8bef9SDimitry Andric     case Instruction::FRem:
342e8d8bef9SDimitry Andric     case Instruction::SDiv:
343e8d8bef9SDimitry Andric     case Instruction::SRem:
344e8d8bef9SDimitry Andric     case Instruction::UDiv:
345e8d8bef9SDimitry Andric     case Instruction::URem:
346e8d8bef9SDimitry Andric       Benefit += 1;
347e8d8bef9SDimitry Andric       break;
348e8d8bef9SDimitry Andric     default:
349*349cc55cSDimitry Andric       Benefit += TTI.getInstructionCost(I, TargetTransformInfo::TCK_CodeSize);
350e8d8bef9SDimitry Andric       break;
351e8d8bef9SDimitry Andric     }
352e8d8bef9SDimitry Andric   }
353e8d8bef9SDimitry Andric 
354e8d8bef9SDimitry Andric   return Benefit;
355e8d8bef9SDimitry Andric }
356e8d8bef9SDimitry Andric 
357e8d8bef9SDimitry Andric /// Find whether \p Region matches the global value numbering to Constant
358e8d8bef9SDimitry Andric /// mapping found so far.
359e8d8bef9SDimitry Andric ///
360e8d8bef9SDimitry Andric /// \param Region - The OutlinableRegion we are checking for constants
361e8d8bef9SDimitry Andric /// \param GVNToConstant - The mapping of global value number to Constants.
362e8d8bef9SDimitry Andric /// \param NotSame - The set of global value numbers that do not have the same
363e8d8bef9SDimitry Andric /// constant in each region.
364e8d8bef9SDimitry Andric /// \returns true if all Constants are the same in every use of a Constant in \p
365e8d8bef9SDimitry Andric /// Region and false if not
366e8d8bef9SDimitry Andric static bool
367e8d8bef9SDimitry Andric collectRegionsConstants(OutlinableRegion &Region,
368e8d8bef9SDimitry Andric                         DenseMap<unsigned, Constant *> &GVNToConstant,
369e8d8bef9SDimitry Andric                         DenseSet<unsigned> &NotSame) {
370e8d8bef9SDimitry Andric   bool ConstantsTheSame = true;
371e8d8bef9SDimitry Andric 
372e8d8bef9SDimitry Andric   IRSimilarityCandidate &C = *Region.Candidate;
373e8d8bef9SDimitry Andric   for (IRInstructionData &ID : C) {
374e8d8bef9SDimitry Andric 
375e8d8bef9SDimitry Andric     // Iterate over the operands in an instruction. If the global value number,
376e8d8bef9SDimitry Andric     // assigned by the IRSimilarityCandidate, has been seen before, we check if
377e8d8bef9SDimitry Andric     // the the number has been found to be not the same value in each instance.
378e8d8bef9SDimitry Andric     for (Value *V : ID.OperVals) {
379e8d8bef9SDimitry Andric       Optional<unsigned> GVNOpt = C.getGVN(V);
380e8d8bef9SDimitry Andric       assert(GVNOpt.hasValue() && "Expected a GVN for operand?");
381e8d8bef9SDimitry Andric       unsigned GVN = GVNOpt.getValue();
382e8d8bef9SDimitry Andric 
383e8d8bef9SDimitry Andric       // Check if this global value has been found to not be the same already.
384e8d8bef9SDimitry Andric       if (NotSame.contains(GVN)) {
385e8d8bef9SDimitry Andric         if (isa<Constant>(V))
386e8d8bef9SDimitry Andric           ConstantsTheSame = false;
387e8d8bef9SDimitry Andric         continue;
388e8d8bef9SDimitry Andric       }
389e8d8bef9SDimitry Andric 
390e8d8bef9SDimitry Andric       // If it has been the same so far, we check the value for if the
391e8d8bef9SDimitry Andric       // associated Constant value match the previous instances of the same
392e8d8bef9SDimitry Andric       // global value number.  If the global value does not map to a Constant,
393e8d8bef9SDimitry Andric       // it is considered to not be the same value.
394e8d8bef9SDimitry Andric       Optional<bool> ConstantMatches = constantMatches(V, GVN, GVNToConstant);
395e8d8bef9SDimitry Andric       if (ConstantMatches.hasValue()) {
396e8d8bef9SDimitry Andric         if (ConstantMatches.getValue())
397e8d8bef9SDimitry Andric           continue;
398e8d8bef9SDimitry Andric         else
399e8d8bef9SDimitry Andric           ConstantsTheSame = false;
400e8d8bef9SDimitry Andric       }
401e8d8bef9SDimitry Andric 
402e8d8bef9SDimitry Andric       // While this value is a register, it might not have been previously,
403e8d8bef9SDimitry Andric       // make sure we don't already have a constant mapped to this global value
404e8d8bef9SDimitry Andric       // number.
405e8d8bef9SDimitry Andric       if (GVNToConstant.find(GVN) != GVNToConstant.end())
406e8d8bef9SDimitry Andric         ConstantsTheSame = false;
407e8d8bef9SDimitry Andric 
408e8d8bef9SDimitry Andric       NotSame.insert(GVN);
409e8d8bef9SDimitry Andric     }
410e8d8bef9SDimitry Andric   }
411e8d8bef9SDimitry Andric 
412e8d8bef9SDimitry Andric   return ConstantsTheSame;
413e8d8bef9SDimitry Andric }
414e8d8bef9SDimitry Andric 
415e8d8bef9SDimitry Andric void OutlinableGroup::findSameConstants(DenseSet<unsigned> &NotSame) {
416e8d8bef9SDimitry Andric   DenseMap<unsigned, Constant *> GVNToConstant;
417e8d8bef9SDimitry Andric 
418e8d8bef9SDimitry Andric   for (OutlinableRegion *Region : Regions)
419e8d8bef9SDimitry Andric     collectRegionsConstants(*Region, GVNToConstant, NotSame);
420e8d8bef9SDimitry Andric }
421e8d8bef9SDimitry Andric 
422e8d8bef9SDimitry Andric void OutlinableGroup::collectGVNStoreSets(Module &M) {
423e8d8bef9SDimitry Andric   for (OutlinableRegion *OS : Regions)
424e8d8bef9SDimitry Andric     OutputGVNCombinations.insert(OS->GVNStores);
425e8d8bef9SDimitry Andric 
426e8d8bef9SDimitry Andric   // We are adding an extracted argument to decide between which output path
427e8d8bef9SDimitry Andric   // to use in the basic block.  It is used in a switch statement and only
428e8d8bef9SDimitry Andric   // needs to be an integer.
429e8d8bef9SDimitry Andric   if (OutputGVNCombinations.size() > 1)
430e8d8bef9SDimitry Andric     ArgumentTypes.push_back(Type::getInt32Ty(M.getContext()));
431e8d8bef9SDimitry Andric }
432e8d8bef9SDimitry Andric 
433fe6060f1SDimitry Andric /// Get the subprogram if it exists for one of the outlined regions.
434fe6060f1SDimitry Andric ///
435fe6060f1SDimitry Andric /// \param [in] Group - The set of regions to find a subprogram for.
436fe6060f1SDimitry Andric /// \returns the subprogram if it exists, or nullptr.
437fe6060f1SDimitry Andric static DISubprogram *getSubprogramOrNull(OutlinableGroup &Group) {
438fe6060f1SDimitry Andric   for (OutlinableRegion *OS : Group.Regions)
439fe6060f1SDimitry Andric     if (Function *F = OS->Call->getFunction())
440fe6060f1SDimitry Andric       if (DISubprogram *SP = F->getSubprogram())
441fe6060f1SDimitry Andric         return SP;
442fe6060f1SDimitry Andric 
443fe6060f1SDimitry Andric   return nullptr;
444fe6060f1SDimitry Andric }
445fe6060f1SDimitry Andric 
446e8d8bef9SDimitry Andric Function *IROutliner::createFunction(Module &M, OutlinableGroup &Group,
447e8d8bef9SDimitry Andric                                      unsigned FunctionNameSuffix) {
448e8d8bef9SDimitry Andric   assert(!Group.OutlinedFunction && "Function is already defined!");
449e8d8bef9SDimitry Andric 
450*349cc55cSDimitry Andric   Type *RetTy = Type::getVoidTy(M.getContext());
451*349cc55cSDimitry Andric   // All extracted functions _should_ have the same return type at this point
452*349cc55cSDimitry Andric   // since the similarity identifier ensures that all branches outside of the
453*349cc55cSDimitry Andric   // region occur in the same place.
454*349cc55cSDimitry Andric 
455*349cc55cSDimitry Andric   // NOTE: Should we ever move to the model that uses a switch at every point
456*349cc55cSDimitry Andric   // needed, meaning that we could branch within the region or out, it is
457*349cc55cSDimitry Andric   // possible that we will need to switch to using the most general case all of
458*349cc55cSDimitry Andric   // the time.
459*349cc55cSDimitry Andric   for (OutlinableRegion *R : Group.Regions) {
460*349cc55cSDimitry Andric     Type *ExtractedFuncType = R->ExtractedFunction->getReturnType();
461*349cc55cSDimitry Andric     if ((RetTy->isVoidTy() && !ExtractedFuncType->isVoidTy()) ||
462*349cc55cSDimitry Andric         (RetTy->isIntegerTy(1) && ExtractedFuncType->isIntegerTy(16)))
463*349cc55cSDimitry Andric       RetTy = ExtractedFuncType;
464*349cc55cSDimitry Andric   }
465*349cc55cSDimitry Andric 
466e8d8bef9SDimitry Andric   Group.OutlinedFunctionType = FunctionType::get(
467*349cc55cSDimitry Andric       RetTy, Group.ArgumentTypes, false);
468e8d8bef9SDimitry Andric 
469e8d8bef9SDimitry Andric   // These functions will only be called from within the same module, so
470e8d8bef9SDimitry Andric   // we can set an internal linkage.
471e8d8bef9SDimitry Andric   Group.OutlinedFunction = Function::Create(
472e8d8bef9SDimitry Andric       Group.OutlinedFunctionType, GlobalValue::InternalLinkage,
473e8d8bef9SDimitry Andric       "outlined_ir_func_" + std::to_string(FunctionNameSuffix), M);
474e8d8bef9SDimitry Andric 
475e8d8bef9SDimitry Andric   // Transfer the swifterr attribute to the correct function parameter.
476e8d8bef9SDimitry Andric   if (Group.SwiftErrorArgument.hasValue())
477e8d8bef9SDimitry Andric     Group.OutlinedFunction->addParamAttr(Group.SwiftErrorArgument.getValue(),
478e8d8bef9SDimitry Andric                                          Attribute::SwiftError);
479e8d8bef9SDimitry Andric 
480e8d8bef9SDimitry Andric   Group.OutlinedFunction->addFnAttr(Attribute::OptimizeForSize);
481e8d8bef9SDimitry Andric   Group.OutlinedFunction->addFnAttr(Attribute::MinSize);
482e8d8bef9SDimitry Andric 
483fe6060f1SDimitry Andric   // If there's a DISubprogram associated with this outlined function, then
484fe6060f1SDimitry Andric   // emit debug info for the outlined function.
485fe6060f1SDimitry Andric   if (DISubprogram *SP = getSubprogramOrNull(Group)) {
486fe6060f1SDimitry Andric     Function *F = Group.OutlinedFunction;
487fe6060f1SDimitry Andric     // We have a DISubprogram. Get its DICompileUnit.
488fe6060f1SDimitry Andric     DICompileUnit *CU = SP->getUnit();
489fe6060f1SDimitry Andric     DIBuilder DB(M, true, CU);
490fe6060f1SDimitry Andric     DIFile *Unit = SP->getFile();
491fe6060f1SDimitry Andric     Mangler Mg;
492fe6060f1SDimitry Andric     // Get the mangled name of the function for the linkage name.
493fe6060f1SDimitry Andric     std::string Dummy;
494fe6060f1SDimitry Andric     llvm::raw_string_ostream MangledNameStream(Dummy);
495fe6060f1SDimitry Andric     Mg.getNameWithPrefix(MangledNameStream, F, false);
496fe6060f1SDimitry Andric 
497fe6060f1SDimitry Andric     DISubprogram *OutlinedSP = DB.createFunction(
498fe6060f1SDimitry Andric         Unit /* Context */, F->getName(), MangledNameStream.str(),
499fe6060f1SDimitry Andric         Unit /* File */,
500fe6060f1SDimitry Andric         0 /* Line 0 is reserved for compiler-generated code. */,
501fe6060f1SDimitry Andric         DB.createSubroutineType(DB.getOrCreateTypeArray(None)), /* void type */
502fe6060f1SDimitry Andric         0, /* Line 0 is reserved for compiler-generated code. */
503fe6060f1SDimitry Andric         DINode::DIFlags::FlagArtificial /* Compiler-generated code. */,
504fe6060f1SDimitry Andric         /* Outlined code is optimized code by definition. */
505fe6060f1SDimitry Andric         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
506fe6060f1SDimitry Andric 
507fe6060f1SDimitry Andric     // Don't add any new variables to the subprogram.
508fe6060f1SDimitry Andric     DB.finalizeSubprogram(OutlinedSP);
509fe6060f1SDimitry Andric 
510fe6060f1SDimitry Andric     // Attach subprogram to the function.
511fe6060f1SDimitry Andric     F->setSubprogram(OutlinedSP);
512fe6060f1SDimitry Andric     // We're done with the DIBuilder.
513fe6060f1SDimitry Andric     DB.finalize();
514fe6060f1SDimitry Andric   }
515fe6060f1SDimitry Andric 
516e8d8bef9SDimitry Andric   return Group.OutlinedFunction;
517e8d8bef9SDimitry Andric }
518e8d8bef9SDimitry Andric 
519e8d8bef9SDimitry Andric /// Move each BasicBlock in \p Old to \p New.
520e8d8bef9SDimitry Andric ///
521fe6060f1SDimitry Andric /// \param [in] Old - The function to move the basic blocks from.
522e8d8bef9SDimitry Andric /// \param [in] New - The function to move the basic blocks to.
523*349cc55cSDimitry Andric /// \param [out] NewEnds - The return blocks of the new overall function.
524*349cc55cSDimitry Andric static void moveFunctionData(Function &Old, Function &New,
525*349cc55cSDimitry Andric                              DenseMap<Value *, BasicBlock *> &NewEnds) {
526*349cc55cSDimitry Andric   for (BasicBlock &CurrBB : llvm::make_early_inc_range(Old)) {
527*349cc55cSDimitry Andric     CurrBB.removeFromParent();
528*349cc55cSDimitry Andric     CurrBB.insertInto(&New);
529*349cc55cSDimitry Andric     Instruction *I = CurrBB.getTerminator();
530fe6060f1SDimitry Andric 
531*349cc55cSDimitry Andric     // For each block we find a return instruction is, it is a potential exit
532*349cc55cSDimitry Andric     // path for the function.  We keep track of each block based on the return
533*349cc55cSDimitry Andric     // value here.
534*349cc55cSDimitry Andric     if (ReturnInst *RI = dyn_cast<ReturnInst>(I))
535*349cc55cSDimitry Andric       NewEnds.insert(std::make_pair(RI->getReturnValue(), &CurrBB));
536*349cc55cSDimitry Andric 
537*349cc55cSDimitry Andric     std::vector<Instruction *> DebugInsts;
538*349cc55cSDimitry Andric 
539*349cc55cSDimitry Andric     for (Instruction &Val : CurrBB) {
540fe6060f1SDimitry Andric       // We must handle the scoping of called functions differently than
541fe6060f1SDimitry Andric       // other outlined instructions.
542fe6060f1SDimitry Andric       if (!isa<CallInst>(&Val)) {
543fe6060f1SDimitry Andric         // Remove the debug information for outlined functions.
544fe6060f1SDimitry Andric         Val.setDebugLoc(DebugLoc());
545fe6060f1SDimitry Andric         continue;
546fe6060f1SDimitry Andric       }
547fe6060f1SDimitry Andric 
548fe6060f1SDimitry Andric       // From this point we are only handling call instructions.
549fe6060f1SDimitry Andric       CallInst *CI = cast<CallInst>(&Val);
550fe6060f1SDimitry Andric 
551fe6060f1SDimitry Andric       // We add any debug statements here, to be removed after.  Since the
552fe6060f1SDimitry Andric       // instructions originate from many different locations in the program,
553fe6060f1SDimitry Andric       // it will cause incorrect reporting from a debugger if we keep the
554fe6060f1SDimitry Andric       // same debug instructions.
555fe6060f1SDimitry Andric       if (isa<DbgInfoIntrinsic>(CI)) {
556fe6060f1SDimitry Andric         DebugInsts.push_back(&Val);
557fe6060f1SDimitry Andric         continue;
558fe6060f1SDimitry Andric       }
559fe6060f1SDimitry Andric 
560fe6060f1SDimitry Andric       // Edit the scope of called functions inside of outlined functions.
561fe6060f1SDimitry Andric       if (DISubprogram *SP = New.getSubprogram()) {
562fe6060f1SDimitry Andric         DILocation *DI = DILocation::get(New.getContext(), 0, 0, SP);
563fe6060f1SDimitry Andric         Val.setDebugLoc(DI);
564fe6060f1SDimitry Andric       }
565fe6060f1SDimitry Andric     }
566fe6060f1SDimitry Andric 
567fe6060f1SDimitry Andric     for (Instruction *I : DebugInsts)
568fe6060f1SDimitry Andric       I->eraseFromParent();
569e8d8bef9SDimitry Andric   }
570e8d8bef9SDimitry Andric 
571*349cc55cSDimitry Andric   assert(NewEnds.size() > 0 && "No return instruction for new function?");
572e8d8bef9SDimitry Andric }
573e8d8bef9SDimitry Andric 
574e8d8bef9SDimitry Andric /// Find the the constants that will need to be lifted into arguments
575e8d8bef9SDimitry Andric /// as they are not the same in each instance of the region.
576e8d8bef9SDimitry Andric ///
577e8d8bef9SDimitry Andric /// \param [in] C - The IRSimilarityCandidate containing the region we are
578e8d8bef9SDimitry Andric /// analyzing.
579e8d8bef9SDimitry Andric /// \param [in] NotSame - The set of global value numbers that do not have a
580e8d8bef9SDimitry Andric /// single Constant across all OutlinableRegions similar to \p C.
581e8d8bef9SDimitry Andric /// \param [out] Inputs - The list containing the global value numbers of the
582e8d8bef9SDimitry Andric /// arguments needed for the region of code.
583e8d8bef9SDimitry Andric static void findConstants(IRSimilarityCandidate &C, DenseSet<unsigned> &NotSame,
584e8d8bef9SDimitry Andric                           std::vector<unsigned> &Inputs) {
585e8d8bef9SDimitry Andric   DenseSet<unsigned> Seen;
586e8d8bef9SDimitry Andric   // Iterate over the instructions, and find what constants will need to be
587e8d8bef9SDimitry Andric   // extracted into arguments.
588e8d8bef9SDimitry Andric   for (IRInstructionDataList::iterator IDIt = C.begin(), EndIDIt = C.end();
589e8d8bef9SDimitry Andric        IDIt != EndIDIt; IDIt++) {
590e8d8bef9SDimitry Andric     for (Value *V : (*IDIt).OperVals) {
591e8d8bef9SDimitry Andric       // Since these are stored before any outlining, they will be in the
592e8d8bef9SDimitry Andric       // global value numbering.
593e8d8bef9SDimitry Andric       unsigned GVN = C.getGVN(V).getValue();
594e8d8bef9SDimitry Andric       if (isa<Constant>(V))
595e8d8bef9SDimitry Andric         if (NotSame.contains(GVN) && !Seen.contains(GVN)) {
596e8d8bef9SDimitry Andric           Inputs.push_back(GVN);
597e8d8bef9SDimitry Andric           Seen.insert(GVN);
598e8d8bef9SDimitry Andric         }
599e8d8bef9SDimitry Andric     }
600e8d8bef9SDimitry Andric   }
601e8d8bef9SDimitry Andric }
602e8d8bef9SDimitry Andric 
603e8d8bef9SDimitry Andric /// Find the GVN for the inputs that have been found by the CodeExtractor.
604e8d8bef9SDimitry Andric ///
605e8d8bef9SDimitry Andric /// \param [in] C - The IRSimilarityCandidate containing the region we are
606e8d8bef9SDimitry Andric /// analyzing.
607e8d8bef9SDimitry Andric /// \param [in] CurrentInputs - The set of inputs found by the
608e8d8bef9SDimitry Andric /// CodeExtractor.
609e8d8bef9SDimitry Andric /// \param [in] OutputMappings - The mapping of values that have been replaced
610e8d8bef9SDimitry Andric /// by a new output value.
611fe6060f1SDimitry Andric /// \param [out] EndInputNumbers - The global value numbers for the extracted
612e8d8bef9SDimitry Andric /// arguments.
613e8d8bef9SDimitry Andric static void mapInputsToGVNs(IRSimilarityCandidate &C,
614e8d8bef9SDimitry Andric                             SetVector<Value *> &CurrentInputs,
615e8d8bef9SDimitry Andric                             const DenseMap<Value *, Value *> &OutputMappings,
616e8d8bef9SDimitry Andric                             std::vector<unsigned> &EndInputNumbers) {
617e8d8bef9SDimitry Andric   // Get the Global Value Number for each input.  We check if the Value has been
618e8d8bef9SDimitry Andric   // replaced by a different value at output, and use the original value before
619e8d8bef9SDimitry Andric   // replacement.
620e8d8bef9SDimitry Andric   for (Value *Input : CurrentInputs) {
621e8d8bef9SDimitry Andric     assert(Input && "Have a nullptr as an input");
622e8d8bef9SDimitry Andric     if (OutputMappings.find(Input) != OutputMappings.end())
623e8d8bef9SDimitry Andric       Input = OutputMappings.find(Input)->second;
624e8d8bef9SDimitry Andric     assert(C.getGVN(Input).hasValue() &&
625e8d8bef9SDimitry Andric            "Could not find a numbering for the given input");
626e8d8bef9SDimitry Andric     EndInputNumbers.push_back(C.getGVN(Input).getValue());
627e8d8bef9SDimitry Andric   }
628e8d8bef9SDimitry Andric }
629e8d8bef9SDimitry Andric 
630e8d8bef9SDimitry Andric /// Find the original value for the \p ArgInput values if any one of them was
631e8d8bef9SDimitry Andric /// replaced during a previous extraction.
632e8d8bef9SDimitry Andric ///
633e8d8bef9SDimitry Andric /// \param [in] ArgInputs - The inputs to be extracted by the code extractor.
634e8d8bef9SDimitry Andric /// \param [in] OutputMappings - The mapping of values that have been replaced
635e8d8bef9SDimitry Andric /// by a new output value.
636e8d8bef9SDimitry Andric /// \param [out] RemappedArgInputs - The remapped values according to
637e8d8bef9SDimitry Andric /// \p OutputMappings that will be extracted.
638e8d8bef9SDimitry Andric static void
639e8d8bef9SDimitry Andric remapExtractedInputs(const ArrayRef<Value *> ArgInputs,
640e8d8bef9SDimitry Andric                      const DenseMap<Value *, Value *> &OutputMappings,
641e8d8bef9SDimitry Andric                      SetVector<Value *> &RemappedArgInputs) {
642e8d8bef9SDimitry Andric   // Get the global value number for each input that will be extracted as an
643e8d8bef9SDimitry Andric   // argument by the code extractor, remapping if needed for reloaded values.
644e8d8bef9SDimitry Andric   for (Value *Input : ArgInputs) {
645e8d8bef9SDimitry Andric     if (OutputMappings.find(Input) != OutputMappings.end())
646e8d8bef9SDimitry Andric       Input = OutputMappings.find(Input)->second;
647e8d8bef9SDimitry Andric     RemappedArgInputs.insert(Input);
648e8d8bef9SDimitry Andric   }
649e8d8bef9SDimitry Andric }
650e8d8bef9SDimitry Andric 
651e8d8bef9SDimitry Andric /// Find the input GVNs and the output values for a region of Instructions.
652e8d8bef9SDimitry Andric /// Using the code extractor, we collect the inputs to the extracted function.
653e8d8bef9SDimitry Andric ///
654e8d8bef9SDimitry Andric /// The \p Region can be identified as needing to be ignored in this function.
655e8d8bef9SDimitry Andric /// It should be checked whether it should be ignored after a call to this
656e8d8bef9SDimitry Andric /// function.
657e8d8bef9SDimitry Andric ///
658e8d8bef9SDimitry Andric /// \param [in,out] Region - The region of code to be analyzed.
659e8d8bef9SDimitry Andric /// \param [out] InputGVNs - The global value numbers for the extracted
660e8d8bef9SDimitry Andric /// arguments.
661e8d8bef9SDimitry Andric /// \param [in] NotSame - The global value numbers in the region that do not
662e8d8bef9SDimitry Andric /// have the same constant value in the regions structurally similar to
663e8d8bef9SDimitry Andric /// \p Region.
664e8d8bef9SDimitry Andric /// \param [in] OutputMappings - The mapping of values that have been replaced
665e8d8bef9SDimitry Andric /// by a new output value after extraction.
666e8d8bef9SDimitry Andric /// \param [out] ArgInputs - The values of the inputs to the extracted function.
667e8d8bef9SDimitry Andric /// \param [out] Outputs - The set of values extracted by the CodeExtractor
668e8d8bef9SDimitry Andric /// as outputs.
669e8d8bef9SDimitry Andric static void getCodeExtractorArguments(
670e8d8bef9SDimitry Andric     OutlinableRegion &Region, std::vector<unsigned> &InputGVNs,
671e8d8bef9SDimitry Andric     DenseSet<unsigned> &NotSame, DenseMap<Value *, Value *> &OutputMappings,
672e8d8bef9SDimitry Andric     SetVector<Value *> &ArgInputs, SetVector<Value *> &Outputs) {
673e8d8bef9SDimitry Andric   IRSimilarityCandidate &C = *Region.Candidate;
674e8d8bef9SDimitry Andric 
675e8d8bef9SDimitry Andric   // OverallInputs are the inputs to the region found by the CodeExtractor,
676e8d8bef9SDimitry Andric   // SinkCands and HoistCands are used by the CodeExtractor to find sunken
677e8d8bef9SDimitry Andric   // allocas of values whose lifetimes are contained completely within the
678e8d8bef9SDimitry Andric   // outlined region. PremappedInputs are the arguments found by the
679e8d8bef9SDimitry Andric   // CodeExtractor, removing conditions such as sunken allocas, but that
680e8d8bef9SDimitry Andric   // may need to be remapped due to the extracted output values replacing
681e8d8bef9SDimitry Andric   // the original values. We use DummyOutputs for this first run of finding
682e8d8bef9SDimitry Andric   // inputs and outputs since the outputs could change during findAllocas,
683e8d8bef9SDimitry Andric   // the correct set of extracted outputs will be in the final Outputs ValueSet.
684e8d8bef9SDimitry Andric   SetVector<Value *> OverallInputs, PremappedInputs, SinkCands, HoistCands,
685e8d8bef9SDimitry Andric       DummyOutputs;
686e8d8bef9SDimitry Andric 
687e8d8bef9SDimitry Andric   // Use the code extractor to get the inputs and outputs, without sunken
688e8d8bef9SDimitry Andric   // allocas or removing llvm.assumes.
689e8d8bef9SDimitry Andric   CodeExtractor *CE = Region.CE;
690e8d8bef9SDimitry Andric   CE->findInputsOutputs(OverallInputs, DummyOutputs, SinkCands);
691e8d8bef9SDimitry Andric   assert(Region.StartBB && "Region must have a start BasicBlock!");
692e8d8bef9SDimitry Andric   Function *OrigF = Region.StartBB->getParent();
693e8d8bef9SDimitry Andric   CodeExtractorAnalysisCache CEAC(*OrigF);
694e8d8bef9SDimitry Andric   BasicBlock *Dummy = nullptr;
695e8d8bef9SDimitry Andric 
696e8d8bef9SDimitry Andric   // The region may be ineligible due to VarArgs in the parent function. In this
697e8d8bef9SDimitry Andric   // case we ignore the region.
698e8d8bef9SDimitry Andric   if (!CE->isEligible()) {
699e8d8bef9SDimitry Andric     Region.IgnoreRegion = true;
700e8d8bef9SDimitry Andric     return;
701e8d8bef9SDimitry Andric   }
702e8d8bef9SDimitry Andric 
703e8d8bef9SDimitry Andric   // Find if any values are going to be sunk into the function when extracted
704e8d8bef9SDimitry Andric   CE->findAllocas(CEAC, SinkCands, HoistCands, Dummy);
705e8d8bef9SDimitry Andric   CE->findInputsOutputs(PremappedInputs, Outputs, SinkCands);
706e8d8bef9SDimitry Andric 
707e8d8bef9SDimitry Andric   // TODO: Support regions with sunken allocas: values whose lifetimes are
708e8d8bef9SDimitry Andric   // contained completely within the outlined region.  These are not guaranteed
709e8d8bef9SDimitry Andric   // to be the same in every region, so we must elevate them all to arguments
710e8d8bef9SDimitry Andric   // when they appear.  If these values are not equal, it means there is some
711e8d8bef9SDimitry Andric   // Input in OverallInputs that was removed for ArgInputs.
712e8d8bef9SDimitry Andric   if (OverallInputs.size() != PremappedInputs.size()) {
713e8d8bef9SDimitry Andric     Region.IgnoreRegion = true;
714e8d8bef9SDimitry Andric     return;
715e8d8bef9SDimitry Andric   }
716e8d8bef9SDimitry Andric 
717e8d8bef9SDimitry Andric   findConstants(C, NotSame, InputGVNs);
718e8d8bef9SDimitry Andric 
719e8d8bef9SDimitry Andric   mapInputsToGVNs(C, OverallInputs, OutputMappings, InputGVNs);
720e8d8bef9SDimitry Andric 
721e8d8bef9SDimitry Andric   remapExtractedInputs(PremappedInputs.getArrayRef(), OutputMappings,
722e8d8bef9SDimitry Andric                        ArgInputs);
723e8d8bef9SDimitry Andric 
724e8d8bef9SDimitry Andric   // Sort the GVNs, since we now have constants included in the \ref InputGVNs
725e8d8bef9SDimitry Andric   // we need to make sure they are in a deterministic order.
726e8d8bef9SDimitry Andric   stable_sort(InputGVNs);
727e8d8bef9SDimitry Andric }
728e8d8bef9SDimitry Andric 
729e8d8bef9SDimitry Andric /// Look over the inputs and map each input argument to an argument in the
730e8d8bef9SDimitry Andric /// overall function for the OutlinableRegions.  This creates a way to replace
731e8d8bef9SDimitry Andric /// the arguments of the extracted function with the arguments of the new
732e8d8bef9SDimitry Andric /// overall function.
733e8d8bef9SDimitry Andric ///
734e8d8bef9SDimitry Andric /// \param [in,out] Region - The region of code to be analyzed.
735fe6060f1SDimitry Andric /// \param [in] InputGVNs - The global value numbering of the input values
736e8d8bef9SDimitry Andric /// collected.
737e8d8bef9SDimitry Andric /// \param [in] ArgInputs - The values of the arguments to the extracted
738e8d8bef9SDimitry Andric /// function.
739e8d8bef9SDimitry Andric static void
740e8d8bef9SDimitry Andric findExtractedInputToOverallInputMapping(OutlinableRegion &Region,
741e8d8bef9SDimitry Andric                                         std::vector<unsigned> &InputGVNs,
742e8d8bef9SDimitry Andric                                         SetVector<Value *> &ArgInputs) {
743e8d8bef9SDimitry Andric 
744e8d8bef9SDimitry Andric   IRSimilarityCandidate &C = *Region.Candidate;
745e8d8bef9SDimitry Andric   OutlinableGroup &Group = *Region.Parent;
746e8d8bef9SDimitry Andric 
747e8d8bef9SDimitry Andric   // This counts the argument number in the overall function.
748e8d8bef9SDimitry Andric   unsigned TypeIndex = 0;
749e8d8bef9SDimitry Andric 
750e8d8bef9SDimitry Andric   // This counts the argument number in the extracted function.
751e8d8bef9SDimitry Andric   unsigned OriginalIndex = 0;
752e8d8bef9SDimitry Andric 
753e8d8bef9SDimitry Andric   // Find the mapping of the extracted arguments to the arguments for the
754e8d8bef9SDimitry Andric   // overall function. Since there may be extra arguments in the overall
755e8d8bef9SDimitry Andric   // function to account for the extracted constants, we have two different
756e8d8bef9SDimitry Andric   // counters as we find extracted arguments, and as we come across overall
757e8d8bef9SDimitry Andric   // arguments.
758*349cc55cSDimitry Andric 
759*349cc55cSDimitry Andric   // Additionally, in our first pass, for the first extracted function,
760*349cc55cSDimitry Andric   // we find argument locations for the canonical value numbering.  This
761*349cc55cSDimitry Andric   // numbering overrides any discovered location for the extracted code.
762e8d8bef9SDimitry Andric   for (unsigned InputVal : InputGVNs) {
763*349cc55cSDimitry Andric     Optional<unsigned> CanonicalNumberOpt = C.getCanonicalNum(InputVal);
764*349cc55cSDimitry Andric     assert(CanonicalNumberOpt.hasValue() && "Canonical number not found?");
765*349cc55cSDimitry Andric     unsigned CanonicalNumber = CanonicalNumberOpt.getValue();
766*349cc55cSDimitry Andric 
767e8d8bef9SDimitry Andric     Optional<Value *> InputOpt = C.fromGVN(InputVal);
768e8d8bef9SDimitry Andric     assert(InputOpt.hasValue() && "Global value number not found?");
769e8d8bef9SDimitry Andric     Value *Input = InputOpt.getValue();
770e8d8bef9SDimitry Andric 
771*349cc55cSDimitry Andric     DenseMap<unsigned, unsigned>::iterator AggArgIt =
772*349cc55cSDimitry Andric         Group.CanonicalNumberToAggArg.find(CanonicalNumber);
773*349cc55cSDimitry Andric 
774e8d8bef9SDimitry Andric     if (!Group.InputTypesSet) {
775e8d8bef9SDimitry Andric       Group.ArgumentTypes.push_back(Input->getType());
776e8d8bef9SDimitry Andric       // If the input value has a swifterr attribute, make sure to mark the
777e8d8bef9SDimitry Andric       // argument in the overall function.
778e8d8bef9SDimitry Andric       if (Input->isSwiftError()) {
779e8d8bef9SDimitry Andric         assert(
780e8d8bef9SDimitry Andric             !Group.SwiftErrorArgument.hasValue() &&
781e8d8bef9SDimitry Andric             "Argument already marked with swifterr for this OutlinableGroup!");
782e8d8bef9SDimitry Andric         Group.SwiftErrorArgument = TypeIndex;
783e8d8bef9SDimitry Andric       }
784e8d8bef9SDimitry Andric     }
785e8d8bef9SDimitry Andric 
786e8d8bef9SDimitry Andric     // Check if we have a constant. If we do add it to the overall argument
787e8d8bef9SDimitry Andric     // number to Constant map for the region, and continue to the next input.
788e8d8bef9SDimitry Andric     if (Constant *CST = dyn_cast<Constant>(Input)) {
789*349cc55cSDimitry Andric       if (AggArgIt != Group.CanonicalNumberToAggArg.end())
790*349cc55cSDimitry Andric         Region.AggArgToConstant.insert(std::make_pair(AggArgIt->second, CST));
791*349cc55cSDimitry Andric       else {
792*349cc55cSDimitry Andric         Group.CanonicalNumberToAggArg.insert(
793*349cc55cSDimitry Andric             std::make_pair(CanonicalNumber, TypeIndex));
794e8d8bef9SDimitry Andric         Region.AggArgToConstant.insert(std::make_pair(TypeIndex, CST));
795*349cc55cSDimitry Andric       }
796e8d8bef9SDimitry Andric       TypeIndex++;
797e8d8bef9SDimitry Andric       continue;
798e8d8bef9SDimitry Andric     }
799e8d8bef9SDimitry Andric 
800e8d8bef9SDimitry Andric     // It is not a constant, we create the mapping from extracted argument list
801*349cc55cSDimitry Andric     // to the overall argument list, using the canonical location, if it exists.
802e8d8bef9SDimitry Andric     assert(ArgInputs.count(Input) && "Input cannot be found!");
803e8d8bef9SDimitry Andric 
804*349cc55cSDimitry Andric     if (AggArgIt != Group.CanonicalNumberToAggArg.end()) {
805*349cc55cSDimitry Andric       if (OriginalIndex != AggArgIt->second)
806*349cc55cSDimitry Andric         Region.ChangedArgOrder = true;
807*349cc55cSDimitry Andric       Region.ExtractedArgToAgg.insert(
808*349cc55cSDimitry Andric           std::make_pair(OriginalIndex, AggArgIt->second));
809*349cc55cSDimitry Andric       Region.AggArgToExtracted.insert(
810*349cc55cSDimitry Andric           std::make_pair(AggArgIt->second, OriginalIndex));
811*349cc55cSDimitry Andric     } else {
812*349cc55cSDimitry Andric       Group.CanonicalNumberToAggArg.insert(
813*349cc55cSDimitry Andric           std::make_pair(CanonicalNumber, TypeIndex));
814e8d8bef9SDimitry Andric       Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, TypeIndex));
815e8d8bef9SDimitry Andric       Region.AggArgToExtracted.insert(std::make_pair(TypeIndex, OriginalIndex));
816*349cc55cSDimitry Andric     }
817e8d8bef9SDimitry Andric     OriginalIndex++;
818e8d8bef9SDimitry Andric     TypeIndex++;
819e8d8bef9SDimitry Andric   }
820e8d8bef9SDimitry Andric 
821e8d8bef9SDimitry Andric   // If the function type definitions for the OutlinableGroup holding the region
822e8d8bef9SDimitry Andric   // have not been set, set the length of the inputs here.  We should have the
823e8d8bef9SDimitry Andric   // same inputs for all of the different regions contained in the
824e8d8bef9SDimitry Andric   // OutlinableGroup since they are all structurally similar to one another.
825e8d8bef9SDimitry Andric   if (!Group.InputTypesSet) {
826e8d8bef9SDimitry Andric     Group.NumAggregateInputs = TypeIndex;
827e8d8bef9SDimitry Andric     Group.InputTypesSet = true;
828e8d8bef9SDimitry Andric   }
829e8d8bef9SDimitry Andric 
830e8d8bef9SDimitry Andric   Region.NumExtractedInputs = OriginalIndex;
831e8d8bef9SDimitry Andric }
832e8d8bef9SDimitry Andric 
833e8d8bef9SDimitry Andric /// Create a mapping of the output arguments for the \p Region to the output
834e8d8bef9SDimitry Andric /// arguments of the overall outlined function.
835e8d8bef9SDimitry Andric ///
836e8d8bef9SDimitry Andric /// \param [in,out] Region - The region of code to be analyzed.
837e8d8bef9SDimitry Andric /// \param [in] Outputs - The values found by the code extractor.
838e8d8bef9SDimitry Andric static void
839e8d8bef9SDimitry Andric findExtractedOutputToOverallOutputMapping(OutlinableRegion &Region,
840*349cc55cSDimitry Andric                                           SetVector<Value *> &Outputs) {
841e8d8bef9SDimitry Andric   OutlinableGroup &Group = *Region.Parent;
842e8d8bef9SDimitry Andric   IRSimilarityCandidate &C = *Region.Candidate;
843e8d8bef9SDimitry Andric 
844*349cc55cSDimitry Andric   SmallVector<BasicBlock *> BE;
845*349cc55cSDimitry Andric   DenseSet<BasicBlock *> BBSet;
846*349cc55cSDimitry Andric   C.getBasicBlocks(BBSet, BE);
847*349cc55cSDimitry Andric 
848*349cc55cSDimitry Andric   // Find the exits to the region.
849*349cc55cSDimitry Andric   SmallPtrSet<BasicBlock *, 1> Exits;
850*349cc55cSDimitry Andric   for (BasicBlock *Block : BE)
851*349cc55cSDimitry Andric     for (BasicBlock *Succ : successors(Block))
852*349cc55cSDimitry Andric       if (!BBSet.contains(Succ))
853*349cc55cSDimitry Andric         Exits.insert(Succ);
854*349cc55cSDimitry Andric 
855*349cc55cSDimitry Andric   // After determining which blocks exit to PHINodes, we add these PHINodes to
856*349cc55cSDimitry Andric   // the set of outputs to be processed.  We also check the incoming values of
857*349cc55cSDimitry Andric   // the PHINodes for whether they should no longer be considered outputs.
858*349cc55cSDimitry Andric   for (BasicBlock *ExitBB : Exits) {
859*349cc55cSDimitry Andric     for (PHINode &PN : ExitBB->phis()) {
860*349cc55cSDimitry Andric       // Find all incoming values from the outlining region.
861*349cc55cSDimitry Andric       SmallVector<unsigned, 2> IncomingVals;
862*349cc55cSDimitry Andric       for (unsigned Idx = 0; Idx < PN.getNumIncomingValues(); ++Idx)
863*349cc55cSDimitry Andric         if (BBSet.contains(PN.getIncomingBlock(Idx)))
864*349cc55cSDimitry Andric           IncomingVals.push_back(Idx);
865*349cc55cSDimitry Andric 
866*349cc55cSDimitry Andric       // Do not process PHI if there is one (or fewer) predecessor from region.
867*349cc55cSDimitry Andric       if (IncomingVals.size() <= 1)
868*349cc55cSDimitry Andric         continue;
869*349cc55cSDimitry Andric 
870*349cc55cSDimitry Andric       Region.IgnoreRegion = true;
871*349cc55cSDimitry Andric       return;
872*349cc55cSDimitry Andric     }
873*349cc55cSDimitry Andric   }
874*349cc55cSDimitry Andric 
875e8d8bef9SDimitry Andric   // This counts the argument number in the extracted function.
876e8d8bef9SDimitry Andric   unsigned OriginalIndex = Region.NumExtractedInputs;
877e8d8bef9SDimitry Andric 
878e8d8bef9SDimitry Andric   // This counts the argument number in the overall function.
879e8d8bef9SDimitry Andric   unsigned TypeIndex = Group.NumAggregateInputs;
880e8d8bef9SDimitry Andric   bool TypeFound;
881e8d8bef9SDimitry Andric   DenseSet<unsigned> AggArgsUsed;
882e8d8bef9SDimitry Andric 
883e8d8bef9SDimitry Andric   // Iterate over the output types and identify if there is an aggregate pointer
884e8d8bef9SDimitry Andric   // type whose base type matches the current output type. If there is, we mark
885e8d8bef9SDimitry Andric   // that we will use this output register for this value. If not we add another
886e8d8bef9SDimitry Andric   // type to the overall argument type list. We also store the GVNs used for
887e8d8bef9SDimitry Andric   // stores to identify which values will need to be moved into an special
888e8d8bef9SDimitry Andric   // block that holds the stores to the output registers.
889e8d8bef9SDimitry Andric   for (Value *Output : Outputs) {
890e8d8bef9SDimitry Andric     TypeFound = false;
891e8d8bef9SDimitry Andric     // We can do this since it is a result value, and will have a number
892e8d8bef9SDimitry Andric     // that is necessarily the same. BUT if in the future, the instructions
893e8d8bef9SDimitry Andric     // do not have to be in same order, but are functionally the same, we will
894e8d8bef9SDimitry Andric     // have to use a different scheme, as one-to-one correspondence is not
895e8d8bef9SDimitry Andric     // guaranteed.
896e8d8bef9SDimitry Andric     unsigned GlobalValue = C.getGVN(Output).getValue();
897e8d8bef9SDimitry Andric     unsigned ArgumentSize = Group.ArgumentTypes.size();
898e8d8bef9SDimitry Andric 
899e8d8bef9SDimitry Andric     for (unsigned Jdx = TypeIndex; Jdx < ArgumentSize; Jdx++) {
900e8d8bef9SDimitry Andric       if (Group.ArgumentTypes[Jdx] != PointerType::getUnqual(Output->getType()))
901e8d8bef9SDimitry Andric         continue;
902e8d8bef9SDimitry Andric 
903e8d8bef9SDimitry Andric       if (AggArgsUsed.contains(Jdx))
904e8d8bef9SDimitry Andric         continue;
905e8d8bef9SDimitry Andric 
906e8d8bef9SDimitry Andric       TypeFound = true;
907e8d8bef9SDimitry Andric       AggArgsUsed.insert(Jdx);
908e8d8bef9SDimitry Andric       Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, Jdx));
909e8d8bef9SDimitry Andric       Region.AggArgToExtracted.insert(std::make_pair(Jdx, OriginalIndex));
910e8d8bef9SDimitry Andric       Region.GVNStores.push_back(GlobalValue);
911e8d8bef9SDimitry Andric       break;
912e8d8bef9SDimitry Andric     }
913e8d8bef9SDimitry Andric 
914e8d8bef9SDimitry Andric     // We were unable to find an unused type in the output type set that matches
915e8d8bef9SDimitry Andric     // the output, so we add a pointer type to the argument types of the overall
916e8d8bef9SDimitry Andric     // function to handle this output and create a mapping to it.
917e8d8bef9SDimitry Andric     if (!TypeFound) {
918e8d8bef9SDimitry Andric       Group.ArgumentTypes.push_back(PointerType::getUnqual(Output->getType()));
919e8d8bef9SDimitry Andric       AggArgsUsed.insert(Group.ArgumentTypes.size() - 1);
920e8d8bef9SDimitry Andric       Region.ExtractedArgToAgg.insert(
921e8d8bef9SDimitry Andric           std::make_pair(OriginalIndex, Group.ArgumentTypes.size() - 1));
922e8d8bef9SDimitry Andric       Region.AggArgToExtracted.insert(
923e8d8bef9SDimitry Andric           std::make_pair(Group.ArgumentTypes.size() - 1, OriginalIndex));
924e8d8bef9SDimitry Andric       Region.GVNStores.push_back(GlobalValue);
925e8d8bef9SDimitry Andric     }
926e8d8bef9SDimitry Andric 
927e8d8bef9SDimitry Andric     stable_sort(Region.GVNStores);
928e8d8bef9SDimitry Andric     OriginalIndex++;
929e8d8bef9SDimitry Andric     TypeIndex++;
930e8d8bef9SDimitry Andric   }
931e8d8bef9SDimitry Andric }
932e8d8bef9SDimitry Andric 
933e8d8bef9SDimitry Andric void IROutliner::findAddInputsOutputs(Module &M, OutlinableRegion &Region,
934e8d8bef9SDimitry Andric                                       DenseSet<unsigned> &NotSame) {
935e8d8bef9SDimitry Andric   std::vector<unsigned> Inputs;
936e8d8bef9SDimitry Andric   SetVector<Value *> ArgInputs, Outputs;
937e8d8bef9SDimitry Andric 
938e8d8bef9SDimitry Andric   getCodeExtractorArguments(Region, Inputs, NotSame, OutputMappings, ArgInputs,
939e8d8bef9SDimitry Andric                             Outputs);
940e8d8bef9SDimitry Andric 
941e8d8bef9SDimitry Andric   if (Region.IgnoreRegion)
942e8d8bef9SDimitry Andric     return;
943e8d8bef9SDimitry Andric 
944e8d8bef9SDimitry Andric   // Map the inputs found by the CodeExtractor to the arguments found for
945e8d8bef9SDimitry Andric   // the overall function.
946e8d8bef9SDimitry Andric   findExtractedInputToOverallInputMapping(Region, Inputs, ArgInputs);
947e8d8bef9SDimitry Andric 
948e8d8bef9SDimitry Andric   // Map the outputs found by the CodeExtractor to the arguments found for
949e8d8bef9SDimitry Andric   // the overall function.
950*349cc55cSDimitry Andric   findExtractedOutputToOverallOutputMapping(Region, Outputs);
951e8d8bef9SDimitry Andric }
952e8d8bef9SDimitry Andric 
953e8d8bef9SDimitry Andric /// Replace the extracted function in the Region with a call to the overall
954e8d8bef9SDimitry Andric /// function constructed from the deduplicated similar regions, replacing and
955e8d8bef9SDimitry Andric /// remapping the values passed to the extracted function as arguments to the
956e8d8bef9SDimitry Andric /// new arguments of the overall function.
957e8d8bef9SDimitry Andric ///
958e8d8bef9SDimitry Andric /// \param [in] M - The module to outline from.
959e8d8bef9SDimitry Andric /// \param [in] Region - The regions of extracted code to be replaced with a new
960e8d8bef9SDimitry Andric /// function.
961e8d8bef9SDimitry Andric /// \returns a call instruction with the replaced function.
962e8d8bef9SDimitry Andric CallInst *replaceCalledFunction(Module &M, OutlinableRegion &Region) {
963e8d8bef9SDimitry Andric   std::vector<Value *> NewCallArgs;
964e8d8bef9SDimitry Andric   DenseMap<unsigned, unsigned>::iterator ArgPair;
965e8d8bef9SDimitry Andric 
966e8d8bef9SDimitry Andric   OutlinableGroup &Group = *Region.Parent;
967e8d8bef9SDimitry Andric   CallInst *Call = Region.Call;
968e8d8bef9SDimitry Andric   assert(Call && "Call to replace is nullptr?");
969e8d8bef9SDimitry Andric   Function *AggFunc = Group.OutlinedFunction;
970e8d8bef9SDimitry Andric   assert(AggFunc && "Function to replace with is nullptr?");
971e8d8bef9SDimitry Andric 
972e8d8bef9SDimitry Andric   // If the arguments are the same size, there are not values that need to be
973*349cc55cSDimitry Andric   // made into an argument, the argument ordering has not been change, or
974*349cc55cSDimitry Andric   // different output registers to handle.  We can simply replace the called
975*349cc55cSDimitry Andric   // function in this case.
976*349cc55cSDimitry Andric   if (!Region.ChangedArgOrder && AggFunc->arg_size() == Call->arg_size()) {
977e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to "
978e8d8bef9SDimitry Andric                       << *AggFunc << " with same number of arguments\n");
979e8d8bef9SDimitry Andric     Call->setCalledFunction(AggFunc);
980e8d8bef9SDimitry Andric     return Call;
981e8d8bef9SDimitry Andric   }
982e8d8bef9SDimitry Andric 
983e8d8bef9SDimitry Andric   // We have a different number of arguments than the new function, so
984e8d8bef9SDimitry Andric   // we need to use our previously mappings off extracted argument to overall
985e8d8bef9SDimitry Andric   // function argument, and constants to overall function argument to create the
986e8d8bef9SDimitry Andric   // new argument list.
987e8d8bef9SDimitry Andric   for (unsigned AggArgIdx = 0; AggArgIdx < AggFunc->arg_size(); AggArgIdx++) {
988e8d8bef9SDimitry Andric 
989e8d8bef9SDimitry Andric     if (AggArgIdx == AggFunc->arg_size() - 1 &&
990e8d8bef9SDimitry Andric         Group.OutputGVNCombinations.size() > 1) {
991e8d8bef9SDimitry Andric       // If we are on the last argument, and we need to differentiate between
992e8d8bef9SDimitry Andric       // output blocks, add an integer to the argument list to determine
993e8d8bef9SDimitry Andric       // what block to take
994e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Set switch block argument to "
995e8d8bef9SDimitry Andric                         << Region.OutputBlockNum << "\n");
996e8d8bef9SDimitry Andric       NewCallArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()),
997e8d8bef9SDimitry Andric                                              Region.OutputBlockNum));
998e8d8bef9SDimitry Andric       continue;
999e8d8bef9SDimitry Andric     }
1000e8d8bef9SDimitry Andric 
1001e8d8bef9SDimitry Andric     ArgPair = Region.AggArgToExtracted.find(AggArgIdx);
1002e8d8bef9SDimitry Andric     if (ArgPair != Region.AggArgToExtracted.end()) {
1003e8d8bef9SDimitry Andric       Value *ArgumentValue = Call->getArgOperand(ArgPair->second);
1004e8d8bef9SDimitry Andric       // If we found the mapping from the extracted function to the overall
1005e8d8bef9SDimitry Andric       // function, we simply add it to the argument list.  We use the same
1006e8d8bef9SDimitry Andric       // value, it just needs to honor the new order of arguments.
1007e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to value "
1008e8d8bef9SDimitry Andric                         << *ArgumentValue << "\n");
1009e8d8bef9SDimitry Andric       NewCallArgs.push_back(ArgumentValue);
1010e8d8bef9SDimitry Andric       continue;
1011e8d8bef9SDimitry Andric     }
1012e8d8bef9SDimitry Andric 
1013e8d8bef9SDimitry Andric     // If it is a constant, we simply add it to the argument list as a value.
1014e8d8bef9SDimitry Andric     if (Region.AggArgToConstant.find(AggArgIdx) !=
1015e8d8bef9SDimitry Andric         Region.AggArgToConstant.end()) {
1016e8d8bef9SDimitry Andric       Constant *CST = Region.AggArgToConstant.find(AggArgIdx)->second;
1017e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to value "
1018e8d8bef9SDimitry Andric                         << *CST << "\n");
1019e8d8bef9SDimitry Andric       NewCallArgs.push_back(CST);
1020e8d8bef9SDimitry Andric       continue;
1021e8d8bef9SDimitry Andric     }
1022e8d8bef9SDimitry Andric 
1023e8d8bef9SDimitry Andric     // Add a nullptr value if the argument is not found in the extracted
1024e8d8bef9SDimitry Andric     // function.  If we cannot find a value, it means it is not in use
1025e8d8bef9SDimitry Andric     // for the region, so we should not pass anything to it.
1026e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to nullptr\n");
1027e8d8bef9SDimitry Andric     NewCallArgs.push_back(ConstantPointerNull::get(
1028e8d8bef9SDimitry Andric         static_cast<PointerType *>(AggFunc->getArg(AggArgIdx)->getType())));
1029e8d8bef9SDimitry Andric   }
1030e8d8bef9SDimitry Andric 
1031e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to "
1032e8d8bef9SDimitry Andric                     << *AggFunc << " with new set of arguments\n");
1033e8d8bef9SDimitry Andric   // Create the new call instruction and erase the old one.
1034e8d8bef9SDimitry Andric   Call = CallInst::Create(AggFunc->getFunctionType(), AggFunc, NewCallArgs, "",
1035e8d8bef9SDimitry Andric                           Call);
1036e8d8bef9SDimitry Andric 
1037e8d8bef9SDimitry Andric   // It is possible that the call to the outlined function is either the first
1038e8d8bef9SDimitry Andric   // instruction is in the new block, the last instruction, or both.  If either
1039e8d8bef9SDimitry Andric   // of these is the case, we need to make sure that we replace the instruction
1040e8d8bef9SDimitry Andric   // in the IRInstructionData struct with the new call.
1041e8d8bef9SDimitry Andric   CallInst *OldCall = Region.Call;
1042e8d8bef9SDimitry Andric   if (Region.NewFront->Inst == OldCall)
1043e8d8bef9SDimitry Andric     Region.NewFront->Inst = Call;
1044e8d8bef9SDimitry Andric   if (Region.NewBack->Inst == OldCall)
1045e8d8bef9SDimitry Andric     Region.NewBack->Inst = Call;
1046e8d8bef9SDimitry Andric 
1047e8d8bef9SDimitry Andric   // Transfer any debug information.
1048e8d8bef9SDimitry Andric   Call->setDebugLoc(Region.Call->getDebugLoc());
1049*349cc55cSDimitry Andric   // Since our output may determine which branch we go to, we make sure to
1050*349cc55cSDimitry Andric   // propogate this new call value through the module.
1051*349cc55cSDimitry Andric   OldCall->replaceAllUsesWith(Call);
1052e8d8bef9SDimitry Andric 
1053e8d8bef9SDimitry Andric   // Remove the old instruction.
1054e8d8bef9SDimitry Andric   OldCall->eraseFromParent();
1055e8d8bef9SDimitry Andric   Region.Call = Call;
1056e8d8bef9SDimitry Andric 
1057e8d8bef9SDimitry Andric   // Make sure that the argument in the new function has the SwiftError
1058e8d8bef9SDimitry Andric   // argument.
1059e8d8bef9SDimitry Andric   if (Group.SwiftErrorArgument.hasValue())
1060e8d8bef9SDimitry Andric     Call->addParamAttr(Group.SwiftErrorArgument.getValue(),
1061e8d8bef9SDimitry Andric                        Attribute::SwiftError);
1062e8d8bef9SDimitry Andric 
1063e8d8bef9SDimitry Andric   return Call;
1064e8d8bef9SDimitry Andric }
1065e8d8bef9SDimitry Andric 
1066e8d8bef9SDimitry Andric // Within an extracted function, replace the argument uses of the extracted
1067e8d8bef9SDimitry Andric // region with the arguments of the function for an OutlinableGroup.
1068e8d8bef9SDimitry Andric //
1069e8d8bef9SDimitry Andric /// \param [in] Region - The region of extracted code to be changed.
1070*349cc55cSDimitry Andric /// \param [in,out] OutputBBs - The BasicBlock for the output stores for this
1071e8d8bef9SDimitry Andric /// region.
1072*349cc55cSDimitry Andric /// \param [in] FirstFunction - A flag to indicate whether we are using this
1073*349cc55cSDimitry Andric /// function to define the overall outlined function for all the regions, or
1074*349cc55cSDimitry Andric /// if we are operating on one of the following regions.
1075*349cc55cSDimitry Andric static void
1076*349cc55cSDimitry Andric replaceArgumentUses(OutlinableRegion &Region,
1077*349cc55cSDimitry Andric                     DenseMap<Value *, BasicBlock *> &OutputBBs,
1078*349cc55cSDimitry Andric                     bool FirstFunction = false) {
1079e8d8bef9SDimitry Andric   OutlinableGroup &Group = *Region.Parent;
1080e8d8bef9SDimitry Andric   assert(Region.ExtractedFunction && "Region has no extracted function?");
1081e8d8bef9SDimitry Andric 
1082*349cc55cSDimitry Andric   Function *DominatingFunction = Region.ExtractedFunction;
1083*349cc55cSDimitry Andric   if (FirstFunction)
1084*349cc55cSDimitry Andric     DominatingFunction = Group.OutlinedFunction;
1085*349cc55cSDimitry Andric   DominatorTree DT(*DominatingFunction);
1086*349cc55cSDimitry Andric 
1087e8d8bef9SDimitry Andric   for (unsigned ArgIdx = 0; ArgIdx < Region.ExtractedFunction->arg_size();
1088e8d8bef9SDimitry Andric        ArgIdx++) {
1089e8d8bef9SDimitry Andric     assert(Region.ExtractedArgToAgg.find(ArgIdx) !=
1090e8d8bef9SDimitry Andric                Region.ExtractedArgToAgg.end() &&
1091e8d8bef9SDimitry Andric            "No mapping from extracted to outlined?");
1092e8d8bef9SDimitry Andric     unsigned AggArgIdx = Region.ExtractedArgToAgg.find(ArgIdx)->second;
1093e8d8bef9SDimitry Andric     Argument *AggArg = Group.OutlinedFunction->getArg(AggArgIdx);
1094e8d8bef9SDimitry Andric     Argument *Arg = Region.ExtractedFunction->getArg(ArgIdx);
1095e8d8bef9SDimitry Andric     // The argument is an input, so we can simply replace it with the overall
1096e8d8bef9SDimitry Andric     // argument value
1097e8d8bef9SDimitry Andric     if (ArgIdx < Region.NumExtractedInputs) {
1098e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Replacing uses of input " << *Arg << " in function "
1099e8d8bef9SDimitry Andric                         << *Region.ExtractedFunction << " with " << *AggArg
1100e8d8bef9SDimitry Andric                         << " in function " << *Group.OutlinedFunction << "\n");
1101e8d8bef9SDimitry Andric       Arg->replaceAllUsesWith(AggArg);
1102e8d8bef9SDimitry Andric       continue;
1103e8d8bef9SDimitry Andric     }
1104e8d8bef9SDimitry Andric 
1105e8d8bef9SDimitry Andric     // If we are replacing an output, we place the store value in its own
1106e8d8bef9SDimitry Andric     // block inside the overall function before replacing the use of the output
1107e8d8bef9SDimitry Andric     // in the function.
1108e8d8bef9SDimitry Andric     assert(Arg->hasOneUse() && "Output argument can only have one use");
1109e8d8bef9SDimitry Andric     User *InstAsUser = Arg->user_back();
1110e8d8bef9SDimitry Andric     assert(InstAsUser && "User is nullptr!");
1111e8d8bef9SDimitry Andric 
1112e8d8bef9SDimitry Andric     Instruction *I = cast<Instruction>(InstAsUser);
1113*349cc55cSDimitry Andric     BasicBlock *BB = I->getParent();
1114*349cc55cSDimitry Andric     SmallVector<BasicBlock *, 4> Descendants;
1115*349cc55cSDimitry Andric     DT.getDescendants(BB, Descendants);
1116*349cc55cSDimitry Andric     bool EdgeAdded = false;
1117*349cc55cSDimitry Andric     if (Descendants.size() == 0) {
1118*349cc55cSDimitry Andric       EdgeAdded = true;
1119*349cc55cSDimitry Andric       DT.insertEdge(&DominatingFunction->getEntryBlock(), BB);
1120*349cc55cSDimitry Andric       DT.getDescendants(BB, Descendants);
1121*349cc55cSDimitry Andric     }
1122*349cc55cSDimitry Andric 
1123*349cc55cSDimitry Andric     // Iterate over the following blocks, looking for return instructions,
1124*349cc55cSDimitry Andric     // if we find one, find the corresponding output block for the return value
1125*349cc55cSDimitry Andric     // and move our store instruction there.
1126*349cc55cSDimitry Andric     for (BasicBlock *DescendBB : Descendants) {
1127*349cc55cSDimitry Andric       ReturnInst *RI = dyn_cast<ReturnInst>(DescendBB->getTerminator());
1128*349cc55cSDimitry Andric       if (!RI)
1129*349cc55cSDimitry Andric         continue;
1130*349cc55cSDimitry Andric       Value *RetVal = RI->getReturnValue();
1131*349cc55cSDimitry Andric       auto VBBIt = OutputBBs.find(RetVal);
1132*349cc55cSDimitry Andric       assert(VBBIt != OutputBBs.end() && "Could not find output value!");
1133*349cc55cSDimitry Andric 
1134*349cc55cSDimitry Andric       // If this is storing a PHINode, we must make sure it is included in the
1135*349cc55cSDimitry Andric       // overall function.
1136*349cc55cSDimitry Andric       StoreInst *SI = cast<StoreInst>(I);
1137*349cc55cSDimitry Andric 
1138*349cc55cSDimitry Andric       Value *ValueOperand = SI->getValueOperand();
1139*349cc55cSDimitry Andric 
1140*349cc55cSDimitry Andric       StoreInst *NewI = cast<StoreInst>(I->clone());
1141*349cc55cSDimitry Andric       NewI->setDebugLoc(DebugLoc());
1142*349cc55cSDimitry Andric       BasicBlock *OutputBB = VBBIt->second;
1143*349cc55cSDimitry Andric       OutputBB->getInstList().push_back(NewI);
1144e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Move store for instruction " << *I << " to "
1145e8d8bef9SDimitry Andric                         << *OutputBB << "\n");
1146e8d8bef9SDimitry Andric 
1147*349cc55cSDimitry Andric       if (FirstFunction)
1148*349cc55cSDimitry Andric         continue;
1149*349cc55cSDimitry Andric       Value *CorrVal =
1150*349cc55cSDimitry Andric           Region.findCorrespondingValueIn(*Group.Regions[0], ValueOperand);
1151*349cc55cSDimitry Andric       assert(CorrVal && "Value is nullptr?");
1152*349cc55cSDimitry Andric       NewI->setOperand(0, CorrVal);
1153*349cc55cSDimitry Andric     }
1154*349cc55cSDimitry Andric 
1155*349cc55cSDimitry Andric     // If we added an edge for basic blocks without a predecessor, we remove it
1156*349cc55cSDimitry Andric     // here.
1157*349cc55cSDimitry Andric     if (EdgeAdded)
1158*349cc55cSDimitry Andric       DT.deleteEdge(&DominatingFunction->getEntryBlock(), BB);
1159*349cc55cSDimitry Andric     I->eraseFromParent();
1160e8d8bef9SDimitry Andric 
1161e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Replacing uses of output " << *Arg << " in function "
1162e8d8bef9SDimitry Andric                       << *Region.ExtractedFunction << " with " << *AggArg
1163e8d8bef9SDimitry Andric                       << " in function " << *Group.OutlinedFunction << "\n");
1164e8d8bef9SDimitry Andric     Arg->replaceAllUsesWith(AggArg);
1165e8d8bef9SDimitry Andric   }
1166e8d8bef9SDimitry Andric }
1167e8d8bef9SDimitry Andric 
1168e8d8bef9SDimitry Andric /// Within an extracted function, replace the constants that need to be lifted
1169e8d8bef9SDimitry Andric /// into arguments with the actual argument.
1170e8d8bef9SDimitry Andric ///
1171e8d8bef9SDimitry Andric /// \param Region [in] - The region of extracted code to be changed.
1172e8d8bef9SDimitry Andric void replaceConstants(OutlinableRegion &Region) {
1173e8d8bef9SDimitry Andric   OutlinableGroup &Group = *Region.Parent;
1174e8d8bef9SDimitry Andric   // Iterate over the constants that need to be elevated into arguments
1175e8d8bef9SDimitry Andric   for (std::pair<unsigned, Constant *> &Const : Region.AggArgToConstant) {
1176e8d8bef9SDimitry Andric     unsigned AggArgIdx = Const.first;
1177e8d8bef9SDimitry Andric     Function *OutlinedFunction = Group.OutlinedFunction;
1178e8d8bef9SDimitry Andric     assert(OutlinedFunction && "Overall Function is not defined?");
1179e8d8bef9SDimitry Andric     Constant *CST = Const.second;
1180e8d8bef9SDimitry Andric     Argument *Arg = Group.OutlinedFunction->getArg(AggArgIdx);
1181e8d8bef9SDimitry Andric     // Identify the argument it will be elevated to, and replace instances of
1182e8d8bef9SDimitry Andric     // that constant in the function.
1183e8d8bef9SDimitry Andric 
1184e8d8bef9SDimitry Andric     // TODO: If in the future constants do not have one global value number,
1185e8d8bef9SDimitry Andric     // i.e. a constant 1 could be mapped to several values, this check will
1186e8d8bef9SDimitry Andric     // have to be more strict.  It cannot be using only replaceUsesWithIf.
1187e8d8bef9SDimitry Andric 
1188e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Replacing uses of constant " << *CST
1189e8d8bef9SDimitry Andric                       << " in function " << *OutlinedFunction << " with "
1190e8d8bef9SDimitry Andric                       << *Arg << "\n");
1191e8d8bef9SDimitry Andric     CST->replaceUsesWithIf(Arg, [OutlinedFunction](Use &U) {
1192e8d8bef9SDimitry Andric       if (Instruction *I = dyn_cast<Instruction>(U.getUser()))
1193e8d8bef9SDimitry Andric         return I->getFunction() == OutlinedFunction;
1194e8d8bef9SDimitry Andric       return false;
1195e8d8bef9SDimitry Andric     });
1196e8d8bef9SDimitry Andric   }
1197e8d8bef9SDimitry Andric }
1198e8d8bef9SDimitry Andric 
1199e8d8bef9SDimitry Andric /// It is possible that there is a basic block that already performs the same
1200e8d8bef9SDimitry Andric /// stores. This returns a duplicate block, if it exists
1201e8d8bef9SDimitry Andric ///
1202*349cc55cSDimitry Andric /// \param OutputBBs [in] the blocks we are looking for a duplicate of.
1203e8d8bef9SDimitry Andric /// \param OutputStoreBBs [in] The existing output blocks.
1204e8d8bef9SDimitry Andric /// \returns an optional value with the number output block if there is a match.
1205*349cc55cSDimitry Andric Optional<unsigned> findDuplicateOutputBlock(
1206*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *> &OutputBBs,
1207*349cc55cSDimitry Andric     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
1208e8d8bef9SDimitry Andric 
1209*349cc55cSDimitry Andric   bool Mismatch = false;
1210e8d8bef9SDimitry Andric   unsigned MatchingNum = 0;
1211*349cc55cSDimitry Andric   // We compare the new set output blocks to the other sets of output blocks.
1212*349cc55cSDimitry Andric   // If they are the same number, and have identical instructions, they are
1213*349cc55cSDimitry Andric   // considered to be the same.
1214*349cc55cSDimitry Andric   for (DenseMap<Value *, BasicBlock *> &CompBBs : OutputStoreBBs) {
1215*349cc55cSDimitry Andric     Mismatch = false;
1216*349cc55cSDimitry Andric     for (std::pair<Value *, BasicBlock *> &VToB : CompBBs) {
1217*349cc55cSDimitry Andric       DenseMap<Value *, BasicBlock *>::iterator OutputBBIt =
1218*349cc55cSDimitry Andric           OutputBBs.find(VToB.first);
1219*349cc55cSDimitry Andric       if (OutputBBIt == OutputBBs.end()) {
1220*349cc55cSDimitry Andric         Mismatch = true;
1221*349cc55cSDimitry Andric         break;
1222e8d8bef9SDimitry Andric       }
1223e8d8bef9SDimitry Andric 
1224*349cc55cSDimitry Andric       BasicBlock *CompBB = VToB.second;
1225*349cc55cSDimitry Andric       BasicBlock *OutputBB = OutputBBIt->second;
1226*349cc55cSDimitry Andric       if (CompBB->size() - 1 != OutputBB->size()) {
1227*349cc55cSDimitry Andric         Mismatch = true;
1228*349cc55cSDimitry Andric         break;
1229*349cc55cSDimitry Andric       }
1230*349cc55cSDimitry Andric 
1231e8d8bef9SDimitry Andric       BasicBlock::iterator NIt = OutputBB->begin();
1232e8d8bef9SDimitry Andric       for (Instruction &I : *CompBB) {
1233e8d8bef9SDimitry Andric         if (isa<BranchInst>(&I))
1234e8d8bef9SDimitry Andric           continue;
1235e8d8bef9SDimitry Andric 
1236e8d8bef9SDimitry Andric         if (!I.isIdenticalTo(&(*NIt))) {
1237*349cc55cSDimitry Andric           Mismatch = true;
1238e8d8bef9SDimitry Andric           break;
1239e8d8bef9SDimitry Andric         }
1240e8d8bef9SDimitry Andric 
1241e8d8bef9SDimitry Andric         NIt++;
1242e8d8bef9SDimitry Andric       }
1243*349cc55cSDimitry Andric     }
1244*349cc55cSDimitry Andric 
1245*349cc55cSDimitry Andric     if (!Mismatch)
1246e8d8bef9SDimitry Andric       return MatchingNum;
1247e8d8bef9SDimitry Andric 
1248e8d8bef9SDimitry Andric     MatchingNum++;
1249e8d8bef9SDimitry Andric   }
1250e8d8bef9SDimitry Andric 
1251e8d8bef9SDimitry Andric   return None;
1252e8d8bef9SDimitry Andric }
1253e8d8bef9SDimitry Andric 
1254*349cc55cSDimitry Andric /// Remove empty output blocks from the outlined region.
1255*349cc55cSDimitry Andric ///
1256*349cc55cSDimitry Andric /// \param BlocksToPrune - Mapping of return values output blocks for the \p
1257*349cc55cSDimitry Andric /// Region.
1258*349cc55cSDimitry Andric /// \param Region - The OutlinableRegion we are analyzing.
1259*349cc55cSDimitry Andric static bool
1260*349cc55cSDimitry Andric analyzeAndPruneOutputBlocks(DenseMap<Value *, BasicBlock *> &BlocksToPrune,
1261*349cc55cSDimitry Andric                             OutlinableRegion &Region) {
1262*349cc55cSDimitry Andric   bool AllRemoved = true;
1263*349cc55cSDimitry Andric   Value *RetValueForBB;
1264*349cc55cSDimitry Andric   BasicBlock *NewBB;
1265*349cc55cSDimitry Andric   SmallVector<Value *, 4> ToRemove;
1266*349cc55cSDimitry Andric   // Iterate over the output blocks created in the outlined section.
1267*349cc55cSDimitry Andric   for (std::pair<Value *, BasicBlock *> &VtoBB : BlocksToPrune) {
1268*349cc55cSDimitry Andric     RetValueForBB = VtoBB.first;
1269*349cc55cSDimitry Andric     NewBB = VtoBB.second;
1270*349cc55cSDimitry Andric 
1271*349cc55cSDimitry Andric     // If there are no instructions, we remove it from the module, and also
1272*349cc55cSDimitry Andric     // mark the value for removal from the return value to output block mapping.
1273*349cc55cSDimitry Andric     if (NewBB->size() == 0) {
1274*349cc55cSDimitry Andric       NewBB->eraseFromParent();
1275*349cc55cSDimitry Andric       ToRemove.push_back(RetValueForBB);
1276*349cc55cSDimitry Andric       continue;
1277*349cc55cSDimitry Andric     }
1278*349cc55cSDimitry Andric 
1279*349cc55cSDimitry Andric     // Mark that we could not remove all the blocks since they were not all
1280*349cc55cSDimitry Andric     // empty.
1281*349cc55cSDimitry Andric     AllRemoved = false;
1282*349cc55cSDimitry Andric   }
1283*349cc55cSDimitry Andric 
1284*349cc55cSDimitry Andric   // Remove the return value from the mapping.
1285*349cc55cSDimitry Andric   for (Value *V : ToRemove)
1286*349cc55cSDimitry Andric     BlocksToPrune.erase(V);
1287*349cc55cSDimitry Andric 
1288*349cc55cSDimitry Andric   // Mark the region as having the no output scheme.
1289*349cc55cSDimitry Andric   if (AllRemoved)
1290*349cc55cSDimitry Andric     Region.OutputBlockNum = -1;
1291*349cc55cSDimitry Andric 
1292*349cc55cSDimitry Andric   return AllRemoved;
1293*349cc55cSDimitry Andric }
1294*349cc55cSDimitry Andric 
1295e8d8bef9SDimitry Andric /// For the outlined section, move needed the StoreInsts for the output
1296e8d8bef9SDimitry Andric /// registers into their own block. Then, determine if there is a duplicate
1297e8d8bef9SDimitry Andric /// output block already created.
1298e8d8bef9SDimitry Andric ///
1299e8d8bef9SDimitry Andric /// \param [in] OG - The OutlinableGroup of regions to be outlined.
1300e8d8bef9SDimitry Andric /// \param [in] Region - The OutlinableRegion that is being analyzed.
1301*349cc55cSDimitry Andric /// \param [in,out] OutputBBs - the blocks that stores for this region will be
1302e8d8bef9SDimitry Andric /// placed in.
1303*349cc55cSDimitry Andric /// \param [in] EndBBs - the final blocks of the extracted function.
1304e8d8bef9SDimitry Andric /// \param [in] OutputMappings - OutputMappings the mapping of values that have
1305e8d8bef9SDimitry Andric /// been replaced by a new output value.
1306e8d8bef9SDimitry Andric /// \param [in,out] OutputStoreBBs - The existing output blocks.
1307*349cc55cSDimitry Andric static void alignOutputBlockWithAggFunc(
1308*349cc55cSDimitry Andric     OutlinableGroup &OG, OutlinableRegion &Region,
1309*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *> &OutputBBs,
1310*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *> &EndBBs,
1311e8d8bef9SDimitry Andric     const DenseMap<Value *, Value *> &OutputMappings,
1312*349cc55cSDimitry Andric     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
1313*349cc55cSDimitry Andric   // If none of the output blocks have any instructions, this means that we do
1314*349cc55cSDimitry Andric   // not have to determine if it matches any of the other output schemes, and we
1315*349cc55cSDimitry Andric   // don't have to do anything else.
1316*349cc55cSDimitry Andric   if (analyzeAndPruneOutputBlocks(OutputBBs, Region))
1317e8d8bef9SDimitry Andric     return;
1318e8d8bef9SDimitry Andric 
1319*349cc55cSDimitry Andric   // Determine is there is a duplicate set of blocks.
1320e8d8bef9SDimitry Andric   Optional<unsigned> MatchingBB =
1321*349cc55cSDimitry Andric       findDuplicateOutputBlock(OutputBBs, OutputStoreBBs);
1322e8d8bef9SDimitry Andric 
1323*349cc55cSDimitry Andric   // If there is, we remove the new output blocks.  If it does not,
1324*349cc55cSDimitry Andric   // we add it to our list of sets of output blocks.
1325e8d8bef9SDimitry Andric   if (MatchingBB.hasValue()) {
1326e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Set output block for region in function"
1327e8d8bef9SDimitry Andric                       << Region.ExtractedFunction << " to "
1328e8d8bef9SDimitry Andric                       << MatchingBB.getValue());
1329e8d8bef9SDimitry Andric 
1330e8d8bef9SDimitry Andric     Region.OutputBlockNum = MatchingBB.getValue();
1331*349cc55cSDimitry Andric     for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs)
1332*349cc55cSDimitry Andric       VtoBB.second->eraseFromParent();
1333e8d8bef9SDimitry Andric     return;
1334e8d8bef9SDimitry Andric   }
1335e8d8bef9SDimitry Andric 
1336e8d8bef9SDimitry Andric   Region.OutputBlockNum = OutputStoreBBs.size();
1337e8d8bef9SDimitry Andric 
1338*349cc55cSDimitry Andric   Value *RetValueForBB;
1339*349cc55cSDimitry Andric   BasicBlock *NewBB;
1340*349cc55cSDimitry Andric   OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
1341*349cc55cSDimitry Andric   for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs) {
1342*349cc55cSDimitry Andric     RetValueForBB = VtoBB.first;
1343*349cc55cSDimitry Andric     NewBB = VtoBB.second;
1344*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *>::iterator VBBIt =
1345*349cc55cSDimitry Andric         EndBBs.find(RetValueForBB);
1346e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Create output block for region in"
1347e8d8bef9SDimitry Andric                       << Region.ExtractedFunction << " to "
1348*349cc55cSDimitry Andric                       << *NewBB);
1349*349cc55cSDimitry Andric     BranchInst::Create(VBBIt->second, NewBB);
1350*349cc55cSDimitry Andric     OutputStoreBBs.back().insert(std::make_pair(RetValueForBB, NewBB));
1351*349cc55cSDimitry Andric   }
1352*349cc55cSDimitry Andric }
1353*349cc55cSDimitry Andric 
1354*349cc55cSDimitry Andric /// Takes in a mapping, \p OldMap of ConstantValues to BasicBlocks, sorts keys,
1355*349cc55cSDimitry Andric /// before creating a basic block for each \p NewMap, and inserting into the new
1356*349cc55cSDimitry Andric /// block. Each BasicBlock is named with the scheme "<basename>_<key_idx>".
1357*349cc55cSDimitry Andric ///
1358*349cc55cSDimitry Andric /// \param OldMap [in] - The mapping to base the new mapping off of.
1359*349cc55cSDimitry Andric /// \param NewMap [out] - The output mapping using the keys of \p OldMap.
1360*349cc55cSDimitry Andric /// \param ParentFunc [in] - The function to put the new basic block in.
1361*349cc55cSDimitry Andric /// \param BaseName [in] - The start of the BasicBlock names to be appended to
1362*349cc55cSDimitry Andric /// by an index value.
1363*349cc55cSDimitry Andric static void createAndInsertBasicBlocks(DenseMap<Value *, BasicBlock *> &OldMap,
1364*349cc55cSDimitry Andric                                        DenseMap<Value *, BasicBlock *> &NewMap,
1365*349cc55cSDimitry Andric                                        Function *ParentFunc, Twine BaseName) {
1366*349cc55cSDimitry Andric   unsigned Idx = 0;
1367*349cc55cSDimitry Andric   std::vector<Value *> SortedKeys;
1368*349cc55cSDimitry Andric 
1369*349cc55cSDimitry Andric   getSortedConstantKeys(SortedKeys, OldMap);
1370*349cc55cSDimitry Andric 
1371*349cc55cSDimitry Andric   for (Value *RetVal : SortedKeys) {
1372*349cc55cSDimitry Andric     BasicBlock *NewBB = BasicBlock::Create(
1373*349cc55cSDimitry Andric         ParentFunc->getContext(),
1374*349cc55cSDimitry Andric         Twine(BaseName) + Twine("_") + Twine(static_cast<unsigned>(Idx++)),
1375*349cc55cSDimitry Andric         ParentFunc);
1376*349cc55cSDimitry Andric     NewMap.insert(std::make_pair(RetVal, NewBB));
1377*349cc55cSDimitry Andric   }
1378e8d8bef9SDimitry Andric }
1379e8d8bef9SDimitry Andric 
1380e8d8bef9SDimitry Andric /// Create the switch statement for outlined function to differentiate between
1381e8d8bef9SDimitry Andric /// all the output blocks.
1382e8d8bef9SDimitry Andric ///
1383e8d8bef9SDimitry Andric /// For the outlined section, determine if an outlined block already exists that
1384e8d8bef9SDimitry Andric /// matches the needed stores for the extracted section.
1385e8d8bef9SDimitry Andric /// \param [in] M - The module we are outlining from.
1386e8d8bef9SDimitry Andric /// \param [in] OG - The group of regions to be outlined.
1387*349cc55cSDimitry Andric /// \param [in] EndBBs - The final blocks of the extracted function.
1388e8d8bef9SDimitry Andric /// \param [in,out] OutputStoreBBs - The existing output blocks.
1389*349cc55cSDimitry Andric void createSwitchStatement(
1390*349cc55cSDimitry Andric     Module &M, OutlinableGroup &OG, DenseMap<Value *, BasicBlock *> &EndBBs,
1391*349cc55cSDimitry Andric     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
1392e8d8bef9SDimitry Andric   // We only need the switch statement if there is more than one store
1393e8d8bef9SDimitry Andric   // combination.
1394e8d8bef9SDimitry Andric   if (OG.OutputGVNCombinations.size() > 1) {
1395e8d8bef9SDimitry Andric     Function *AggFunc = OG.OutlinedFunction;
1396*349cc55cSDimitry Andric     // Create a final block for each different return block.
1397*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *> ReturnBBs;
1398*349cc55cSDimitry Andric     createAndInsertBasicBlocks(OG.EndBBs, ReturnBBs, AggFunc, "final_block");
1399*349cc55cSDimitry Andric 
1400*349cc55cSDimitry Andric     for (std::pair<Value *, BasicBlock *> &RetBlockPair : ReturnBBs) {
1401*349cc55cSDimitry Andric       std::pair<Value *, BasicBlock *> &OutputBlock =
1402*349cc55cSDimitry Andric           *OG.EndBBs.find(RetBlockPair.first);
1403*349cc55cSDimitry Andric       BasicBlock *ReturnBlock = RetBlockPair.second;
1404*349cc55cSDimitry Andric       BasicBlock *EndBB = OutputBlock.second;
1405e8d8bef9SDimitry Andric       Instruction *Term = EndBB->getTerminator();
1406*349cc55cSDimitry Andric       // Move the return value to the final block instead of the original exit
1407*349cc55cSDimitry Andric       // stub.
1408e8d8bef9SDimitry Andric       Term->moveBefore(*ReturnBlock, ReturnBlock->end());
1409*349cc55cSDimitry Andric       // Put the switch statement in the old end basic block for the function
1410*349cc55cSDimitry Andric       // with a fall through to the new return block.
1411e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Create switch statement in " << *AggFunc << " for "
1412e8d8bef9SDimitry Andric                         << OutputStoreBBs.size() << "\n");
1413e8d8bef9SDimitry Andric       SwitchInst *SwitchI =
1414e8d8bef9SDimitry Andric           SwitchInst::Create(AggFunc->getArg(AggFunc->arg_size() - 1),
1415e8d8bef9SDimitry Andric                              ReturnBlock, OutputStoreBBs.size(), EndBB);
1416e8d8bef9SDimitry Andric 
1417e8d8bef9SDimitry Andric       unsigned Idx = 0;
1418*349cc55cSDimitry Andric       for (DenseMap<Value *, BasicBlock *> &OutputStoreBB : OutputStoreBBs) {
1419*349cc55cSDimitry Andric         DenseMap<Value *, BasicBlock *>::iterator OSBBIt =
1420*349cc55cSDimitry Andric             OutputStoreBB.find(OutputBlock.first);
1421*349cc55cSDimitry Andric 
1422*349cc55cSDimitry Andric         if (OSBBIt == OutputStoreBB.end())
1423*349cc55cSDimitry Andric           continue;
1424*349cc55cSDimitry Andric 
1425*349cc55cSDimitry Andric         BasicBlock *BB = OSBBIt->second;
1426*349cc55cSDimitry Andric         SwitchI->addCase(
1427*349cc55cSDimitry Andric             ConstantInt::get(Type::getInt32Ty(M.getContext()), Idx), BB);
1428e8d8bef9SDimitry Andric         Term = BB->getTerminator();
1429e8d8bef9SDimitry Andric         Term->setSuccessor(0, ReturnBlock);
1430e8d8bef9SDimitry Andric         Idx++;
1431e8d8bef9SDimitry Andric       }
1432*349cc55cSDimitry Andric     }
1433e8d8bef9SDimitry Andric     return;
1434e8d8bef9SDimitry Andric   }
1435e8d8bef9SDimitry Andric 
1436*349cc55cSDimitry Andric   // If there needs to be stores, move them from the output blocks to their
1437*349cc55cSDimitry Andric   // corresponding ending block.
1438e8d8bef9SDimitry Andric   if (OutputStoreBBs.size() == 1) {
1439e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Move store instructions to the end block in "
1440e8d8bef9SDimitry Andric                       << *OG.OutlinedFunction << "\n");
1441*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *> OutputBlocks = OutputStoreBBs[0];
1442*349cc55cSDimitry Andric     for (std::pair<Value *, BasicBlock *> &VBPair : OutputBlocks) {
1443*349cc55cSDimitry Andric       DenseMap<Value *, BasicBlock *>::iterator EndBBIt =
1444*349cc55cSDimitry Andric           EndBBs.find(VBPair.first);
1445*349cc55cSDimitry Andric       assert(EndBBIt != EndBBs.end() && "Could not find end block");
1446*349cc55cSDimitry Andric       BasicBlock *EndBB = EndBBIt->second;
1447*349cc55cSDimitry Andric       BasicBlock *OutputBB = VBPair.second;
1448*349cc55cSDimitry Andric       Instruction *Term = OutputBB->getTerminator();
1449e8d8bef9SDimitry Andric       Term->eraseFromParent();
1450e8d8bef9SDimitry Andric       Term = EndBB->getTerminator();
1451*349cc55cSDimitry Andric       moveBBContents(*OutputBB, *EndBB);
1452e8d8bef9SDimitry Andric       Term->moveBefore(*EndBB, EndBB->end());
1453*349cc55cSDimitry Andric       OutputBB->eraseFromParent();
1454*349cc55cSDimitry Andric     }
1455e8d8bef9SDimitry Andric   }
1456e8d8bef9SDimitry Andric }
1457e8d8bef9SDimitry Andric 
1458e8d8bef9SDimitry Andric /// Fill the new function that will serve as the replacement function for all of
1459e8d8bef9SDimitry Andric /// the extracted regions of a certain structure from the first region in the
1460e8d8bef9SDimitry Andric /// list of regions.  Replace this first region's extracted function with the
1461e8d8bef9SDimitry Andric /// new overall function.
1462e8d8bef9SDimitry Andric ///
1463e8d8bef9SDimitry Andric /// \param [in] M - The module we are outlining from.
1464e8d8bef9SDimitry Andric /// \param [in] CurrentGroup - The group of regions to be outlined.
1465e8d8bef9SDimitry Andric /// \param [in,out] OutputStoreBBs - The output blocks for each different
1466e8d8bef9SDimitry Andric /// set of stores needed for the different functions.
1467e8d8bef9SDimitry Andric /// \param [in,out] FuncsToRemove - Extracted functions to erase from module
1468e8d8bef9SDimitry Andric /// once outlining is complete.
1469*349cc55cSDimitry Andric static void fillOverallFunction(
1470*349cc55cSDimitry Andric     Module &M, OutlinableGroup &CurrentGroup,
1471*349cc55cSDimitry Andric     std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs,
1472e8d8bef9SDimitry Andric     std::vector<Function *> &FuncsToRemove) {
1473e8d8bef9SDimitry Andric   OutlinableRegion *CurrentOS = CurrentGroup.Regions[0];
1474e8d8bef9SDimitry Andric 
1475e8d8bef9SDimitry Andric   // Move first extracted function's instructions into new function.
1476e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Move instructions from "
1477e8d8bef9SDimitry Andric                     << *CurrentOS->ExtractedFunction << " to instruction "
1478e8d8bef9SDimitry Andric                     << *CurrentGroup.OutlinedFunction << "\n");
1479*349cc55cSDimitry Andric   moveFunctionData(*CurrentOS->ExtractedFunction,
1480*349cc55cSDimitry Andric                    *CurrentGroup.OutlinedFunction, CurrentGroup.EndBBs);
1481e8d8bef9SDimitry Andric 
1482e8d8bef9SDimitry Andric   // Transfer the attributes from the function to the new function.
1483*349cc55cSDimitry Andric   for (Attribute A : CurrentOS->ExtractedFunction->getAttributes().getFnAttrs())
1484e8d8bef9SDimitry Andric     CurrentGroup.OutlinedFunction->addFnAttr(A);
1485e8d8bef9SDimitry Andric 
1486*349cc55cSDimitry Andric   // Create a new set of output blocks for the first extracted function.
1487*349cc55cSDimitry Andric   DenseMap<Value *, BasicBlock *> NewBBs;
1488*349cc55cSDimitry Andric   createAndInsertBasicBlocks(CurrentGroup.EndBBs, NewBBs,
1489*349cc55cSDimitry Andric                              CurrentGroup.OutlinedFunction, "output_block_0");
1490e8d8bef9SDimitry Andric   CurrentOS->OutputBlockNum = 0;
1491e8d8bef9SDimitry Andric 
1492*349cc55cSDimitry Andric   replaceArgumentUses(*CurrentOS, NewBBs, true);
1493e8d8bef9SDimitry Andric   replaceConstants(*CurrentOS);
1494e8d8bef9SDimitry Andric 
1495*349cc55cSDimitry Andric   // We first identify if any output blocks are empty, if they are we remove
1496*349cc55cSDimitry Andric   // them. We then create a branch instruction to the basic block to the return
1497*349cc55cSDimitry Andric   // block for the function for each non empty output block.
1498*349cc55cSDimitry Andric   if (!analyzeAndPruneOutputBlocks(NewBBs, *CurrentOS)) {
1499*349cc55cSDimitry Andric     OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
1500*349cc55cSDimitry Andric     for (std::pair<Value *, BasicBlock *> &VToBB : NewBBs) {
1501*349cc55cSDimitry Andric       DenseMap<Value *, BasicBlock *>::iterator VBBIt =
1502*349cc55cSDimitry Andric           CurrentGroup.EndBBs.find(VToBB.first);
1503*349cc55cSDimitry Andric       BasicBlock *EndBB = VBBIt->second;
1504*349cc55cSDimitry Andric       BranchInst::Create(EndBB, VToBB.second);
1505*349cc55cSDimitry Andric       OutputStoreBBs.back().insert(VToBB);
1506*349cc55cSDimitry Andric     }
1507e8d8bef9SDimitry Andric   }
1508e8d8bef9SDimitry Andric 
1509e8d8bef9SDimitry Andric   // Replace the call to the extracted function with the outlined function.
1510e8d8bef9SDimitry Andric   CurrentOS->Call = replaceCalledFunction(M, *CurrentOS);
1511e8d8bef9SDimitry Andric 
1512e8d8bef9SDimitry Andric   // We only delete the extracted functions at the end since we may need to
1513e8d8bef9SDimitry Andric   // reference instructions contained in them for mapping purposes.
1514e8d8bef9SDimitry Andric   FuncsToRemove.push_back(CurrentOS->ExtractedFunction);
1515e8d8bef9SDimitry Andric }
1516e8d8bef9SDimitry Andric 
1517e8d8bef9SDimitry Andric void IROutliner::deduplicateExtractedSections(
1518e8d8bef9SDimitry Andric     Module &M, OutlinableGroup &CurrentGroup,
1519e8d8bef9SDimitry Andric     std::vector<Function *> &FuncsToRemove, unsigned &OutlinedFunctionNum) {
1520e8d8bef9SDimitry Andric   createFunction(M, CurrentGroup, OutlinedFunctionNum);
1521e8d8bef9SDimitry Andric 
1522*349cc55cSDimitry Andric   std::vector<DenseMap<Value *, BasicBlock *>> OutputStoreBBs;
1523e8d8bef9SDimitry Andric 
1524e8d8bef9SDimitry Andric   OutlinableRegion *CurrentOS;
1525e8d8bef9SDimitry Andric 
1526e8d8bef9SDimitry Andric   fillOverallFunction(M, CurrentGroup, OutputStoreBBs, FuncsToRemove);
1527e8d8bef9SDimitry Andric 
1528*349cc55cSDimitry Andric   std::vector<Value *> SortedKeys;
1529e8d8bef9SDimitry Andric   for (unsigned Idx = 1; Idx < CurrentGroup.Regions.size(); Idx++) {
1530e8d8bef9SDimitry Andric     CurrentOS = CurrentGroup.Regions[Idx];
1531e8d8bef9SDimitry Andric     AttributeFuncs::mergeAttributesForOutlining(*CurrentGroup.OutlinedFunction,
1532e8d8bef9SDimitry Andric                                                *CurrentOS->ExtractedFunction);
1533e8d8bef9SDimitry Andric 
1534*349cc55cSDimitry Andric     // Create a set of BasicBlocks, one for each return block, to hold the
1535*349cc55cSDimitry Andric     // needed store instructions.
1536*349cc55cSDimitry Andric     DenseMap<Value *, BasicBlock *> NewBBs;
1537*349cc55cSDimitry Andric     createAndInsertBasicBlocks(
1538*349cc55cSDimitry Andric         CurrentGroup.EndBBs, NewBBs, CurrentGroup.OutlinedFunction,
1539*349cc55cSDimitry Andric         "output_block_" + Twine(static_cast<unsigned>(Idx)));
1540e8d8bef9SDimitry Andric 
1541*349cc55cSDimitry Andric     replaceArgumentUses(*CurrentOS, NewBBs);
1542*349cc55cSDimitry Andric     alignOutputBlockWithAggFunc(CurrentGroup, *CurrentOS, NewBBs,
1543*349cc55cSDimitry Andric                                 CurrentGroup.EndBBs, OutputMappings,
1544e8d8bef9SDimitry Andric                                 OutputStoreBBs);
1545e8d8bef9SDimitry Andric 
1546e8d8bef9SDimitry Andric     CurrentOS->Call = replaceCalledFunction(M, *CurrentOS);
1547e8d8bef9SDimitry Andric     FuncsToRemove.push_back(CurrentOS->ExtractedFunction);
1548e8d8bef9SDimitry Andric   }
1549e8d8bef9SDimitry Andric 
1550e8d8bef9SDimitry Andric   // Create a switch statement to handle the different output schemes.
1551*349cc55cSDimitry Andric   createSwitchStatement(M, CurrentGroup, CurrentGroup.EndBBs, OutputStoreBBs);
1552e8d8bef9SDimitry Andric 
1553e8d8bef9SDimitry Andric   OutlinedFunctionNum++;
1554e8d8bef9SDimitry Andric }
1555e8d8bef9SDimitry Andric 
1556*349cc55cSDimitry Andric /// Checks that the next instruction in the InstructionDataList matches the
1557*349cc55cSDimitry Andric /// next instruction in the module.  If they do not, there could be the
1558*349cc55cSDimitry Andric /// possibility that extra code has been inserted, and we must ignore it.
1559*349cc55cSDimitry Andric ///
1560*349cc55cSDimitry Andric /// \param ID - The IRInstructionData to check the next instruction of.
1561*349cc55cSDimitry Andric /// \returns true if the InstructionDataList and actual instruction match.
1562*349cc55cSDimitry Andric static bool nextIRInstructionDataMatchesNextInst(IRInstructionData &ID) {
1563*349cc55cSDimitry Andric   // We check if there is a discrepancy between the InstructionDataList
1564*349cc55cSDimitry Andric   // and the actual next instruction in the module.  If there is, it means
1565*349cc55cSDimitry Andric   // that an extra instruction was added, likely by the CodeExtractor.
1566*349cc55cSDimitry Andric 
1567*349cc55cSDimitry Andric   // Since we do not have any similarity data about this particular
1568*349cc55cSDimitry Andric   // instruction, we cannot confidently outline it, and must discard this
1569*349cc55cSDimitry Andric   // candidate.
1570*349cc55cSDimitry Andric   IRInstructionDataList::iterator NextIDIt = std::next(ID.getIterator());
1571*349cc55cSDimitry Andric   Instruction *NextIDLInst = NextIDIt->Inst;
1572*349cc55cSDimitry Andric   Instruction *NextModuleInst = nullptr;
1573*349cc55cSDimitry Andric   if (!ID.Inst->isTerminator())
1574*349cc55cSDimitry Andric     NextModuleInst = ID.Inst->getNextNonDebugInstruction();
1575*349cc55cSDimitry Andric   else if (NextIDLInst != nullptr)
1576*349cc55cSDimitry Andric     NextModuleInst =
1577*349cc55cSDimitry Andric         &*NextIDIt->Inst->getParent()->instructionsWithoutDebug().begin();
1578*349cc55cSDimitry Andric 
1579*349cc55cSDimitry Andric   if (NextIDLInst && NextIDLInst != NextModuleInst)
1580*349cc55cSDimitry Andric     return false;
1581*349cc55cSDimitry Andric 
1582*349cc55cSDimitry Andric   return true;
1583*349cc55cSDimitry Andric }
1584*349cc55cSDimitry Andric 
1585*349cc55cSDimitry Andric bool IROutliner::isCompatibleWithAlreadyOutlinedCode(
1586*349cc55cSDimitry Andric     const OutlinableRegion &Region) {
1587*349cc55cSDimitry Andric   IRSimilarityCandidate *IRSC = Region.Candidate;
1588*349cc55cSDimitry Andric   unsigned StartIdx = IRSC->getStartIdx();
1589*349cc55cSDimitry Andric   unsigned EndIdx = IRSC->getEndIdx();
1590*349cc55cSDimitry Andric 
1591*349cc55cSDimitry Andric   // A check to make sure that we are not about to attempt to outline something
1592*349cc55cSDimitry Andric   // that has already been outlined.
1593*349cc55cSDimitry Andric   for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
1594*349cc55cSDimitry Andric     if (Outlined.contains(Idx))
1595*349cc55cSDimitry Andric       return false;
1596*349cc55cSDimitry Andric 
1597*349cc55cSDimitry Andric   // We check if the recorded instruction matches the actual next instruction,
1598*349cc55cSDimitry Andric   // if it does not, we fix it in the InstructionDataList.
1599*349cc55cSDimitry Andric   if (!Region.Candidate->backInstruction()->isTerminator()) {
1600*349cc55cSDimitry Andric     Instruction *NewEndInst =
1601*349cc55cSDimitry Andric         Region.Candidate->backInstruction()->getNextNonDebugInstruction();
1602*349cc55cSDimitry Andric     assert(NewEndInst && "Next instruction is a nullptr?");
1603*349cc55cSDimitry Andric     if (Region.Candidate->end()->Inst != NewEndInst) {
1604*349cc55cSDimitry Andric       IRInstructionDataList *IDL = Region.Candidate->front()->IDL;
1605*349cc55cSDimitry Andric       IRInstructionData *NewEndIRID = new (InstDataAllocator.Allocate())
1606*349cc55cSDimitry Andric           IRInstructionData(*NewEndInst,
1607*349cc55cSDimitry Andric                             InstructionClassifier.visit(*NewEndInst), *IDL);
1608*349cc55cSDimitry Andric 
1609*349cc55cSDimitry Andric       // Insert the first IRInstructionData of the new region after the
1610*349cc55cSDimitry Andric       // last IRInstructionData of the IRSimilarityCandidate.
1611*349cc55cSDimitry Andric       IDL->insert(Region.Candidate->end(), *NewEndIRID);
1612*349cc55cSDimitry Andric     }
1613*349cc55cSDimitry Andric   }
1614*349cc55cSDimitry Andric 
1615*349cc55cSDimitry Andric   return none_of(*IRSC, [this](IRInstructionData &ID) {
1616*349cc55cSDimitry Andric     if (!nextIRInstructionDataMatchesNextInst(ID))
1617*349cc55cSDimitry Andric       return true;
1618*349cc55cSDimitry Andric 
1619*349cc55cSDimitry Andric     return !this->InstructionClassifier.visit(ID.Inst);
1620*349cc55cSDimitry Andric   });
1621*349cc55cSDimitry Andric }
1622*349cc55cSDimitry Andric 
1623e8d8bef9SDimitry Andric void IROutliner::pruneIncompatibleRegions(
1624e8d8bef9SDimitry Andric     std::vector<IRSimilarityCandidate> &CandidateVec,
1625e8d8bef9SDimitry Andric     OutlinableGroup &CurrentGroup) {
1626e8d8bef9SDimitry Andric   bool PreviouslyOutlined;
1627e8d8bef9SDimitry Andric 
1628e8d8bef9SDimitry Andric   // Sort from beginning to end, so the IRSimilarityCandidates are in order.
1629e8d8bef9SDimitry Andric   stable_sort(CandidateVec, [](const IRSimilarityCandidate &LHS,
1630e8d8bef9SDimitry Andric                                const IRSimilarityCandidate &RHS) {
1631e8d8bef9SDimitry Andric     return LHS.getStartIdx() < RHS.getStartIdx();
1632e8d8bef9SDimitry Andric   });
1633e8d8bef9SDimitry Andric 
1634*349cc55cSDimitry Andric   IRSimilarityCandidate &FirstCandidate = CandidateVec[0];
1635*349cc55cSDimitry Andric   // Since outlining a call and a branch instruction will be the same as only
1636*349cc55cSDimitry Andric   // outlinining a call instruction, we ignore it as a space saving.
1637*349cc55cSDimitry Andric   if (FirstCandidate.getLength() == 2) {
1638*349cc55cSDimitry Andric     if (isa<CallInst>(FirstCandidate.front()->Inst) &&
1639*349cc55cSDimitry Andric         isa<BranchInst>(FirstCandidate.back()->Inst))
1640*349cc55cSDimitry Andric         return;
1641*349cc55cSDimitry Andric   }
1642*349cc55cSDimitry Andric 
1643e8d8bef9SDimitry Andric   unsigned CurrentEndIdx = 0;
1644e8d8bef9SDimitry Andric   for (IRSimilarityCandidate &IRSC : CandidateVec) {
1645e8d8bef9SDimitry Andric     PreviouslyOutlined = false;
1646e8d8bef9SDimitry Andric     unsigned StartIdx = IRSC.getStartIdx();
1647e8d8bef9SDimitry Andric     unsigned EndIdx = IRSC.getEndIdx();
1648e8d8bef9SDimitry Andric 
1649e8d8bef9SDimitry Andric     for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
1650e8d8bef9SDimitry Andric       if (Outlined.contains(Idx)) {
1651e8d8bef9SDimitry Andric         PreviouslyOutlined = true;
1652e8d8bef9SDimitry Andric         break;
1653e8d8bef9SDimitry Andric       }
1654e8d8bef9SDimitry Andric 
1655e8d8bef9SDimitry Andric     if (PreviouslyOutlined)
1656e8d8bef9SDimitry Andric       continue;
1657e8d8bef9SDimitry Andric 
1658*349cc55cSDimitry Andric     // Check over the instructions, and if the basic block has its address
1659*349cc55cSDimitry Andric     // taken for use somewhere else, we do not outline that block.
1660*349cc55cSDimitry Andric     bool BBHasAddressTaken = any_of(IRSC, [](IRInstructionData &ID){
1661*349cc55cSDimitry Andric       return ID.Inst->getParent()->hasAddressTaken();
1662*349cc55cSDimitry Andric     });
1663*349cc55cSDimitry Andric 
1664*349cc55cSDimitry Andric     if (BBHasAddressTaken)
1665e8d8bef9SDimitry Andric       continue;
1666e8d8bef9SDimitry Andric 
1667e8d8bef9SDimitry Andric     if (IRSC.front()->Inst->getFunction()->hasLinkOnceODRLinkage() &&
1668e8d8bef9SDimitry Andric         !OutlineFromLinkODRs)
1669e8d8bef9SDimitry Andric       continue;
1670e8d8bef9SDimitry Andric 
1671e8d8bef9SDimitry Andric     // Greedily prune out any regions that will overlap with already chosen
1672e8d8bef9SDimitry Andric     // regions.
1673e8d8bef9SDimitry Andric     if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
1674e8d8bef9SDimitry Andric       continue;
1675e8d8bef9SDimitry Andric 
1676e8d8bef9SDimitry Andric     bool BadInst = any_of(IRSC, [this](IRInstructionData &ID) {
1677*349cc55cSDimitry Andric       if (!nextIRInstructionDataMatchesNextInst(ID))
1678e8d8bef9SDimitry Andric         return true;
1679*349cc55cSDimitry Andric 
1680e8d8bef9SDimitry Andric       return !this->InstructionClassifier.visit(ID.Inst);
1681e8d8bef9SDimitry Andric     });
1682e8d8bef9SDimitry Andric 
1683e8d8bef9SDimitry Andric     if (BadInst)
1684e8d8bef9SDimitry Andric       continue;
1685e8d8bef9SDimitry Andric 
1686e8d8bef9SDimitry Andric     OutlinableRegion *OS = new (RegionAllocator.Allocate())
1687e8d8bef9SDimitry Andric         OutlinableRegion(IRSC, CurrentGroup);
1688e8d8bef9SDimitry Andric     CurrentGroup.Regions.push_back(OS);
1689e8d8bef9SDimitry Andric 
1690e8d8bef9SDimitry Andric     CurrentEndIdx = EndIdx;
1691e8d8bef9SDimitry Andric   }
1692e8d8bef9SDimitry Andric }
1693e8d8bef9SDimitry Andric 
1694e8d8bef9SDimitry Andric InstructionCost
1695e8d8bef9SDimitry Andric IROutliner::findBenefitFromAllRegions(OutlinableGroup &CurrentGroup) {
1696e8d8bef9SDimitry Andric   InstructionCost RegionBenefit = 0;
1697e8d8bef9SDimitry Andric   for (OutlinableRegion *Region : CurrentGroup.Regions) {
1698e8d8bef9SDimitry Andric     TargetTransformInfo &TTI = getTTI(*Region->StartBB->getParent());
1699e8d8bef9SDimitry Andric     // We add the number of instructions in the region to the benefit as an
1700e8d8bef9SDimitry Andric     // estimate as to how much will be removed.
1701e8d8bef9SDimitry Andric     RegionBenefit += Region->getBenefit(TTI);
1702e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Adding: " << RegionBenefit
1703e8d8bef9SDimitry Andric                       << " saved instructions to overfall benefit.\n");
1704e8d8bef9SDimitry Andric   }
1705e8d8bef9SDimitry Andric 
1706e8d8bef9SDimitry Andric   return RegionBenefit;
1707e8d8bef9SDimitry Andric }
1708e8d8bef9SDimitry Andric 
1709e8d8bef9SDimitry Andric InstructionCost
1710e8d8bef9SDimitry Andric IROutliner::findCostOutputReloads(OutlinableGroup &CurrentGroup) {
1711e8d8bef9SDimitry Andric   InstructionCost OverallCost = 0;
1712e8d8bef9SDimitry Andric   for (OutlinableRegion *Region : CurrentGroup.Regions) {
1713e8d8bef9SDimitry Andric     TargetTransformInfo &TTI = getTTI(*Region->StartBB->getParent());
1714e8d8bef9SDimitry Andric 
1715e8d8bef9SDimitry Andric     // Each output incurs a load after the call, so we add that to the cost.
1716e8d8bef9SDimitry Andric     for (unsigned OutputGVN : Region->GVNStores) {
1717e8d8bef9SDimitry Andric       Optional<Value *> OV = Region->Candidate->fromGVN(OutputGVN);
1718e8d8bef9SDimitry Andric       assert(OV.hasValue() && "Could not find value for GVN?");
1719e8d8bef9SDimitry Andric       Value *V = OV.getValue();
1720e8d8bef9SDimitry Andric       InstructionCost LoadCost =
1721e8d8bef9SDimitry Andric           TTI.getMemoryOpCost(Instruction::Load, V->getType(), Align(1), 0,
1722e8d8bef9SDimitry Andric                               TargetTransformInfo::TCK_CodeSize);
1723e8d8bef9SDimitry Andric 
1724e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Adding: " << LoadCost
1725e8d8bef9SDimitry Andric                         << " instructions to cost for output of type "
1726e8d8bef9SDimitry Andric                         << *V->getType() << "\n");
1727e8d8bef9SDimitry Andric       OverallCost += LoadCost;
1728e8d8bef9SDimitry Andric     }
1729e8d8bef9SDimitry Andric   }
1730e8d8bef9SDimitry Andric 
1731e8d8bef9SDimitry Andric   return OverallCost;
1732e8d8bef9SDimitry Andric }
1733e8d8bef9SDimitry Andric 
1734e8d8bef9SDimitry Andric /// Find the extra instructions needed to handle any output values for the
1735e8d8bef9SDimitry Andric /// region.
1736e8d8bef9SDimitry Andric ///
1737e8d8bef9SDimitry Andric /// \param [in] M - The Module to outline from.
1738e8d8bef9SDimitry Andric /// \param [in] CurrentGroup - The collection of OutlinableRegions to analyze.
1739e8d8bef9SDimitry Andric /// \param [in] TTI - The TargetTransformInfo used to collect information for
1740e8d8bef9SDimitry Andric /// new instruction costs.
1741e8d8bef9SDimitry Andric /// \returns the additional cost to handle the outputs.
1742e8d8bef9SDimitry Andric static InstructionCost findCostForOutputBlocks(Module &M,
1743e8d8bef9SDimitry Andric                                                OutlinableGroup &CurrentGroup,
1744e8d8bef9SDimitry Andric                                                TargetTransformInfo &TTI) {
1745e8d8bef9SDimitry Andric   InstructionCost OutputCost = 0;
1746*349cc55cSDimitry Andric   unsigned NumOutputBranches = 0;
1747*349cc55cSDimitry Andric 
1748*349cc55cSDimitry Andric   IRSimilarityCandidate &Candidate = *CurrentGroup.Regions[0]->Candidate;
1749*349cc55cSDimitry Andric   DenseSet<BasicBlock *> CandidateBlocks;
1750*349cc55cSDimitry Andric   Candidate.getBasicBlocks(CandidateBlocks);
1751*349cc55cSDimitry Andric 
1752*349cc55cSDimitry Andric   // Count the number of different output branches that point to blocks outside
1753*349cc55cSDimitry Andric   // of the region.
1754*349cc55cSDimitry Andric   DenseSet<BasicBlock *> FoundBlocks;
1755*349cc55cSDimitry Andric   for (IRInstructionData &ID : Candidate) {
1756*349cc55cSDimitry Andric     if (!isa<BranchInst>(ID.Inst))
1757*349cc55cSDimitry Andric       continue;
1758*349cc55cSDimitry Andric 
1759*349cc55cSDimitry Andric     for (Value *V : ID.OperVals) {
1760*349cc55cSDimitry Andric       BasicBlock *BB = static_cast<BasicBlock *>(V);
1761*349cc55cSDimitry Andric       DenseSet<BasicBlock *>::iterator CBIt = CandidateBlocks.find(BB);
1762*349cc55cSDimitry Andric       if (CBIt != CandidateBlocks.end() || FoundBlocks.contains(BB))
1763*349cc55cSDimitry Andric         continue;
1764*349cc55cSDimitry Andric       FoundBlocks.insert(BB);
1765*349cc55cSDimitry Andric       NumOutputBranches++;
1766*349cc55cSDimitry Andric     }
1767*349cc55cSDimitry Andric   }
1768*349cc55cSDimitry Andric 
1769*349cc55cSDimitry Andric   CurrentGroup.BranchesToOutside = NumOutputBranches;
1770e8d8bef9SDimitry Andric 
1771e8d8bef9SDimitry Andric   for (const ArrayRef<unsigned> &OutputUse :
1772e8d8bef9SDimitry Andric        CurrentGroup.OutputGVNCombinations) {
1773e8d8bef9SDimitry Andric     for (unsigned GVN : OutputUse) {
1774e8d8bef9SDimitry Andric       Optional<Value *> OV = Candidate.fromGVN(GVN);
1775e8d8bef9SDimitry Andric       assert(OV.hasValue() && "Could not find value for GVN?");
1776e8d8bef9SDimitry Andric       Value *V = OV.getValue();
1777e8d8bef9SDimitry Andric       InstructionCost StoreCost =
1778e8d8bef9SDimitry Andric           TTI.getMemoryOpCost(Instruction::Load, V->getType(), Align(1), 0,
1779e8d8bef9SDimitry Andric                               TargetTransformInfo::TCK_CodeSize);
1780e8d8bef9SDimitry Andric 
1781e8d8bef9SDimitry Andric       // An instruction cost is added for each store set that needs to occur for
1782e8d8bef9SDimitry Andric       // various output combinations inside the function, plus a branch to
1783e8d8bef9SDimitry Andric       // return to the exit block.
1784e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Adding: " << StoreCost
1785e8d8bef9SDimitry Andric                         << " instructions to cost for output of type "
1786e8d8bef9SDimitry Andric                         << *V->getType() << "\n");
1787*349cc55cSDimitry Andric       OutputCost += StoreCost * NumOutputBranches;
1788e8d8bef9SDimitry Andric     }
1789e8d8bef9SDimitry Andric 
1790e8d8bef9SDimitry Andric     InstructionCost BranchCost =
1791e8d8bef9SDimitry Andric         TTI.getCFInstrCost(Instruction::Br, TargetTransformInfo::TCK_CodeSize);
1792e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Adding " << BranchCost << " to the current cost for"
1793e8d8bef9SDimitry Andric                       << " a branch instruction\n");
1794*349cc55cSDimitry Andric     OutputCost += BranchCost * NumOutputBranches;
1795e8d8bef9SDimitry Andric   }
1796e8d8bef9SDimitry Andric 
1797e8d8bef9SDimitry Andric   // If there is more than one output scheme, we must have a comparison and
1798e8d8bef9SDimitry Andric   // branch for each different item in the switch statement.
1799e8d8bef9SDimitry Andric   if (CurrentGroup.OutputGVNCombinations.size() > 1) {
1800e8d8bef9SDimitry Andric     InstructionCost ComparisonCost = TTI.getCmpSelInstrCost(
1801e8d8bef9SDimitry Andric         Instruction::ICmp, Type::getInt32Ty(M.getContext()),
1802e8d8bef9SDimitry Andric         Type::getInt32Ty(M.getContext()), CmpInst::BAD_ICMP_PREDICATE,
1803e8d8bef9SDimitry Andric         TargetTransformInfo::TCK_CodeSize);
1804e8d8bef9SDimitry Andric     InstructionCost BranchCost =
1805e8d8bef9SDimitry Andric         TTI.getCFInstrCost(Instruction::Br, TargetTransformInfo::TCK_CodeSize);
1806e8d8bef9SDimitry Andric 
1807e8d8bef9SDimitry Andric     unsigned DifferentBlocks = CurrentGroup.OutputGVNCombinations.size();
1808e8d8bef9SDimitry Andric     InstructionCost TotalCost = ComparisonCost * BranchCost * DifferentBlocks;
1809e8d8bef9SDimitry Andric 
1810e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Adding: " << TotalCost
1811e8d8bef9SDimitry Andric                       << " instructions for each switch case for each different"
1812e8d8bef9SDimitry Andric                       << " output path in a function\n");
1813*349cc55cSDimitry Andric     OutputCost += TotalCost * NumOutputBranches;
1814e8d8bef9SDimitry Andric   }
1815e8d8bef9SDimitry Andric 
1816e8d8bef9SDimitry Andric   return OutputCost;
1817e8d8bef9SDimitry Andric }
1818e8d8bef9SDimitry Andric 
1819e8d8bef9SDimitry Andric void IROutliner::findCostBenefit(Module &M, OutlinableGroup &CurrentGroup) {
1820e8d8bef9SDimitry Andric   InstructionCost RegionBenefit = findBenefitFromAllRegions(CurrentGroup);
1821e8d8bef9SDimitry Andric   CurrentGroup.Benefit += RegionBenefit;
1822e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Current Benefit: " << CurrentGroup.Benefit << "\n");
1823e8d8bef9SDimitry Andric 
1824e8d8bef9SDimitry Andric   InstructionCost OutputReloadCost = findCostOutputReloads(CurrentGroup);
1825e8d8bef9SDimitry Andric   CurrentGroup.Cost += OutputReloadCost;
1826e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
1827e8d8bef9SDimitry Andric 
1828e8d8bef9SDimitry Andric   InstructionCost AverageRegionBenefit =
1829e8d8bef9SDimitry Andric       RegionBenefit / CurrentGroup.Regions.size();
1830e8d8bef9SDimitry Andric   unsigned OverallArgumentNum = CurrentGroup.ArgumentTypes.size();
1831e8d8bef9SDimitry Andric   unsigned NumRegions = CurrentGroup.Regions.size();
1832e8d8bef9SDimitry Andric   TargetTransformInfo &TTI =
1833e8d8bef9SDimitry Andric       getTTI(*CurrentGroup.Regions[0]->Candidate->getFunction());
1834e8d8bef9SDimitry Andric 
1835e8d8bef9SDimitry Andric   // We add one region to the cost once, to account for the instructions added
1836e8d8bef9SDimitry Andric   // inside of the newly created function.
1837e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Adding: " << AverageRegionBenefit
1838e8d8bef9SDimitry Andric                     << " instructions to cost for body of new function.\n");
1839e8d8bef9SDimitry Andric   CurrentGroup.Cost += AverageRegionBenefit;
1840e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
1841e8d8bef9SDimitry Andric 
1842e8d8bef9SDimitry Andric   // For each argument, we must add an instruction for loading the argument
1843e8d8bef9SDimitry Andric   // out of the register and into a value inside of the newly outlined function.
1844e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Adding: " << OverallArgumentNum
1845e8d8bef9SDimitry Andric                     << " instructions to cost for each argument in the new"
1846e8d8bef9SDimitry Andric                     << " function.\n");
1847e8d8bef9SDimitry Andric   CurrentGroup.Cost +=
1848e8d8bef9SDimitry Andric       OverallArgumentNum * TargetTransformInfo::TCC_Basic;
1849e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
1850e8d8bef9SDimitry Andric 
1851e8d8bef9SDimitry Andric   // Each argument needs to either be loaded into a register or onto the stack.
1852e8d8bef9SDimitry Andric   // Some arguments will only be loaded into the stack once the argument
1853e8d8bef9SDimitry Andric   // registers are filled.
1854e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Adding: " << OverallArgumentNum
1855e8d8bef9SDimitry Andric                     << " instructions to cost for each argument in the new"
1856e8d8bef9SDimitry Andric                     << " function " << NumRegions << " times for the "
1857e8d8bef9SDimitry Andric                     << "needed argument handling at the call site.\n");
1858e8d8bef9SDimitry Andric   CurrentGroup.Cost +=
1859e8d8bef9SDimitry Andric       2 * OverallArgumentNum * TargetTransformInfo::TCC_Basic * NumRegions;
1860e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
1861e8d8bef9SDimitry Andric 
1862e8d8bef9SDimitry Andric   CurrentGroup.Cost += findCostForOutputBlocks(M, CurrentGroup, TTI);
1863e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
1864e8d8bef9SDimitry Andric }
1865e8d8bef9SDimitry Andric 
1866e8d8bef9SDimitry Andric void IROutliner::updateOutputMapping(OutlinableRegion &Region,
1867e8d8bef9SDimitry Andric                                      ArrayRef<Value *> Outputs,
1868e8d8bef9SDimitry Andric                                      LoadInst *LI) {
1869e8d8bef9SDimitry Andric   // For and load instructions following the call
1870e8d8bef9SDimitry Andric   Value *Operand = LI->getPointerOperand();
1871e8d8bef9SDimitry Andric   Optional<unsigned> OutputIdx = None;
1872e8d8bef9SDimitry Andric   // Find if the operand it is an output register.
1873e8d8bef9SDimitry Andric   for (unsigned ArgIdx = Region.NumExtractedInputs;
1874e8d8bef9SDimitry Andric        ArgIdx < Region.Call->arg_size(); ArgIdx++) {
1875e8d8bef9SDimitry Andric     if (Operand == Region.Call->getArgOperand(ArgIdx)) {
1876e8d8bef9SDimitry Andric       OutputIdx = ArgIdx - Region.NumExtractedInputs;
1877e8d8bef9SDimitry Andric       break;
1878e8d8bef9SDimitry Andric     }
1879e8d8bef9SDimitry Andric   }
1880e8d8bef9SDimitry Andric 
1881e8d8bef9SDimitry Andric   // If we found an output register, place a mapping of the new value
1882e8d8bef9SDimitry Andric   // to the original in the mapping.
1883e8d8bef9SDimitry Andric   if (!OutputIdx.hasValue())
1884e8d8bef9SDimitry Andric     return;
1885e8d8bef9SDimitry Andric 
1886e8d8bef9SDimitry Andric   if (OutputMappings.find(Outputs[OutputIdx.getValue()]) ==
1887e8d8bef9SDimitry Andric       OutputMappings.end()) {
1888e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Mapping extracted output " << *LI << " to "
1889e8d8bef9SDimitry Andric                       << *Outputs[OutputIdx.getValue()] << "\n");
1890e8d8bef9SDimitry Andric     OutputMappings.insert(std::make_pair(LI, Outputs[OutputIdx.getValue()]));
1891e8d8bef9SDimitry Andric   } else {
1892e8d8bef9SDimitry Andric     Value *Orig = OutputMappings.find(Outputs[OutputIdx.getValue()])->second;
1893e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Mapping extracted output " << *Orig << " to "
1894e8d8bef9SDimitry Andric                       << *Outputs[OutputIdx.getValue()] << "\n");
1895e8d8bef9SDimitry Andric     OutputMappings.insert(std::make_pair(LI, Orig));
1896e8d8bef9SDimitry Andric   }
1897e8d8bef9SDimitry Andric }
1898e8d8bef9SDimitry Andric 
1899e8d8bef9SDimitry Andric bool IROutliner::extractSection(OutlinableRegion &Region) {
1900e8d8bef9SDimitry Andric   SetVector<Value *> ArgInputs, Outputs, SinkCands;
1901e8d8bef9SDimitry Andric   assert(Region.StartBB && "StartBB for the OutlinableRegion is nullptr!");
1902*349cc55cSDimitry Andric   BasicBlock *InitialStart = Region.StartBB;
1903e8d8bef9SDimitry Andric   Function *OrigF = Region.StartBB->getParent();
1904e8d8bef9SDimitry Andric   CodeExtractorAnalysisCache CEAC(*OrigF);
1905*349cc55cSDimitry Andric   Region.ExtractedFunction =
1906*349cc55cSDimitry Andric       Region.CE->extractCodeRegion(CEAC, ArgInputs, Outputs);
1907e8d8bef9SDimitry Andric 
1908e8d8bef9SDimitry Andric   // If the extraction was successful, find the BasicBlock, and reassign the
1909e8d8bef9SDimitry Andric   // OutlinableRegion blocks
1910e8d8bef9SDimitry Andric   if (!Region.ExtractedFunction) {
1911e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "CodeExtractor failed to outline " << Region.StartBB
1912e8d8bef9SDimitry Andric                       << "\n");
1913e8d8bef9SDimitry Andric     Region.reattachCandidate();
1914e8d8bef9SDimitry Andric     return false;
1915e8d8bef9SDimitry Andric   }
1916e8d8bef9SDimitry Andric 
1917*349cc55cSDimitry Andric   // Get the block containing the called branch, and reassign the blocks as
1918*349cc55cSDimitry Andric   // necessary.  If the original block still exists, it is because we ended on
1919*349cc55cSDimitry Andric   // a branch instruction, and so we move the contents into the block before
1920*349cc55cSDimitry Andric   // and assign the previous block correctly.
1921*349cc55cSDimitry Andric   User *InstAsUser = Region.ExtractedFunction->user_back();
1922*349cc55cSDimitry Andric   BasicBlock *RewrittenBB = cast<Instruction>(InstAsUser)->getParent();
1923*349cc55cSDimitry Andric   Region.PrevBB = RewrittenBB->getSinglePredecessor();
1924*349cc55cSDimitry Andric   assert(Region.PrevBB && "PrevBB is nullptr?");
1925*349cc55cSDimitry Andric   if (Region.PrevBB == InitialStart) {
1926*349cc55cSDimitry Andric     BasicBlock *NewPrev = InitialStart->getSinglePredecessor();
1927*349cc55cSDimitry Andric     Instruction *BI = NewPrev->getTerminator();
1928*349cc55cSDimitry Andric     BI->eraseFromParent();
1929*349cc55cSDimitry Andric     moveBBContents(*InitialStart, *NewPrev);
1930*349cc55cSDimitry Andric     Region.PrevBB = NewPrev;
1931*349cc55cSDimitry Andric     InitialStart->eraseFromParent();
1932*349cc55cSDimitry Andric   }
1933*349cc55cSDimitry Andric 
1934e8d8bef9SDimitry Andric   Region.StartBB = RewrittenBB;
1935e8d8bef9SDimitry Andric   Region.EndBB = RewrittenBB;
1936e8d8bef9SDimitry Andric 
1937e8d8bef9SDimitry Andric   // The sequences of outlinable regions has now changed.  We must fix the
1938e8d8bef9SDimitry Andric   // IRInstructionDataList for consistency.  Although they may not be illegal
1939e8d8bef9SDimitry Andric   // instructions, they should not be compared with anything else as they
1940e8d8bef9SDimitry Andric   // should not be outlined in this round.  So marking these as illegal is
1941e8d8bef9SDimitry Andric   // allowed.
1942e8d8bef9SDimitry Andric   IRInstructionDataList *IDL = Region.Candidate->front()->IDL;
1943e8d8bef9SDimitry Andric   Instruction *BeginRewritten = &*RewrittenBB->begin();
1944e8d8bef9SDimitry Andric   Instruction *EndRewritten = &*RewrittenBB->begin();
1945e8d8bef9SDimitry Andric   Region.NewFront = new (InstDataAllocator.Allocate()) IRInstructionData(
1946e8d8bef9SDimitry Andric       *BeginRewritten, InstructionClassifier.visit(*BeginRewritten), *IDL);
1947e8d8bef9SDimitry Andric   Region.NewBack = new (InstDataAllocator.Allocate()) IRInstructionData(
1948e8d8bef9SDimitry Andric       *EndRewritten, InstructionClassifier.visit(*EndRewritten), *IDL);
1949e8d8bef9SDimitry Andric 
1950e8d8bef9SDimitry Andric   // Insert the first IRInstructionData of the new region in front of the
1951e8d8bef9SDimitry Andric   // first IRInstructionData of the IRSimilarityCandidate.
1952e8d8bef9SDimitry Andric   IDL->insert(Region.Candidate->begin(), *Region.NewFront);
1953e8d8bef9SDimitry Andric   // Insert the first IRInstructionData of the new region after the
1954e8d8bef9SDimitry Andric   // last IRInstructionData of the IRSimilarityCandidate.
1955e8d8bef9SDimitry Andric   IDL->insert(Region.Candidate->end(), *Region.NewBack);
1956e8d8bef9SDimitry Andric   // Remove the IRInstructionData from the IRSimilarityCandidate.
1957e8d8bef9SDimitry Andric   IDL->erase(Region.Candidate->begin(), std::prev(Region.Candidate->end()));
1958e8d8bef9SDimitry Andric 
1959e8d8bef9SDimitry Andric   assert(RewrittenBB != nullptr &&
1960e8d8bef9SDimitry Andric          "Could not find a predecessor after extraction!");
1961e8d8bef9SDimitry Andric 
1962e8d8bef9SDimitry Andric   // Iterate over the new set of instructions to find the new call
1963e8d8bef9SDimitry Andric   // instruction.
1964e8d8bef9SDimitry Andric   for (Instruction &I : *RewrittenBB)
1965e8d8bef9SDimitry Andric     if (CallInst *CI = dyn_cast<CallInst>(&I)) {
1966e8d8bef9SDimitry Andric       if (Region.ExtractedFunction == CI->getCalledFunction())
1967e8d8bef9SDimitry Andric         Region.Call = CI;
1968e8d8bef9SDimitry Andric     } else if (LoadInst *LI = dyn_cast<LoadInst>(&I))
1969e8d8bef9SDimitry Andric       updateOutputMapping(Region, Outputs.getArrayRef(), LI);
1970e8d8bef9SDimitry Andric   Region.reattachCandidate();
1971e8d8bef9SDimitry Andric   return true;
1972e8d8bef9SDimitry Andric }
1973e8d8bef9SDimitry Andric 
1974e8d8bef9SDimitry Andric unsigned IROutliner::doOutline(Module &M) {
1975e8d8bef9SDimitry Andric   // Find the possible similarity sections.
1976*349cc55cSDimitry Andric   InstructionClassifier.EnableBranches = !DisableBranches;
1977e8d8bef9SDimitry Andric   IRSimilarityIdentifier &Identifier = getIRSI(M);
1978e8d8bef9SDimitry Andric   SimilarityGroupList &SimilarityCandidates = *Identifier.getSimilarity();
1979e8d8bef9SDimitry Andric 
1980e8d8bef9SDimitry Andric   // Sort them by size of extracted sections
1981e8d8bef9SDimitry Andric   unsigned OutlinedFunctionNum = 0;
1982e8d8bef9SDimitry Andric   // If we only have one SimilarityGroup in SimilarityCandidates, we do not have
1983e8d8bef9SDimitry Andric   // to sort them by the potential number of instructions to be outlined
1984e8d8bef9SDimitry Andric   if (SimilarityCandidates.size() > 1)
1985e8d8bef9SDimitry Andric     llvm::stable_sort(SimilarityCandidates,
1986e8d8bef9SDimitry Andric                       [](const std::vector<IRSimilarityCandidate> &LHS,
1987e8d8bef9SDimitry Andric                          const std::vector<IRSimilarityCandidate> &RHS) {
1988e8d8bef9SDimitry Andric                         return LHS[0].getLength() * LHS.size() >
1989e8d8bef9SDimitry Andric                                RHS[0].getLength() * RHS.size();
1990e8d8bef9SDimitry Andric                       });
1991*349cc55cSDimitry Andric   // Creating OutlinableGroups for each SimilarityCandidate to be used in
1992*349cc55cSDimitry Andric   // each of the following for loops to avoid making an allocator.
1993*349cc55cSDimitry Andric   std::vector<OutlinableGroup> PotentialGroups(SimilarityCandidates.size());
1994e8d8bef9SDimitry Andric 
1995e8d8bef9SDimitry Andric   DenseSet<unsigned> NotSame;
1996*349cc55cSDimitry Andric   std::vector<OutlinableGroup *> NegativeCostGroups;
1997*349cc55cSDimitry Andric   std::vector<OutlinableRegion *> OutlinedRegions;
1998e8d8bef9SDimitry Andric   // Iterate over the possible sets of similarity.
1999*349cc55cSDimitry Andric   unsigned PotentialGroupIdx = 0;
2000e8d8bef9SDimitry Andric   for (SimilarityGroup &CandidateVec : SimilarityCandidates) {
2001*349cc55cSDimitry Andric     OutlinableGroup &CurrentGroup = PotentialGroups[PotentialGroupIdx++];
2002e8d8bef9SDimitry Andric 
2003e8d8bef9SDimitry Andric     // Remove entries that were previously outlined
2004e8d8bef9SDimitry Andric     pruneIncompatibleRegions(CandidateVec, CurrentGroup);
2005e8d8bef9SDimitry Andric 
2006e8d8bef9SDimitry Andric     // We pruned the number of regions to 0 to 1, meaning that it's not worth
2007e8d8bef9SDimitry Andric     // trying to outlined since there is no compatible similar instance of this
2008e8d8bef9SDimitry Andric     // code.
2009e8d8bef9SDimitry Andric     if (CurrentGroup.Regions.size() < 2)
2010e8d8bef9SDimitry Andric       continue;
2011e8d8bef9SDimitry Andric 
2012e8d8bef9SDimitry Andric     // Determine if there are any values that are the same constant throughout
2013e8d8bef9SDimitry Andric     // each section in the set.
2014e8d8bef9SDimitry Andric     NotSame.clear();
2015e8d8bef9SDimitry Andric     CurrentGroup.findSameConstants(NotSame);
2016e8d8bef9SDimitry Andric 
2017e8d8bef9SDimitry Andric     if (CurrentGroup.IgnoreGroup)
2018e8d8bef9SDimitry Andric       continue;
2019e8d8bef9SDimitry Andric 
2020e8d8bef9SDimitry Andric     // Create a CodeExtractor for each outlinable region. Identify inputs and
2021e8d8bef9SDimitry Andric     // outputs for each section using the code extractor and create the argument
2022e8d8bef9SDimitry Andric     // types for the Aggregate Outlining Function.
2023*349cc55cSDimitry Andric     OutlinedRegions.clear();
2024e8d8bef9SDimitry Andric     for (OutlinableRegion *OS : CurrentGroup.Regions) {
2025e8d8bef9SDimitry Andric       // Break the outlinable region out of its parent BasicBlock into its own
2026e8d8bef9SDimitry Andric       // BasicBlocks (see function implementation).
2027e8d8bef9SDimitry Andric       OS->splitCandidate();
2028*349cc55cSDimitry Andric 
2029*349cc55cSDimitry Andric       // There's a chance that when the region is split, extra instructions are
2030*349cc55cSDimitry Andric       // added to the region. This makes the region no longer viable
2031*349cc55cSDimitry Andric       // to be split, so we ignore it for outlining.
2032*349cc55cSDimitry Andric       if (!OS->CandidateSplit)
2033*349cc55cSDimitry Andric         continue;
2034*349cc55cSDimitry Andric 
2035*349cc55cSDimitry Andric       SmallVector<BasicBlock *> BE;
2036*349cc55cSDimitry Andric       DenseSet<BasicBlock *> BBSet;
2037*349cc55cSDimitry Andric       OS->Candidate->getBasicBlocks(BBSet, BE);
2038e8d8bef9SDimitry Andric       OS->CE = new (ExtractorAllocator.Allocate())
2039e8d8bef9SDimitry Andric           CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false,
2040e8d8bef9SDimitry Andric                         false, "outlined");
2041e8d8bef9SDimitry Andric       findAddInputsOutputs(M, *OS, NotSame);
2042e8d8bef9SDimitry Andric       if (!OS->IgnoreRegion)
2043e8d8bef9SDimitry Andric         OutlinedRegions.push_back(OS);
2044*349cc55cSDimitry Andric 
2045*349cc55cSDimitry Andric       // We recombine the blocks together now that we have gathered all the
2046*349cc55cSDimitry Andric       // needed information.
2047e8d8bef9SDimitry Andric       OS->reattachCandidate();
2048e8d8bef9SDimitry Andric     }
2049e8d8bef9SDimitry Andric 
2050e8d8bef9SDimitry Andric     CurrentGroup.Regions = std::move(OutlinedRegions);
2051e8d8bef9SDimitry Andric 
2052e8d8bef9SDimitry Andric     if (CurrentGroup.Regions.empty())
2053e8d8bef9SDimitry Andric       continue;
2054e8d8bef9SDimitry Andric 
2055e8d8bef9SDimitry Andric     CurrentGroup.collectGVNStoreSets(M);
2056e8d8bef9SDimitry Andric 
2057e8d8bef9SDimitry Andric     if (CostModel)
2058e8d8bef9SDimitry Andric       findCostBenefit(M, CurrentGroup);
2059e8d8bef9SDimitry Andric 
2060*349cc55cSDimitry Andric     // If we are adhering to the cost model, skip those groups where the cost
2061*349cc55cSDimitry Andric     // outweighs the benefits.
2062e8d8bef9SDimitry Andric     if (CurrentGroup.Cost >= CurrentGroup.Benefit && CostModel) {
2063*349cc55cSDimitry Andric       OptimizationRemarkEmitter &ORE =
2064*349cc55cSDimitry Andric           getORE(*CurrentGroup.Regions[0]->Candidate->getFunction());
2065e8d8bef9SDimitry Andric       ORE.emit([&]() {
2066e8d8bef9SDimitry Andric         IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate;
2067e8d8bef9SDimitry Andric         OptimizationRemarkMissed R(DEBUG_TYPE, "WouldNotDecreaseSize",
2068e8d8bef9SDimitry Andric                                    C->frontInstruction());
2069e8d8bef9SDimitry Andric         R << "did not outline "
2070e8d8bef9SDimitry Andric           << ore::NV(std::to_string(CurrentGroup.Regions.size()))
2071e8d8bef9SDimitry Andric           << " regions due to estimated increase of "
2072e8d8bef9SDimitry Andric           << ore::NV("InstructionIncrease",
2073e8d8bef9SDimitry Andric                      CurrentGroup.Cost - CurrentGroup.Benefit)
2074e8d8bef9SDimitry Andric           << " instructions at locations ";
2075e8d8bef9SDimitry Andric         interleave(
2076e8d8bef9SDimitry Andric             CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(),
2077e8d8bef9SDimitry Andric             [&R](OutlinableRegion *Region) {
2078e8d8bef9SDimitry Andric               R << ore::NV(
2079e8d8bef9SDimitry Andric                   "DebugLoc",
2080e8d8bef9SDimitry Andric                   Region->Candidate->frontInstruction()->getDebugLoc());
2081e8d8bef9SDimitry Andric             },
2082e8d8bef9SDimitry Andric             [&R]() { R << " "; });
2083e8d8bef9SDimitry Andric         return R;
2084e8d8bef9SDimitry Andric       });
2085e8d8bef9SDimitry Andric       continue;
2086e8d8bef9SDimitry Andric     }
2087e8d8bef9SDimitry Andric 
2088*349cc55cSDimitry Andric     NegativeCostGroups.push_back(&CurrentGroup);
2089*349cc55cSDimitry Andric   }
2090*349cc55cSDimitry Andric 
2091*349cc55cSDimitry Andric   ExtractorAllocator.DestroyAll();
2092*349cc55cSDimitry Andric 
2093*349cc55cSDimitry Andric   if (NegativeCostGroups.size() > 1)
2094*349cc55cSDimitry Andric     stable_sort(NegativeCostGroups,
2095*349cc55cSDimitry Andric                 [](const OutlinableGroup *LHS, const OutlinableGroup *RHS) {
2096*349cc55cSDimitry Andric                   return LHS->Benefit - LHS->Cost > RHS->Benefit - RHS->Cost;
2097*349cc55cSDimitry Andric                 });
2098*349cc55cSDimitry Andric 
2099*349cc55cSDimitry Andric   std::vector<Function *> FuncsToRemove;
2100*349cc55cSDimitry Andric   for (OutlinableGroup *CG : NegativeCostGroups) {
2101*349cc55cSDimitry Andric     OutlinableGroup &CurrentGroup = *CG;
2102*349cc55cSDimitry Andric 
2103*349cc55cSDimitry Andric     OutlinedRegions.clear();
2104*349cc55cSDimitry Andric     for (OutlinableRegion *Region : CurrentGroup.Regions) {
2105*349cc55cSDimitry Andric       // We check whether our region is compatible with what has already been
2106*349cc55cSDimitry Andric       // outlined, and whether we need to ignore this item.
2107*349cc55cSDimitry Andric       if (!isCompatibleWithAlreadyOutlinedCode(*Region))
2108*349cc55cSDimitry Andric         continue;
2109*349cc55cSDimitry Andric       OutlinedRegions.push_back(Region);
2110*349cc55cSDimitry Andric     }
2111*349cc55cSDimitry Andric 
2112*349cc55cSDimitry Andric     if (OutlinedRegions.size() < 2)
2113*349cc55cSDimitry Andric       continue;
2114*349cc55cSDimitry Andric 
2115*349cc55cSDimitry Andric     // Reestimate the cost and benefit of the OutlinableGroup. Continue only if
2116*349cc55cSDimitry Andric     // we are still outlining enough regions to make up for the added cost.
2117*349cc55cSDimitry Andric     CurrentGroup.Regions = std::move(OutlinedRegions);
2118*349cc55cSDimitry Andric     if (CostModel) {
2119*349cc55cSDimitry Andric       CurrentGroup.Benefit = 0;
2120*349cc55cSDimitry Andric       CurrentGroup.Cost = 0;
2121*349cc55cSDimitry Andric       findCostBenefit(M, CurrentGroup);
2122*349cc55cSDimitry Andric       if (CurrentGroup.Cost >= CurrentGroup.Benefit)
2123*349cc55cSDimitry Andric         continue;
2124*349cc55cSDimitry Andric     }
2125*349cc55cSDimitry Andric     OutlinedRegions.clear();
2126*349cc55cSDimitry Andric     for (OutlinableRegion *Region : CurrentGroup.Regions) {
2127*349cc55cSDimitry Andric       Region->splitCandidate();
2128*349cc55cSDimitry Andric       if (!Region->CandidateSplit)
2129*349cc55cSDimitry Andric         continue;
2130*349cc55cSDimitry Andric       OutlinedRegions.push_back(Region);
2131*349cc55cSDimitry Andric     }
2132*349cc55cSDimitry Andric 
2133*349cc55cSDimitry Andric     CurrentGroup.Regions = std::move(OutlinedRegions);
2134*349cc55cSDimitry Andric     if (CurrentGroup.Regions.size() < 2) {
2135*349cc55cSDimitry Andric       for (OutlinableRegion *R : CurrentGroup.Regions)
2136*349cc55cSDimitry Andric         R->reattachCandidate();
2137*349cc55cSDimitry Andric       continue;
2138*349cc55cSDimitry Andric     }
2139*349cc55cSDimitry Andric 
2140e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Outlining regions with cost " << CurrentGroup.Cost
2141e8d8bef9SDimitry Andric                       << " and benefit " << CurrentGroup.Benefit << "\n");
2142e8d8bef9SDimitry Andric 
2143e8d8bef9SDimitry Andric     // Create functions out of all the sections, and mark them as outlined.
2144e8d8bef9SDimitry Andric     OutlinedRegions.clear();
2145e8d8bef9SDimitry Andric     for (OutlinableRegion *OS : CurrentGroup.Regions) {
2146*349cc55cSDimitry Andric       SmallVector<BasicBlock *> BE;
2147*349cc55cSDimitry Andric       DenseSet<BasicBlock *> BBSet;
2148*349cc55cSDimitry Andric       OS->Candidate->getBasicBlocks(BBSet, BE);
2149*349cc55cSDimitry Andric       OS->CE = new (ExtractorAllocator.Allocate())
2150*349cc55cSDimitry Andric           CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false,
2151*349cc55cSDimitry Andric                         false, "outlined");
2152e8d8bef9SDimitry Andric       bool FunctionOutlined = extractSection(*OS);
2153e8d8bef9SDimitry Andric       if (FunctionOutlined) {
2154e8d8bef9SDimitry Andric         unsigned StartIdx = OS->Candidate->getStartIdx();
2155e8d8bef9SDimitry Andric         unsigned EndIdx = OS->Candidate->getEndIdx();
2156e8d8bef9SDimitry Andric         for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2157e8d8bef9SDimitry Andric           Outlined.insert(Idx);
2158e8d8bef9SDimitry Andric 
2159e8d8bef9SDimitry Andric         OutlinedRegions.push_back(OS);
2160e8d8bef9SDimitry Andric       }
2161e8d8bef9SDimitry Andric     }
2162e8d8bef9SDimitry Andric 
2163e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Outlined " << OutlinedRegions.size()
2164e8d8bef9SDimitry Andric                       << " with benefit " << CurrentGroup.Benefit
2165e8d8bef9SDimitry Andric                       << " and cost " << CurrentGroup.Cost << "\n");
2166e8d8bef9SDimitry Andric 
2167e8d8bef9SDimitry Andric     CurrentGroup.Regions = std::move(OutlinedRegions);
2168e8d8bef9SDimitry Andric 
2169e8d8bef9SDimitry Andric     if (CurrentGroup.Regions.empty())
2170e8d8bef9SDimitry Andric       continue;
2171e8d8bef9SDimitry Andric 
2172e8d8bef9SDimitry Andric     OptimizationRemarkEmitter &ORE =
2173e8d8bef9SDimitry Andric         getORE(*CurrentGroup.Regions[0]->Call->getFunction());
2174e8d8bef9SDimitry Andric     ORE.emit([&]() {
2175e8d8bef9SDimitry Andric       IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate;
2176e8d8bef9SDimitry Andric       OptimizationRemark R(DEBUG_TYPE, "Outlined", C->front()->Inst);
2177e8d8bef9SDimitry Andric       R << "outlined " << ore::NV(std::to_string(CurrentGroup.Regions.size()))
2178e8d8bef9SDimitry Andric         << " regions with decrease of "
2179e8d8bef9SDimitry Andric         << ore::NV("Benefit", CurrentGroup.Benefit - CurrentGroup.Cost)
2180e8d8bef9SDimitry Andric         << " instructions at locations ";
2181e8d8bef9SDimitry Andric       interleave(
2182e8d8bef9SDimitry Andric           CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(),
2183e8d8bef9SDimitry Andric           [&R](OutlinableRegion *Region) {
2184e8d8bef9SDimitry Andric             R << ore::NV("DebugLoc",
2185e8d8bef9SDimitry Andric                          Region->Candidate->frontInstruction()->getDebugLoc());
2186e8d8bef9SDimitry Andric           },
2187e8d8bef9SDimitry Andric           [&R]() { R << " "; });
2188e8d8bef9SDimitry Andric       return R;
2189e8d8bef9SDimitry Andric     });
2190e8d8bef9SDimitry Andric 
2191e8d8bef9SDimitry Andric     deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove,
2192e8d8bef9SDimitry Andric                                  OutlinedFunctionNum);
2193e8d8bef9SDimitry Andric   }
2194e8d8bef9SDimitry Andric 
2195e8d8bef9SDimitry Andric   for (Function *F : FuncsToRemove)
2196e8d8bef9SDimitry Andric     F->eraseFromParent();
2197e8d8bef9SDimitry Andric 
2198e8d8bef9SDimitry Andric   return OutlinedFunctionNum;
2199e8d8bef9SDimitry Andric }
2200e8d8bef9SDimitry Andric 
2201e8d8bef9SDimitry Andric bool IROutliner::run(Module &M) {
2202e8d8bef9SDimitry Andric   CostModel = !NoCostModel;
2203e8d8bef9SDimitry Andric   OutlineFromLinkODRs = EnableLinkOnceODRIROutlining;
2204e8d8bef9SDimitry Andric 
2205e8d8bef9SDimitry Andric   return doOutline(M) > 0;
2206e8d8bef9SDimitry Andric }
2207e8d8bef9SDimitry Andric 
2208e8d8bef9SDimitry Andric // Pass Manager Boilerplate
2209*349cc55cSDimitry Andric namespace {
2210e8d8bef9SDimitry Andric class IROutlinerLegacyPass : public ModulePass {
2211e8d8bef9SDimitry Andric public:
2212e8d8bef9SDimitry Andric   static char ID;
2213e8d8bef9SDimitry Andric   IROutlinerLegacyPass() : ModulePass(ID) {
2214e8d8bef9SDimitry Andric     initializeIROutlinerLegacyPassPass(*PassRegistry::getPassRegistry());
2215e8d8bef9SDimitry Andric   }
2216e8d8bef9SDimitry Andric 
2217e8d8bef9SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
2218e8d8bef9SDimitry Andric     AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
2219e8d8bef9SDimitry Andric     AU.addRequired<TargetTransformInfoWrapperPass>();
2220e8d8bef9SDimitry Andric     AU.addRequired<IRSimilarityIdentifierWrapperPass>();
2221e8d8bef9SDimitry Andric   }
2222e8d8bef9SDimitry Andric 
2223e8d8bef9SDimitry Andric   bool runOnModule(Module &M) override;
2224e8d8bef9SDimitry Andric };
2225*349cc55cSDimitry Andric } // namespace
2226e8d8bef9SDimitry Andric 
2227e8d8bef9SDimitry Andric bool IROutlinerLegacyPass::runOnModule(Module &M) {
2228e8d8bef9SDimitry Andric   if (skipModule(M))
2229e8d8bef9SDimitry Andric     return false;
2230e8d8bef9SDimitry Andric 
2231e8d8bef9SDimitry Andric   std::unique_ptr<OptimizationRemarkEmitter> ORE;
2232e8d8bef9SDimitry Andric   auto GORE = [&ORE](Function &F) -> OptimizationRemarkEmitter & {
2233e8d8bef9SDimitry Andric     ORE.reset(new OptimizationRemarkEmitter(&F));
2234e8d8bef9SDimitry Andric     return *ORE.get();
2235e8d8bef9SDimitry Andric   };
2236e8d8bef9SDimitry Andric 
2237e8d8bef9SDimitry Andric   auto GTTI = [this](Function &F) -> TargetTransformInfo & {
2238e8d8bef9SDimitry Andric     return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
2239e8d8bef9SDimitry Andric   };
2240e8d8bef9SDimitry Andric 
2241e8d8bef9SDimitry Andric   auto GIRSI = [this](Module &) -> IRSimilarityIdentifier & {
2242e8d8bef9SDimitry Andric     return this->getAnalysis<IRSimilarityIdentifierWrapperPass>().getIRSI();
2243e8d8bef9SDimitry Andric   };
2244e8d8bef9SDimitry Andric 
2245e8d8bef9SDimitry Andric   return IROutliner(GTTI, GIRSI, GORE).run(M);
2246e8d8bef9SDimitry Andric }
2247e8d8bef9SDimitry Andric 
2248e8d8bef9SDimitry Andric PreservedAnalyses IROutlinerPass::run(Module &M, ModuleAnalysisManager &AM) {
2249e8d8bef9SDimitry Andric   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
2250e8d8bef9SDimitry Andric 
2251e8d8bef9SDimitry Andric   std::function<TargetTransformInfo &(Function &)> GTTI =
2252e8d8bef9SDimitry Andric       [&FAM](Function &F) -> TargetTransformInfo & {
2253e8d8bef9SDimitry Andric     return FAM.getResult<TargetIRAnalysis>(F);
2254e8d8bef9SDimitry Andric   };
2255e8d8bef9SDimitry Andric 
2256e8d8bef9SDimitry Andric   std::function<IRSimilarityIdentifier &(Module &)> GIRSI =
2257e8d8bef9SDimitry Andric       [&AM](Module &M) -> IRSimilarityIdentifier & {
2258e8d8bef9SDimitry Andric     return AM.getResult<IRSimilarityAnalysis>(M);
2259e8d8bef9SDimitry Andric   };
2260e8d8bef9SDimitry Andric 
2261e8d8bef9SDimitry Andric   std::unique_ptr<OptimizationRemarkEmitter> ORE;
2262e8d8bef9SDimitry Andric   std::function<OptimizationRemarkEmitter &(Function &)> GORE =
2263e8d8bef9SDimitry Andric       [&ORE](Function &F) -> OptimizationRemarkEmitter & {
2264e8d8bef9SDimitry Andric     ORE.reset(new OptimizationRemarkEmitter(&F));
2265e8d8bef9SDimitry Andric     return *ORE.get();
2266e8d8bef9SDimitry Andric   };
2267e8d8bef9SDimitry Andric 
2268e8d8bef9SDimitry Andric   if (IROutliner(GTTI, GIRSI, GORE).run(M))
2269e8d8bef9SDimitry Andric     return PreservedAnalyses::none();
2270e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
2271e8d8bef9SDimitry Andric }
2272e8d8bef9SDimitry Andric 
2273e8d8bef9SDimitry Andric char IROutlinerLegacyPass::ID = 0;
2274e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(IROutlinerLegacyPass, "iroutliner", "IR Outliner", false,
2275e8d8bef9SDimitry Andric                       false)
2276e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(IRSimilarityIdentifierWrapperPass)
2277e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
2278e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
2279e8d8bef9SDimitry Andric INITIALIZE_PASS_END(IROutlinerLegacyPass, "iroutliner", "IR Outliner", false,
2280e8d8bef9SDimitry Andric                     false)
2281e8d8bef9SDimitry Andric 
2282e8d8bef9SDimitry Andric ModulePass *llvm::createIROutlinerPass() { return new IROutlinerLegacyPass(); }
2283