xref: /src/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1d8e91e46SDimitry Andric //===-- ControlHeightReduction.cpp - Control Height Reduction -------------===//
2d8e91e46SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d8e91e46SDimitry Andric //
7d8e91e46SDimitry Andric //===----------------------------------------------------------------------===//
8d8e91e46SDimitry Andric //
9d8e91e46SDimitry Andric // This pass merges conditional blocks of code and reduces the number of
10d8e91e46SDimitry Andric // conditional branches in the hot paths based on profiles.
11d8e91e46SDimitry Andric //
12d8e91e46SDimitry Andric //===----------------------------------------------------------------------===//
13d8e91e46SDimitry Andric 
14d8e91e46SDimitry Andric #include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"
15d8e91e46SDimitry Andric #include "llvm/ADT/DenseMap.h"
16d8e91e46SDimitry Andric #include "llvm/ADT/DenseSet.h"
17d8e91e46SDimitry Andric #include "llvm/ADT/SmallVector.h"
18d8e91e46SDimitry Andric #include "llvm/ADT/StringSet.h"
19d8e91e46SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
20d8e91e46SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
21d8e91e46SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
22d8e91e46SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
23d8e91e46SDimitry Andric #include "llvm/Analysis/RegionInfo.h"
24d8e91e46SDimitry Andric #include "llvm/Analysis/RegionIterator.h"
25d8e91e46SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
26d8e91e46SDimitry Andric #include "llvm/IR/CFG.h"
27d8e91e46SDimitry Andric #include "llvm/IR/Dominators.h"
28d8e91e46SDimitry Andric #include "llvm/IR/IRBuilder.h"
29145449b1SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
30d8e91e46SDimitry Andric #include "llvm/IR/MDBuilder.h"
31ac9a064cSDimitry Andric #include "llvm/IR/Module.h"
32344a3780SDimitry Andric #include "llvm/IR/PassManager.h"
33e3b55780SDimitry Andric #include "llvm/IR/ProfDataUtils.h"
34d8e91e46SDimitry Andric #include "llvm/Support/BranchProbability.h"
35706b4fc4SDimitry Andric #include "llvm/Support/CommandLine.h"
36d8e91e46SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
37d8e91e46SDimitry Andric #include "llvm/Transforms/Utils.h"
38d8e91e46SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
39d8e91e46SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
40d8e91e46SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h"
41d8e91e46SDimitry Andric 
42e3b55780SDimitry Andric #include <optional>
43d8e91e46SDimitry Andric #include <set>
44d8e91e46SDimitry Andric #include <sstream>
45d8e91e46SDimitry Andric 
46d8e91e46SDimitry Andric using namespace llvm;
47d8e91e46SDimitry Andric 
48d8e91e46SDimitry Andric #define DEBUG_TYPE "chr"
49d8e91e46SDimitry Andric 
50d8e91e46SDimitry Andric #define CHR_DEBUG(X) LLVM_DEBUG(X)
51d8e91e46SDimitry Andric 
52e3b55780SDimitry Andric static cl::opt<bool> DisableCHR("disable-chr", cl::init(false), cl::Hidden,
53e3b55780SDimitry Andric                                 cl::desc("Disable CHR for all functions"));
54e3b55780SDimitry Andric 
55d8e91e46SDimitry Andric static cl::opt<bool> ForceCHR("force-chr", cl::init(false), cl::Hidden,
56d8e91e46SDimitry Andric                               cl::desc("Apply CHR for all functions"));
57d8e91e46SDimitry Andric 
58d8e91e46SDimitry Andric static cl::opt<double> CHRBiasThreshold(
59d8e91e46SDimitry Andric     "chr-bias-threshold", cl::init(0.99), cl::Hidden,
60d8e91e46SDimitry Andric     cl::desc("CHR considers a branch bias greater than this ratio as biased"));
61d8e91e46SDimitry Andric 
62d8e91e46SDimitry Andric static cl::opt<unsigned> CHRMergeThreshold(
63d8e91e46SDimitry Andric     "chr-merge-threshold", cl::init(2), cl::Hidden,
64d8e91e46SDimitry Andric     cl::desc("CHR merges a group of N branches/selects where N >= this value"));
65d8e91e46SDimitry Andric 
66d8e91e46SDimitry Andric static cl::opt<std::string> CHRModuleList(
67d8e91e46SDimitry Andric     "chr-module-list", cl::init(""), cl::Hidden,
68d8e91e46SDimitry Andric     cl::desc("Specify file to retrieve the list of modules to apply CHR to"));
69d8e91e46SDimitry Andric 
70d8e91e46SDimitry Andric static cl::opt<std::string> CHRFunctionList(
71d8e91e46SDimitry Andric     "chr-function-list", cl::init(""), cl::Hidden,
72d8e91e46SDimitry Andric     cl::desc("Specify file to retrieve the list of functions to apply CHR to"));
73d8e91e46SDimitry Andric 
74e3b55780SDimitry Andric static cl::opt<unsigned> CHRDupThreshsold(
75e3b55780SDimitry Andric     "chr-dup-threshold", cl::init(3), cl::Hidden,
76e3b55780SDimitry Andric     cl::desc("Max number of duplications by CHR for a region"));
77e3b55780SDimitry Andric 
78d8e91e46SDimitry Andric static StringSet<> CHRModules;
79d8e91e46SDimitry Andric static StringSet<> CHRFunctions;
80d8e91e46SDimitry Andric 
parseCHRFilterFiles()81d8e91e46SDimitry Andric static void parseCHRFilterFiles() {
82d8e91e46SDimitry Andric   if (!CHRModuleList.empty()) {
83d8e91e46SDimitry Andric     auto FileOrErr = MemoryBuffer::getFile(CHRModuleList);
84d8e91e46SDimitry Andric     if (!FileOrErr) {
85d8e91e46SDimitry Andric       errs() << "Error: Couldn't read the chr-module-list file " << CHRModuleList << "\n";
86d8e91e46SDimitry Andric       std::exit(1);
87d8e91e46SDimitry Andric     }
88d8e91e46SDimitry Andric     StringRef Buf = FileOrErr->get()->getBuffer();
89d8e91e46SDimitry Andric     SmallVector<StringRef, 0> Lines;
90d8e91e46SDimitry Andric     Buf.split(Lines, '\n');
91d8e91e46SDimitry Andric     for (StringRef Line : Lines) {
92d8e91e46SDimitry Andric       Line = Line.trim();
93d8e91e46SDimitry Andric       if (!Line.empty())
94d8e91e46SDimitry Andric         CHRModules.insert(Line);
95d8e91e46SDimitry Andric     }
96d8e91e46SDimitry Andric   }
97d8e91e46SDimitry Andric   if (!CHRFunctionList.empty()) {
98d8e91e46SDimitry Andric     auto FileOrErr = MemoryBuffer::getFile(CHRFunctionList);
99d8e91e46SDimitry Andric     if (!FileOrErr) {
100d8e91e46SDimitry Andric       errs() << "Error: Couldn't read the chr-function-list file " << CHRFunctionList << "\n";
101d8e91e46SDimitry Andric       std::exit(1);
102d8e91e46SDimitry Andric     }
103d8e91e46SDimitry Andric     StringRef Buf = FileOrErr->get()->getBuffer();
104d8e91e46SDimitry Andric     SmallVector<StringRef, 0> Lines;
105d8e91e46SDimitry Andric     Buf.split(Lines, '\n');
106d8e91e46SDimitry Andric     for (StringRef Line : Lines) {
107d8e91e46SDimitry Andric       Line = Line.trim();
108d8e91e46SDimitry Andric       if (!Line.empty())
109d8e91e46SDimitry Andric         CHRFunctions.insert(Line);
110d8e91e46SDimitry Andric     }
111d8e91e46SDimitry Andric   }
112d8e91e46SDimitry Andric }
113d8e91e46SDimitry Andric 
114d8e91e46SDimitry Andric namespace {
115d8e91e46SDimitry Andric 
116d8e91e46SDimitry Andric struct CHRStats {
117145449b1SDimitry Andric   CHRStats() = default;
print__anon6d5ead4d0111::CHRStats118d8e91e46SDimitry Andric   void print(raw_ostream &OS) const {
119d8e91e46SDimitry Andric     OS << "CHRStats: NumBranches " << NumBranches
120d8e91e46SDimitry Andric        << " NumBranchesDelta " << NumBranchesDelta
121d8e91e46SDimitry Andric        << " WeightedNumBranchesDelta " << WeightedNumBranchesDelta;
122d8e91e46SDimitry Andric   }
123145449b1SDimitry Andric   // The original number of conditional branches / selects
124145449b1SDimitry Andric   uint64_t NumBranches = 0;
125145449b1SDimitry Andric   // The decrease of the number of conditional branches / selects in the hot
126145449b1SDimitry Andric   // paths due to CHR.
127145449b1SDimitry Andric   uint64_t NumBranchesDelta = 0;
128145449b1SDimitry Andric   // NumBranchesDelta weighted by the profile count at the scope entry.
129145449b1SDimitry Andric   uint64_t WeightedNumBranchesDelta = 0;
130d8e91e46SDimitry Andric };
131d8e91e46SDimitry Andric 
132d8e91e46SDimitry Andric // RegInfo - some properties of a Region.
133d8e91e46SDimitry Andric struct RegInfo {
134145449b1SDimitry Andric   RegInfo() = default;
RegInfo__anon6d5ead4d0111::RegInfo135145449b1SDimitry Andric   RegInfo(Region *RegionIn) : R(RegionIn) {}
136145449b1SDimitry Andric   Region *R = nullptr;
137145449b1SDimitry Andric   bool HasBranch = false;
138d8e91e46SDimitry Andric   SmallVector<SelectInst *, 8> Selects;
139d8e91e46SDimitry Andric };
140d8e91e46SDimitry Andric 
141d8e91e46SDimitry Andric typedef DenseMap<Region *, DenseSet<Instruction *>> HoistStopMapTy;
142d8e91e46SDimitry Andric 
143d8e91e46SDimitry Andric // CHRScope - a sequence of regions to CHR together. It corresponds to a
144d8e91e46SDimitry Andric // sequence of conditional blocks. It can have subscopes which correspond to
145d8e91e46SDimitry Andric // nested conditional blocks. Nested CHRScopes form a tree.
146d8e91e46SDimitry Andric class CHRScope {
147d8e91e46SDimitry Andric  public:
CHRScope(RegInfo RI)148d8e91e46SDimitry Andric   CHRScope(RegInfo RI) : BranchInsertPoint(nullptr) {
149d8e91e46SDimitry Andric     assert(RI.R && "Null RegionIn");
150d8e91e46SDimitry Andric     RegInfos.push_back(RI);
151d8e91e46SDimitry Andric   }
152d8e91e46SDimitry Andric 
getParentRegion()153d8e91e46SDimitry Andric   Region *getParentRegion() {
154d8e91e46SDimitry Andric     assert(RegInfos.size() > 0 && "Empty CHRScope");
155d8e91e46SDimitry Andric     Region *Parent = RegInfos[0].R->getParent();
156d8e91e46SDimitry Andric     assert(Parent && "Unexpected to call this on the top-level region");
157d8e91e46SDimitry Andric     return Parent;
158d8e91e46SDimitry Andric   }
159d8e91e46SDimitry Andric 
getEntryBlock()160d8e91e46SDimitry Andric   BasicBlock *getEntryBlock() {
161d8e91e46SDimitry Andric     assert(RegInfos.size() > 0 && "Empty CHRScope");
162d8e91e46SDimitry Andric     return RegInfos.front().R->getEntry();
163d8e91e46SDimitry Andric   }
164d8e91e46SDimitry Andric 
getExitBlock()165d8e91e46SDimitry Andric   BasicBlock *getExitBlock() {
166d8e91e46SDimitry Andric     assert(RegInfos.size() > 0 && "Empty CHRScope");
167d8e91e46SDimitry Andric     return RegInfos.back().R->getExit();
168d8e91e46SDimitry Andric   }
169d8e91e46SDimitry Andric 
appendable(CHRScope * Next)170d8e91e46SDimitry Andric   bool appendable(CHRScope *Next) {
171d8e91e46SDimitry Andric     // The next scope is appendable only if this scope is directly connected to
172d8e91e46SDimitry Andric     // it (which implies it post-dominates this scope) and this scope dominates
173d8e91e46SDimitry Andric     // it (no edge to the next scope outside this scope).
174d8e91e46SDimitry Andric     BasicBlock *NextEntry = Next->getEntryBlock();
175d8e91e46SDimitry Andric     if (getExitBlock() != NextEntry)
176d8e91e46SDimitry Andric       // Not directly connected.
177d8e91e46SDimitry Andric       return false;
178d8e91e46SDimitry Andric     Region *LastRegion = RegInfos.back().R;
179d8e91e46SDimitry Andric     for (BasicBlock *Pred : predecessors(NextEntry))
180d8e91e46SDimitry Andric       if (!LastRegion->contains(Pred))
181d8e91e46SDimitry Andric         // There's an edge going into the entry of the next scope from outside
182d8e91e46SDimitry Andric         // of this scope.
183d8e91e46SDimitry Andric         return false;
184d8e91e46SDimitry Andric     return true;
185d8e91e46SDimitry Andric   }
186d8e91e46SDimitry Andric 
append(CHRScope * Next)187d8e91e46SDimitry Andric   void append(CHRScope *Next) {
188d8e91e46SDimitry Andric     assert(RegInfos.size() > 0 && "Empty CHRScope");
189d8e91e46SDimitry Andric     assert(Next->RegInfos.size() > 0 && "Empty CHRScope");
190d8e91e46SDimitry Andric     assert(getParentRegion() == Next->getParentRegion() &&
191d8e91e46SDimitry Andric            "Must be siblings");
192d8e91e46SDimitry Andric     assert(getExitBlock() == Next->getEntryBlock() &&
193d8e91e46SDimitry Andric            "Must be adjacent");
194cfca06d7SDimitry Andric     RegInfos.append(Next->RegInfos.begin(), Next->RegInfos.end());
195cfca06d7SDimitry Andric     Subs.append(Next->Subs.begin(), Next->Subs.end());
196d8e91e46SDimitry Andric   }
197d8e91e46SDimitry Andric 
addSub(CHRScope * SubIn)198d8e91e46SDimitry Andric   void addSub(CHRScope *SubIn) {
199d8e91e46SDimitry Andric #ifndef NDEBUG
200d8e91e46SDimitry Andric     bool IsChild = false;
201d8e91e46SDimitry Andric     for (RegInfo &RI : RegInfos)
202d8e91e46SDimitry Andric       if (RI.R == SubIn->getParentRegion()) {
203d8e91e46SDimitry Andric         IsChild = true;
204d8e91e46SDimitry Andric         break;
205d8e91e46SDimitry Andric       }
206d8e91e46SDimitry Andric     assert(IsChild && "Must be a child");
207d8e91e46SDimitry Andric #endif
208d8e91e46SDimitry Andric     Subs.push_back(SubIn);
209d8e91e46SDimitry Andric   }
210d8e91e46SDimitry Andric 
211d8e91e46SDimitry Andric   // Split this scope at the boundary region into two, which will belong to the
212d8e91e46SDimitry Andric   // tail and returns the tail.
split(Region * Boundary)213d8e91e46SDimitry Andric   CHRScope *split(Region *Boundary) {
214d8e91e46SDimitry Andric     assert(Boundary && "Boundary null");
215d8e91e46SDimitry Andric     assert(RegInfos.begin()->R != Boundary &&
216d8e91e46SDimitry Andric            "Can't be split at beginning");
217cfca06d7SDimitry Andric     auto BoundaryIt = llvm::find_if(
218cfca06d7SDimitry Andric         RegInfos, [&Boundary](const RegInfo &RI) { return Boundary == RI.R; });
219d8e91e46SDimitry Andric     if (BoundaryIt == RegInfos.end())
220d8e91e46SDimitry Andric       return nullptr;
221cfca06d7SDimitry Andric     ArrayRef<RegInfo> TailRegInfos(BoundaryIt, RegInfos.end());
222d8e91e46SDimitry Andric     DenseSet<Region *> TailRegionSet;
223cfca06d7SDimitry Andric     for (const RegInfo &RI : TailRegInfos)
224d8e91e46SDimitry Andric       TailRegionSet.insert(RI.R);
225cfca06d7SDimitry Andric 
226cfca06d7SDimitry Andric     auto TailIt =
227cfca06d7SDimitry Andric         std::stable_partition(Subs.begin(), Subs.end(), [&](CHRScope *Sub) {
228d8e91e46SDimitry Andric           assert(Sub && "null Sub");
229d8e91e46SDimitry Andric           Region *Parent = Sub->getParentRegion();
230cfca06d7SDimitry Andric           if (TailRegionSet.count(Parent))
231cfca06d7SDimitry Andric             return false;
232cfca06d7SDimitry Andric 
233b60736ecSDimitry Andric           assert(llvm::any_of(
234b60736ecSDimitry Andric                      RegInfos,
235b60736ecSDimitry Andric                      [&Parent](const RegInfo &RI) { return Parent == RI.R; }) &&
236d8e91e46SDimitry Andric                  "Must be in head");
237cfca06d7SDimitry Andric           return true;
238cfca06d7SDimitry Andric         });
239cfca06d7SDimitry Andric     ArrayRef<CHRScope *> TailSubs(TailIt, Subs.end());
240cfca06d7SDimitry Andric 
241d8e91e46SDimitry Andric     assert(HoistStopMap.empty() && "MapHoistStops must be empty");
242cfca06d7SDimitry Andric     auto *Scope = new CHRScope(TailRegInfos, TailSubs);
243cfca06d7SDimitry Andric     RegInfos.erase(BoundaryIt, RegInfos.end());
244cfca06d7SDimitry Andric     Subs.erase(TailIt, Subs.end());
245cfca06d7SDimitry Andric     return Scope;
246d8e91e46SDimitry Andric   }
247d8e91e46SDimitry Andric 
contains(Instruction * I) const248d8e91e46SDimitry Andric   bool contains(Instruction *I) const {
249d8e91e46SDimitry Andric     BasicBlock *Parent = I->getParent();
250d8e91e46SDimitry Andric     for (const RegInfo &RI : RegInfos)
251d8e91e46SDimitry Andric       if (RI.R->contains(Parent))
252d8e91e46SDimitry Andric         return true;
253d8e91e46SDimitry Andric     return false;
254d8e91e46SDimitry Andric   }
255d8e91e46SDimitry Andric 
256d8e91e46SDimitry Andric   void print(raw_ostream &OS) const;
257d8e91e46SDimitry Andric 
258d8e91e46SDimitry Andric   SmallVector<RegInfo, 8> RegInfos; // Regions that belong to this scope
259d8e91e46SDimitry Andric   SmallVector<CHRScope *, 8> Subs;  // Subscopes.
260d8e91e46SDimitry Andric 
261d8e91e46SDimitry Andric   // The instruction at which to insert the CHR conditional branch (and hoist
262d8e91e46SDimitry Andric   // the dependent condition values).
263d8e91e46SDimitry Andric   Instruction *BranchInsertPoint;
264d8e91e46SDimitry Andric 
265d8e91e46SDimitry Andric   // True-biased and false-biased regions (conditional blocks),
266d8e91e46SDimitry Andric   // respectively. Used only for the outermost scope and includes regions in
267d8e91e46SDimitry Andric   // subscopes. The rest are unbiased.
268d8e91e46SDimitry Andric   DenseSet<Region *> TrueBiasedRegions;
269d8e91e46SDimitry Andric   DenseSet<Region *> FalseBiasedRegions;
270d8e91e46SDimitry Andric   // Among the biased regions, the regions that get CHRed.
271d8e91e46SDimitry Andric   SmallVector<RegInfo, 8> CHRRegions;
272d8e91e46SDimitry Andric 
273d8e91e46SDimitry Andric   // True-biased and false-biased selects, respectively. Used only for the
274d8e91e46SDimitry Andric   // outermost scope and includes ones in subscopes.
275d8e91e46SDimitry Andric   DenseSet<SelectInst *> TrueBiasedSelects;
276d8e91e46SDimitry Andric   DenseSet<SelectInst *> FalseBiasedSelects;
277d8e91e46SDimitry Andric 
278d8e91e46SDimitry Andric   // Map from one of the above regions to the instructions to stop
279d8e91e46SDimitry Andric   // hoisting instructions at through use-def chains.
280d8e91e46SDimitry Andric   HoistStopMapTy HoistStopMap;
281d8e91e46SDimitry Andric 
282d8e91e46SDimitry Andric  private:
CHRScope(ArrayRef<RegInfo> RegInfosIn,ArrayRef<CHRScope * > SubsIn)283cfca06d7SDimitry Andric    CHRScope(ArrayRef<RegInfo> RegInfosIn, ArrayRef<CHRScope *> SubsIn)
284cfca06d7SDimitry Andric        : RegInfos(RegInfosIn.begin(), RegInfosIn.end()),
285cfca06d7SDimitry Andric          Subs(SubsIn.begin(), SubsIn.end()), BranchInsertPoint(nullptr) {}
286d8e91e46SDimitry Andric };
287d8e91e46SDimitry Andric 
288d8e91e46SDimitry Andric class CHR {
289d8e91e46SDimitry Andric  public:
CHR(Function & Fin,BlockFrequencyInfo & BFIin,DominatorTree & DTin,ProfileSummaryInfo & PSIin,RegionInfo & RIin,OptimizationRemarkEmitter & OREin)290d8e91e46SDimitry Andric   CHR(Function &Fin, BlockFrequencyInfo &BFIin, DominatorTree &DTin,
291d8e91e46SDimitry Andric       ProfileSummaryInfo &PSIin, RegionInfo &RIin,
292d8e91e46SDimitry Andric       OptimizationRemarkEmitter &OREin)
293d8e91e46SDimitry Andric       : F(Fin), BFI(BFIin), DT(DTin), PSI(PSIin), RI(RIin), ORE(OREin) {}
294d8e91e46SDimitry Andric 
~CHR()295d8e91e46SDimitry Andric   ~CHR() {
296d8e91e46SDimitry Andric     for (CHRScope *Scope : Scopes) {
297d8e91e46SDimitry Andric       delete Scope;
298d8e91e46SDimitry Andric     }
299d8e91e46SDimitry Andric   }
300d8e91e46SDimitry Andric 
301d8e91e46SDimitry Andric   bool run();
302d8e91e46SDimitry Andric 
303d8e91e46SDimitry Andric  private:
304d8e91e46SDimitry Andric   // See the comments in CHR::run() for the high level flow of the algorithm and
305d8e91e46SDimitry Andric   // what the following functions do.
306d8e91e46SDimitry Andric 
findScopes(SmallVectorImpl<CHRScope * > & Output)307d8e91e46SDimitry Andric   void findScopes(SmallVectorImpl<CHRScope *> &Output) {
308d8e91e46SDimitry Andric     Region *R = RI.getTopLevelRegion();
309cfca06d7SDimitry Andric     if (CHRScope *Scope = findScopes(R, nullptr, nullptr, Output)) {
310d8e91e46SDimitry Andric       Output.push_back(Scope);
311d8e91e46SDimitry Andric     }
312d8e91e46SDimitry Andric   }
313d8e91e46SDimitry Andric   CHRScope *findScopes(Region *R, Region *NextRegion, Region *ParentRegion,
314d8e91e46SDimitry Andric                         SmallVectorImpl<CHRScope *> &Scopes);
315d8e91e46SDimitry Andric   CHRScope *findScope(Region *R);
316d8e91e46SDimitry Andric   void checkScopeHoistable(CHRScope *Scope);
317d8e91e46SDimitry Andric 
318d8e91e46SDimitry Andric   void splitScopes(SmallVectorImpl<CHRScope *> &Input,
319d8e91e46SDimitry Andric                    SmallVectorImpl<CHRScope *> &Output);
320d8e91e46SDimitry Andric   SmallVector<CHRScope *, 8> splitScope(CHRScope *Scope,
321d8e91e46SDimitry Andric                                         CHRScope *Outer,
322d8e91e46SDimitry Andric                                         DenseSet<Value *> *OuterConditionValues,
323d8e91e46SDimitry Andric                                         Instruction *OuterInsertPoint,
324d8e91e46SDimitry Andric                                         SmallVectorImpl<CHRScope *> &Output,
325d8e91e46SDimitry Andric                                         DenseSet<Instruction *> &Unhoistables);
326d8e91e46SDimitry Andric 
327d8e91e46SDimitry Andric   void classifyBiasedScopes(SmallVectorImpl<CHRScope *> &Scopes);
328d8e91e46SDimitry Andric   void classifyBiasedScopes(CHRScope *Scope, CHRScope *OutermostScope);
329d8e91e46SDimitry Andric 
330d8e91e46SDimitry Andric   void filterScopes(SmallVectorImpl<CHRScope *> &Input,
331d8e91e46SDimitry Andric                     SmallVectorImpl<CHRScope *> &Output);
332d8e91e46SDimitry Andric 
333d8e91e46SDimitry Andric   void setCHRRegions(SmallVectorImpl<CHRScope *> &Input,
334d8e91e46SDimitry Andric                      SmallVectorImpl<CHRScope *> &Output);
335d8e91e46SDimitry Andric   void setCHRRegions(CHRScope *Scope, CHRScope *OutermostScope);
336d8e91e46SDimitry Andric 
337d8e91e46SDimitry Andric   void sortScopes(SmallVectorImpl<CHRScope *> &Input,
338d8e91e46SDimitry Andric                   SmallVectorImpl<CHRScope *> &Output);
339d8e91e46SDimitry Andric 
340d8e91e46SDimitry Andric   void transformScopes(SmallVectorImpl<CHRScope *> &CHRScopes);
341d8e91e46SDimitry Andric   void transformScopes(CHRScope *Scope, DenseSet<PHINode *> &TrivialPHIs);
342d8e91e46SDimitry Andric   void cloneScopeBlocks(CHRScope *Scope,
343d8e91e46SDimitry Andric                         BasicBlock *PreEntryBlock,
344d8e91e46SDimitry Andric                         BasicBlock *ExitBlock,
345d8e91e46SDimitry Andric                         Region *LastRegion,
346d8e91e46SDimitry Andric                         ValueToValueMapTy &VMap);
347d8e91e46SDimitry Andric   BranchInst *createMergedBranch(BasicBlock *PreEntryBlock,
348d8e91e46SDimitry Andric                                  BasicBlock *EntryBlock,
349d8e91e46SDimitry Andric                                  BasicBlock *NewEntryBlock,
350d8e91e46SDimitry Andric                                  ValueToValueMapTy &VMap);
351e3b55780SDimitry Andric   void fixupBranchesAndSelects(CHRScope *Scope, BasicBlock *PreEntryBlock,
352e3b55780SDimitry Andric                                BranchInst *MergedBR, uint64_t ProfileCount);
353e3b55780SDimitry Andric   void fixupBranch(Region *R, CHRScope *Scope, IRBuilder<> &IRB,
354d8e91e46SDimitry Andric                    Value *&MergedCondition, BranchProbability &CHRBranchBias);
355e3b55780SDimitry Andric   void fixupSelect(SelectInst *SI, CHRScope *Scope, IRBuilder<> &IRB,
356d8e91e46SDimitry Andric                    Value *&MergedCondition, BranchProbability &CHRBranchBias);
357d8e91e46SDimitry Andric   void addToMergedCondition(bool IsTrueBiased, Value *Cond,
358e3b55780SDimitry Andric                             Instruction *BranchOrSelect, CHRScope *Scope,
359e3b55780SDimitry Andric                             IRBuilder<> &IRB, Value *&MergedCondition);
getRegionDuplicationCount(const Region * R)360e3b55780SDimitry Andric   unsigned getRegionDuplicationCount(const Region *R) {
361e3b55780SDimitry Andric     unsigned Count = 0;
362e3b55780SDimitry Andric     // Find out how many times region R is cloned. Note that if the parent
363e3b55780SDimitry Andric     // of R is cloned, R is also cloned, but R's clone count is not updated
364e3b55780SDimitry Andric     // from the clone of the parent. We need to accumlate all the counts
365e3b55780SDimitry Andric     // from the ancestors to get the clone count.
366e3b55780SDimitry Andric     while (R) {
367e3b55780SDimitry Andric       Count += DuplicationCount[R];
368e3b55780SDimitry Andric       R = R->getParent();
369e3b55780SDimitry Andric     }
370e3b55780SDimitry Andric     return Count;
371e3b55780SDimitry Andric   }
372d8e91e46SDimitry Andric 
373d8e91e46SDimitry Andric   Function &F;
374d8e91e46SDimitry Andric   BlockFrequencyInfo &BFI;
375d8e91e46SDimitry Andric   DominatorTree &DT;
376d8e91e46SDimitry Andric   ProfileSummaryInfo &PSI;
377d8e91e46SDimitry Andric   RegionInfo &RI;
378d8e91e46SDimitry Andric   OptimizationRemarkEmitter &ORE;
379d8e91e46SDimitry Andric   CHRStats Stats;
380d8e91e46SDimitry Andric 
381d8e91e46SDimitry Andric   // All the true-biased regions in the function
382d8e91e46SDimitry Andric   DenseSet<Region *> TrueBiasedRegionsGlobal;
383d8e91e46SDimitry Andric   // All the false-biased regions in the function
384d8e91e46SDimitry Andric   DenseSet<Region *> FalseBiasedRegionsGlobal;
385d8e91e46SDimitry Andric   // All the true-biased selects in the function
386d8e91e46SDimitry Andric   DenseSet<SelectInst *> TrueBiasedSelectsGlobal;
387d8e91e46SDimitry Andric   // All the false-biased selects in the function
388d8e91e46SDimitry Andric   DenseSet<SelectInst *> FalseBiasedSelectsGlobal;
389d8e91e46SDimitry Andric   // A map from biased regions to their branch bias
390d8e91e46SDimitry Andric   DenseMap<Region *, BranchProbability> BranchBiasMap;
391d8e91e46SDimitry Andric   // A map from biased selects to their branch bias
392d8e91e46SDimitry Andric   DenseMap<SelectInst *, BranchProbability> SelectBiasMap;
393d8e91e46SDimitry Andric   // All the scopes.
394d8e91e46SDimitry Andric   DenseSet<CHRScope *> Scopes;
395e3b55780SDimitry Andric   // This maps records how many times this region is cloned.
396e3b55780SDimitry Andric   DenseMap<const Region *, unsigned> DuplicationCount;
397d8e91e46SDimitry Andric };
398d8e91e46SDimitry Andric 
399d8e91e46SDimitry Andric } // end anonymous namespace
400d8e91e46SDimitry Andric 
401d8e91e46SDimitry Andric static inline
operator <<(raw_ostream & OS,const CHRStats & Stats)402d8e91e46SDimitry Andric raw_ostream LLVM_ATTRIBUTE_UNUSED &operator<<(raw_ostream &OS,
403d8e91e46SDimitry Andric                                               const CHRStats &Stats) {
404d8e91e46SDimitry Andric   Stats.print(OS);
405d8e91e46SDimitry Andric   return OS;
406d8e91e46SDimitry Andric }
407d8e91e46SDimitry Andric 
408d8e91e46SDimitry Andric static inline
operator <<(raw_ostream & OS,const CHRScope & Scope)409d8e91e46SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const CHRScope &Scope) {
410d8e91e46SDimitry Andric   Scope.print(OS);
411d8e91e46SDimitry Andric   return OS;
412d8e91e46SDimitry Andric }
413d8e91e46SDimitry Andric 
shouldApply(Function & F,ProfileSummaryInfo & PSI)414d8e91e46SDimitry Andric static bool shouldApply(Function &F, ProfileSummaryInfo &PSI) {
415e3b55780SDimitry Andric   if (DisableCHR)
416e3b55780SDimitry Andric     return false;
417e3b55780SDimitry Andric 
418d8e91e46SDimitry Andric   if (ForceCHR)
419d8e91e46SDimitry Andric     return true;
420d8e91e46SDimitry Andric 
421d8e91e46SDimitry Andric   if (!CHRModuleList.empty() || !CHRFunctionList.empty()) {
422d8e91e46SDimitry Andric     if (CHRModules.count(F.getParent()->getName()))
423d8e91e46SDimitry Andric       return true;
424d8e91e46SDimitry Andric     return CHRFunctions.count(F.getName());
425d8e91e46SDimitry Andric   }
426d8e91e46SDimitry Andric 
427d8e91e46SDimitry Andric   return PSI.isFunctionEntryHot(&F);
428d8e91e46SDimitry Andric }
429d8e91e46SDimitry Andric 
dumpIR(Function & F,const char * Label,CHRStats * Stats)430d8e91e46SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpIR(Function &F, const char *Label,
431d8e91e46SDimitry Andric                                          CHRStats *Stats) {
432d8e91e46SDimitry Andric   StringRef FuncName = F.getName();
433d8e91e46SDimitry Andric   StringRef ModuleName = F.getParent()->getName();
434d8e91e46SDimitry Andric   (void)(FuncName); // Unused in release build.
435d8e91e46SDimitry Andric   (void)(ModuleName); // Unused in release build.
436d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "CHR IR dump " << Label << " " << ModuleName << " "
437d8e91e46SDimitry Andric             << FuncName);
438d8e91e46SDimitry Andric   if (Stats)
439d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << " " << *Stats);
440d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "\n");
441d8e91e46SDimitry Andric   CHR_DEBUG(F.dump());
442d8e91e46SDimitry Andric }
443d8e91e46SDimitry Andric 
print(raw_ostream & OS) const444d8e91e46SDimitry Andric void CHRScope::print(raw_ostream &OS) const {
445d8e91e46SDimitry Andric   assert(RegInfos.size() > 0 && "Empty CHRScope");
446d8e91e46SDimitry Andric   OS << "CHRScope[";
447d8e91e46SDimitry Andric   OS << RegInfos.size() << ", Regions[";
448d8e91e46SDimitry Andric   for (const RegInfo &RI : RegInfos) {
449d8e91e46SDimitry Andric     OS << RI.R->getNameStr();
450d8e91e46SDimitry Andric     if (RI.HasBranch)
451d8e91e46SDimitry Andric       OS << " B";
452d8e91e46SDimitry Andric     if (RI.Selects.size() > 0)
453d8e91e46SDimitry Andric       OS << " S" << RI.Selects.size();
454d8e91e46SDimitry Andric     OS << ", ";
455d8e91e46SDimitry Andric   }
456d8e91e46SDimitry Andric   if (RegInfos[0].R->getParent()) {
457d8e91e46SDimitry Andric     OS << "], Parent " << RegInfos[0].R->getParent()->getNameStr();
458d8e91e46SDimitry Andric   } else {
459d8e91e46SDimitry Andric     // top level region
460d8e91e46SDimitry Andric     OS << "]";
461d8e91e46SDimitry Andric   }
462d8e91e46SDimitry Andric   OS << ", Subs[";
463d8e91e46SDimitry Andric   for (CHRScope *Sub : Subs) {
464d8e91e46SDimitry Andric     OS << *Sub << ", ";
465d8e91e46SDimitry Andric   }
466d8e91e46SDimitry Andric   OS << "]]";
467d8e91e46SDimitry Andric }
468d8e91e46SDimitry Andric 
469d8e91e46SDimitry Andric // Return true if the given instruction type can be hoisted by CHR.
isHoistableInstructionType(Instruction * I)470d8e91e46SDimitry Andric static bool isHoistableInstructionType(Instruction *I) {
471d8e91e46SDimitry Andric   return isa<BinaryOperator>(I) || isa<CastInst>(I) || isa<SelectInst>(I) ||
472d8e91e46SDimitry Andric       isa<GetElementPtrInst>(I) || isa<CmpInst>(I) ||
473d8e91e46SDimitry Andric       isa<InsertElementInst>(I) || isa<ExtractElementInst>(I) ||
474d8e91e46SDimitry Andric       isa<ShuffleVectorInst>(I) || isa<ExtractValueInst>(I) ||
475d8e91e46SDimitry Andric       isa<InsertValueInst>(I);
476d8e91e46SDimitry Andric }
477d8e91e46SDimitry Andric 
478d8e91e46SDimitry Andric // Return true if the given instruction can be hoisted by CHR.
isHoistable(Instruction * I,DominatorTree & DT)479d8e91e46SDimitry Andric static bool isHoistable(Instruction *I, DominatorTree &DT) {
480d8e91e46SDimitry Andric   if (!isHoistableInstructionType(I))
481d8e91e46SDimitry Andric     return false;
482e3b55780SDimitry Andric   return isSafeToSpeculativelyExecute(I, nullptr, nullptr, &DT);
483d8e91e46SDimitry Andric }
484d8e91e46SDimitry Andric 
485d8e91e46SDimitry Andric // Recursively traverse the use-def chains of the given value and return a set
486d8e91e46SDimitry Andric // of the unhoistable base values defined within the scope (excluding the
487d8e91e46SDimitry Andric // first-region entry block) or the (hoistable or unhoistable) base values that
488d8e91e46SDimitry Andric // are defined outside (including the first-region entry block) of the
489d8e91e46SDimitry Andric // scope. The returned set doesn't include constants.
490cfca06d7SDimitry Andric static const std::set<Value *> &
getBaseValues(Value * V,DominatorTree & DT,DenseMap<Value *,std::set<Value * >> & Visited)491cfca06d7SDimitry Andric getBaseValues(Value *V, DominatorTree &DT,
4921d5ae102SDimitry Andric               DenseMap<Value *, std::set<Value *>> &Visited) {
493cfca06d7SDimitry Andric   auto It = Visited.find(V);
494cfca06d7SDimitry Andric   if (It != Visited.end()) {
495cfca06d7SDimitry Andric     return It->second;
4961d5ae102SDimitry Andric   }
497d8e91e46SDimitry Andric   std::set<Value *> Result;
498d8e91e46SDimitry Andric   if (auto *I = dyn_cast<Instruction>(V)) {
499cfca06d7SDimitry Andric     // We don't stop at a block that's not in the Scope because we would miss
500cfca06d7SDimitry Andric     // some instructions that are based on the same base values if we stop
501cfca06d7SDimitry Andric     // there.
502d8e91e46SDimitry Andric     if (!isHoistable(I, DT)) {
503d8e91e46SDimitry Andric       Result.insert(I);
504cfca06d7SDimitry Andric       return Visited.insert(std::make_pair(V, std::move(Result))).first->second;
505d8e91e46SDimitry Andric     }
506d8e91e46SDimitry Andric     // I is hoistable above the Scope.
507d8e91e46SDimitry Andric     for (Value *Op : I->operands()) {
508cfca06d7SDimitry Andric       const std::set<Value *> &OpResult = getBaseValues(Op, DT, Visited);
509d8e91e46SDimitry Andric       Result.insert(OpResult.begin(), OpResult.end());
510d8e91e46SDimitry Andric     }
511cfca06d7SDimitry Andric     return Visited.insert(std::make_pair(V, std::move(Result))).first->second;
512d8e91e46SDimitry Andric   }
513d8e91e46SDimitry Andric   if (isa<Argument>(V)) {
514d8e91e46SDimitry Andric     Result.insert(V);
515d8e91e46SDimitry Andric   }
516d8e91e46SDimitry Andric   // We don't include others like constants because those won't lead to any
517d8e91e46SDimitry Andric   // chance of folding of conditions (eg two bit checks merged into one check)
518d8e91e46SDimitry Andric   // after CHR.
519cfca06d7SDimitry Andric   return Visited.insert(std::make_pair(V, std::move(Result))).first->second;
520d8e91e46SDimitry Andric }
521d8e91e46SDimitry Andric 
522d8e91e46SDimitry Andric // Return true if V is already hoisted or can be hoisted (along with its
523d8e91e46SDimitry Andric // operands) above the insert point. When it returns true and HoistStops is
524d8e91e46SDimitry Andric // non-null, the instructions to stop hoisting at through the use-def chains are
525d8e91e46SDimitry Andric // inserted into HoistStops.
526d8e91e46SDimitry Andric static bool
checkHoistValue(Value * V,Instruction * InsertPoint,DominatorTree & DT,DenseSet<Instruction * > & Unhoistables,DenseSet<Instruction * > * HoistStops,DenseMap<Instruction *,bool> & Visited)527d8e91e46SDimitry Andric checkHoistValue(Value *V, Instruction *InsertPoint, DominatorTree &DT,
528d8e91e46SDimitry Andric                 DenseSet<Instruction *> &Unhoistables,
529e6d15924SDimitry Andric                 DenseSet<Instruction *> *HoistStops,
530e6d15924SDimitry Andric                 DenseMap<Instruction *, bool> &Visited) {
531d8e91e46SDimitry Andric   assert(InsertPoint && "Null InsertPoint");
532d8e91e46SDimitry Andric   if (auto *I = dyn_cast<Instruction>(V)) {
533cfca06d7SDimitry Andric     auto It = Visited.find(I);
534cfca06d7SDimitry Andric     if (It != Visited.end()) {
535cfca06d7SDimitry Andric       return It->second;
536e6d15924SDimitry Andric     }
537d8e91e46SDimitry Andric     assert(DT.getNode(I->getParent()) && "DT must contain I's parent block");
538d8e91e46SDimitry Andric     assert(DT.getNode(InsertPoint->getParent()) && "DT must contain Destination");
539d8e91e46SDimitry Andric     if (Unhoistables.count(I)) {
540d8e91e46SDimitry Andric       // Don't hoist if they are not to be hoisted.
541e6d15924SDimitry Andric       Visited[I] = false;
542d8e91e46SDimitry Andric       return false;
543d8e91e46SDimitry Andric     }
544d8e91e46SDimitry Andric     if (DT.dominates(I, InsertPoint)) {
545d8e91e46SDimitry Andric       // We are already above the insert point. Stop here.
546d8e91e46SDimitry Andric       if (HoistStops)
547d8e91e46SDimitry Andric         HoistStops->insert(I);
548e6d15924SDimitry Andric       Visited[I] = true;
549d8e91e46SDimitry Andric       return true;
550d8e91e46SDimitry Andric     }
551d8e91e46SDimitry Andric     // We aren't not above the insert point, check if we can hoist it above the
552d8e91e46SDimitry Andric     // insert point.
553d8e91e46SDimitry Andric     if (isHoistable(I, DT)) {
554d8e91e46SDimitry Andric       // Check operands first.
555d8e91e46SDimitry Andric       DenseSet<Instruction *> OpsHoistStops;
556d8e91e46SDimitry Andric       bool AllOpsHoisted = true;
557d8e91e46SDimitry Andric       for (Value *Op : I->operands()) {
558e6d15924SDimitry Andric         if (!checkHoistValue(Op, InsertPoint, DT, Unhoistables, &OpsHoistStops,
559e6d15924SDimitry Andric                              Visited)) {
560d8e91e46SDimitry Andric           AllOpsHoisted = false;
561d8e91e46SDimitry Andric           break;
562d8e91e46SDimitry Andric         }
563d8e91e46SDimitry Andric       }
564d8e91e46SDimitry Andric       if (AllOpsHoisted) {
565d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "checkHoistValue " << *I << "\n");
566d8e91e46SDimitry Andric         if (HoistStops)
567d8e91e46SDimitry Andric           HoistStops->insert(OpsHoistStops.begin(), OpsHoistStops.end());
568e6d15924SDimitry Andric         Visited[I] = true;
569d8e91e46SDimitry Andric         return true;
570d8e91e46SDimitry Andric       }
571d8e91e46SDimitry Andric     }
572e6d15924SDimitry Andric     Visited[I] = false;
573d8e91e46SDimitry Andric     return false;
574d8e91e46SDimitry Andric   }
575d8e91e46SDimitry Andric   // Non-instructions are considered hoistable.
576d8e91e46SDimitry Andric   return true;
577d8e91e46SDimitry Andric }
578d8e91e46SDimitry Andric 
579e3b55780SDimitry Andric // Constructs the true and false branch probabilities if the the instruction has
580e3b55780SDimitry Andric // valid branch weights. Returns true when this was successful, false otherwise.
extractBranchProbabilities(Instruction * I,BranchProbability & TrueProb,BranchProbability & FalseProb)581e3b55780SDimitry Andric static bool extractBranchProbabilities(Instruction *I,
582e3b55780SDimitry Andric                                        BranchProbability &TrueProb,
583d8e91e46SDimitry Andric                                        BranchProbability &FalseProb) {
584e3b55780SDimitry Andric   uint64_t TrueWeight;
585e3b55780SDimitry Andric   uint64_t FalseWeight;
586e3b55780SDimitry Andric   if (!extractBranchWeights(*I, TrueWeight, FalseWeight))
587d8e91e46SDimitry Andric     return false;
588e3b55780SDimitry Andric   uint64_t SumWeight = TrueWeight + FalseWeight;
589d8e91e46SDimitry Andric 
590e3b55780SDimitry Andric   assert(SumWeight >= TrueWeight && SumWeight >= FalseWeight &&
591d8e91e46SDimitry Andric          "Overflow calculating branch probabilities.");
592d8e91e46SDimitry Andric 
593706b4fc4SDimitry Andric   // Guard against 0-to-0 branch weights to avoid a division-by-zero crash.
594e3b55780SDimitry Andric   if (SumWeight == 0)
595706b4fc4SDimitry Andric     return false;
596706b4fc4SDimitry Andric 
597e3b55780SDimitry Andric   TrueProb = BranchProbability::getBranchProbability(TrueWeight, SumWeight);
598e3b55780SDimitry Andric   FalseProb = BranchProbability::getBranchProbability(FalseWeight, SumWeight);
599d8e91e46SDimitry Andric   return true;
600d8e91e46SDimitry Andric }
601d8e91e46SDimitry Andric 
getCHRBiasThreshold()602d8e91e46SDimitry Andric static BranchProbability getCHRBiasThreshold() {
603d8e91e46SDimitry Andric   return BranchProbability::getBranchProbability(
604d8e91e46SDimitry Andric       static_cast<uint64_t>(CHRBiasThreshold * 1000000), 1000000);
605d8e91e46SDimitry Andric }
606d8e91e46SDimitry Andric 
607d8e91e46SDimitry Andric // A helper for CheckBiasedBranch and CheckBiasedSelect. If TrueProb >=
608d8e91e46SDimitry Andric // CHRBiasThreshold, put Key into TrueSet and return true. If FalseProb >=
609d8e91e46SDimitry Andric // CHRBiasThreshold, put Key into FalseSet and return true. Otherwise, return
610d8e91e46SDimitry Andric // false.
611d8e91e46SDimitry Andric template <typename K, typename S, typename M>
checkBias(K * Key,BranchProbability TrueProb,BranchProbability FalseProb,S & TrueSet,S & FalseSet,M & BiasMap)612d8e91e46SDimitry Andric static bool checkBias(K *Key, BranchProbability TrueProb,
613d8e91e46SDimitry Andric                       BranchProbability FalseProb, S &TrueSet, S &FalseSet,
614d8e91e46SDimitry Andric                       M &BiasMap) {
615d8e91e46SDimitry Andric   BranchProbability Threshold = getCHRBiasThreshold();
616d8e91e46SDimitry Andric   if (TrueProb >= Threshold) {
617d8e91e46SDimitry Andric     TrueSet.insert(Key);
618d8e91e46SDimitry Andric     BiasMap[Key] = TrueProb;
619d8e91e46SDimitry Andric     return true;
620d8e91e46SDimitry Andric   } else if (FalseProb >= Threshold) {
621d8e91e46SDimitry Andric     FalseSet.insert(Key);
622d8e91e46SDimitry Andric     BiasMap[Key] = FalseProb;
623d8e91e46SDimitry Andric     return true;
624d8e91e46SDimitry Andric   }
625d8e91e46SDimitry Andric   return false;
626d8e91e46SDimitry Andric }
627d8e91e46SDimitry Andric 
628d8e91e46SDimitry Andric // Returns true and insert a region into the right biased set and the map if the
629d8e91e46SDimitry Andric // branch of the region is biased.
checkBiasedBranch(BranchInst * BI,Region * R,DenseSet<Region * > & TrueBiasedRegionsGlobal,DenseSet<Region * > & FalseBiasedRegionsGlobal,DenseMap<Region *,BranchProbability> & BranchBiasMap)630d8e91e46SDimitry Andric static bool checkBiasedBranch(BranchInst *BI, Region *R,
631d8e91e46SDimitry Andric                               DenseSet<Region *> &TrueBiasedRegionsGlobal,
632d8e91e46SDimitry Andric                               DenseSet<Region *> &FalseBiasedRegionsGlobal,
633d8e91e46SDimitry Andric                               DenseMap<Region *, BranchProbability> &BranchBiasMap) {
634d8e91e46SDimitry Andric   if (!BI->isConditional())
635d8e91e46SDimitry Andric     return false;
636d8e91e46SDimitry Andric   BranchProbability ThenProb, ElseProb;
637e3b55780SDimitry Andric   if (!extractBranchProbabilities(BI, ThenProb, ElseProb))
638d8e91e46SDimitry Andric     return false;
639d8e91e46SDimitry Andric   BasicBlock *IfThen = BI->getSuccessor(0);
640d8e91e46SDimitry Andric   BasicBlock *IfElse = BI->getSuccessor(1);
641d8e91e46SDimitry Andric   assert((IfThen == R->getExit() || IfElse == R->getExit()) &&
642d8e91e46SDimitry Andric          IfThen != IfElse &&
643d8e91e46SDimitry Andric          "Invariant from findScopes");
644d8e91e46SDimitry Andric   if (IfThen == R->getExit()) {
645d8e91e46SDimitry Andric     // Swap them so that IfThen/ThenProb means going into the conditional code
646d8e91e46SDimitry Andric     // and IfElse/ElseProb means skipping it.
647d8e91e46SDimitry Andric     std::swap(IfThen, IfElse);
648d8e91e46SDimitry Andric     std::swap(ThenProb, ElseProb);
649d8e91e46SDimitry Andric   }
650d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "BI " << *BI << " ");
651d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "ThenProb " << ThenProb << " ");
652d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "ElseProb " << ElseProb << "\n");
653d8e91e46SDimitry Andric   return checkBias(R, ThenProb, ElseProb,
654d8e91e46SDimitry Andric                    TrueBiasedRegionsGlobal, FalseBiasedRegionsGlobal,
655d8e91e46SDimitry Andric                    BranchBiasMap);
656d8e91e46SDimitry Andric }
657d8e91e46SDimitry Andric 
658d8e91e46SDimitry Andric // Returns true and insert a select into the right biased set and the map if the
659d8e91e46SDimitry Andric // select is biased.
checkBiasedSelect(SelectInst * SI,Region * R,DenseSet<SelectInst * > & TrueBiasedSelectsGlobal,DenseSet<SelectInst * > & FalseBiasedSelectsGlobal,DenseMap<SelectInst *,BranchProbability> & SelectBiasMap)660d8e91e46SDimitry Andric static bool checkBiasedSelect(
661d8e91e46SDimitry Andric     SelectInst *SI, Region *R,
662d8e91e46SDimitry Andric     DenseSet<SelectInst *> &TrueBiasedSelectsGlobal,
663d8e91e46SDimitry Andric     DenseSet<SelectInst *> &FalseBiasedSelectsGlobal,
664d8e91e46SDimitry Andric     DenseMap<SelectInst *, BranchProbability> &SelectBiasMap) {
665d8e91e46SDimitry Andric   BranchProbability TrueProb, FalseProb;
666e3b55780SDimitry Andric   if (!extractBranchProbabilities(SI, TrueProb, FalseProb))
667d8e91e46SDimitry Andric     return false;
668d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "SI " << *SI << " ");
669d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "TrueProb " << TrueProb << " ");
670d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "FalseProb " << FalseProb << "\n");
671d8e91e46SDimitry Andric   return checkBias(SI, TrueProb, FalseProb,
672d8e91e46SDimitry Andric                    TrueBiasedSelectsGlobal, FalseBiasedSelectsGlobal,
673d8e91e46SDimitry Andric                    SelectBiasMap);
674d8e91e46SDimitry Andric }
675d8e91e46SDimitry Andric 
676d8e91e46SDimitry Andric // Returns the instruction at which to hoist the dependent condition values and
677d8e91e46SDimitry Andric // insert the CHR branch for a region. This is the terminator branch in the
678d8e91e46SDimitry Andric // entry block or the first select in the entry block, if any.
getBranchInsertPoint(RegInfo & RI)679d8e91e46SDimitry Andric static Instruction* getBranchInsertPoint(RegInfo &RI) {
680d8e91e46SDimitry Andric   Region *R = RI.R;
681d8e91e46SDimitry Andric   BasicBlock *EntryBB = R->getEntry();
682d8e91e46SDimitry Andric   // The hoist point is by default the terminator of the entry block, which is
683d8e91e46SDimitry Andric   // the same as the branch instruction if RI.HasBranch is true.
684d8e91e46SDimitry Andric   Instruction *HoistPoint = EntryBB->getTerminator();
685d8e91e46SDimitry Andric   for (SelectInst *SI : RI.Selects) {
686d8e91e46SDimitry Andric     if (SI->getParent() == EntryBB) {
687d8e91e46SDimitry Andric       // Pick the first select in Selects in the entry block.  Note Selects is
688d8e91e46SDimitry Andric       // sorted in the instruction order within a block (asserted below).
689d8e91e46SDimitry Andric       HoistPoint = SI;
690d8e91e46SDimitry Andric       break;
691d8e91e46SDimitry Andric     }
692d8e91e46SDimitry Andric   }
693d8e91e46SDimitry Andric   assert(HoistPoint && "Null HoistPoint");
694d8e91e46SDimitry Andric #ifndef NDEBUG
695d8e91e46SDimitry Andric   // Check that HoistPoint is the first one in Selects in the entry block,
696d8e91e46SDimitry Andric   // if any.
697d8e91e46SDimitry Andric   DenseSet<Instruction *> EntryBlockSelectSet;
698d8e91e46SDimitry Andric   for (SelectInst *SI : RI.Selects) {
699d8e91e46SDimitry Andric     if (SI->getParent() == EntryBB) {
700d8e91e46SDimitry Andric       EntryBlockSelectSet.insert(SI);
701d8e91e46SDimitry Andric     }
702d8e91e46SDimitry Andric   }
703d8e91e46SDimitry Andric   for (Instruction &I : *EntryBB) {
704b60736ecSDimitry Andric     if (EntryBlockSelectSet.contains(&I)) {
705d8e91e46SDimitry Andric       assert(&I == HoistPoint &&
706d8e91e46SDimitry Andric              "HoistPoint must be the first one in Selects");
707d8e91e46SDimitry Andric       break;
708d8e91e46SDimitry Andric     }
709d8e91e46SDimitry Andric   }
710d8e91e46SDimitry Andric #endif
711d8e91e46SDimitry Andric   return HoistPoint;
712d8e91e46SDimitry Andric }
713d8e91e46SDimitry Andric 
714d8e91e46SDimitry Andric // Find a CHR scope in the given region.
findScope(Region * R)715d8e91e46SDimitry Andric CHRScope * CHR::findScope(Region *R) {
716d8e91e46SDimitry Andric   CHRScope *Result = nullptr;
717d8e91e46SDimitry Andric   BasicBlock *Entry = R->getEntry();
718d8e91e46SDimitry Andric   BasicBlock *Exit = R->getExit();  // null if top level.
719d8e91e46SDimitry Andric   assert(Entry && "Entry must not be null");
720d8e91e46SDimitry Andric   assert((Exit == nullptr) == (R->isTopLevelRegion()) &&
721d8e91e46SDimitry Andric          "Only top level region has a null exit");
722d8e91e46SDimitry Andric   if (Entry)
723d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Entry " << Entry->getName() << "\n");
724d8e91e46SDimitry Andric   else
725d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Entry null\n");
726d8e91e46SDimitry Andric   if (Exit)
727d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Exit " << Exit->getName() << "\n");
728d8e91e46SDimitry Andric   else
729d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Exit null\n");
730d8e91e46SDimitry Andric   // Exclude cases where Entry is part of a subregion (hence it doesn't belong
731d8e91e46SDimitry Andric   // to this region).
732d8e91e46SDimitry Andric   bool EntryInSubregion = RI.getRegionFor(Entry) != R;
733d8e91e46SDimitry Andric   if (EntryInSubregion)
734d8e91e46SDimitry Andric     return nullptr;
735d8e91e46SDimitry Andric   // Exclude loops
736d8e91e46SDimitry Andric   for (BasicBlock *Pred : predecessors(Entry))
737d8e91e46SDimitry Andric     if (R->contains(Pred))
738d8e91e46SDimitry Andric       return nullptr;
739344a3780SDimitry Andric   // If any of the basic blocks have address taken, we must skip this region
740344a3780SDimitry Andric   // because we cannot clone basic blocks that have address taken.
741145449b1SDimitry Andric   for (BasicBlock *BB : R->blocks()) {
742344a3780SDimitry Andric     if (BB->hasAddressTaken())
743344a3780SDimitry Andric       return nullptr;
744145449b1SDimitry Andric     // If we encounter llvm.coro.id, skip this region because if the basic block
745145449b1SDimitry Andric     // is cloned, we end up inserting a token type PHI node to the block with
746145449b1SDimitry Andric     // llvm.coro.begin.
747145449b1SDimitry Andric     // FIXME: This could lead to less optimal codegen, because the region is
748145449b1SDimitry Andric     // excluded, it can prevent CHR from merging adjacent regions into bigger
749145449b1SDimitry Andric     // scope and hoisting more branches.
750145449b1SDimitry Andric     for (Instruction &I : *BB)
751145449b1SDimitry Andric       if (auto *II = dyn_cast<IntrinsicInst>(&I))
752145449b1SDimitry Andric         if (II->getIntrinsicID() == Intrinsic::coro_id)
753145449b1SDimitry Andric           return nullptr;
754145449b1SDimitry Andric   }
755145449b1SDimitry Andric 
756d8e91e46SDimitry Andric   if (Exit) {
757d8e91e46SDimitry Andric     // Try to find an if-then block (check if R is an if-then).
758d8e91e46SDimitry Andric     // if (cond) {
759d8e91e46SDimitry Andric     //  ...
760d8e91e46SDimitry Andric     // }
761d8e91e46SDimitry Andric     auto *BI = dyn_cast<BranchInst>(Entry->getTerminator());
762d8e91e46SDimitry Andric     if (BI)
763d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "BI.isConditional " << BI->isConditional() << "\n");
764d8e91e46SDimitry Andric     else
765d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "BI null\n");
766d8e91e46SDimitry Andric     if (BI && BI->isConditional()) {
767d8e91e46SDimitry Andric       BasicBlock *S0 = BI->getSuccessor(0);
768d8e91e46SDimitry Andric       BasicBlock *S1 = BI->getSuccessor(1);
769d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "S0 " << S0->getName() << "\n");
770d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "S1 " << S1->getName() << "\n");
771d8e91e46SDimitry Andric       if (S0 != S1 && (S0 == Exit || S1 == Exit)) {
772d8e91e46SDimitry Andric         RegInfo RI(R);
773d8e91e46SDimitry Andric         RI.HasBranch = checkBiasedBranch(
774d8e91e46SDimitry Andric             BI, R, TrueBiasedRegionsGlobal, FalseBiasedRegionsGlobal,
775d8e91e46SDimitry Andric             BranchBiasMap);
776d8e91e46SDimitry Andric         Result = new CHRScope(RI);
777d8e91e46SDimitry Andric         Scopes.insert(Result);
778d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Found a region with a branch\n");
779d8e91e46SDimitry Andric         ++Stats.NumBranches;
780d8e91e46SDimitry Andric         if (!RI.HasBranch) {
781d8e91e46SDimitry Andric           ORE.emit([&]() {
782d8e91e46SDimitry Andric             return OptimizationRemarkMissed(DEBUG_TYPE, "BranchNotBiased", BI)
783d8e91e46SDimitry Andric                 << "Branch not biased";
784d8e91e46SDimitry Andric           });
785d8e91e46SDimitry Andric         }
786d8e91e46SDimitry Andric       }
787d8e91e46SDimitry Andric     }
788d8e91e46SDimitry Andric   }
789d8e91e46SDimitry Andric   {
790d8e91e46SDimitry Andric     // Try to look for selects in the direct child blocks (as opposed to in
791d8e91e46SDimitry Andric     // subregions) of R.
792d8e91e46SDimitry Andric     // ...
793d8e91e46SDimitry Andric     // if (..) { // Some subregion
794d8e91e46SDimitry Andric     //   ...
795d8e91e46SDimitry Andric     // }
796d8e91e46SDimitry Andric     // if (..) { // Some subregion
797d8e91e46SDimitry Andric     //   ...
798d8e91e46SDimitry Andric     // }
799d8e91e46SDimitry Andric     // ...
800d8e91e46SDimitry Andric     // a = cond ? b : c;
801d8e91e46SDimitry Andric     // ...
802d8e91e46SDimitry Andric     SmallVector<SelectInst *, 8> Selects;
803d8e91e46SDimitry Andric     for (RegionNode *E : R->elements()) {
804d8e91e46SDimitry Andric       if (E->isSubRegion())
805d8e91e46SDimitry Andric         continue;
806d8e91e46SDimitry Andric       // This returns the basic block of E if E is a direct child of R (not a
807d8e91e46SDimitry Andric       // subregion.)
808d8e91e46SDimitry Andric       BasicBlock *BB = E->getEntry();
809d8e91e46SDimitry Andric       // Need to push in the order to make it easier to find the first Select
810d8e91e46SDimitry Andric       // later.
811d8e91e46SDimitry Andric       for (Instruction &I : *BB) {
812d8e91e46SDimitry Andric         if (auto *SI = dyn_cast<SelectInst>(&I)) {
813d8e91e46SDimitry Andric           Selects.push_back(SI);
814d8e91e46SDimitry Andric           ++Stats.NumBranches;
815d8e91e46SDimitry Andric         }
816d8e91e46SDimitry Andric       }
817d8e91e46SDimitry Andric     }
818d8e91e46SDimitry Andric     if (Selects.size() > 0) {
819d8e91e46SDimitry Andric       auto AddSelects = [&](RegInfo &RI) {
820d8e91e46SDimitry Andric         for (auto *SI : Selects)
821d8e91e46SDimitry Andric           if (checkBiasedSelect(SI, RI.R,
822d8e91e46SDimitry Andric                                 TrueBiasedSelectsGlobal,
823d8e91e46SDimitry Andric                                 FalseBiasedSelectsGlobal,
824d8e91e46SDimitry Andric                                 SelectBiasMap))
825d8e91e46SDimitry Andric             RI.Selects.push_back(SI);
826d8e91e46SDimitry Andric           else
827d8e91e46SDimitry Andric             ORE.emit([&]() {
828d8e91e46SDimitry Andric               return OptimizationRemarkMissed(DEBUG_TYPE, "SelectNotBiased", SI)
829d8e91e46SDimitry Andric                   << "Select not biased";
830d8e91e46SDimitry Andric             });
831d8e91e46SDimitry Andric       };
832d8e91e46SDimitry Andric       if (!Result) {
833d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Found a select-only region\n");
834d8e91e46SDimitry Andric         RegInfo RI(R);
835d8e91e46SDimitry Andric         AddSelects(RI);
836d8e91e46SDimitry Andric         Result = new CHRScope(RI);
837d8e91e46SDimitry Andric         Scopes.insert(Result);
838d8e91e46SDimitry Andric       } else {
839d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Found select(s) in a region with a branch\n");
840d8e91e46SDimitry Andric         AddSelects(Result->RegInfos[0]);
841d8e91e46SDimitry Andric       }
842d8e91e46SDimitry Andric     }
843d8e91e46SDimitry Andric   }
844d8e91e46SDimitry Andric 
845d8e91e46SDimitry Andric   if (Result) {
846d8e91e46SDimitry Andric     checkScopeHoistable(Result);
847d8e91e46SDimitry Andric   }
848d8e91e46SDimitry Andric   return Result;
849d8e91e46SDimitry Andric }
850d8e91e46SDimitry Andric 
851d8e91e46SDimitry Andric // Check that any of the branch and the selects in the region could be
852d8e91e46SDimitry Andric // hoisted above the the CHR branch insert point (the most dominating of
853d8e91e46SDimitry Andric // them, either the branch (at the end of the first block) or the first
854d8e91e46SDimitry Andric // select in the first block). If the branch can't be hoisted, drop the
855d8e91e46SDimitry Andric // selects in the first blocks.
856d8e91e46SDimitry Andric //
857d8e91e46SDimitry Andric // For example, for the following scope/region with selects, we want to insert
858d8e91e46SDimitry Andric // the merged branch right before the first select in the first/entry block by
859d8e91e46SDimitry Andric // hoisting c1, c2, c3, and c4.
860d8e91e46SDimitry Andric //
861d8e91e46SDimitry Andric // // Branch insert point here.
862d8e91e46SDimitry Andric // a = c1 ? b : c; // Select 1
863d8e91e46SDimitry Andric // d = c2 ? e : f; // Select 2
864d8e91e46SDimitry Andric // if (c3) { // Branch
865d8e91e46SDimitry Andric //   ...
866d8e91e46SDimitry Andric //   c4 = foo() // A call.
867d8e91e46SDimitry Andric //   g = c4 ? h : i; // Select 3
868d8e91e46SDimitry Andric // }
869d8e91e46SDimitry Andric //
870d8e91e46SDimitry Andric // But suppose we can't hoist c4 because it's dependent on the preceding
871d8e91e46SDimitry Andric // call. Then, we drop Select 3. Furthermore, if we can't hoist c2, we also drop
872d8e91e46SDimitry Andric // Select 2. If we can't hoist c3, we drop Selects 1 & 2.
checkScopeHoistable(CHRScope * Scope)873d8e91e46SDimitry Andric void CHR::checkScopeHoistable(CHRScope *Scope) {
874d8e91e46SDimitry Andric   RegInfo &RI = Scope->RegInfos[0];
875d8e91e46SDimitry Andric   Region *R = RI.R;
876d8e91e46SDimitry Andric   BasicBlock *EntryBB = R->getEntry();
877d8e91e46SDimitry Andric   auto *Branch = RI.HasBranch ?
878d8e91e46SDimitry Andric                  cast<BranchInst>(EntryBB->getTerminator()) : nullptr;
879d8e91e46SDimitry Andric   SmallVector<SelectInst *, 8> &Selects = RI.Selects;
880d8e91e46SDimitry Andric   if (RI.HasBranch || !Selects.empty()) {
881d8e91e46SDimitry Andric     Instruction *InsertPoint = getBranchInsertPoint(RI);
882d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "InsertPoint " << *InsertPoint << "\n");
883d8e91e46SDimitry Andric     // Avoid a data dependence from a select or a branch to a(nother)
884d8e91e46SDimitry Andric     // select. Note no instruction can't data-depend on a branch (a branch
885d8e91e46SDimitry Andric     // instruction doesn't produce a value).
886d8e91e46SDimitry Andric     DenseSet<Instruction *> Unhoistables;
887d8e91e46SDimitry Andric     // Initialize Unhoistables with the selects.
888d8e91e46SDimitry Andric     for (SelectInst *SI : Selects) {
889d8e91e46SDimitry Andric       Unhoistables.insert(SI);
890d8e91e46SDimitry Andric     }
891d8e91e46SDimitry Andric     // Remove Selects that can't be hoisted.
892d8e91e46SDimitry Andric     for (auto it = Selects.begin(); it != Selects.end(); ) {
893d8e91e46SDimitry Andric       SelectInst *SI = *it;
894d8e91e46SDimitry Andric       if (SI == InsertPoint) {
895d8e91e46SDimitry Andric         ++it;
896d8e91e46SDimitry Andric         continue;
897d8e91e46SDimitry Andric       }
898e6d15924SDimitry Andric       DenseMap<Instruction *, bool> Visited;
899d8e91e46SDimitry Andric       bool IsHoistable = checkHoistValue(SI->getCondition(), InsertPoint,
900e6d15924SDimitry Andric                                          DT, Unhoistables, nullptr, Visited);
901d8e91e46SDimitry Andric       if (!IsHoistable) {
902d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Dropping select " << *SI << "\n");
903d8e91e46SDimitry Andric         ORE.emit([&]() {
904d8e91e46SDimitry Andric           return OptimizationRemarkMissed(DEBUG_TYPE,
905d8e91e46SDimitry Andric                                           "DropUnhoistableSelect", SI)
906d8e91e46SDimitry Andric               << "Dropped unhoistable select";
907d8e91e46SDimitry Andric         });
908d8e91e46SDimitry Andric         it = Selects.erase(it);
909d8e91e46SDimitry Andric         // Since we are dropping the select here, we also drop it from
910d8e91e46SDimitry Andric         // Unhoistables.
911d8e91e46SDimitry Andric         Unhoistables.erase(SI);
912d8e91e46SDimitry Andric       } else
913d8e91e46SDimitry Andric         ++it;
914d8e91e46SDimitry Andric     }
915d8e91e46SDimitry Andric     // Update InsertPoint after potentially removing selects.
916d8e91e46SDimitry Andric     InsertPoint = getBranchInsertPoint(RI);
917d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "InsertPoint " << *InsertPoint << "\n");
918d8e91e46SDimitry Andric     if (RI.HasBranch && InsertPoint != Branch) {
919e6d15924SDimitry Andric       DenseMap<Instruction *, bool> Visited;
920d8e91e46SDimitry Andric       bool IsHoistable = checkHoistValue(Branch->getCondition(), InsertPoint,
921e6d15924SDimitry Andric                                          DT, Unhoistables, nullptr, Visited);
922d8e91e46SDimitry Andric       if (!IsHoistable) {
923d8e91e46SDimitry Andric         // If the branch isn't hoistable, drop the selects in the entry
924d8e91e46SDimitry Andric         // block, preferring the branch, which makes the branch the hoist
925d8e91e46SDimitry Andric         // point.
926d8e91e46SDimitry Andric         assert(InsertPoint != Branch && "Branch must not be the hoist point");
927d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Dropping selects in entry block \n");
928d8e91e46SDimitry Andric         CHR_DEBUG(
929d8e91e46SDimitry Andric             for (SelectInst *SI : Selects) {
930d8e91e46SDimitry Andric               dbgs() << "SI " << *SI << "\n";
931d8e91e46SDimitry Andric             });
932d8e91e46SDimitry Andric         for (SelectInst *SI : Selects) {
933d8e91e46SDimitry Andric           ORE.emit([&]() {
934d8e91e46SDimitry Andric             return OptimizationRemarkMissed(DEBUG_TYPE,
935d8e91e46SDimitry Andric                                             "DropSelectUnhoistableBranch", SI)
936d8e91e46SDimitry Andric                 << "Dropped select due to unhoistable branch";
937d8e91e46SDimitry Andric           });
938d8e91e46SDimitry Andric         }
939b60736ecSDimitry Andric         llvm::erase_if(Selects, [EntryBB](SelectInst *SI) {
940d8e91e46SDimitry Andric           return SI->getParent() == EntryBB;
941b60736ecSDimitry Andric         });
942d8e91e46SDimitry Andric         Unhoistables.clear();
943d8e91e46SDimitry Andric         InsertPoint = Branch;
944d8e91e46SDimitry Andric       }
945d8e91e46SDimitry Andric     }
946d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "InsertPoint " << *InsertPoint << "\n");
947d8e91e46SDimitry Andric #ifndef NDEBUG
948d8e91e46SDimitry Andric     if (RI.HasBranch) {
949d8e91e46SDimitry Andric       assert(!DT.dominates(Branch, InsertPoint) &&
950d8e91e46SDimitry Andric              "Branch can't be already above the hoist point");
951e6d15924SDimitry Andric       DenseMap<Instruction *, bool> Visited;
952d8e91e46SDimitry Andric       assert(checkHoistValue(Branch->getCondition(), InsertPoint,
953e6d15924SDimitry Andric                              DT, Unhoistables, nullptr, Visited) &&
954d8e91e46SDimitry Andric              "checkHoistValue for branch");
955d8e91e46SDimitry Andric     }
956d8e91e46SDimitry Andric     for (auto *SI : Selects) {
957d8e91e46SDimitry Andric       assert(!DT.dominates(SI, InsertPoint) &&
958d8e91e46SDimitry Andric              "SI can't be already above the hoist point");
959e6d15924SDimitry Andric       DenseMap<Instruction *, bool> Visited;
960d8e91e46SDimitry Andric       assert(checkHoistValue(SI->getCondition(), InsertPoint, DT,
961e6d15924SDimitry Andric                              Unhoistables, nullptr, Visited) &&
962d8e91e46SDimitry Andric              "checkHoistValue for selects");
963d8e91e46SDimitry Andric     }
964d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Result\n");
965d8e91e46SDimitry Andric     if (RI.HasBranch) {
966d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "BI " << *Branch << "\n");
967d8e91e46SDimitry Andric     }
968d8e91e46SDimitry Andric     for (auto *SI : Selects) {
969d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "SI " << *SI << "\n");
970d8e91e46SDimitry Andric     }
971d8e91e46SDimitry Andric #endif
972d8e91e46SDimitry Andric   }
973d8e91e46SDimitry Andric }
974d8e91e46SDimitry Andric 
975d8e91e46SDimitry Andric // Traverse the region tree, find all nested scopes and merge them if possible.
findScopes(Region * R,Region * NextRegion,Region * ParentRegion,SmallVectorImpl<CHRScope * > & Scopes)976d8e91e46SDimitry Andric CHRScope * CHR::findScopes(Region *R, Region *NextRegion, Region *ParentRegion,
977d8e91e46SDimitry Andric                            SmallVectorImpl<CHRScope *> &Scopes) {
978d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "findScopes " << R->getNameStr() << "\n");
979d8e91e46SDimitry Andric   CHRScope *Result = findScope(R);
980d8e91e46SDimitry Andric   // Visit subscopes.
981d8e91e46SDimitry Andric   CHRScope *ConsecutiveSubscope = nullptr;
982d8e91e46SDimitry Andric   SmallVector<CHRScope *, 8> Subscopes;
983d8e91e46SDimitry Andric   for (auto It = R->begin(); It != R->end(); ++It) {
984d8e91e46SDimitry Andric     const std::unique_ptr<Region> &SubR = *It;
985d8e91e46SDimitry Andric     auto NextIt = std::next(It);
986d8e91e46SDimitry Andric     Region *NextSubR = NextIt != R->end() ? NextIt->get() : nullptr;
987d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Looking at subregion " << SubR.get()->getNameStr()
988d8e91e46SDimitry Andric               << "\n");
989d8e91e46SDimitry Andric     CHRScope *SubCHRScope = findScopes(SubR.get(), NextSubR, R, Scopes);
990d8e91e46SDimitry Andric     if (SubCHRScope) {
991d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "Subregion Scope " << *SubCHRScope << "\n");
992d8e91e46SDimitry Andric     } else {
993d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "Subregion Scope null\n");
994d8e91e46SDimitry Andric     }
995d8e91e46SDimitry Andric     if (SubCHRScope) {
996d8e91e46SDimitry Andric       if (!ConsecutiveSubscope)
997d8e91e46SDimitry Andric         ConsecutiveSubscope = SubCHRScope;
998d8e91e46SDimitry Andric       else if (!ConsecutiveSubscope->appendable(SubCHRScope)) {
999d8e91e46SDimitry Andric         Subscopes.push_back(ConsecutiveSubscope);
1000d8e91e46SDimitry Andric         ConsecutiveSubscope = SubCHRScope;
1001d8e91e46SDimitry Andric       } else
1002d8e91e46SDimitry Andric         ConsecutiveSubscope->append(SubCHRScope);
1003d8e91e46SDimitry Andric     } else {
1004d8e91e46SDimitry Andric       if (ConsecutiveSubscope) {
1005d8e91e46SDimitry Andric         Subscopes.push_back(ConsecutiveSubscope);
1006d8e91e46SDimitry Andric       }
1007d8e91e46SDimitry Andric       ConsecutiveSubscope = nullptr;
1008d8e91e46SDimitry Andric     }
1009d8e91e46SDimitry Andric   }
1010d8e91e46SDimitry Andric   if (ConsecutiveSubscope) {
1011d8e91e46SDimitry Andric     Subscopes.push_back(ConsecutiveSubscope);
1012d8e91e46SDimitry Andric   }
1013d8e91e46SDimitry Andric   for (CHRScope *Sub : Subscopes) {
1014d8e91e46SDimitry Andric     if (Result) {
1015d8e91e46SDimitry Andric       // Combine it with the parent.
1016d8e91e46SDimitry Andric       Result->addSub(Sub);
1017d8e91e46SDimitry Andric     } else {
1018d8e91e46SDimitry Andric       // Push Subscopes as they won't be combined with the parent.
1019d8e91e46SDimitry Andric       Scopes.push_back(Sub);
1020d8e91e46SDimitry Andric     }
1021d8e91e46SDimitry Andric   }
1022d8e91e46SDimitry Andric   return Result;
1023d8e91e46SDimitry Andric }
1024d8e91e46SDimitry Andric 
getCHRConditionValuesForRegion(RegInfo & RI)1025d8e91e46SDimitry Andric static DenseSet<Value *> getCHRConditionValuesForRegion(RegInfo &RI) {
1026d8e91e46SDimitry Andric   DenseSet<Value *> ConditionValues;
1027d8e91e46SDimitry Andric   if (RI.HasBranch) {
1028d8e91e46SDimitry Andric     auto *BI = cast<BranchInst>(RI.R->getEntry()->getTerminator());
1029d8e91e46SDimitry Andric     ConditionValues.insert(BI->getCondition());
1030d8e91e46SDimitry Andric   }
1031d8e91e46SDimitry Andric   for (SelectInst *SI : RI.Selects) {
1032d8e91e46SDimitry Andric     ConditionValues.insert(SI->getCondition());
1033d8e91e46SDimitry Andric   }
1034d8e91e46SDimitry Andric   return ConditionValues;
1035d8e91e46SDimitry Andric }
1036d8e91e46SDimitry Andric 
1037d8e91e46SDimitry Andric 
1038d8e91e46SDimitry Andric // Determine whether to split a scope depending on the sets of the branch
1039d8e91e46SDimitry Andric // condition values of the previous region and the current region. We split
1040d8e91e46SDimitry Andric // (return true) it if 1) the condition values of the inner/lower scope can't be
1041d8e91e46SDimitry Andric // hoisted up to the outer/upper scope, or 2) the two sets of the condition
1042d8e91e46SDimitry Andric // values have an empty intersection (because the combined branch conditions
1043d8e91e46SDimitry Andric // won't probably lead to a simpler combined condition).
shouldSplit(Instruction * InsertPoint,DenseSet<Value * > & PrevConditionValues,DenseSet<Value * > & ConditionValues,DominatorTree & DT,DenseSet<Instruction * > & Unhoistables)1044d8e91e46SDimitry Andric static bool shouldSplit(Instruction *InsertPoint,
1045d8e91e46SDimitry Andric                         DenseSet<Value *> &PrevConditionValues,
1046d8e91e46SDimitry Andric                         DenseSet<Value *> &ConditionValues,
1047d8e91e46SDimitry Andric                         DominatorTree &DT,
1048d8e91e46SDimitry Andric                         DenseSet<Instruction *> &Unhoistables) {
1049706b4fc4SDimitry Andric   assert(InsertPoint && "Null InsertPoint");
1050d8e91e46SDimitry Andric   CHR_DEBUG(
1051d8e91e46SDimitry Andric       dbgs() << "shouldSplit " << *InsertPoint << " PrevConditionValues ";
1052d8e91e46SDimitry Andric       for (Value *V : PrevConditionValues) {
1053d8e91e46SDimitry Andric         dbgs() << *V << ", ";
1054d8e91e46SDimitry Andric       }
1055d8e91e46SDimitry Andric       dbgs() << " ConditionValues ";
1056d8e91e46SDimitry Andric       for (Value *V : ConditionValues) {
1057d8e91e46SDimitry Andric         dbgs() << *V << ", ";
1058d8e91e46SDimitry Andric       }
1059d8e91e46SDimitry Andric       dbgs() << "\n");
1060d8e91e46SDimitry Andric   // If any of Bases isn't hoistable to the hoist point, split.
1061d8e91e46SDimitry Andric   for (Value *V : ConditionValues) {
1062e6d15924SDimitry Andric     DenseMap<Instruction *, bool> Visited;
1063e6d15924SDimitry Andric     if (!checkHoistValue(V, InsertPoint, DT, Unhoistables, nullptr, Visited)) {
1064d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "Split. checkHoistValue false " << *V << "\n");
1065d8e91e46SDimitry Andric       return true; // Not hoistable, split.
1066d8e91e46SDimitry Andric     }
1067d8e91e46SDimitry Andric   }
1068d8e91e46SDimitry Andric   // If PrevConditionValues or ConditionValues is empty, don't split to avoid
1069d8e91e46SDimitry Andric   // unnecessary splits at scopes with no branch/selects.  If
1070d8e91e46SDimitry Andric   // PrevConditionValues and ConditionValues don't intersect at all, split.
1071d8e91e46SDimitry Andric   if (!PrevConditionValues.empty() && !ConditionValues.empty()) {
1072d8e91e46SDimitry Andric     // Use std::set as DenseSet doesn't work with set_intersection.
1073d8e91e46SDimitry Andric     std::set<Value *> PrevBases, Bases;
10741d5ae102SDimitry Andric     DenseMap<Value *, std::set<Value *>> Visited;
1075d8e91e46SDimitry Andric     for (Value *V : PrevConditionValues) {
1076cfca06d7SDimitry Andric       const std::set<Value *> &BaseValues = getBaseValues(V, DT, Visited);
1077d8e91e46SDimitry Andric       PrevBases.insert(BaseValues.begin(), BaseValues.end());
1078d8e91e46SDimitry Andric     }
1079d8e91e46SDimitry Andric     for (Value *V : ConditionValues) {
1080cfca06d7SDimitry Andric       const std::set<Value *> &BaseValues = getBaseValues(V, DT, Visited);
1081d8e91e46SDimitry Andric       Bases.insert(BaseValues.begin(), BaseValues.end());
1082d8e91e46SDimitry Andric     }
1083d8e91e46SDimitry Andric     CHR_DEBUG(
1084d8e91e46SDimitry Andric         dbgs() << "PrevBases ";
1085d8e91e46SDimitry Andric         for (Value *V : PrevBases) {
1086d8e91e46SDimitry Andric           dbgs() << *V << ", ";
1087d8e91e46SDimitry Andric         }
1088d8e91e46SDimitry Andric         dbgs() << " Bases ";
1089d8e91e46SDimitry Andric         for (Value *V : Bases) {
1090d8e91e46SDimitry Andric           dbgs() << *V << ", ";
1091d8e91e46SDimitry Andric         }
1092d8e91e46SDimitry Andric         dbgs() << "\n");
1093cfca06d7SDimitry Andric     std::vector<Value *> Intersection;
1094cfca06d7SDimitry Andric     std::set_intersection(PrevBases.begin(), PrevBases.end(), Bases.begin(),
1095cfca06d7SDimitry Andric                           Bases.end(), std::back_inserter(Intersection));
1096d8e91e46SDimitry Andric     if (Intersection.empty()) {
1097d8e91e46SDimitry Andric       // Empty intersection, split.
1098d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "Split. Intersection empty\n");
1099d8e91e46SDimitry Andric       return true;
1100d8e91e46SDimitry Andric     }
1101d8e91e46SDimitry Andric   }
1102d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "No split\n");
1103d8e91e46SDimitry Andric   return false;  // Don't split.
1104d8e91e46SDimitry Andric }
1105d8e91e46SDimitry Andric 
getSelectsInScope(CHRScope * Scope,DenseSet<Instruction * > & Output)1106d8e91e46SDimitry Andric static void getSelectsInScope(CHRScope *Scope,
1107d8e91e46SDimitry Andric                               DenseSet<Instruction *> &Output) {
1108d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->RegInfos)
1109d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects)
1110d8e91e46SDimitry Andric       Output.insert(SI);
1111d8e91e46SDimitry Andric   for (CHRScope *Sub : Scope->Subs)
1112d8e91e46SDimitry Andric     getSelectsInScope(Sub, Output);
1113d8e91e46SDimitry Andric }
1114d8e91e46SDimitry Andric 
splitScopes(SmallVectorImpl<CHRScope * > & Input,SmallVectorImpl<CHRScope * > & Output)1115d8e91e46SDimitry Andric void CHR::splitScopes(SmallVectorImpl<CHRScope *> &Input,
1116d8e91e46SDimitry Andric                       SmallVectorImpl<CHRScope *> &Output) {
1117d8e91e46SDimitry Andric   for (CHRScope *Scope : Input) {
1118d8e91e46SDimitry Andric     assert(!Scope->BranchInsertPoint &&
1119d8e91e46SDimitry Andric            "BranchInsertPoint must not be set");
1120d8e91e46SDimitry Andric     DenseSet<Instruction *> Unhoistables;
1121d8e91e46SDimitry Andric     getSelectsInScope(Scope, Unhoistables);
1122d8e91e46SDimitry Andric     splitScope(Scope, nullptr, nullptr, nullptr, Output, Unhoistables);
1123d8e91e46SDimitry Andric   }
1124d8e91e46SDimitry Andric #ifndef NDEBUG
1125d8e91e46SDimitry Andric   for (CHRScope *Scope : Output) {
1126d8e91e46SDimitry Andric     assert(Scope->BranchInsertPoint && "BranchInsertPoint must be set");
1127d8e91e46SDimitry Andric   }
1128d8e91e46SDimitry Andric #endif
1129d8e91e46SDimitry Andric }
1130d8e91e46SDimitry Andric 
splitScope(CHRScope * Scope,CHRScope * Outer,DenseSet<Value * > * OuterConditionValues,Instruction * OuterInsertPoint,SmallVectorImpl<CHRScope * > & Output,DenseSet<Instruction * > & Unhoistables)1131d8e91e46SDimitry Andric SmallVector<CHRScope *, 8> CHR::splitScope(
1132d8e91e46SDimitry Andric     CHRScope *Scope,
1133d8e91e46SDimitry Andric     CHRScope *Outer,
1134d8e91e46SDimitry Andric     DenseSet<Value *> *OuterConditionValues,
1135d8e91e46SDimitry Andric     Instruction *OuterInsertPoint,
1136d8e91e46SDimitry Andric     SmallVectorImpl<CHRScope *> &Output,
1137d8e91e46SDimitry Andric     DenseSet<Instruction *> &Unhoistables) {
1138d8e91e46SDimitry Andric   if (Outer) {
1139d8e91e46SDimitry Andric     assert(OuterConditionValues && "Null OuterConditionValues");
1140d8e91e46SDimitry Andric     assert(OuterInsertPoint && "Null OuterInsertPoint");
1141d8e91e46SDimitry Andric   }
1142d8e91e46SDimitry Andric   bool PrevSplitFromOuter = true;
1143d8e91e46SDimitry Andric   DenseSet<Value *> PrevConditionValues;
1144d8e91e46SDimitry Andric   Instruction *PrevInsertPoint = nullptr;
1145d8e91e46SDimitry Andric   SmallVector<CHRScope *, 8> Splits;
1146d8e91e46SDimitry Andric   SmallVector<bool, 8> SplitsSplitFromOuter;
1147d8e91e46SDimitry Andric   SmallVector<DenseSet<Value *>, 8> SplitsConditionValues;
1148d8e91e46SDimitry Andric   SmallVector<Instruction *, 8> SplitsInsertPoints;
1149d8e91e46SDimitry Andric   SmallVector<RegInfo, 8> RegInfos(Scope->RegInfos);  // Copy
1150d8e91e46SDimitry Andric   for (RegInfo &RI : RegInfos) {
1151d8e91e46SDimitry Andric     Instruction *InsertPoint = getBranchInsertPoint(RI);
1152d8e91e46SDimitry Andric     DenseSet<Value *> ConditionValues = getCHRConditionValuesForRegion(RI);
1153d8e91e46SDimitry Andric     CHR_DEBUG(
1154d8e91e46SDimitry Andric         dbgs() << "ConditionValues ";
1155d8e91e46SDimitry Andric         for (Value *V : ConditionValues) {
1156d8e91e46SDimitry Andric           dbgs() << *V << ", ";
1157d8e91e46SDimitry Andric         }
1158d8e91e46SDimitry Andric         dbgs() << "\n");
1159d8e91e46SDimitry Andric     if (RI.R == RegInfos[0].R) {
1160d8e91e46SDimitry Andric       // First iteration. Check to see if we should split from the outer.
1161d8e91e46SDimitry Andric       if (Outer) {
1162d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Outer " << *Outer << "\n");
1163d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Should split from outer at "
1164d8e91e46SDimitry Andric                   << RI.R->getNameStr() << "\n");
1165d8e91e46SDimitry Andric         if (shouldSplit(OuterInsertPoint, *OuterConditionValues,
1166d8e91e46SDimitry Andric                         ConditionValues, DT, Unhoistables)) {
1167d8e91e46SDimitry Andric           PrevConditionValues = ConditionValues;
1168d8e91e46SDimitry Andric           PrevInsertPoint = InsertPoint;
1169d8e91e46SDimitry Andric           ORE.emit([&]() {
1170d8e91e46SDimitry Andric             return OptimizationRemarkMissed(DEBUG_TYPE,
1171d8e91e46SDimitry Andric                                             "SplitScopeFromOuter",
1172d8e91e46SDimitry Andric                                             RI.R->getEntry()->getTerminator())
1173d8e91e46SDimitry Andric                 << "Split scope from outer due to unhoistable branch/select "
1174d8e91e46SDimitry Andric                 << "and/or lack of common condition values";
1175d8e91e46SDimitry Andric           });
1176d8e91e46SDimitry Andric         } else {
1177d8e91e46SDimitry Andric           // Not splitting from the outer. Use the outer bases and insert
1178d8e91e46SDimitry Andric           // point. Union the bases.
1179d8e91e46SDimitry Andric           PrevSplitFromOuter = false;
1180d8e91e46SDimitry Andric           PrevConditionValues = *OuterConditionValues;
1181d8e91e46SDimitry Andric           PrevConditionValues.insert(ConditionValues.begin(),
1182d8e91e46SDimitry Andric                                      ConditionValues.end());
1183d8e91e46SDimitry Andric           PrevInsertPoint = OuterInsertPoint;
1184d8e91e46SDimitry Andric         }
1185d8e91e46SDimitry Andric       } else {
1186d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Outer null\n");
1187d8e91e46SDimitry Andric         PrevConditionValues = ConditionValues;
1188d8e91e46SDimitry Andric         PrevInsertPoint = InsertPoint;
1189d8e91e46SDimitry Andric       }
1190d8e91e46SDimitry Andric     } else {
1191d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "Should split from prev at "
1192d8e91e46SDimitry Andric                 << RI.R->getNameStr() << "\n");
1193d8e91e46SDimitry Andric       if (shouldSplit(PrevInsertPoint, PrevConditionValues, ConditionValues,
1194d8e91e46SDimitry Andric                       DT, Unhoistables)) {
1195d8e91e46SDimitry Andric         CHRScope *Tail = Scope->split(RI.R);
1196d8e91e46SDimitry Andric         Scopes.insert(Tail);
1197d8e91e46SDimitry Andric         Splits.push_back(Scope);
1198d8e91e46SDimitry Andric         SplitsSplitFromOuter.push_back(PrevSplitFromOuter);
1199d8e91e46SDimitry Andric         SplitsConditionValues.push_back(PrevConditionValues);
1200d8e91e46SDimitry Andric         SplitsInsertPoints.push_back(PrevInsertPoint);
1201d8e91e46SDimitry Andric         Scope = Tail;
1202d8e91e46SDimitry Andric         PrevConditionValues = ConditionValues;
1203d8e91e46SDimitry Andric         PrevInsertPoint = InsertPoint;
1204d8e91e46SDimitry Andric         PrevSplitFromOuter = true;
1205d8e91e46SDimitry Andric         ORE.emit([&]() {
1206d8e91e46SDimitry Andric           return OptimizationRemarkMissed(DEBUG_TYPE,
1207d8e91e46SDimitry Andric                                           "SplitScopeFromPrev",
1208d8e91e46SDimitry Andric                                           RI.R->getEntry()->getTerminator())
1209d8e91e46SDimitry Andric               << "Split scope from previous due to unhoistable branch/select "
1210d8e91e46SDimitry Andric               << "and/or lack of common condition values";
1211d8e91e46SDimitry Andric         });
1212d8e91e46SDimitry Andric       } else {
1213d8e91e46SDimitry Andric         // Not splitting. Union the bases. Keep the hoist point.
1214d8e91e46SDimitry Andric         PrevConditionValues.insert(ConditionValues.begin(), ConditionValues.end());
1215d8e91e46SDimitry Andric       }
1216d8e91e46SDimitry Andric     }
1217d8e91e46SDimitry Andric   }
1218d8e91e46SDimitry Andric   Splits.push_back(Scope);
1219d8e91e46SDimitry Andric   SplitsSplitFromOuter.push_back(PrevSplitFromOuter);
1220d8e91e46SDimitry Andric   SplitsConditionValues.push_back(PrevConditionValues);
1221d8e91e46SDimitry Andric   assert(PrevInsertPoint && "Null PrevInsertPoint");
1222d8e91e46SDimitry Andric   SplitsInsertPoints.push_back(PrevInsertPoint);
1223d8e91e46SDimitry Andric   assert(Splits.size() == SplitsConditionValues.size() &&
1224d8e91e46SDimitry Andric          Splits.size() == SplitsSplitFromOuter.size() &&
1225d8e91e46SDimitry Andric          Splits.size() == SplitsInsertPoints.size() && "Mismatching sizes");
1226d8e91e46SDimitry Andric   for (size_t I = 0; I < Splits.size(); ++I) {
1227d8e91e46SDimitry Andric     CHRScope *Split = Splits[I];
1228d8e91e46SDimitry Andric     DenseSet<Value *> &SplitConditionValues = SplitsConditionValues[I];
1229d8e91e46SDimitry Andric     Instruction *SplitInsertPoint = SplitsInsertPoints[I];
1230d8e91e46SDimitry Andric     SmallVector<CHRScope *, 8> NewSubs;
1231d8e91e46SDimitry Andric     DenseSet<Instruction *> SplitUnhoistables;
1232d8e91e46SDimitry Andric     getSelectsInScope(Split, SplitUnhoistables);
1233d8e91e46SDimitry Andric     for (CHRScope *Sub : Split->Subs) {
1234d8e91e46SDimitry Andric       SmallVector<CHRScope *, 8> SubSplits = splitScope(
1235d8e91e46SDimitry Andric           Sub, Split, &SplitConditionValues, SplitInsertPoint, Output,
1236d8e91e46SDimitry Andric           SplitUnhoistables);
1237b60736ecSDimitry Andric       llvm::append_range(NewSubs, SubSplits);
1238d8e91e46SDimitry Andric     }
1239d8e91e46SDimitry Andric     Split->Subs = NewSubs;
1240d8e91e46SDimitry Andric   }
1241d8e91e46SDimitry Andric   SmallVector<CHRScope *, 8> Result;
1242d8e91e46SDimitry Andric   for (size_t I = 0; I < Splits.size(); ++I) {
1243d8e91e46SDimitry Andric     CHRScope *Split = Splits[I];
1244d8e91e46SDimitry Andric     if (SplitsSplitFromOuter[I]) {
1245d8e91e46SDimitry Andric       // Split from the outer.
1246d8e91e46SDimitry Andric       Output.push_back(Split);
1247d8e91e46SDimitry Andric       Split->BranchInsertPoint = SplitsInsertPoints[I];
1248d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "BranchInsertPoint " << *SplitsInsertPoints[I]
1249d8e91e46SDimitry Andric                 << "\n");
1250d8e91e46SDimitry Andric     } else {
1251d8e91e46SDimitry Andric       // Connected to the outer.
1252d8e91e46SDimitry Andric       Result.push_back(Split);
1253d8e91e46SDimitry Andric     }
1254d8e91e46SDimitry Andric   }
1255d8e91e46SDimitry Andric   if (!Outer)
1256d8e91e46SDimitry Andric     assert(Result.empty() &&
1257d8e91e46SDimitry Andric            "If no outer (top-level), must return no nested ones");
1258d8e91e46SDimitry Andric   return Result;
1259d8e91e46SDimitry Andric }
1260d8e91e46SDimitry Andric 
classifyBiasedScopes(SmallVectorImpl<CHRScope * > & Scopes)1261d8e91e46SDimitry Andric void CHR::classifyBiasedScopes(SmallVectorImpl<CHRScope *> &Scopes) {
1262d8e91e46SDimitry Andric   for (CHRScope *Scope : Scopes) {
1263d8e91e46SDimitry Andric     assert(Scope->TrueBiasedRegions.empty() && Scope->FalseBiasedRegions.empty() && "Empty");
1264d8e91e46SDimitry Andric     classifyBiasedScopes(Scope, Scope);
1265d8e91e46SDimitry Andric     CHR_DEBUG(
1266d8e91e46SDimitry Andric         dbgs() << "classifyBiasedScopes " << *Scope << "\n";
1267d8e91e46SDimitry Andric         dbgs() << "TrueBiasedRegions ";
1268d8e91e46SDimitry Andric         for (Region *R : Scope->TrueBiasedRegions) {
1269d8e91e46SDimitry Andric           dbgs() << R->getNameStr() << ", ";
1270d8e91e46SDimitry Andric         }
1271d8e91e46SDimitry Andric         dbgs() << "\n";
1272d8e91e46SDimitry Andric         dbgs() << "FalseBiasedRegions ";
1273d8e91e46SDimitry Andric         for (Region *R : Scope->FalseBiasedRegions) {
1274d8e91e46SDimitry Andric           dbgs() << R->getNameStr() << ", ";
1275d8e91e46SDimitry Andric         }
1276d8e91e46SDimitry Andric         dbgs() << "\n";
1277d8e91e46SDimitry Andric         dbgs() << "TrueBiasedSelects ";
1278d8e91e46SDimitry Andric         for (SelectInst *SI : Scope->TrueBiasedSelects) {
1279d8e91e46SDimitry Andric           dbgs() << *SI << ", ";
1280d8e91e46SDimitry Andric         }
1281d8e91e46SDimitry Andric         dbgs() << "\n";
1282d8e91e46SDimitry Andric         dbgs() << "FalseBiasedSelects ";
1283d8e91e46SDimitry Andric         for (SelectInst *SI : Scope->FalseBiasedSelects) {
1284d8e91e46SDimitry Andric           dbgs() << *SI << ", ";
1285d8e91e46SDimitry Andric         }
1286d8e91e46SDimitry Andric         dbgs() << "\n";);
1287d8e91e46SDimitry Andric   }
1288d8e91e46SDimitry Andric }
1289d8e91e46SDimitry Andric 
classifyBiasedScopes(CHRScope * Scope,CHRScope * OutermostScope)1290d8e91e46SDimitry Andric void CHR::classifyBiasedScopes(CHRScope *Scope, CHRScope *OutermostScope) {
1291d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->RegInfos) {
1292d8e91e46SDimitry Andric     if (RI.HasBranch) {
1293d8e91e46SDimitry Andric       Region *R = RI.R;
1294b60736ecSDimitry Andric       if (TrueBiasedRegionsGlobal.contains(R))
1295d8e91e46SDimitry Andric         OutermostScope->TrueBiasedRegions.insert(R);
1296b60736ecSDimitry Andric       else if (FalseBiasedRegionsGlobal.contains(R))
1297d8e91e46SDimitry Andric         OutermostScope->FalseBiasedRegions.insert(R);
1298d8e91e46SDimitry Andric       else
1299d8e91e46SDimitry Andric         llvm_unreachable("Must be biased");
1300d8e91e46SDimitry Andric     }
1301d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects) {
1302b60736ecSDimitry Andric       if (TrueBiasedSelectsGlobal.contains(SI))
1303d8e91e46SDimitry Andric         OutermostScope->TrueBiasedSelects.insert(SI);
1304b60736ecSDimitry Andric       else if (FalseBiasedSelectsGlobal.contains(SI))
1305d8e91e46SDimitry Andric         OutermostScope->FalseBiasedSelects.insert(SI);
1306d8e91e46SDimitry Andric       else
1307d8e91e46SDimitry Andric         llvm_unreachable("Must be biased");
1308d8e91e46SDimitry Andric     }
1309d8e91e46SDimitry Andric   }
1310d8e91e46SDimitry Andric   for (CHRScope *Sub : Scope->Subs) {
1311d8e91e46SDimitry Andric     classifyBiasedScopes(Sub, OutermostScope);
1312d8e91e46SDimitry Andric   }
1313d8e91e46SDimitry Andric }
1314d8e91e46SDimitry Andric 
hasAtLeastTwoBiasedBranches(CHRScope * Scope)1315d8e91e46SDimitry Andric static bool hasAtLeastTwoBiasedBranches(CHRScope *Scope) {
1316d8e91e46SDimitry Andric   unsigned NumBiased = Scope->TrueBiasedRegions.size() +
1317d8e91e46SDimitry Andric                        Scope->FalseBiasedRegions.size() +
1318d8e91e46SDimitry Andric                        Scope->TrueBiasedSelects.size() +
1319d8e91e46SDimitry Andric                        Scope->FalseBiasedSelects.size();
1320d8e91e46SDimitry Andric   return NumBiased >= CHRMergeThreshold;
1321d8e91e46SDimitry Andric }
1322d8e91e46SDimitry Andric 
filterScopes(SmallVectorImpl<CHRScope * > & Input,SmallVectorImpl<CHRScope * > & Output)1323d8e91e46SDimitry Andric void CHR::filterScopes(SmallVectorImpl<CHRScope *> &Input,
1324d8e91e46SDimitry Andric                        SmallVectorImpl<CHRScope *> &Output) {
1325d8e91e46SDimitry Andric   for (CHRScope *Scope : Input) {
1326d8e91e46SDimitry Andric     // Filter out the ones with only one region and no subs.
1327d8e91e46SDimitry Andric     if (!hasAtLeastTwoBiasedBranches(Scope)) {
1328d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << "Filtered out by biased branches truthy-regions "
1329d8e91e46SDimitry Andric                 << Scope->TrueBiasedRegions.size()
1330d8e91e46SDimitry Andric                 << " falsy-regions " << Scope->FalseBiasedRegions.size()
1331d8e91e46SDimitry Andric                 << " true-selects " << Scope->TrueBiasedSelects.size()
1332d8e91e46SDimitry Andric                 << " false-selects " << Scope->FalseBiasedSelects.size() << "\n");
1333d8e91e46SDimitry Andric       ORE.emit([&]() {
1334d8e91e46SDimitry Andric         return OptimizationRemarkMissed(
1335d8e91e46SDimitry Andric             DEBUG_TYPE,
1336d8e91e46SDimitry Andric             "DropScopeWithOneBranchOrSelect",
1337d8e91e46SDimitry Andric             Scope->RegInfos[0].R->getEntry()->getTerminator())
1338d8e91e46SDimitry Andric             << "Drop scope with < "
1339d8e91e46SDimitry Andric             << ore::NV("CHRMergeThreshold", CHRMergeThreshold)
1340d8e91e46SDimitry Andric             << " biased branch(es) or select(s)";
1341d8e91e46SDimitry Andric       });
1342d8e91e46SDimitry Andric       continue;
1343d8e91e46SDimitry Andric     }
1344d8e91e46SDimitry Andric     Output.push_back(Scope);
1345d8e91e46SDimitry Andric   }
1346d8e91e46SDimitry Andric }
1347d8e91e46SDimitry Andric 
setCHRRegions(SmallVectorImpl<CHRScope * > & Input,SmallVectorImpl<CHRScope * > & Output)1348d8e91e46SDimitry Andric void CHR::setCHRRegions(SmallVectorImpl<CHRScope *> &Input,
1349d8e91e46SDimitry Andric                         SmallVectorImpl<CHRScope *> &Output) {
1350d8e91e46SDimitry Andric   for (CHRScope *Scope : Input) {
1351d8e91e46SDimitry Andric     assert(Scope->HoistStopMap.empty() && Scope->CHRRegions.empty() &&
1352d8e91e46SDimitry Andric            "Empty");
1353d8e91e46SDimitry Andric     setCHRRegions(Scope, Scope);
1354d8e91e46SDimitry Andric     Output.push_back(Scope);
1355d8e91e46SDimitry Andric     CHR_DEBUG(
1356d8e91e46SDimitry Andric         dbgs() << "setCHRRegions HoistStopMap " << *Scope << "\n";
1357d8e91e46SDimitry Andric         for (auto pair : Scope->HoistStopMap) {
1358d8e91e46SDimitry Andric           Region *R = pair.first;
1359d8e91e46SDimitry Andric           dbgs() << "Region " << R->getNameStr() << "\n";
1360d8e91e46SDimitry Andric           for (Instruction *I : pair.second) {
1361d8e91e46SDimitry Andric             dbgs() << "HoistStop " << *I << "\n";
1362d8e91e46SDimitry Andric           }
1363d8e91e46SDimitry Andric         }
1364d8e91e46SDimitry Andric         dbgs() << "CHRRegions" << "\n";
1365d8e91e46SDimitry Andric         for (RegInfo &RI : Scope->CHRRegions) {
1366d8e91e46SDimitry Andric           dbgs() << RI.R->getNameStr() << "\n";
1367d8e91e46SDimitry Andric         });
1368d8e91e46SDimitry Andric   }
1369d8e91e46SDimitry Andric }
1370d8e91e46SDimitry Andric 
setCHRRegions(CHRScope * Scope,CHRScope * OutermostScope)1371d8e91e46SDimitry Andric void CHR::setCHRRegions(CHRScope *Scope, CHRScope *OutermostScope) {
1372d8e91e46SDimitry Andric   DenseSet<Instruction *> Unhoistables;
1373d8e91e46SDimitry Andric   // Put the biased selects in Unhoistables because they should stay where they
1374d8e91e46SDimitry Andric   // are and constant-folded after CHR (in case one biased select or a branch
1375d8e91e46SDimitry Andric   // can depend on another biased select.)
1376d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->RegInfos) {
1377d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects) {
1378d8e91e46SDimitry Andric       Unhoistables.insert(SI);
1379d8e91e46SDimitry Andric     }
1380d8e91e46SDimitry Andric   }
1381d8e91e46SDimitry Andric   Instruction *InsertPoint = OutermostScope->BranchInsertPoint;
1382d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->RegInfos) {
1383d8e91e46SDimitry Andric     Region *R = RI.R;
1384d8e91e46SDimitry Andric     DenseSet<Instruction *> HoistStops;
1385d8e91e46SDimitry Andric     bool IsHoisted = false;
1386d8e91e46SDimitry Andric     if (RI.HasBranch) {
1387b60736ecSDimitry Andric       assert((OutermostScope->TrueBiasedRegions.contains(R) ||
1388b60736ecSDimitry Andric               OutermostScope->FalseBiasedRegions.contains(R)) &&
1389d8e91e46SDimitry Andric              "Must be truthy or falsy");
1390d8e91e46SDimitry Andric       auto *BI = cast<BranchInst>(R->getEntry()->getTerminator());
1391d8e91e46SDimitry Andric       // Note checkHoistValue fills in HoistStops.
1392e6d15924SDimitry Andric       DenseMap<Instruction *, bool> Visited;
1393d8e91e46SDimitry Andric       bool IsHoistable = checkHoistValue(BI->getCondition(), InsertPoint, DT,
1394e6d15924SDimitry Andric                                          Unhoistables, &HoistStops, Visited);
1395d8e91e46SDimitry Andric       assert(IsHoistable && "Must be hoistable");
1396d8e91e46SDimitry Andric       (void)(IsHoistable);  // Unused in release build
1397d8e91e46SDimitry Andric       IsHoisted = true;
1398d8e91e46SDimitry Andric     }
1399d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects) {
1400b60736ecSDimitry Andric       assert((OutermostScope->TrueBiasedSelects.contains(SI) ||
1401b60736ecSDimitry Andric               OutermostScope->FalseBiasedSelects.contains(SI)) &&
1402d8e91e46SDimitry Andric              "Must be true or false biased");
1403d8e91e46SDimitry Andric       // Note checkHoistValue fills in HoistStops.
1404e6d15924SDimitry Andric       DenseMap<Instruction *, bool> Visited;
1405d8e91e46SDimitry Andric       bool IsHoistable = checkHoistValue(SI->getCondition(), InsertPoint, DT,
1406e6d15924SDimitry Andric                                          Unhoistables, &HoistStops, Visited);
1407d8e91e46SDimitry Andric       assert(IsHoistable && "Must be hoistable");
1408d8e91e46SDimitry Andric       (void)(IsHoistable);  // Unused in release build
1409d8e91e46SDimitry Andric       IsHoisted = true;
1410d8e91e46SDimitry Andric     }
1411d8e91e46SDimitry Andric     if (IsHoisted) {
1412d8e91e46SDimitry Andric       OutermostScope->CHRRegions.push_back(RI);
1413d8e91e46SDimitry Andric       OutermostScope->HoistStopMap[R] = HoistStops;
1414d8e91e46SDimitry Andric     }
1415d8e91e46SDimitry Andric   }
1416d8e91e46SDimitry Andric   for (CHRScope *Sub : Scope->Subs)
1417d8e91e46SDimitry Andric     setCHRRegions(Sub, OutermostScope);
1418d8e91e46SDimitry Andric }
1419d8e91e46SDimitry Andric 
CHRScopeSorter(CHRScope * Scope1,CHRScope * Scope2)1420cfca06d7SDimitry Andric static bool CHRScopeSorter(CHRScope *Scope1, CHRScope *Scope2) {
1421d8e91e46SDimitry Andric   return Scope1->RegInfos[0].R->getDepth() < Scope2->RegInfos[0].R->getDepth();
1422d8e91e46SDimitry Andric }
1423d8e91e46SDimitry Andric 
sortScopes(SmallVectorImpl<CHRScope * > & Input,SmallVectorImpl<CHRScope * > & Output)1424d8e91e46SDimitry Andric void CHR::sortScopes(SmallVectorImpl<CHRScope *> &Input,
1425d8e91e46SDimitry Andric                      SmallVectorImpl<CHRScope *> &Output) {
1426d8e91e46SDimitry Andric   Output.resize(Input.size());
1427d8e91e46SDimitry Andric   llvm::copy(Input, Output.begin());
1428e6d15924SDimitry Andric   llvm::stable_sort(Output, CHRScopeSorter);
1429d8e91e46SDimitry Andric }
1430d8e91e46SDimitry Andric 
1431d8e91e46SDimitry Andric // Return true if V is already hoisted or was hoisted (along with its operands)
1432d8e91e46SDimitry Andric // to the insert point.
hoistValue(Value * V,Instruction * HoistPoint,Region * R,HoistStopMapTy & HoistStopMap,DenseSet<Instruction * > & HoistedSet,DenseSet<PHINode * > & TrivialPHIs,DominatorTree & DT)1433d8e91e46SDimitry Andric static void hoistValue(Value *V, Instruction *HoistPoint, Region *R,
1434d8e91e46SDimitry Andric                        HoistStopMapTy &HoistStopMap,
1435d8e91e46SDimitry Andric                        DenseSet<Instruction *> &HoistedSet,
1436e6d15924SDimitry Andric                        DenseSet<PHINode *> &TrivialPHIs,
1437e6d15924SDimitry Andric                        DominatorTree &DT) {
1438d8e91e46SDimitry Andric   auto IT = HoistStopMap.find(R);
1439d8e91e46SDimitry Andric   assert(IT != HoistStopMap.end() && "Region must be in hoist stop map");
1440d8e91e46SDimitry Andric   DenseSet<Instruction *> &HoistStops = IT->second;
1441d8e91e46SDimitry Andric   if (auto *I = dyn_cast<Instruction>(V)) {
1442d8e91e46SDimitry Andric     if (I == HoistPoint)
1443d8e91e46SDimitry Andric       return;
1444d8e91e46SDimitry Andric     if (HoistStops.count(I))
1445d8e91e46SDimitry Andric       return;
1446d8e91e46SDimitry Andric     if (auto *PN = dyn_cast<PHINode>(I))
1447d8e91e46SDimitry Andric       if (TrivialPHIs.count(PN))
1448d8e91e46SDimitry Andric         // The trivial phi inserted by the previous CHR scope could replace a
1449d8e91e46SDimitry Andric         // non-phi in HoistStops. Note that since this phi is at the exit of a
1450d8e91e46SDimitry Andric         // previous CHR scope, which dominates this scope, it's safe to stop
1451d8e91e46SDimitry Andric         // hoisting there.
1452d8e91e46SDimitry Andric         return;
1453d8e91e46SDimitry Andric     if (HoistedSet.count(I))
1454d8e91e46SDimitry Andric       // Already hoisted, return.
1455d8e91e46SDimitry Andric       return;
1456d8e91e46SDimitry Andric     assert(isHoistableInstructionType(I) && "Unhoistable instruction type");
1457e6d15924SDimitry Andric     assert(DT.getNode(I->getParent()) && "DT must contain I's block");
1458e6d15924SDimitry Andric     assert(DT.getNode(HoistPoint->getParent()) &&
1459e6d15924SDimitry Andric            "DT must contain HoistPoint block");
1460e6d15924SDimitry Andric     if (DT.dominates(I, HoistPoint))
1461e6d15924SDimitry Andric       // We are already above the hoist point. Stop here. This may be necessary
1462e6d15924SDimitry Andric       // when multiple scopes would independently hoist the same
1463e6d15924SDimitry Andric       // instruction. Since an outer (dominating) scope would hoist it to its
1464e6d15924SDimitry Andric       // entry before an inner (dominated) scope would to its entry, the inner
1465e6d15924SDimitry Andric       // scope may see the instruction already hoisted, in which case it
1466e6d15924SDimitry Andric       // potentially wrong for the inner scope to hoist it and could cause bad
1467e6d15924SDimitry Andric       // IR (non-dominating def), but safe to skip hoisting it instead because
1468e6d15924SDimitry Andric       // it's already in a block that dominates the inner scope.
1469e6d15924SDimitry Andric       return;
1470d8e91e46SDimitry Andric     for (Value *Op : I->operands()) {
1471e6d15924SDimitry Andric       hoistValue(Op, HoistPoint, R, HoistStopMap, HoistedSet, TrivialPHIs, DT);
1472d8e91e46SDimitry Andric     }
1473d8e91e46SDimitry Andric     I->moveBefore(HoistPoint);
1474d8e91e46SDimitry Andric     HoistedSet.insert(I);
1475d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "hoistValue " << *I << "\n");
1476d8e91e46SDimitry Andric   }
1477d8e91e46SDimitry Andric }
1478d8e91e46SDimitry Andric 
1479d8e91e46SDimitry Andric // Hoist the dependent condition values of the branches and the selects in the
1480d8e91e46SDimitry Andric // scope to the insert point.
hoistScopeConditions(CHRScope * Scope,Instruction * HoistPoint,DenseSet<PHINode * > & TrivialPHIs,DominatorTree & DT)1481d8e91e46SDimitry Andric static void hoistScopeConditions(CHRScope *Scope, Instruction *HoistPoint,
1482e6d15924SDimitry Andric                                  DenseSet<PHINode *> &TrivialPHIs,
1483e6d15924SDimitry Andric                                  DominatorTree &DT) {
1484d8e91e46SDimitry Andric   DenseSet<Instruction *> HoistedSet;
1485d8e91e46SDimitry Andric   for (const RegInfo &RI : Scope->CHRRegions) {
1486d8e91e46SDimitry Andric     Region *R = RI.R;
1487d8e91e46SDimitry Andric     bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
1488d8e91e46SDimitry Andric     bool IsFalseBiased = Scope->FalseBiasedRegions.count(R);
1489d8e91e46SDimitry Andric     if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
1490d8e91e46SDimitry Andric       auto *BI = cast<BranchInst>(R->getEntry()->getTerminator());
1491d8e91e46SDimitry Andric       hoistValue(BI->getCondition(), HoistPoint, R, Scope->HoistStopMap,
1492e6d15924SDimitry Andric                  HoistedSet, TrivialPHIs, DT);
1493d8e91e46SDimitry Andric     }
1494d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects) {
1495d8e91e46SDimitry Andric       bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
1496d8e91e46SDimitry Andric       bool IsFalseBiased = Scope->FalseBiasedSelects.count(SI);
1497d8e91e46SDimitry Andric       if (!(IsTrueBiased || IsFalseBiased))
1498d8e91e46SDimitry Andric         continue;
1499d8e91e46SDimitry Andric       hoistValue(SI->getCondition(), HoistPoint, R, Scope->HoistStopMap,
1500e6d15924SDimitry Andric                  HoistedSet, TrivialPHIs, DT);
1501d8e91e46SDimitry Andric     }
1502d8e91e46SDimitry Andric   }
1503d8e91e46SDimitry Andric }
1504d8e91e46SDimitry Andric 
1505d8e91e46SDimitry Andric // Negate the predicate if an ICmp if it's used only by branches or selects by
1506d8e91e46SDimitry Andric // swapping the operands of the branches or the selects. Returns true if success.
negateICmpIfUsedByBranchOrSelectOnly(ICmpInst * ICmp,Instruction * ExcludedUser,CHRScope * Scope)1507d8e91e46SDimitry Andric static bool negateICmpIfUsedByBranchOrSelectOnly(ICmpInst *ICmp,
1508d8e91e46SDimitry Andric                                                  Instruction *ExcludedUser,
1509d8e91e46SDimitry Andric                                                  CHRScope *Scope) {
1510d8e91e46SDimitry Andric   for (User *U : ICmp->users()) {
1511d8e91e46SDimitry Andric     if (U == ExcludedUser)
1512d8e91e46SDimitry Andric       continue;
1513d8e91e46SDimitry Andric     if (isa<BranchInst>(U) && cast<BranchInst>(U)->isConditional())
1514d8e91e46SDimitry Andric       continue;
1515d8e91e46SDimitry Andric     if (isa<SelectInst>(U) && cast<SelectInst>(U)->getCondition() == ICmp)
1516d8e91e46SDimitry Andric       continue;
1517d8e91e46SDimitry Andric     return false;
1518d8e91e46SDimitry Andric   }
1519d8e91e46SDimitry Andric   for (User *U : ICmp->users()) {
1520d8e91e46SDimitry Andric     if (U == ExcludedUser)
1521d8e91e46SDimitry Andric       continue;
1522d8e91e46SDimitry Andric     if (auto *BI = dyn_cast<BranchInst>(U)) {
1523d8e91e46SDimitry Andric       assert(BI->isConditional() && "Must be conditional");
1524d8e91e46SDimitry Andric       BI->swapSuccessors();
1525d8e91e46SDimitry Andric       // Don't need to swap this in terms of
1526d8e91e46SDimitry Andric       // TrueBiasedRegions/FalseBiasedRegions because true-based/false-based
1527d8e91e46SDimitry Andric       // mean whehter the branch is likely go into the if-then rather than
1528d8e91e46SDimitry Andric       // successor0/successor1 and because we can tell which edge is the then or
1529d8e91e46SDimitry Andric       // the else one by comparing the destination to the region exit block.
1530d8e91e46SDimitry Andric       continue;
1531d8e91e46SDimitry Andric     }
1532d8e91e46SDimitry Andric     if (auto *SI = dyn_cast<SelectInst>(U)) {
1533d8e91e46SDimitry Andric       // Swap operands
15341d5ae102SDimitry Andric       SI->swapValues();
1535d8e91e46SDimitry Andric       SI->swapProfMetadata();
1536d8e91e46SDimitry Andric       if (Scope->TrueBiasedSelects.count(SI)) {
1537c0981da4SDimitry Andric         assert(!Scope->FalseBiasedSelects.contains(SI) &&
1538d8e91e46SDimitry Andric                "Must not be already in");
1539d8e91e46SDimitry Andric         Scope->FalseBiasedSelects.insert(SI);
1540d8e91e46SDimitry Andric       } else if (Scope->FalseBiasedSelects.count(SI)) {
1541c0981da4SDimitry Andric         assert(!Scope->TrueBiasedSelects.contains(SI) &&
1542d8e91e46SDimitry Andric                "Must not be already in");
1543d8e91e46SDimitry Andric         Scope->TrueBiasedSelects.insert(SI);
1544d8e91e46SDimitry Andric       }
1545d8e91e46SDimitry Andric       continue;
1546d8e91e46SDimitry Andric     }
1547d8e91e46SDimitry Andric     llvm_unreachable("Must be a branch or a select");
1548d8e91e46SDimitry Andric   }
1549d8e91e46SDimitry Andric   ICmp->setPredicate(CmpInst::getInversePredicate(ICmp->getPredicate()));
1550d8e91e46SDimitry Andric   return true;
1551d8e91e46SDimitry Andric }
1552d8e91e46SDimitry Andric 
1553d8e91e46SDimitry Andric // A helper for transformScopes. Insert a trivial phi at the scope exit block
1554d8e91e46SDimitry Andric // for a value that's defined in the scope but used outside it (meaning it's
1555d8e91e46SDimitry Andric // alive at the exit block).
insertTrivialPHIs(CHRScope * Scope,BasicBlock * EntryBlock,BasicBlock * ExitBlock,DenseSet<PHINode * > & TrivialPHIs)1556d8e91e46SDimitry Andric static void insertTrivialPHIs(CHRScope *Scope,
1557d8e91e46SDimitry Andric                               BasicBlock *EntryBlock, BasicBlock *ExitBlock,
1558d8e91e46SDimitry Andric                               DenseSet<PHINode *> &TrivialPHIs) {
1559cfca06d7SDimitry Andric   SmallSetVector<BasicBlock *, 8> BlocksInScope;
1560d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->RegInfos) {
1561d8e91e46SDimitry Andric     for (BasicBlock *BB : RI.R->blocks()) { // This includes the blocks in the
1562d8e91e46SDimitry Andric                                             // sub-Scopes.
1563cfca06d7SDimitry Andric       BlocksInScope.insert(BB);
1564d8e91e46SDimitry Andric     }
1565d8e91e46SDimitry Andric   }
1566cfca06d7SDimitry Andric   CHR_DEBUG({
1567cfca06d7SDimitry Andric     dbgs() << "Inserting redundant phis\n";
1568cfca06d7SDimitry Andric     for (BasicBlock *BB : BlocksInScope)
1569d8e91e46SDimitry Andric       dbgs() << "BlockInScope " << BB->getName() << "\n";
1570d8e91e46SDimitry Andric   });
1571cfca06d7SDimitry Andric   for (BasicBlock *BB : BlocksInScope) {
1572d8e91e46SDimitry Andric     for (Instruction &I : *BB) {
1573d8e91e46SDimitry Andric       SmallVector<Instruction *, 8> Users;
1574d8e91e46SDimitry Andric       for (User *U : I.users()) {
1575d8e91e46SDimitry Andric         if (auto *UI = dyn_cast<Instruction>(U)) {
1576c0981da4SDimitry Andric           if (!BlocksInScope.contains(UI->getParent()) &&
1577d8e91e46SDimitry Andric               // Unless there's already a phi for I at the exit block.
1578d8e91e46SDimitry Andric               !(isa<PHINode>(UI) && UI->getParent() == ExitBlock)) {
1579d8e91e46SDimitry Andric             CHR_DEBUG(dbgs() << "V " << I << "\n");
1580d8e91e46SDimitry Andric             CHR_DEBUG(dbgs() << "Used outside scope by user " << *UI << "\n");
1581d8e91e46SDimitry Andric             Users.push_back(UI);
1582d8e91e46SDimitry Andric           } else if (UI->getParent() == EntryBlock && isa<PHINode>(UI)) {
1583d8e91e46SDimitry Andric             // There's a loop backedge from a block that's dominated by this
1584d8e91e46SDimitry Andric             // scope to the entry block.
1585d8e91e46SDimitry Andric             CHR_DEBUG(dbgs() << "V " << I << "\n");
1586d8e91e46SDimitry Andric             CHR_DEBUG(dbgs()
1587d8e91e46SDimitry Andric                       << "Used at entry block (for a back edge) by a phi user "
1588d8e91e46SDimitry Andric                       << *UI << "\n");
1589d8e91e46SDimitry Andric             Users.push_back(UI);
1590d8e91e46SDimitry Andric           }
1591d8e91e46SDimitry Andric         }
1592d8e91e46SDimitry Andric       }
1593d8e91e46SDimitry Andric       if (Users.size() > 0) {
1594d8e91e46SDimitry Andric         // Insert a trivial phi for I (phi [&I, P0], [&I, P1], ...) at
1595d8e91e46SDimitry Andric         // ExitBlock. Replace I with the new phi in UI unless UI is another
1596d8e91e46SDimitry Andric         // phi at ExitBlock.
1597b1c73532SDimitry Andric         PHINode *PN = PHINode::Create(I.getType(), pred_size(ExitBlock), "");
1598b1c73532SDimitry Andric         PN->insertBefore(ExitBlock->begin());
1599d8e91e46SDimitry Andric         for (BasicBlock *Pred : predecessors(ExitBlock)) {
1600d8e91e46SDimitry Andric           PN->addIncoming(&I, Pred);
1601d8e91e46SDimitry Andric         }
1602d8e91e46SDimitry Andric         TrivialPHIs.insert(PN);
1603d8e91e46SDimitry Andric         CHR_DEBUG(dbgs() << "Insert phi " << *PN << "\n");
1604d8e91e46SDimitry Andric         for (Instruction *UI : Users) {
1605d8e91e46SDimitry Andric           for (unsigned J = 0, NumOps = UI->getNumOperands(); J < NumOps; ++J) {
1606d8e91e46SDimitry Andric             if (UI->getOperand(J) == &I) {
1607d8e91e46SDimitry Andric               UI->setOperand(J, PN);
1608d8e91e46SDimitry Andric             }
1609d8e91e46SDimitry Andric           }
1610d8e91e46SDimitry Andric           CHR_DEBUG(dbgs() << "Updated user " << *UI << "\n");
1611d8e91e46SDimitry Andric         }
1612d8e91e46SDimitry Andric       }
1613d8e91e46SDimitry Andric     }
1614d8e91e46SDimitry Andric   }
1615d8e91e46SDimitry Andric }
1616d8e91e46SDimitry Andric 
1617d8e91e46SDimitry Andric // Assert that all the CHR regions of the scope have a biased branch or select.
1618d8e91e46SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED
assertCHRRegionsHaveBiasedBranchOrSelect(CHRScope * Scope)1619d8e91e46SDimitry Andric assertCHRRegionsHaveBiasedBranchOrSelect(CHRScope *Scope) {
1620d8e91e46SDimitry Andric #ifndef NDEBUG
1621d8e91e46SDimitry Andric   auto HasBiasedBranchOrSelect = [](RegInfo &RI, CHRScope *Scope) {
1622d8e91e46SDimitry Andric     if (Scope->TrueBiasedRegions.count(RI.R) ||
1623d8e91e46SDimitry Andric         Scope->FalseBiasedRegions.count(RI.R))
1624d8e91e46SDimitry Andric       return true;
1625d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects)
1626d8e91e46SDimitry Andric       if (Scope->TrueBiasedSelects.count(SI) ||
1627d8e91e46SDimitry Andric           Scope->FalseBiasedSelects.count(SI))
1628d8e91e46SDimitry Andric         return true;
1629d8e91e46SDimitry Andric     return false;
1630d8e91e46SDimitry Andric   };
1631d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->CHRRegions) {
1632d8e91e46SDimitry Andric     assert(HasBiasedBranchOrSelect(RI, Scope) &&
1633d8e91e46SDimitry Andric            "Must have biased branch or select");
1634d8e91e46SDimitry Andric   }
1635d8e91e46SDimitry Andric #endif
1636d8e91e46SDimitry Andric }
1637d8e91e46SDimitry Andric 
1638d8e91e46SDimitry Andric // Assert that all the condition values of the biased branches and selects have
1639d8e91e46SDimitry Andric // been hoisted to the pre-entry block or outside of the scope.
assertBranchOrSelectConditionHoisted(CHRScope * Scope,BasicBlock * PreEntryBlock)1640d8e91e46SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED assertBranchOrSelectConditionHoisted(
1641d8e91e46SDimitry Andric     CHRScope *Scope, BasicBlock *PreEntryBlock) {
1642d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "Biased regions condition values \n");
1643d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->CHRRegions) {
1644d8e91e46SDimitry Andric     Region *R = RI.R;
1645d8e91e46SDimitry Andric     bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
1646d8e91e46SDimitry Andric     bool IsFalseBiased = Scope->FalseBiasedRegions.count(R);
1647d8e91e46SDimitry Andric     if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
1648d8e91e46SDimitry Andric       auto *BI = cast<BranchInst>(R->getEntry()->getTerminator());
1649d8e91e46SDimitry Andric       Value *V = BI->getCondition();
1650d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << *V << "\n");
1651d8e91e46SDimitry Andric       if (auto *I = dyn_cast<Instruction>(V)) {
1652d8e91e46SDimitry Andric         (void)(I); // Unused in release build.
1653d8e91e46SDimitry Andric         assert((I->getParent() == PreEntryBlock ||
1654d8e91e46SDimitry Andric                 !Scope->contains(I)) &&
1655d8e91e46SDimitry Andric                "Must have been hoisted to PreEntryBlock or outside the scope");
1656d8e91e46SDimitry Andric       }
1657d8e91e46SDimitry Andric     }
1658d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects) {
1659d8e91e46SDimitry Andric       bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
1660d8e91e46SDimitry Andric       bool IsFalseBiased = Scope->FalseBiasedSelects.count(SI);
1661d8e91e46SDimitry Andric       if (!(IsTrueBiased || IsFalseBiased))
1662d8e91e46SDimitry Andric         continue;
1663d8e91e46SDimitry Andric       Value *V = SI->getCondition();
1664d8e91e46SDimitry Andric       CHR_DEBUG(dbgs() << *V << "\n");
1665d8e91e46SDimitry Andric       if (auto *I = dyn_cast<Instruction>(V)) {
1666d8e91e46SDimitry Andric         (void)(I); // Unused in release build.
1667d8e91e46SDimitry Andric         assert((I->getParent() == PreEntryBlock ||
1668d8e91e46SDimitry Andric                 !Scope->contains(I)) &&
1669d8e91e46SDimitry Andric                "Must have been hoisted to PreEntryBlock or outside the scope");
1670d8e91e46SDimitry Andric       }
1671d8e91e46SDimitry Andric     }
1672d8e91e46SDimitry Andric   }
1673d8e91e46SDimitry Andric }
1674d8e91e46SDimitry Andric 
transformScopes(CHRScope * Scope,DenseSet<PHINode * > & TrivialPHIs)1675d8e91e46SDimitry Andric void CHR::transformScopes(CHRScope *Scope, DenseSet<PHINode *> &TrivialPHIs) {
1676d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "transformScopes " << *Scope << "\n");
1677d8e91e46SDimitry Andric 
1678d8e91e46SDimitry Andric   assert(Scope->RegInfos.size() >= 1 && "Should have at least one Region");
1679e3b55780SDimitry Andric 
1680e3b55780SDimitry Andric   for (RegInfo &RI : Scope->RegInfos) {
1681e3b55780SDimitry Andric     const Region *R = RI.R;
1682e3b55780SDimitry Andric     unsigned Duplication = getRegionDuplicationCount(R);
1683e3b55780SDimitry Andric     CHR_DEBUG(dbgs() << "Dup count for R=" << R << "  is " << Duplication
1684e3b55780SDimitry Andric                      << "\n");
1685e3b55780SDimitry Andric     if (Duplication >= CHRDupThreshsold) {
1686e3b55780SDimitry Andric       CHR_DEBUG(dbgs() << "Reached the dup threshold of " << Duplication
1687e3b55780SDimitry Andric                        << " for this region");
1688e3b55780SDimitry Andric       ORE.emit([&]() {
1689e3b55780SDimitry Andric         return OptimizationRemarkMissed(DEBUG_TYPE, "DupThresholdReached",
1690e3b55780SDimitry Andric                                         R->getEntry()->getTerminator())
1691e3b55780SDimitry Andric                << "Reached the duplication threshold for the region";
1692e3b55780SDimitry Andric       });
1693e3b55780SDimitry Andric       return;
1694e3b55780SDimitry Andric     }
1695e3b55780SDimitry Andric   }
1696e3b55780SDimitry Andric   for (RegInfo &RI : Scope->RegInfos) {
1697e3b55780SDimitry Andric     DuplicationCount[RI.R]++;
1698e3b55780SDimitry Andric   }
1699e3b55780SDimitry Andric 
1700d8e91e46SDimitry Andric   Region *FirstRegion = Scope->RegInfos[0].R;
1701d8e91e46SDimitry Andric   BasicBlock *EntryBlock = FirstRegion->getEntry();
1702d8e91e46SDimitry Andric   Region *LastRegion = Scope->RegInfos[Scope->RegInfos.size() - 1].R;
1703d8e91e46SDimitry Andric   BasicBlock *ExitBlock = LastRegion->getExit();
1704e3b55780SDimitry Andric   std::optional<uint64_t> ProfileCount = BFI.getBlockProfileCount(EntryBlock);
1705d8e91e46SDimitry Andric 
1706d8e91e46SDimitry Andric   if (ExitBlock) {
1707d8e91e46SDimitry Andric     // Insert a trivial phi at the exit block (where the CHR hot path and the
1708d8e91e46SDimitry Andric     // cold path merges) for a value that's defined in the scope but used
1709d8e91e46SDimitry Andric     // outside it (meaning it's alive at the exit block). We will add the
1710d8e91e46SDimitry Andric     // incoming values for the CHR cold paths to it below. Without this, we'd
1711d8e91e46SDimitry Andric     // miss updating phi's for such values unless there happens to already be a
1712d8e91e46SDimitry Andric     // phi for that value there.
1713d8e91e46SDimitry Andric     insertTrivialPHIs(Scope, EntryBlock, ExitBlock, TrivialPHIs);
1714d8e91e46SDimitry Andric   }
1715d8e91e46SDimitry Andric 
1716d8e91e46SDimitry Andric   // Split the entry block of the first region. The new block becomes the new
1717d8e91e46SDimitry Andric   // entry block of the first region. The old entry block becomes the block to
1718d8e91e46SDimitry Andric   // insert the CHR branch into. Note DT gets updated. Since DT gets updated
1719d8e91e46SDimitry Andric   // through the split, we update the entry of the first region after the split,
1720d8e91e46SDimitry Andric   // and Region only points to the entry and the exit blocks, rather than
1721d8e91e46SDimitry Andric   // keeping everything in a list or set, the blocks membership and the
1722d8e91e46SDimitry Andric   // entry/exit blocks of the region are still valid after the split.
1723d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "Splitting entry block " << EntryBlock->getName()
1724d8e91e46SDimitry Andric             << " at " << *Scope->BranchInsertPoint << "\n");
1725d8e91e46SDimitry Andric   BasicBlock *NewEntryBlock =
1726d8e91e46SDimitry Andric       SplitBlock(EntryBlock, Scope->BranchInsertPoint, &DT);
1727d8e91e46SDimitry Andric   assert(NewEntryBlock->getSinglePredecessor() == EntryBlock &&
1728d8e91e46SDimitry Andric          "NewEntryBlock's only pred must be EntryBlock");
1729d8e91e46SDimitry Andric   FirstRegion->replaceEntryRecursive(NewEntryBlock);
1730d8e91e46SDimitry Andric   BasicBlock *PreEntryBlock = EntryBlock;
1731d8e91e46SDimitry Andric 
1732d8e91e46SDimitry Andric   ValueToValueMapTy VMap;
1733d8e91e46SDimitry Andric   // Clone the blocks in the scope (excluding the PreEntryBlock) to split into a
1734d8e91e46SDimitry Andric   // hot path (originals) and a cold path (clones) and update the PHIs at the
1735d8e91e46SDimitry Andric   // exit block.
1736d8e91e46SDimitry Andric   cloneScopeBlocks(Scope, PreEntryBlock, ExitBlock, LastRegion, VMap);
1737d8e91e46SDimitry Andric 
1738d8e91e46SDimitry Andric   // Replace the old (placeholder) branch with the new (merged) conditional
1739d8e91e46SDimitry Andric   // branch.
1740d8e91e46SDimitry Andric   BranchInst *MergedBr = createMergedBranch(PreEntryBlock, EntryBlock,
1741d8e91e46SDimitry Andric                                             NewEntryBlock, VMap);
1742d8e91e46SDimitry Andric 
1743d8e91e46SDimitry Andric #ifndef NDEBUG
1744d8e91e46SDimitry Andric   assertCHRRegionsHaveBiasedBranchOrSelect(Scope);
1745d8e91e46SDimitry Andric #endif
1746d8e91e46SDimitry Andric 
1747d8e91e46SDimitry Andric   // Hoist the conditional values of the branches/selects.
1748e6d15924SDimitry Andric   hoistScopeConditions(Scope, PreEntryBlock->getTerminator(), TrivialPHIs, DT);
1749d8e91e46SDimitry Andric 
1750d8e91e46SDimitry Andric #ifndef NDEBUG
1751d8e91e46SDimitry Andric   assertBranchOrSelectConditionHoisted(Scope, PreEntryBlock);
1752d8e91e46SDimitry Andric #endif
1753d8e91e46SDimitry Andric 
1754d8e91e46SDimitry Andric   // Create the combined branch condition and constant-fold the branches/selects
1755d8e91e46SDimitry Andric   // in the hot path.
1756d8e91e46SDimitry Andric   fixupBranchesAndSelects(Scope, PreEntryBlock, MergedBr,
1757145449b1SDimitry Andric                           ProfileCount.value_or(0));
1758d8e91e46SDimitry Andric }
1759d8e91e46SDimitry Andric 
1760d8e91e46SDimitry Andric // A helper for transformScopes. Clone the blocks in the scope (excluding the
1761d8e91e46SDimitry Andric // PreEntryBlock) to split into a hot path and a cold path and update the PHIs
1762d8e91e46SDimitry Andric // at the exit block.
cloneScopeBlocks(CHRScope * Scope,BasicBlock * PreEntryBlock,BasicBlock * ExitBlock,Region * LastRegion,ValueToValueMapTy & VMap)1763d8e91e46SDimitry Andric void CHR::cloneScopeBlocks(CHRScope *Scope,
1764d8e91e46SDimitry Andric                            BasicBlock *PreEntryBlock,
1765d8e91e46SDimitry Andric                            BasicBlock *ExitBlock,
1766d8e91e46SDimitry Andric                            Region *LastRegion,
1767d8e91e46SDimitry Andric                            ValueToValueMapTy &VMap) {
1768d8e91e46SDimitry Andric   // Clone all the blocks. The original blocks will be the hot-path
1769d8e91e46SDimitry Andric   // CHR-optimized code and the cloned blocks will be the original unoptimized
1770d8e91e46SDimitry Andric   // code. This is so that the block pointers from the
1771d8e91e46SDimitry Andric   // CHRScope/Region/RegionInfo can stay valid in pointing to the hot-path code
1772d8e91e46SDimitry Andric   // which CHR should apply to.
1773d8e91e46SDimitry Andric   SmallVector<BasicBlock*, 8> NewBlocks;
1774d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->RegInfos)
1775d8e91e46SDimitry Andric     for (BasicBlock *BB : RI.R->blocks()) { // This includes the blocks in the
1776d8e91e46SDimitry Andric                                             // sub-Scopes.
1777d8e91e46SDimitry Andric       assert(BB != PreEntryBlock && "Don't copy the preetntry block");
1778d8e91e46SDimitry Andric       BasicBlock *NewBB = CloneBasicBlock(BB, VMap, ".nonchr", &F);
1779d8e91e46SDimitry Andric       NewBlocks.push_back(NewBB);
1780d8e91e46SDimitry Andric       VMap[BB] = NewBB;
1781b1c73532SDimitry Andric 
1782b1c73532SDimitry Andric       // Unreachable predecessors will not be cloned and will not have an edge
1783b1c73532SDimitry Andric       // to the cloned block. As such, also remove them from any phi nodes.
1784b1c73532SDimitry Andric       for (PHINode &PN : make_early_inc_range(NewBB->phis()))
1785b1c73532SDimitry Andric         PN.removeIncomingValueIf([&](unsigned Idx) {
1786b1c73532SDimitry Andric           return !DT.isReachableFromEntry(PN.getIncomingBlock(Idx));
1787b1c73532SDimitry Andric         });
1788d8e91e46SDimitry Andric     }
1789d8e91e46SDimitry Andric 
1790d8e91e46SDimitry Andric   // Place the cloned blocks right after the original blocks (right before the
1791d8e91e46SDimitry Andric   // exit block of.)
1792d8e91e46SDimitry Andric   if (ExitBlock)
1793e3b55780SDimitry Andric     F.splice(ExitBlock->getIterator(), &F, NewBlocks[0]->getIterator(),
1794e3b55780SDimitry Andric              F.end());
1795d8e91e46SDimitry Andric 
1796d8e91e46SDimitry Andric   // Update the cloned blocks/instructions to refer to themselves.
1797e3b55780SDimitry Andric   for (BasicBlock *NewBB : NewBlocks)
1798e3b55780SDimitry Andric     for (Instruction &I : *NewBB)
1799d8e91e46SDimitry Andric       RemapInstruction(&I, VMap,
1800d8e91e46SDimitry Andric                        RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
1801d8e91e46SDimitry Andric 
1802d8e91e46SDimitry Andric   // Add the cloned blocks to the PHIs of the exit blocks. ExitBlock is null for
1803d8e91e46SDimitry Andric   // the top-level region but we don't need to add PHIs. The trivial PHIs
1804d8e91e46SDimitry Andric   // inserted above will be updated here.
1805d8e91e46SDimitry Andric   if (ExitBlock)
1806d8e91e46SDimitry Andric     for (PHINode &PN : ExitBlock->phis())
1807d8e91e46SDimitry Andric       for (unsigned I = 0, NumOps = PN.getNumIncomingValues(); I < NumOps;
1808d8e91e46SDimitry Andric            ++I) {
1809d8e91e46SDimitry Andric         BasicBlock *Pred = PN.getIncomingBlock(I);
1810d8e91e46SDimitry Andric         if (LastRegion->contains(Pred)) {
1811d8e91e46SDimitry Andric           Value *V = PN.getIncomingValue(I);
1812d8e91e46SDimitry Andric           auto It = VMap.find(V);
1813d8e91e46SDimitry Andric           if (It != VMap.end()) V = It->second;
1814d8e91e46SDimitry Andric           assert(VMap.find(Pred) != VMap.end() && "Pred must have been cloned");
1815d8e91e46SDimitry Andric           PN.addIncoming(V, cast<BasicBlock>(VMap[Pred]));
1816d8e91e46SDimitry Andric         }
1817d8e91e46SDimitry Andric       }
1818d8e91e46SDimitry Andric }
1819d8e91e46SDimitry Andric 
1820d8e91e46SDimitry Andric // A helper for transformScope. Replace the old (placeholder) branch with the
1821d8e91e46SDimitry Andric // new (merged) conditional branch.
createMergedBranch(BasicBlock * PreEntryBlock,BasicBlock * EntryBlock,BasicBlock * NewEntryBlock,ValueToValueMapTy & VMap)1822d8e91e46SDimitry Andric BranchInst *CHR::createMergedBranch(BasicBlock *PreEntryBlock,
1823d8e91e46SDimitry Andric                                     BasicBlock *EntryBlock,
1824d8e91e46SDimitry Andric                                     BasicBlock *NewEntryBlock,
1825d8e91e46SDimitry Andric                                     ValueToValueMapTy &VMap) {
1826d8e91e46SDimitry Andric   BranchInst *OldBR = cast<BranchInst>(PreEntryBlock->getTerminator());
1827d8e91e46SDimitry Andric   assert(OldBR->isUnconditional() && OldBR->getSuccessor(0) == NewEntryBlock &&
1828d8e91e46SDimitry Andric          "SplitBlock did not work correctly!");
1829d8e91e46SDimitry Andric   assert(NewEntryBlock->getSinglePredecessor() == EntryBlock &&
1830d8e91e46SDimitry Andric          "NewEntryBlock's only pred must be EntryBlock");
1831d8e91e46SDimitry Andric   assert(VMap.find(NewEntryBlock) != VMap.end() &&
1832d8e91e46SDimitry Andric          "NewEntryBlock must have been copied");
1833d8e91e46SDimitry Andric   OldBR->dropAllReferences();
1834d8e91e46SDimitry Andric   OldBR->eraseFromParent();
1835d8e91e46SDimitry Andric   // The true predicate is a placeholder. It will be replaced later in
1836d8e91e46SDimitry Andric   // fixupBranchesAndSelects().
1837d8e91e46SDimitry Andric   BranchInst *NewBR = BranchInst::Create(NewEntryBlock,
1838d8e91e46SDimitry Andric                                          cast<BasicBlock>(VMap[NewEntryBlock]),
1839d8e91e46SDimitry Andric                                          ConstantInt::getTrue(F.getContext()));
1840e3b55780SDimitry Andric   NewBR->insertInto(PreEntryBlock, PreEntryBlock->end());
1841d8e91e46SDimitry Andric   assert(NewEntryBlock->getSinglePredecessor() == EntryBlock &&
1842d8e91e46SDimitry Andric          "NewEntryBlock's only pred must be EntryBlock");
1843d8e91e46SDimitry Andric   return NewBR;
1844d8e91e46SDimitry Andric }
1845d8e91e46SDimitry Andric 
1846d8e91e46SDimitry Andric // A helper for transformScopes. Create the combined branch condition and
1847d8e91e46SDimitry Andric // constant-fold the branches/selects in the hot path.
fixupBranchesAndSelects(CHRScope * Scope,BasicBlock * PreEntryBlock,BranchInst * MergedBR,uint64_t ProfileCount)1848d8e91e46SDimitry Andric void CHR::fixupBranchesAndSelects(CHRScope *Scope,
1849d8e91e46SDimitry Andric                                   BasicBlock *PreEntryBlock,
1850d8e91e46SDimitry Andric                                   BranchInst *MergedBR,
1851d8e91e46SDimitry Andric                                   uint64_t ProfileCount) {
1852d8e91e46SDimitry Andric   Value *MergedCondition = ConstantInt::getTrue(F.getContext());
1853d8e91e46SDimitry Andric   BranchProbability CHRBranchBias(1, 1);
1854d8e91e46SDimitry Andric   uint64_t NumCHRedBranches = 0;
1855d8e91e46SDimitry Andric   IRBuilder<> IRB(PreEntryBlock->getTerminator());
1856d8e91e46SDimitry Andric   for (RegInfo &RI : Scope->CHRRegions) {
1857d8e91e46SDimitry Andric     Region *R = RI.R;
1858d8e91e46SDimitry Andric     if (RI.HasBranch) {
1859d8e91e46SDimitry Andric       fixupBranch(R, Scope, IRB, MergedCondition, CHRBranchBias);
1860d8e91e46SDimitry Andric       ++NumCHRedBranches;
1861d8e91e46SDimitry Andric     }
1862d8e91e46SDimitry Andric     for (SelectInst *SI : RI.Selects) {
1863d8e91e46SDimitry Andric       fixupSelect(SI, Scope, IRB, MergedCondition, CHRBranchBias);
1864d8e91e46SDimitry Andric       ++NumCHRedBranches;
1865d8e91e46SDimitry Andric     }
1866d8e91e46SDimitry Andric   }
1867d8e91e46SDimitry Andric   Stats.NumBranchesDelta += NumCHRedBranches - 1;
1868d8e91e46SDimitry Andric   Stats.WeightedNumBranchesDelta += (NumCHRedBranches - 1) * ProfileCount;
1869d8e91e46SDimitry Andric   ORE.emit([&]() {
1870d8e91e46SDimitry Andric     return OptimizationRemark(DEBUG_TYPE,
1871d8e91e46SDimitry Andric                               "CHR",
1872d8e91e46SDimitry Andric                               // Refer to the hot (original) path
1873d8e91e46SDimitry Andric                               MergedBR->getSuccessor(0)->getTerminator())
1874d8e91e46SDimitry Andric         << "Merged " << ore::NV("NumCHRedBranches", NumCHRedBranches)
1875d8e91e46SDimitry Andric         << " branches or selects";
1876d8e91e46SDimitry Andric   });
1877d8e91e46SDimitry Andric   MergedBR->setCondition(MergedCondition);
1878cfca06d7SDimitry Andric   uint32_t Weights[] = {
1879cfca06d7SDimitry Andric       static_cast<uint32_t>(CHRBranchBias.scale(1000)),
1880cfca06d7SDimitry Andric       static_cast<uint32_t>(CHRBranchBias.getCompl().scale(1000)),
1881cfca06d7SDimitry Andric   };
1882ac9a064cSDimitry Andric   setBranchWeights(*MergedBR, Weights, /*IsExpected=*/false);
1883d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "CHR branch bias " << Weights[0] << ":" << Weights[1]
1884d8e91e46SDimitry Andric             << "\n");
1885d8e91e46SDimitry Andric }
1886d8e91e46SDimitry Andric 
1887d8e91e46SDimitry Andric // A helper for fixupBranchesAndSelects. Add to the combined branch condition
1888d8e91e46SDimitry Andric // and constant-fold a branch in the hot path.
fixupBranch(Region * R,CHRScope * Scope,IRBuilder<> & IRB,Value * & MergedCondition,BranchProbability & CHRBranchBias)1889d8e91e46SDimitry Andric void CHR::fixupBranch(Region *R, CHRScope *Scope,
1890d8e91e46SDimitry Andric                       IRBuilder<> &IRB,
1891d8e91e46SDimitry Andric                       Value *&MergedCondition,
1892d8e91e46SDimitry Andric                       BranchProbability &CHRBranchBias) {
1893d8e91e46SDimitry Andric   bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
1894d8e91e46SDimitry Andric   assert((IsTrueBiased || Scope->FalseBiasedRegions.count(R)) &&
1895d8e91e46SDimitry Andric          "Must be truthy or falsy");
1896d8e91e46SDimitry Andric   auto *BI = cast<BranchInst>(R->getEntry()->getTerminator());
18977fa27ce4SDimitry Andric   assert(BranchBiasMap.contains(R) && "Must be in the bias map");
1898d8e91e46SDimitry Andric   BranchProbability Bias = BranchBiasMap[R];
1899d8e91e46SDimitry Andric   assert(Bias >= getCHRBiasThreshold() && "Must be highly biased");
1900d8e91e46SDimitry Andric   // Take the min.
1901d8e91e46SDimitry Andric   if (CHRBranchBias > Bias)
1902d8e91e46SDimitry Andric     CHRBranchBias = Bias;
1903d8e91e46SDimitry Andric   BasicBlock *IfThen = BI->getSuccessor(1);
1904d8e91e46SDimitry Andric   BasicBlock *IfElse = BI->getSuccessor(0);
1905d8e91e46SDimitry Andric   BasicBlock *RegionExitBlock = R->getExit();
1906d8e91e46SDimitry Andric   assert(RegionExitBlock && "Null ExitBlock");
1907d8e91e46SDimitry Andric   assert((IfThen == RegionExitBlock || IfElse == RegionExitBlock) &&
1908d8e91e46SDimitry Andric          IfThen != IfElse && "Invariant from findScopes");
1909d8e91e46SDimitry Andric   if (IfThen == RegionExitBlock) {
1910d8e91e46SDimitry Andric     // Swap them so that IfThen means going into it and IfElse means skipping
1911d8e91e46SDimitry Andric     // it.
1912d8e91e46SDimitry Andric     std::swap(IfThen, IfElse);
1913d8e91e46SDimitry Andric   }
1914d8e91e46SDimitry Andric   CHR_DEBUG(dbgs() << "IfThen " << IfThen->getName()
1915d8e91e46SDimitry Andric             << " IfElse " << IfElse->getName() << "\n");
1916d8e91e46SDimitry Andric   Value *Cond = BI->getCondition();
1917d8e91e46SDimitry Andric   BasicBlock *HotTarget = IsTrueBiased ? IfThen : IfElse;
1918d8e91e46SDimitry Andric   bool ConditionTrue = HotTarget == BI->getSuccessor(0);
1919d8e91e46SDimitry Andric   addToMergedCondition(ConditionTrue, Cond, BI, Scope, IRB,
1920d8e91e46SDimitry Andric                        MergedCondition);
1921d8e91e46SDimitry Andric   // Constant-fold the branch at ClonedEntryBlock.
1922d8e91e46SDimitry Andric   assert(ConditionTrue == (HotTarget == BI->getSuccessor(0)) &&
1923d8e91e46SDimitry Andric          "The successor shouldn't change");
1924d8e91e46SDimitry Andric   Value *NewCondition = ConditionTrue ?
1925d8e91e46SDimitry Andric                         ConstantInt::getTrue(F.getContext()) :
1926d8e91e46SDimitry Andric                         ConstantInt::getFalse(F.getContext());
1927d8e91e46SDimitry Andric   BI->setCondition(NewCondition);
1928d8e91e46SDimitry Andric }
1929d8e91e46SDimitry Andric 
1930d8e91e46SDimitry Andric // A helper for fixupBranchesAndSelects. Add to the combined branch condition
1931d8e91e46SDimitry Andric // and constant-fold a select in the hot path.
fixupSelect(SelectInst * SI,CHRScope * Scope,IRBuilder<> & IRB,Value * & MergedCondition,BranchProbability & CHRBranchBias)1932d8e91e46SDimitry Andric void CHR::fixupSelect(SelectInst *SI, CHRScope *Scope,
1933d8e91e46SDimitry Andric                       IRBuilder<> &IRB,
1934d8e91e46SDimitry Andric                       Value *&MergedCondition,
1935d8e91e46SDimitry Andric                       BranchProbability &CHRBranchBias) {
1936d8e91e46SDimitry Andric   bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
1937d8e91e46SDimitry Andric   assert((IsTrueBiased ||
1938d8e91e46SDimitry Andric           Scope->FalseBiasedSelects.count(SI)) && "Must be biased");
19397fa27ce4SDimitry Andric   assert(SelectBiasMap.contains(SI) && "Must be in the bias map");
1940d8e91e46SDimitry Andric   BranchProbability Bias = SelectBiasMap[SI];
1941d8e91e46SDimitry Andric   assert(Bias >= getCHRBiasThreshold() && "Must be highly biased");
1942d8e91e46SDimitry Andric   // Take the min.
1943d8e91e46SDimitry Andric   if (CHRBranchBias > Bias)
1944d8e91e46SDimitry Andric     CHRBranchBias = Bias;
1945d8e91e46SDimitry Andric   Value *Cond = SI->getCondition();
1946d8e91e46SDimitry Andric   addToMergedCondition(IsTrueBiased, Cond, SI, Scope, IRB,
1947d8e91e46SDimitry Andric                        MergedCondition);
1948d8e91e46SDimitry Andric   Value *NewCondition = IsTrueBiased ?
1949d8e91e46SDimitry Andric                         ConstantInt::getTrue(F.getContext()) :
1950d8e91e46SDimitry Andric                         ConstantInt::getFalse(F.getContext());
1951d8e91e46SDimitry Andric   SI->setCondition(NewCondition);
1952d8e91e46SDimitry Andric }
1953d8e91e46SDimitry Andric 
1954d8e91e46SDimitry Andric // A helper for fixupBranch/fixupSelect. Add a branch condition to the merged
1955d8e91e46SDimitry Andric // condition.
addToMergedCondition(bool IsTrueBiased,Value * Cond,Instruction * BranchOrSelect,CHRScope * Scope,IRBuilder<> & IRB,Value * & MergedCondition)1956d8e91e46SDimitry Andric void CHR::addToMergedCondition(bool IsTrueBiased, Value *Cond,
1957145449b1SDimitry Andric                                Instruction *BranchOrSelect, CHRScope *Scope,
1958145449b1SDimitry Andric                                IRBuilder<> &IRB, Value *&MergedCondition) {
1959145449b1SDimitry Andric   if (!IsTrueBiased) {
1960d8e91e46SDimitry Andric     // If Cond is an icmp and all users of V except for BranchOrSelect is a
1961d8e91e46SDimitry Andric     // branch, negate the icmp predicate and swap the branch targets and avoid
1962d8e91e46SDimitry Andric     // inserting an Xor to negate Cond.
1963145449b1SDimitry Andric     auto *ICmp = dyn_cast<ICmpInst>(Cond);
1964145449b1SDimitry Andric     if (!ICmp ||
1965145449b1SDimitry Andric         !negateICmpIfUsedByBranchOrSelectOnly(ICmp, BranchOrSelect, Scope))
1966145449b1SDimitry Andric       Cond = IRB.CreateXor(ConstantInt::getTrue(F.getContext()), Cond);
1967d8e91e46SDimitry Andric   }
1968145449b1SDimitry Andric 
19697fa27ce4SDimitry Andric   // Freeze potentially poisonous conditions.
19707fa27ce4SDimitry Andric   if (!isGuaranteedNotToBeUndefOrPoison(Cond))
1971145449b1SDimitry Andric     Cond = IRB.CreateFreeze(Cond);
1972145449b1SDimitry Andric 
1973145449b1SDimitry Andric   // Use logical and to avoid propagating poison from later conditions.
1974145449b1SDimitry Andric   MergedCondition = IRB.CreateLogicalAnd(MergedCondition, Cond);
1975d8e91e46SDimitry Andric }
1976d8e91e46SDimitry Andric 
transformScopes(SmallVectorImpl<CHRScope * > & CHRScopes)1977d8e91e46SDimitry Andric void CHR::transformScopes(SmallVectorImpl<CHRScope *> &CHRScopes) {
1978d8e91e46SDimitry Andric   unsigned I = 0;
1979d8e91e46SDimitry Andric   DenseSet<PHINode *> TrivialPHIs;
1980d8e91e46SDimitry Andric   for (CHRScope *Scope : CHRScopes) {
1981d8e91e46SDimitry Andric     transformScopes(Scope, TrivialPHIs);
1982d8e91e46SDimitry Andric     CHR_DEBUG(
1983d8e91e46SDimitry Andric         std::ostringstream oss;
1984d8e91e46SDimitry Andric         oss << " after transformScopes " << I++;
1985d8e91e46SDimitry Andric         dumpIR(F, oss.str().c_str(), nullptr));
1986d8e91e46SDimitry Andric     (void)I;
1987d8e91e46SDimitry Andric   }
1988d8e91e46SDimitry Andric }
1989d8e91e46SDimitry Andric 
1990d8e91e46SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED
dumpScopes(SmallVectorImpl<CHRScope * > & Scopes,const char * Label)1991d8e91e46SDimitry Andric dumpScopes(SmallVectorImpl<CHRScope *> &Scopes, const char *Label) {
1992d8e91e46SDimitry Andric   dbgs() << Label << " " << Scopes.size() << "\n";
1993d8e91e46SDimitry Andric   for (CHRScope *Scope : Scopes) {
1994d8e91e46SDimitry Andric     dbgs() << *Scope << "\n";
1995d8e91e46SDimitry Andric   }
1996d8e91e46SDimitry Andric }
1997d8e91e46SDimitry Andric 
run()1998d8e91e46SDimitry Andric bool CHR::run() {
1999d8e91e46SDimitry Andric   if (!shouldApply(F, PSI))
2000d8e91e46SDimitry Andric     return false;
2001d8e91e46SDimitry Andric 
2002d8e91e46SDimitry Andric   CHR_DEBUG(dumpIR(F, "before", nullptr));
2003d8e91e46SDimitry Andric 
2004d8e91e46SDimitry Andric   bool Changed = false;
2005d8e91e46SDimitry Andric   {
2006d8e91e46SDimitry Andric     CHR_DEBUG(
2007d8e91e46SDimitry Andric         dbgs() << "RegionInfo:\n";
2008d8e91e46SDimitry Andric         RI.print(dbgs()));
2009d8e91e46SDimitry Andric 
2010d8e91e46SDimitry Andric     // Recursively traverse the region tree and find regions that have biased
2011d8e91e46SDimitry Andric     // branches and/or selects and create scopes.
2012d8e91e46SDimitry Andric     SmallVector<CHRScope *, 8> AllScopes;
2013d8e91e46SDimitry Andric     findScopes(AllScopes);
2014d8e91e46SDimitry Andric     CHR_DEBUG(dumpScopes(AllScopes, "All scopes"));
2015d8e91e46SDimitry Andric 
2016e3b55780SDimitry Andric     // Split the scopes if 1) the conditional values of the biased
2017d8e91e46SDimitry Andric     // branches/selects of the inner/lower scope can't be hoisted up to the
2018d8e91e46SDimitry Andric     // outermost/uppermost scope entry, or 2) the condition values of the biased
2019d8e91e46SDimitry Andric     // branches/selects in a scope (including subscopes) don't share at least
2020d8e91e46SDimitry Andric     // one common value.
2021d8e91e46SDimitry Andric     SmallVector<CHRScope *, 8> SplitScopes;
2022d8e91e46SDimitry Andric     splitScopes(AllScopes, SplitScopes);
2023d8e91e46SDimitry Andric     CHR_DEBUG(dumpScopes(SplitScopes, "Split scopes"));
2024d8e91e46SDimitry Andric 
2025d8e91e46SDimitry Andric     // After splitting, set the biased regions and selects of a scope (a tree
2026d8e91e46SDimitry Andric     // root) that include those of the subscopes.
2027d8e91e46SDimitry Andric     classifyBiasedScopes(SplitScopes);
2028d8e91e46SDimitry Andric     CHR_DEBUG(dbgs() << "Set per-scope bias " << SplitScopes.size() << "\n");
2029d8e91e46SDimitry Andric 
2030d8e91e46SDimitry Andric     // Filter out the scopes that has only one biased region or select (CHR
2031d8e91e46SDimitry Andric     // isn't useful in such a case).
2032d8e91e46SDimitry Andric     SmallVector<CHRScope *, 8> FilteredScopes;
2033d8e91e46SDimitry Andric     filterScopes(SplitScopes, FilteredScopes);
2034d8e91e46SDimitry Andric     CHR_DEBUG(dumpScopes(FilteredScopes, "Filtered scopes"));
2035d8e91e46SDimitry Andric 
2036d8e91e46SDimitry Andric     // Set the regions to be CHR'ed and their hoist stops for each scope.
2037d8e91e46SDimitry Andric     SmallVector<CHRScope *, 8> SetScopes;
2038d8e91e46SDimitry Andric     setCHRRegions(FilteredScopes, SetScopes);
2039d8e91e46SDimitry Andric     CHR_DEBUG(dumpScopes(SetScopes, "Set CHR regions"));
2040d8e91e46SDimitry Andric 
2041d8e91e46SDimitry Andric     // Sort CHRScopes by the depth so that outer CHRScopes comes before inner
2042d8e91e46SDimitry Andric     // ones. We need to apply CHR from outer to inner so that we apply CHR only
2043d8e91e46SDimitry Andric     // to the hot path, rather than both hot and cold paths.
2044d8e91e46SDimitry Andric     SmallVector<CHRScope *, 8> SortedScopes;
2045d8e91e46SDimitry Andric     sortScopes(SetScopes, SortedScopes);
2046d8e91e46SDimitry Andric     CHR_DEBUG(dumpScopes(SortedScopes, "Sorted scopes"));
2047d8e91e46SDimitry Andric 
2048d8e91e46SDimitry Andric     CHR_DEBUG(
2049d8e91e46SDimitry Andric         dbgs() << "RegionInfo:\n";
2050d8e91e46SDimitry Andric         RI.print(dbgs()));
2051d8e91e46SDimitry Andric 
2052d8e91e46SDimitry Andric     // Apply the CHR transformation.
2053d8e91e46SDimitry Andric     if (!SortedScopes.empty()) {
2054d8e91e46SDimitry Andric       transformScopes(SortedScopes);
2055d8e91e46SDimitry Andric       Changed = true;
2056d8e91e46SDimitry Andric     }
2057d8e91e46SDimitry Andric   }
2058d8e91e46SDimitry Andric 
2059d8e91e46SDimitry Andric   if (Changed) {
2060d8e91e46SDimitry Andric     CHR_DEBUG(dumpIR(F, "after", &Stats));
2061d8e91e46SDimitry Andric     ORE.emit([&]() {
2062d8e91e46SDimitry Andric       return OptimizationRemark(DEBUG_TYPE, "Stats", &F)
2063d8e91e46SDimitry Andric           << ore::NV("Function", &F) << " "
2064d8e91e46SDimitry Andric           << "Reduced the number of branches in hot paths by "
2065d8e91e46SDimitry Andric           << ore::NV("NumBranchesDelta", Stats.NumBranchesDelta)
2066d8e91e46SDimitry Andric           << " (static) and "
2067d8e91e46SDimitry Andric           << ore::NV("WeightedNumBranchesDelta", Stats.WeightedNumBranchesDelta)
2068d8e91e46SDimitry Andric           << " (weighted by PGO count)";
2069d8e91e46SDimitry Andric     });
2070d8e91e46SDimitry Andric   }
2071d8e91e46SDimitry Andric 
2072d8e91e46SDimitry Andric   return Changed;
2073d8e91e46SDimitry Andric }
2074d8e91e46SDimitry Andric 
2075d8e91e46SDimitry Andric namespace llvm {
2076d8e91e46SDimitry Andric 
ControlHeightReductionPass()2077d8e91e46SDimitry Andric ControlHeightReductionPass::ControlHeightReductionPass() {
2078d8e91e46SDimitry Andric   parseCHRFilterFiles();
2079d8e91e46SDimitry Andric }
2080d8e91e46SDimitry Andric 
run(Function & F,FunctionAnalysisManager & FAM)2081d8e91e46SDimitry Andric PreservedAnalyses ControlHeightReductionPass::run(
2082d8e91e46SDimitry Andric     Function &F,
2083d8e91e46SDimitry Andric     FunctionAnalysisManager &FAM) {
20847fa27ce4SDimitry Andric   auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
20857fa27ce4SDimitry Andric   auto PPSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
20867fa27ce4SDimitry Andric   // If there is no profile summary, we should not do CHR.
20877fa27ce4SDimitry Andric   if (!PPSI || !PPSI->hasProfileSummary())
20887fa27ce4SDimitry Andric     return PreservedAnalyses::all();
20897fa27ce4SDimitry Andric   auto &PSI = *PPSI;
2090d8e91e46SDimitry Andric   auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
2091d8e91e46SDimitry Andric   auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2092d8e91e46SDimitry Andric   auto &RI = FAM.getResult<RegionInfoAnalysis>(F);
2093d8e91e46SDimitry Andric   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
2094d8e91e46SDimitry Andric   bool Changed = CHR(F, BFI, DT, PSI, RI, ORE).run();
2095d8e91e46SDimitry Andric   if (!Changed)
2096d8e91e46SDimitry Andric     return PreservedAnalyses::all();
2097344a3780SDimitry Andric   return PreservedAnalyses::none();
2098d8e91e46SDimitry Andric }
2099d8e91e46SDimitry Andric 
2100d8e91e46SDimitry Andric } // namespace llvm
2101