61#define DEBUG_TYPE "loop-unroll-and-jam"
63STATISTIC(NumUnrolledAndJammed,
"Number of loops unroll and jammed");
64STATISTIC(NumCompletelyUnrolledAndJammed,
"Number of loops unroll and jammed");
72 Loop *SubLoop = L.getSubLoops()[0];
88 if (BB == SubLoopPreHeader)
92 if (!ForeBlocks.
count(Succ))
143 if (!VisitedInstr.
insert(
I).second)
146 if (AftBlocks.
count(
I->getParent()))
147 for (
auto &U :
I->operands())
149 if (!ProcessInstr(
II))
155 for (
auto &Phi : Header->phis()) {
156 Value *V = Phi.getIncomingValueForBlock(Latch);
158 if (!ProcessInstr(
I))
174 if (AftBlocks.
count(
I->getParent()))
175 I->moveBefore(InsertLoc);
216 unsigned TripMultiple,
bool UnrollRemainder,
223 assert(Header &&
"No header.");
224 assert(L->getSubLoops().size() == 1);
225 Loop *SubLoop = *L->begin();
228 if (TripCount == 0 && Count < 2) {
229 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; almost nothing to do\n");
230 return LoopUnrollResult::Unmodified;
235 assert(TripCount == 0 || TripCount % TripMultiple == 0);
238 bool CompletelyUnroll = (Count == TripCount);
241 if (TripMultiple % Count != 0) {
244 UnrollRemainder,
false,
245 LI, SE, DT, AC,
TTI,
true,
247 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; remainder loop could not be "
248 "generated when assuming runtime trip count\n");
249 return LoopUnrollResult::Unmodified;
262 if (CompletelyUnroll) {
264 << Header->getName() <<
" with trip count " << TripCount
268 <<
"completely unroll and jammed loop with "
269 << NV(
"UnrollCount", TripCount) <<
" iterations");
271 auto DiagBuilder = [&]() {
274 return Diag <<
"unroll and jammed loop by a factor of "
275 << NV(
"UnrollCount", Count);
278 LLVM_DEBUG(
dbgs() <<
"UNROLL AND JAMMING loop %" << Header->getName()
280 if (TripMultiple != 1) {
281 LLVM_DEBUG(
dbgs() <<
" with " << TripMultiple <<
" trips per branch");
283 return DiagBuilder() <<
" with " << NV(
"TripMultiple", TripMultiple)
284 <<
" trips per branch";
288 ORE->
emit([&]() {
return DiagBuilder() <<
" with run-time trip count"; });
293 BasicBlock *Preheader = L->getLoopPreheader();
295 assert(Preheader &&
"No preheader");
296 assert(LatchBlock &&
"No latch block");
301 bool SubLoopContinueOnTrue = SubLoop->
contains(
315 std::vector<BasicBlock *> ForeBlocksFirst;
316 std::vector<BasicBlock *> ForeBlocksLast;
317 std::vector<BasicBlock *> SubLoopBlocksFirst;
318 std::vector<BasicBlock *> SubLoopBlocksLast;
319 std::vector<BasicBlock *> AftBlocksFirst;
320 std::vector<BasicBlock *> AftBlocksLast;
321 ForeBlocksFirst.push_back(Header);
323 SubLoopBlocksFirst.push_back(SubLoop->
getHeader());
326 AftBlocksLast.push_back(L->getExitingBlock());
332 Header, LatchBlock, ForeBlocksLast[0]->getTerminator(), AftBlocks);
345 if (Header->getParent()->shouldEmitDebugInfoForProfiling() &&
349 if (!
I.isDebugOrPseudoInst())
351 auto NewDIL = DIL->cloneByMultiplyingDuplicationFactor(Count);
353 I.setDebugLoc(*NewDIL);
356 <<
"Failed to create new discriminator: "
357 << DIL->getFilename() <<
" Line: " << DIL->getLine());
361 for (
unsigned It = 1; It != Count; ++It) {
367 NewLoops[SubLoop] = SubLoop;
372 Header->getParent()->insert(Header->getParent()->end(), New);
377 if (ForeBlocks.
count(*BB)) {
378 if (*BB == ForeBlocksFirst[0])
379 ForeBlocksFirst.push_back(New);
380 if (*BB == ForeBlocksLast[0])
381 ForeBlocksLast.push_back(New);
382 }
else if (SubLoopBlocks.
count(*BB)) {
383 if (*BB == SubLoopBlocksFirst[0])
384 SubLoopBlocksFirst.push_back(New);
385 if (*BB == SubLoopBlocksLast[0])
386 SubLoopBlocksLast.push_back(New);
387 }
else if (AftBlocks.
count(*BB)) {
388 if (*BB == AftBlocksFirst[0])
389 AftBlocksFirst.push_back(New);
390 if (*BB == AftBlocksLast[0])
391 AftBlocksLast.push_back(New);
397 PrevItValueMap[New] = (It == 1 ? *BB : LastValueMap[*BB]);
398 LastValueMap[*BB] = New;
401 PrevItValueMap[VI->second] =
402 const_cast<Value *
>(It == 1 ? VI->first : LastValueMap[VI->first]);
403 LastValueMap[VI->first] = VI->second;
409 if (*BB == ForeBlocksFirst[0])
411 else if (*BB == SubLoopBlocksFirst[0])
413 else if (*BB == AftBlocksFirst[0])
418 auto BBDomNode = DT->
getNode(*BB);
419 auto BBIDom = BBDomNode->
getIDom();
420 BasicBlock *OriginalBBIDom = BBIDom->getBlock();
422 assert(LastValueMap[cast<Value>(OriginalBBIDom)]);
424 New, cast<BasicBlock>(LastValueMap[cast<Value>(OriginalBBIDom)]));
432 if (
auto *
II = dyn_cast<AssumeInst>(&
I))
439 for (
PHINode &Phi : ForeBlocksFirst[It]->phis()) {
440 Value *OldValue = Phi.getIncomingValueForBlock(AftBlocksLast[It]);
441 assert(OldValue &&
"should have incoming edge from Aft[It]");
442 Value *NewValue = OldValue;
443 if (
Value *PrevValue = PrevItValueMap[OldValue])
444 NewValue = PrevValue;
446 assert(Phi.getNumOperands() == 2);
447 Phi.setIncomingBlock(0, ForeBlocksLast[It - 1]);
448 Phi.setIncomingValue(0, NewValue);
449 Phi.removeIncomingValue(1);
462 for (
PHINode &Phi : BB->phis()) {
463 for (
unsigned b = 0; b < Phi.getNumIncomingValues(); ++b) {
464 if (Phi.getIncomingBlock(b) == OldBB) {
465 Value *OldValue = Phi.getIncomingValue(b);
466 if (
Value *LastValue = LastValueMap[OldValue])
467 Phi.setIncomingValue(b, LastValue);
468 Phi.setIncomingBlock(b, NewBB);
477 while (
PHINode *Phi = dyn_cast<PHINode>(Src->begin()))
478 Phi->moveBefore(*Dest, insertPoint);
482 updatePHIBlocksAndValues(LoopExit, AftBlocksLast[0], AftBlocksLast.
back(),
487 cast<BranchInst>(ForeBlocksLast.back()->getTerminator());
491 if (CompletelyUnroll) {
492 while (
PHINode *Phi = dyn_cast<PHINode>(ForeBlocksFirst[0]->begin())) {
493 Phi->replaceAllUsesWith(Phi->getIncomingValueForBlock(Preheader));
494 Phi->eraseFromParent();
498 updatePHIBlocksAndValues(ForeBlocksFirst[0], AftBlocksLast[0],
499 AftBlocksLast.back(), LastValueMap);
502 for (
unsigned It = 1; It != Count; It++) {
505 cast<BranchInst>(ForeBlocksLast[It - 1]->getTerminator());
512 cast<BranchInst>(SubLoopBlocksLast.back()->getTerminator());
513 SubTerm->
setSuccessor(!SubLoopContinueOnTrue, SubLoopBlocksFirst[0]);
514 SubTerm->
setSuccessor(SubLoopContinueOnTrue, AftBlocksFirst[0]);
515 SubLoopBlocksFirst[0]->replacePhiUsesWith(ForeBlocksLast[0],
516 ForeBlocksLast.back());
517 SubLoopBlocksFirst[0]->replacePhiUsesWith(SubLoopBlocksLast[0],
518 SubLoopBlocksLast.back());
520 for (
unsigned It = 1; It != Count; It++) {
524 cast<BranchInst>(SubLoopBlocksLast[It - 1]->getTerminator());
528 SubLoopBlocksFirst[It]->replacePhiUsesWith(ForeBlocksLast[It],
529 ForeBlocksLast.back());
530 SubLoopBlocksFirst[It]->replacePhiUsesWith(SubLoopBlocksLast[It],
531 SubLoopBlocksLast.back());
532 movePHIs(SubLoopBlocksFirst[It], SubLoopBlocksFirst[0]);
536 BranchInst *AftTerm = cast<BranchInst>(AftBlocksLast.back()->getTerminator());
537 if (CompletelyUnroll) {
541 AftTerm->
setSuccessor(!ContinueOnTrue, ForeBlocksFirst[0]);
543 "Expecting the ContinueOnTrue successor of AftTerm to be LoopExit");
545 AftBlocksFirst[0]->replacePhiUsesWith(SubLoopBlocksLast[0],
546 SubLoopBlocksLast.back());
548 for (
unsigned It = 1; It != Count; It++) {
552 cast<BranchInst>(AftBlocksLast[It - 1]->getTerminator());
556 AftBlocksFirst[It]->replacePhiUsesWith(SubLoopBlocksLast[It],
557 SubLoopBlocksLast.back());
558 movePHIs(AftBlocksFirst[It], AftBlocksFirst[0]);
566 DTUpdates.
emplace_back(DominatorTree::UpdateKind::Delete, ForeBlocksLast[0],
567 SubLoopBlocksFirst[0]);
568 DTUpdates.
emplace_back(DominatorTree::UpdateKind::Delete,
569 SubLoopBlocksLast[0], AftBlocksFirst[0]);
571 DTUpdates.
emplace_back(DominatorTree::UpdateKind::Insert,
572 ForeBlocksLast.back(), SubLoopBlocksFirst[0]);
573 DTUpdates.
emplace_back(DominatorTree::UpdateKind::Insert,
574 SubLoopBlocksLast.back(), AftBlocksFirst[0]);
580 MergeBlocks.
insert(ForeBlocksLast.begin(), ForeBlocksLast.end());
581 MergeBlocks.
insert(SubLoopBlocksLast.begin(), SubLoopBlocksLast.end());
582 MergeBlocks.
insert(AftBlocksLast.begin(), AftBlocksLast.end());
596 NumCompletelyUnrolledAndJammed += CompletelyUnroll;
597 ++NumUnrolledAndJammed;
600 if (CompletelyUnroll)
613 if (!CompletelyUnroll)
614 assert(L->isLoopSimplifyForm());
619 return CompletelyUnroll ? LoopUnrollResult::FullyUnrolled
620 : LoopUnrollResult::PartiallyUnrolled;
629 if (
auto *Ld = dyn_cast<LoadInst>(&
I)) {
633 }
else if (
auto *St = dyn_cast<StoreInst>(&
I)) {
637 }
else if (
I.mayReadOrWriteMemory()) {
646 unsigned UnrollLevel,
unsigned JamLevel,
650 for (
unsigned CurLoopDepth = UnrollLevel + 1; CurLoopDepth <= JamLevel;
652 auto JammedDir =
D->getDirection(CurLoopDepth);
664 unsigned UnrollLevel,
unsigned JamLevel,
667 for (
unsigned CurLoopDepth = UnrollLevel + 1; CurLoopDepth <= JamLevel;
669 auto JammedDir =
D->getDirection(CurLoopDepth);
678 return Sequentialized;
690 unsigned UnrollLevel,
unsigned JamLevel,
692 assert(UnrollLevel <= JamLevel &&
693 "Expecting JamLevel to be at least UnrollLevel");
698 if (isa<LoadInst>(Src) && isa<LoadInst>(Dst))
711 std::unique_ptr<Dependence>
D = DI.
depends(Src, Dst,
true);
714 assert(
D->isOrdered() &&
"Expected an output, flow or anti dep.");
716 if (
D->isConfused()) {
718 <<
" " << *Src <<
"\n"
719 <<
" " << *Dst <<
"\n");
727 for (
unsigned CurLoopDepth = 1; CurLoopDepth < UnrollLevel; ++CurLoopDepth)
731 auto UnrollDirection =
D->getDirection(UnrollLevel);
741 Sequentialized,
D.get()))
746 Sequentialized,
D.get()))
770 CurrentLoadsAndStores.
clear();
777 for (
auto *Earlier : EarlierLoadsAndStores) {
780 unsigned CommonLoopDepth = std::min(EarlierDepth, CurLoopDepth);
781 for (
auto *Later : CurrentLoadsAndStores) {
782 if (!
checkDependency(Earlier, Later, LoopDepth, CommonLoopDepth,
false,
788 size_t NumInsts = CurrentLoadsAndStores.
size();
789 for (
size_t I = 0;
I < NumInsts; ++
I) {
790 for (
size_t J =
I; J < NumInsts; ++J) {
792 LoopDepth, CurLoopDepth,
true, DI))
797 EarlierLoadsAndStores.append(CurrentLoadsAndStores.
begin(),
798 CurrentLoadsAndStores.
end());
808 const Loop *L = &Root;
811 if (!L->isLoopSimplifyForm())
814 if (!L->isRotatedForm())
817 if (L->getHeader()->hasAddressTaken()) {
822 unsigned SubLoopsSize = L->getSubLoops().size();
823 if (SubLoopsSize == 0)
827 if (SubLoopsSize != 1)
834 if (!L->getExitBlock()) {
835 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; only loops with single exit "
836 "blocks can be unrolled and jammed.\n");
841 if (!L->getExitingBlock()) {
842 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; only loops with single "
843 "exiting blocks can be unrolled and jammed.\n");
847 L = L->getSubLoops()[0];
854 while (!L->getSubLoops().empty())
855 L = L->getSubLoops()[0];
862 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; Ineligible loop form\n");
924 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; Incompatible loop layout\n");
931 if (AftBlocksMap[L].
size() != 1) {
932 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; Can't currently handle "
933 "multiple blocks after the loop\n");
939 if (
any_of(L->getLoopsInPreorder(), [&SE](
Loop *SubLoop) {
940 return !hasIterationCountInvariantInParent(SubLoop, SE);
942 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; Inner loop iteration count is "
943 "not consistent on each iteration\n");
951 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; Something may throw\n");
965 Loop *SubLoop = L->getSubLoops()[0];
967 Header, Latch, AftBlocks, [&AftBlocks, &SubLoop](
Instruction *
I) {
970 if (AftBlocks.
count(
I->getParent())) {
977 if (I->mayHaveSideEffects() || I->mayReadOrWriteMemory())
984 "instructions after subloop to before it\n");
993 LLVM_DEBUG(
dbgs() <<
"Won't unroll-and-jam; failed dependency check\n");
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
DenseMap< Block *, BlockRelaxAux > Blocks
This file defines a set of templates that efficiently compute a dominator tree over a generic graph.
SmallPtrSet< BasicBlock *, 4 > BasicBlockSet
static bool partitionLoopBlocks(Loop &L, BasicBlockSet &ForeBlocks, BasicBlockSet &AftBlocks, DominatorTree &DT)
static Loop * getInnerMostLoop(Loop *L)
static void moveHeaderPhiOperandsToForeBlocks(BasicBlock *Header, BasicBlock *Latch, Instruction *InsertLoc, BasicBlockSet &AftBlocks)
static bool getLoadsAndStores(BasicBlockSet &Blocks, SmallVector< Instruction *, 4 > &MemInstr)
static bool preservesForwardDependence(Instruction *Src, Instruction *Dst, unsigned UnrollLevel, unsigned JamLevel, bool Sequentialized, Dependence *D)
static bool partitionOuterLoopBlocks(Loop &Root, Loop &JamLoop, BasicBlockSet &JamLoopBlocks, DenseMap< Loop *, BasicBlockSet > &ForeBlocksMap, DenseMap< Loop *, BasicBlockSet > &AftBlocksMap, DominatorTree &DT)
Partition blocks in a loop nest into blocks before and after each inner loop.
static bool isEligibleLoopForm(const Loop &Root)
static bool preservesBackwardDependence(Instruction *Src, Instruction *Dst, unsigned UnrollLevel, unsigned JamLevel, bool Sequentialized, Dependence *D)
static bool checkDependencies(Loop &Root, const BasicBlockSet &SubLoopBlocks, const DenseMap< Loop *, BasicBlockSet > &ForeBlocksMap, const DenseMap< Loop *, BasicBlockSet > &AftBlocksMap, DependenceInfo &DI, LoopInfo &LI)
static bool processHeaderPhiOperands(BasicBlock *Header, BasicBlock *Latch, BasicBlockSet &AftBlocks, T Visit)
static bool checkDependency(Instruction *Src, Instruction *Dst, unsigned UnrollLevel, unsigned JamLevel, bool Sequentialized, DependenceInfo &DI)
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A cache of @llvm.assume calls within a function.
void registerAssumption(AssumeInst *CI)
Add an @llvm.assume intrinsic to this function's cache.
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
const Instruction & back() const
Conditional or Unconditional Branch instruction.
unsigned getNumSuccessors() const
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i) const
bool isUnconditional() const
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
DependenceInfo - This class is the main dependence-analysis driver.
std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool PossiblyLoopIndependent)
depends - Tests for a dependence between the Src and Dst instructions.
Dependence - This class represents a dependence between two memory memory references in a function.
DomTreeNodeBase * getIDom() const
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
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.
DomTreeT & getDomTree()
Flush DomTree updates and return DomTree.
void applyUpdatesPermissive(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
SmallVector< const LoopT *, 4 > getLoopsInPreorder() const
Return all loops in the loop nest rooted by the loop in preorder, with siblings in forward program or...
const std::vector< LoopT * > & getSubLoops() const
Return the loops contained entirely within this loop.
BlockT * getHeader() const
unsigned getLoopDepth() const
Return the nesting level of this loop.
block_iterator block_end() const
BlockT * getExitBlock() const
If getExitBlocks would return exactly one block, return that block.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
BlockT * getExitingBlock() const
If getExitingBlocks would return exactly one block, return that block.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
block_iterator block_begin() const
Store the result of a depth first search within basic blocks contained by a single loop.
RPOIterator beginRPO() const
Reverse iterate over the cached postorder blocks.
std::vector< BasicBlock * >::const_reverse_iterator RPOIterator
void perform(const LoopInfo *LI)
Traverse the loop blocks and store the DFS result.
RPOIterator endRPO() const
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
void erase(Loop *L)
Update LoopInfo after removing the last backedge from a loop.
Represents a single loop in the control flow graph.
bool isLoopSimplifyForm() const
Return true if the Loop is in the form that the LoopSimplify form transforms loops to,...
bool isRecursivelyLCSSAForm(const DominatorTree &DT, const LoopInfo &LI, bool IgnoreTokens=true) const
Return true if this Loop and all inner subloops are in LCSSA form.
The main scalar evolution driver.
void forgetLoop(const Loop *L)
This method should be called by the client when it has changed a loop in a way that may effect Scalar...
void forgetBlockAndLoopDispositions(Value *V=nullptr)
Called when the client has changed the disposition of values in a loop or block.
Simple and conservative implementation of LoopSafetyInfo that can give false-positive answers to its ...
void computeLoopSafetyInfo(const Loop *CurLoop) override
Computes safety information for a loop checks loop body & header for the possibility of may throw exc...
bool anyBlockMayThrow() const override
Returns true iff any block of the loop for which this info is contains an instruction that may throw ...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
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.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
bool isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree &DT, DependenceInfo &DI, LoopInfo &LI)
void simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC, const TargetTransformInfo *TTI, AAResults *AA=nullptr)
Perform some cleanup and simplifications on loops after unrolling.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto successors(const MachineBasicBlock *BB)
bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count, bool AllowExpensiveTripCount, bool UseEpilogRemainder, bool UnrollRemainder, bool ForgetAllSCEV, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC, const TargetTransformInfo *TTI, bool PreserveLCSSA, unsigned SCEVExpansionBudget, Loop **ResultLoop=nullptr)
Insert code in the prolog/epilog code when unrolling a loop with a run-time trip-count.
cl::opt< bool > EnableFSDiscriminator
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool MergeBlockSuccessorsIntoGivenBlocks(SmallPtrSetImpl< BasicBlock * > &MergeBlocks, Loop *L=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
Merge block(s) sucessors, if possible.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
cl::opt< unsigned > SCEVCheapExpansionBudget
LoopUnrollResult
Represents the result of a UnrollLoop invocation.
BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
const Loop * addClonedBlockToLoopInfo(BasicBlock *OriginalBB, BasicBlock *ClonedBB, LoopInfo *LI, NewLoopsMap &NewLoops)
Adds ClonedBB to LoopInfo, creates a new loop for ClonedBB if necessary and adds a mapping from the o...
LoopUnrollResult UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount, unsigned TripMultiple, bool UnrollRemainder, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC, const TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE, Loop **EpilogueLoop=nullptr)