53#define DEBUG_TYPE "loopsink"
55STATISTIC(NumLoopSunk,
"Number of instructions sunk into loop");
56STATISTIC(NumLoopSunkCloned,
"Number of cloned instructions sunk into loop");
60 cl::desc(
"Do not sink instructions that require cloning unless they "
61 "execute less than this percent of the time."));
65 cl::desc(
"Do not sink instructions that have too many uses."));
84 T += BFI.getBlockFreq(
B);
122 if (UseBBs.
size() == 0)
123 return BBsToSinkInto;
137 BBsDominatedByColdestBB.
clear();
140 BBsDominatedByColdestBB.
insert(SinkedBB);
141 if (BBsDominatedByColdestBB.
size() == 0)
144 BFI.getBlockFreq(ColdestBB)) {
145 for (
BasicBlock *DominatedBB : BBsDominatedByColdestBB) {
146 BBsToSinkInto.erase(DominatedBB);
148 BBsToSinkInto.insert(ColdestBB);
154 if (BB->getFirstInsertionPt() == BB->end()) {
155 BBsToSinkInto.
clear();
163 BFI.getBlockFreq(L.getLoopPreheader()))
164 BBsToSinkInto.
clear();
165 return BBsToSinkInto;
178 for (
auto &U :
I.uses()) {
185 if (!isa<PHINode>(UI)) {
192 PHINode *PN = dyn_cast<PHINode>(UI);
197 if (L.getLoopPreheader() == PhiBB)
212 if (BBsToSinkInto.
empty())
216 if (BBsToSinkInto.
size() > 1 &&
225 if (SortedBBsToSinkInto.
size() > 1) {
227 return LoopBlockNumber.
find(
A)->second < LoopBlockNumber.
find(
B)->second;
236 LoopBlockNumber.
find(MoveBB)->second &&
248 if (
auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
251 auto *MemUse = cast<MemoryUse>(NewMemAcc);
259 I.replaceUsesWithIf(IC, [
N](
Use &U) {
260 Instruction *UIToReplace = cast<Instruction>(U.getUser());
261 return UIToReplace->
getParent() ==
N && !isa<PHINode>(UIToReplace);
289 assert(Preheader &&
"Expected loop to have preheader");
292 "Unexpected call when profile data unavailable.");
299 return BFI.getBlockFreq(BB) > PreheaderFreq;
306 bool Changed =
false;
313 if (BFI.getBlockFreq(
B) < BFI.getBlockFreq(L.getLoopPreheader())) {
315 LoopBlockNumber[
B] = ++i;
318 return BFI.getBlockFreq(
A) < BFI.getBlockFreq(
B);
325 if (isa<PHINode>(&
I))
328 assert(L.hasLoopInvariantOperands(&
I) &&
329 "Insts in a loop's preheader should have loop invariant operands!");
346 if (!
F.hasProfileData())
366 bool Changed =
false;
379 }
while (!PreorderLoops.
empty());
389 MSSA.verifyMemorySSA();
395struct LegacyLoopSinkPass :
public LoopPass {
405 BasicBlock *Preheader = L->getLoopPreheader();
414 AAResults &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
415 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
416 auto *SE = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>();
418 *L, AA, getAnalysis<LoopInfoWrapperPass>().getLoopInfo(),
419 getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
420 getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI(),
421 MSSA, SE ? &SE->getSE() :
nullptr);
439char LegacyLoopSinkPass::ID = 0;
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE)
When an instruction is found to only be used outside of the loop, this function moves it to the exit ...
static cl::opt< unsigned > SinkFrequencyPercentThreshold("sink-freq-percent-threshold", cl::Hidden, cl::init(90), cl::desc("Do not sink instructions that require cloning unless they " "execute less than this percent of the time."))
static bool sinkInstruction(Loop &L, Instruction &I, const SmallVectorImpl< BasicBlock * > &ColdLoopBBs, const SmallDenseMap< BasicBlock *, int, 16 > &LoopBlockNumber, LoopInfo &LI, DominatorTree &DT, BlockFrequencyInfo &BFI, MemorySSAUpdater *MSSAU)
static SmallPtrSet< BasicBlock *, 2 > findBBsToSinkInto(const Loop &L, const SmallPtrSetImpl< BasicBlock * > &UseBBs, const SmallVectorImpl< BasicBlock * > &ColdLoopBBs, DominatorTree &DT, BlockFrequencyInfo &BFI)
Return a set of basic blocks to insert sinked instructions.
static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI, DominatorTree &DT, BlockFrequencyInfo &BFI, MemorySSA &MSSA, ScalarEvolution *SE)
Sinks instructions from loop's preheader to the loop body if the sum frequency of inserted copy is sm...
static BlockFrequency adjustedSumFreq(SmallPtrSetImpl< BasicBlock * > &BBs, BlockFrequencyInfo &BFI)
Return adjusted total frequency of BBs.
static cl::opt< unsigned > MaxNumberOfUseBBsForSinking("max-uses-for-sinking", cl::Hidden, cl::init(30), cl::desc("Do not sink instructions that have too many uses."))
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines generic set operations that may be used on set's of different types,...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A manager for alias analyses.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
Analysis pass which computes BlockFrequencyInfo.
Legacy analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Represents analyses that only rely on functions' control flow.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
const BasicBlock * getParent() const
Analysis pass that exposes the LoopInfo for a function.
SmallVector< LoopT *, 4 > getLoopsInPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in forward p...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Represents a single loop in the control flow graph.
An analysis that produces MemorySSA for a function.
MemorySSA * getMemorySSA() const
Get handle on MemorySSA.
void insertDef(MemoryDef *Def, bool RenameUses=false)
Insert a definition into the MemorySSA IR.
MemoryAccess * createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition, const BasicBlock *BB, MemorySSA::InsertionPlace Point)
Create a MemoryAccess in MemorySSA at a specified point in a block.
void insertUse(MemoryUse *Use, bool RenameUses=false)
void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB, MemorySSA::InsertionPlace Where)
Legacy analysis pass which computes MemorySSA.
Encapsulates MemorySSA, including all data associated with memory accesses.
void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
Class that has the common methods + fields of memory uses/defs.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
The main scalar evolution driver.
void forgetBlockAndLoopDispositions(Value *V=nullptr)
Called when the client has changed the disposition of values in a loop or block.
Flags controlling how much is checked when sinking or hoisting instructions.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
void setName(const Twine &Name)
Change the name of the value.
StringRef getName() const
Return a constant reference to the value's name.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, Loop *CurLoop, MemorySSAUpdater &MSSAU, bool TargetExecutesOncePerLoop, SinkAndHoistLICMFlags &LICMFlags, OptimizationRemarkEmitter *ORE=nullptr)
Returns true if is legal to hoist or sink this instruction disregarding the possible introduction of ...
bool set_is_subset(const S1Ty &S1, const S2Ty &S2)
set_is_subset(A, B) - Return true iff A in B
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge)
Replace each use of 'From' with 'To' if that use is dominated by the given edge.
void initializeLegacyLoopSinkPassPass(PassRegistry &)
void getLoopAnalysisUsage(AnalysisUsage &AU)
Helper to consistently add the set of standard passes to a loop pass's AnalysisUsage.
bool VerifyMemorySSA
Enables verification of MemorySSA.
Pass * createLoopSinkPass()