#include "llvm/Transforms/Utils/LoopPeel.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/LoopSimplify.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
using namespace llvm;
using namespace llvm::PatternMatch;
#define DEBUG_TYPE "loop-peel"
STATISTIC(NumPeeled, "Number of loops peeled");
static cl::opt<unsigned> UnrollPeelCount(
"unroll-peel-count", cl::Hidden,
cl::desc("Set the unroll peeling count, for testing purposes"));
static cl::opt<bool>
UnrollAllowPeeling("unroll-allow-peeling", cl::init(true), cl::Hidden,
cl::desc("Allows loops to be peeled when the dynamic "
"trip count is known to be low."));
static cl::opt<bool>
UnrollAllowLoopNestsPeeling("unroll-allow-loop-nests-peeling",
cl::init(false), cl::Hidden,
cl::desc("Allows loop nests to be peeled."));
static cl::opt<unsigned> UnrollPeelMaxCount(
"unroll-peel-max-count", cl::init(7), cl::Hidden,
cl::desc("Max average trip count which will cause loop peeling."));
static cl::opt<unsigned> UnrollForcePeelCount(
"unroll-force-peel-count", cl::init(0), cl::Hidden,
cl::desc("Force a peel count regardless of profiling information."));
static const char *PeeledCountMetaData = "llvm.loop.peeled.count";
bool llvm::canPeel(Loop *L) {
if (!L->isLoopSimplifyForm())
return false;
const BasicBlock *Latch = L->getLoopLatch();
if (!L->isLoopExiting(Latch))
return false;
if (!isa<BranchInst>(Latch->getTerminator()))
return false;
SmallVector<BasicBlock *, 4> Exits;
L->getUniqueNonLatchExitBlocks(Exits);
return llvm::all_of(Exits, IsBlockFollowedByDeoptOrUnreachable);
}
static Optional<unsigned> calculateIterationsToInvariance(
PHINode *Phi, Loop *L, BasicBlock *BackEdge,
SmallDenseMap<PHINode *, Optional<unsigned> > &IterationsToInvariance) {
assert(Phi->getParent() == L->getHeader() &&
"Non-loop Phi should not be checked for turning into invariant.");
assert(BackEdge == L->getLoopLatch() && "Wrong latch?");
auto I = IterationsToInvariance.find(Phi);
if (I != IterationsToInvariance.end())
return I->second;
Value *Input = Phi->getIncomingValueForBlock(BackEdge);
IterationsToInvariance[Phi] = None;
Optional<unsigned> ToInvariance = None;
if (L->isLoopInvariant(Input))
ToInvariance = 1u;
else if (PHINode *IncPhi = dyn_cast<PHINode>(Input)) {
if (IncPhi->getParent() != L->getHeader())
return None;
auto InputToInvariance = calculateIterationsToInvariance(
IncPhi, L, BackEdge, IterationsToInvariance);
if (InputToInvariance)
ToInvariance = *InputToInvariance + 1u;
}
if (ToInvariance)
IterationsToInvariance[Phi] = ToInvariance;
return ToInvariance;
}
static unsigned peelToTurnInvariantLoadsDerefencebale(Loop &L,
DominatorTree &DT) {
if (L.getExitingBlock())
return 0;
SmallVector<BasicBlock *, 4> Exits;
L.getUniqueNonLatchExitBlocks(Exits);
if (any_of(Exits, [](const BasicBlock *BB) {
return !isa<UnreachableInst>(BB->getTerminator());
}))
return 0;
BasicBlock *Header = L.getHeader();
BasicBlock *Latch = L.getLoopLatch();
SmallPtrSet<Value *, 8> LoadUsers;
const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
for (BasicBlock *BB : L.blocks()) {
for (Instruction &I : *BB) {
if (I.mayWriteToMemory())
return 0;
auto Iter = LoadUsers.find(&I);
if (Iter != LoadUsers.end()) {
for (Value *U : I.users())
LoadUsers.insert(U);
}
if (BB == Header)
continue;
if (auto *LI = dyn_cast<LoadInst>(&I)) {
Value *Ptr = LI->getPointerOperand();
if (DT.dominates(BB, Latch) && L.isLoopInvariant(Ptr) &&
!isDereferenceablePointer(Ptr, LI->getType(), DL, LI, &DT))
for (Value *U : I.users())
LoadUsers.insert(U);
}
}
}
SmallVector<BasicBlock *> ExitingBlocks;
L.getExitingBlocks(ExitingBlocks);
if (any_of(ExitingBlocks, [&LoadUsers](BasicBlock *Exiting) {
return LoadUsers.contains(Exiting->getTerminator());
}))
return 1;
return 0;
}
static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount,
ScalarEvolution &SE) {
assert(L.isLoopSimplifyForm() && "Loop needs to be in loop simplify form");
unsigned DesiredPeelCount = 0;
for (auto *BB : L.blocks()) {
auto *BI = dyn_cast<BranchInst>(BB->getTerminator());
if (!BI || BI->isUnconditional())
continue;
if (L.getLoopLatch() == BB)
continue;
Value *Condition = BI->getCondition();
Value *LeftVal, *RightVal;
CmpInst::Predicate Pred;
if (!match(Condition, m_ICmp(Pred, m_Value(LeftVal), m_Value(RightVal))))
continue;
const SCEV *LeftSCEV = SE.getSCEV(LeftVal);
const SCEV *RightSCEV = SE.getSCEV(RightVal);
if (SE.evaluatePredicate(Pred, LeftSCEV, RightSCEV))
continue;
if (!isa<SCEVAddRecExpr>(LeftSCEV)) {
if (isa<SCEVAddRecExpr>(RightSCEV)) {
std::swap(LeftSCEV, RightSCEV);
Pred = ICmpInst::getSwappedPredicate(Pred);
} else
continue;
}
const SCEVAddRecExpr *LeftAR = cast<SCEVAddRecExpr>(LeftSCEV);
if (!LeftAR->isAffine() || LeftAR->getLoop() != &L)
continue;
if (!(ICmpInst::isEquality(Pred) && LeftAR->hasNoSelfWrap()) &&
!SE.getMonotonicPredicateType(LeftAR, Pred))
continue;
unsigned NewPeelCount = DesiredPeelCount;
const SCEV *IterVal = LeftAR->evaluateAtIteration(
SE.getConstant(LeftSCEV->getType(), NewPeelCount), SE);
if (!SE.isKnownPredicate(Pred, IterVal, RightSCEV))
Pred = ICmpInst::getInversePredicate(Pred);
const SCEV *Step = LeftAR->getStepRecurrence(SE);
const SCEV *NextIterVal = SE.getAddExpr(IterVal, Step);
auto PeelOneMoreIteration = [&IterVal, &NextIterVal, &SE, Step,
&NewPeelCount]() {
IterVal = NextIterVal;
NextIterVal = SE.getAddExpr(IterVal, Step);
NewPeelCount++;
};
auto CanPeelOneMoreIteration = [&NewPeelCount, &MaxPeelCount]() {
return NewPeelCount < MaxPeelCount;
};
while (CanPeelOneMoreIteration() &&
SE.isKnownPredicate(Pred, IterVal, RightSCEV))
PeelOneMoreIteration();
if (!SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), IterVal,
RightSCEV))
continue;
if (ICmpInst::isEquality(Pred) &&
!SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), NextIterVal,
RightSCEV) &&
!SE.isKnownPredicate(Pred, IterVal, RightSCEV) &&
SE.isKnownPredicate(Pred, NextIterVal, RightSCEV)) {
if (!CanPeelOneMoreIteration())
continue; PeelOneMoreIteration(); }
DesiredPeelCount = std::max(DesiredPeelCount, NewPeelCount);
}
return DesiredPeelCount;
}
static bool violatesLegacyMultiExitLoopCheck(Loop *L) {
BasicBlock *Latch = L->getLoopLatch();
if (!Latch)
return true;
BranchInst *LatchBR = dyn_cast<BranchInst>(Latch->getTerminator());
if (!LatchBR || LatchBR->getNumSuccessors() != 2 || !L->isLoopExiting(Latch))
return true;
assert((LatchBR->getSuccessor(0) == L->getHeader() ||
LatchBR->getSuccessor(1) == L->getHeader()) &&
"At least one edge out of the latch must go to the header");
SmallVector<BasicBlock *, 4> ExitBlocks;
L->getUniqueNonLatchExitBlocks(ExitBlocks);
return any_of(ExitBlocks, [](const BasicBlock *EB) {
return !EB->getTerminatingDeoptimizeCall();
});
}
void llvm::computePeelCount(Loop *L, unsigned LoopSize,
TargetTransformInfo::PeelingPreferences &PP,
unsigned TripCount, DominatorTree &DT,
ScalarEvolution &SE, unsigned Threshold) {
assert(LoopSize > 0 && "Zero loop size is not allowed!");
unsigned TargetPeelCount = PP.PeelCount;
PP.PeelCount = 0;
if (!canPeel(L))
return;
if (!PP.AllowLoopNestsPeeling && !L->isInnermost())
return;
bool UserPeelCount = UnrollForcePeelCount.getNumOccurrences() > 0;
if (UserPeelCount) {
LLVM_DEBUG(dbgs() << "Force-peeling first " << UnrollForcePeelCount
<< " iterations.\n");
PP.PeelCount = UnrollForcePeelCount;
PP.PeelProfiledIterations = true;
return;
}
if (!PP.AllowPeeling)
return;
if (2 * LoopSize > Threshold)
return;
unsigned AlreadyPeeled = 0;
if (auto Peeled = getOptionalIntLoopAttribute(L, PeeledCountMetaData))
AlreadyPeeled = *Peeled;
if (AlreadyPeeled >= UnrollPeelMaxCount)
return;
SmallDenseMap<PHINode *, Optional<unsigned>> IterationsToInvariance;
unsigned DesiredPeelCount = TargetPeelCount;
BasicBlock *BackEdge = L->getLoopLatch();
assert(BackEdge && "Loop is not in simplified form?");
for (auto BI = L->getHeader()->begin(); isa<PHINode>(&*BI); ++BI) {
PHINode *Phi = cast<PHINode>(&*BI);
auto ToInvariance = calculateIterationsToInvariance(Phi, L, BackEdge,
IterationsToInvariance);
if (ToInvariance)
DesiredPeelCount = std::max(DesiredPeelCount, *ToInvariance);
}
unsigned MaxPeelCount = UnrollPeelMaxCount;
MaxPeelCount = std::min(MaxPeelCount, Threshold / LoopSize - 1);
DesiredPeelCount = std::max(DesiredPeelCount,
countToEliminateCompares(*L, MaxPeelCount, SE));
if (DesiredPeelCount == 0)
DesiredPeelCount = peelToTurnInvariantLoadsDerefencebale(*L, DT);
if (DesiredPeelCount > 0) {
DesiredPeelCount = std::min(DesiredPeelCount, MaxPeelCount);
assert(DesiredPeelCount > 0 && "Wrong loop size estimation?");
if (DesiredPeelCount + AlreadyPeeled <= UnrollPeelMaxCount) {
LLVM_DEBUG(dbgs() << "Peel " << DesiredPeelCount
<< " iteration(s) to turn"
<< " some Phis into invariants.\n");
PP.PeelCount = DesiredPeelCount;
PP.PeelProfiledIterations = false;
return;
}
}
if (TripCount)
return;
if (!PP.PeelProfiledIterations)
return;
if (L->getHeader()->getParent()->hasProfileData()) {
if (violatesLegacyMultiExitLoopCheck(L))
return;
Optional<unsigned> EstimatedTripCount = getLoopEstimatedTripCount(L);
if (!EstimatedTripCount)
return;
LLVM_DEBUG(dbgs() << "Profile-based estimated trip count is "
<< *EstimatedTripCount << "\n");
if (*EstimatedTripCount) {
if (*EstimatedTripCount + AlreadyPeeled <= MaxPeelCount) {
unsigned PeelCount = *EstimatedTripCount;
LLVM_DEBUG(dbgs() << "Peeling first " << PeelCount << " iterations.\n");
PP.PeelCount = PeelCount;
return;
}
LLVM_DEBUG(dbgs() << "Already peel count: " << AlreadyPeeled << "\n");
LLVM_DEBUG(dbgs() << "Max peel count: " << UnrollPeelMaxCount << "\n");
LLVM_DEBUG(dbgs() << "Loop cost: " << LoopSize << "\n");
LLVM_DEBUG(dbgs() << "Max peel cost: " << Threshold << "\n");
LLVM_DEBUG(dbgs() << "Max peel count by cost: "
<< (Threshold / LoopSize - 1) << "\n");
}
}
}
static void updateBranchWeights(BasicBlock *Header, BranchInst *LatchBR,
uint64_t ExitWeight,
uint64_t &FallThroughWeight) {
if (!FallThroughWeight)
return;
unsigned HeaderIdx = (LatchBR->getSuccessor(0) == Header ? 0 : 1);
MDBuilder MDB(LatchBR->getContext());
MDNode *WeightNode =
HeaderIdx ? MDB.createBranchWeights(ExitWeight, FallThroughWeight)
: MDB.createBranchWeights(FallThroughWeight, ExitWeight);
LatchBR->setMetadata(LLVMContext::MD_prof, WeightNode);
FallThroughWeight =
FallThroughWeight > ExitWeight ? FallThroughWeight - ExitWeight : 1;
}
static void initBranchWeights(BasicBlock *Header, BranchInst *LatchBR,
uint64_t &ExitWeight,
uint64_t &FallThroughWeight) {
uint64_t TrueWeight, FalseWeight;
if (!LatchBR->extractProfMetadata(TrueWeight, FalseWeight))
return;
unsigned HeaderIdx = LatchBR->getSuccessor(0) == Header ? 0 : 1;
ExitWeight = HeaderIdx ? TrueWeight : FalseWeight;
FallThroughWeight = HeaderIdx ? FalseWeight : TrueWeight;
}
static void fixupBranchWeights(BasicBlock *Header, BranchInst *LatchBR,
uint64_t ExitWeight,
uint64_t FallThroughWeight) {
if (!FallThroughWeight)
return;
MDBuilder MDB(LatchBR->getContext());
unsigned HeaderIdx = LatchBR->getSuccessor(0) == Header ? 0 : 1;
MDNode *WeightNode =
HeaderIdx ? MDB.createBranchWeights(ExitWeight, FallThroughWeight)
: MDB.createBranchWeights(FallThroughWeight, ExitWeight);
LatchBR->setMetadata(LLVMContext::MD_prof, WeightNode);
}
static void cloneLoopBlocks(
Loop *L, unsigned IterNumber, BasicBlock *InsertTop, BasicBlock *InsertBot,
SmallVectorImpl<std::pair<BasicBlock *, BasicBlock *>> &ExitEdges,
SmallVectorImpl<BasicBlock *> &NewBlocks, LoopBlocksDFS &LoopBlocks,
ValueToValueMapTy &VMap, ValueToValueMapTy &LVMap, DominatorTree *DT,
LoopInfo *LI, ArrayRef<MDNode *> LoopLocalNoAliasDeclScopes,
ScalarEvolution &SE) {
BasicBlock *Header = L->getHeader();
BasicBlock *Latch = L->getLoopLatch();
BasicBlock *PreHeader = L->getLoopPreheader();
Function *F = Header->getParent();
LoopBlocksDFS::RPOIterator BlockBegin = LoopBlocks.beginRPO();
LoopBlocksDFS::RPOIterator BlockEnd = LoopBlocks.endRPO();
Loop *ParentLoop = L->getParentLoop();
for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) {
BasicBlock *NewBB = CloneBasicBlock(*BB, VMap, ".peel", F);
NewBlocks.push_back(NewBB);
if (ParentLoop && LI->getLoopFor(*BB) == L)
ParentLoop->addBasicBlockToLoop(NewBB, *LI);
VMap[*BB] = NewBB;
if (DT) {
if (Header == *BB)
DT->addNewBlock(NewBB, InsertTop);
else {
DomTreeNode *IDom = DT->getNode(*BB)->getIDom();
DT->addNewBlock(NewBB, cast<BasicBlock>(VMap[IDom->getBlock()]));
}
}
}
{
std::string Ext = (Twine("Peel") + Twine(IterNumber)).str();
cloneAndAdaptNoAliasScopes(LoopLocalNoAliasDeclScopes, NewBlocks,
Header->getContext(), Ext);
}
for (Loop *ChildLoop : *L) {
cloneLoop(ChildLoop, ParentLoop, VMap, LI, nullptr);
}
InsertTop->getTerminator()->setSuccessor(0, cast<BasicBlock>(VMap[Header]));
BasicBlock *NewLatch = cast<BasicBlock>(VMap[Latch]);
BranchInst *LatchBR = cast<BranchInst>(NewLatch->getTerminator());
for (unsigned idx = 0, e = LatchBR->getNumSuccessors(); idx < e; ++idx)
if (LatchBR->getSuccessor(idx) == Header) {
LatchBR->setSuccessor(idx, InsertBot);
break;
}
if (DT)
DT->changeImmediateDominator(InsertBot, NewLatch);
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
PHINode *NewPHI = cast<PHINode>(VMap[&*I]);
if (IterNumber == 0) {
VMap[&*I] = NewPHI->getIncomingValueForBlock(PreHeader);
} else {
Value *LatchVal = NewPHI->getIncomingValueForBlock(Latch);
Instruction *LatchInst = dyn_cast<Instruction>(LatchVal);
if (LatchInst && L->contains(LatchInst))
VMap[&*I] = LVMap[LatchInst];
else
VMap[&*I] = LatchVal;
}
cast<BasicBlock>(VMap[Header])->getInstList().erase(NewPHI);
}
for (auto Edge : ExitEdges)
for (PHINode &PHI : Edge.second->phis()) {
Value *LatchVal = PHI.getIncomingValueForBlock(Edge.first);
Instruction *LatchInst = dyn_cast<Instruction>(LatchVal);
if (LatchInst && L->contains(LatchInst))
LatchVal = VMap[LatchVal];
PHI.addIncoming(LatchVal, cast<BasicBlock>(VMap[Edge.first]));
SE.forgetValue(&PHI);
}
for (auto KV : VMap)
LVMap[KV.first] = KV.second;
}
TargetTransformInfo::PeelingPreferences llvm::gatherPeelingPreferences(
Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI,
Optional<bool> UserAllowPeeling,
Optional<bool> UserAllowProfileBasedPeeling, bool UnrollingSpecficValues) {
TargetTransformInfo::PeelingPreferences PP;
PP.PeelCount = 0;
PP.AllowPeeling = true;
PP.AllowLoopNestsPeeling = false;
PP.PeelProfiledIterations = true;
TTI.getPeelingPreferences(L, SE, PP);
if (UnrollingSpecficValues) {
if (UnrollPeelCount.getNumOccurrences() > 0)
PP.PeelCount = UnrollPeelCount;
if (UnrollAllowPeeling.getNumOccurrences() > 0)
PP.AllowPeeling = UnrollAllowPeeling;
if (UnrollAllowLoopNestsPeeling.getNumOccurrences() > 0)
PP.AllowLoopNestsPeeling = UnrollAllowLoopNestsPeeling;
}
if (UserAllowPeeling)
PP.AllowPeeling = *UserAllowPeeling;
if (UserAllowProfileBasedPeeling)
PP.PeelProfiledIterations = *UserAllowProfileBasedPeeling;
return PP;
}
bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
ScalarEvolution *SE, DominatorTree &DT, AssumptionCache *AC,
bool PreserveLCSSA) {
assert(PeelCount > 0 && "Attempt to peel out zero iterations?");
assert(canPeel(L) && "Attempt to peel a loop which is not peelable?");
LoopBlocksDFS LoopBlocks(L);
LoopBlocks.perform(LI);
BasicBlock *Header = L->getHeader();
BasicBlock *PreHeader = L->getLoopPreheader();
BasicBlock *Latch = L->getLoopLatch();
SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> ExitEdges;
L->getExitEdges(ExitEdges);
DenseMap<BasicBlock *, BasicBlock *> NonLoopBlocksIDom;
for (auto *BB : L->blocks()) {
auto *BBDomNode = DT.getNode(BB);
SmallVector<BasicBlock *, 16> ChildrenToUpdate;
for (auto *ChildDomNode : BBDomNode->children()) {
auto *ChildBB = ChildDomNode->getBlock();
if (!L->contains(ChildBB))
ChildrenToUpdate.push_back(ChildBB);
}
BasicBlock *NewIDom = DT.findNearestCommonDominator(BB, Latch);
for (auto *ChildBB : ChildrenToUpdate)
NonLoopBlocksIDom[ChildBB] = NewIDom;
}
Function *F = Header->getParent();
BasicBlock *InsertTop = SplitEdge(PreHeader, Header, &DT, LI);
BasicBlock *InsertBot =
SplitBlock(InsertTop, InsertTop->getTerminator(), &DT, LI);
BasicBlock *NewPreHeader =
SplitBlock(InsertBot, InsertBot->getTerminator(), &DT, LI);
InsertTop->setName(Header->getName() + ".peel.begin");
InsertBot->setName(Header->getName() + ".peel.next");
NewPreHeader->setName(PreHeader->getName() + ".peel.newph");
ValueToValueMapTy LVMap;
BranchInst *LatchBR =
cast<BranchInst>(cast<BasicBlock>(Latch)->getTerminator());
uint64_t ExitWeight = 0, FallThroughWeight = 0;
initBranchWeights(Header, LatchBR, ExitWeight, FallThroughWeight);
SmallVector<MDNode *, 6> LoopLocalNoAliasDeclScopes;
identifyNoAliasScopesToClone(L->getBlocks(), LoopLocalNoAliasDeclScopes);
for (unsigned Iter = 0; Iter < PeelCount; ++Iter) {
SmallVector<BasicBlock *, 8> NewBlocks;
ValueToValueMapTy VMap;
cloneLoopBlocks(L, Iter, InsertTop, InsertBot, ExitEdges, NewBlocks,
LoopBlocks, VMap, LVMap, &DT, LI,
LoopLocalNoAliasDeclScopes, *SE);
remapInstructionsInBlocks(NewBlocks, VMap);
if (Iter == 0)
for (auto BBIDom : NonLoopBlocksIDom)
DT.changeImmediateDominator(BBIDom.first,
cast<BasicBlock>(LVMap[BBIDom.second]));
#ifdef EXPENSIVE_CHECKS
assert(DT.verify(DominatorTree::VerificationLevel::Fast));
#endif
auto *LatchBRCopy = cast<BranchInst>(VMap[LatchBR]);
updateBranchWeights(InsertBot, LatchBRCopy, ExitWeight, FallThroughWeight);
LatchBRCopy->setMetadata(LLVMContext::MD_loop, nullptr);
InsertTop = InsertBot;
InsertBot = SplitBlock(InsertBot, InsertBot->getTerminator(), &DT, LI);
InsertBot->setName(Header->getName() + ".peel.next");
F->getBasicBlockList().splice(InsertTop->getIterator(),
F->getBasicBlockList(),
NewBlocks[0]->getIterator(), F->end());
}
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
PHINode *PHI = cast<PHINode>(I);
Value *NewVal = PHI->getIncomingValueForBlock(Latch);
Instruction *LatchInst = dyn_cast<Instruction>(NewVal);
if (LatchInst && L->contains(LatchInst))
NewVal = LVMap[LatchInst];
PHI->setIncomingValueForBlock(NewPreHeader, NewVal);
}
fixupBranchWeights(Header, LatchBR, ExitWeight, FallThroughWeight);
unsigned AlreadyPeeled = 0;
if (auto Peeled = getOptionalIntLoopAttribute(L, PeeledCountMetaData))
AlreadyPeeled = *Peeled;
addStringMetadataToLoop(L, PeeledCountMetaData, AlreadyPeeled + PeelCount);
if (Loop *ParentLoop = L->getParentLoop())
L = ParentLoop;
SE->forgetTopmostLoop(L);
#ifdef EXPENSIVE_CHECKS
assert(DT.verify(DominatorTree::VerificationLevel::Fast));
#endif
simplifyLoop(L, &DT, LI, SE, AC, nullptr, PreserveLCSSA);
NumPeeled++;
return true;
}