#include "llvm/Transforms/Utils/LoopSimplify.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/DependenceAnalysis.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
using namespace llvm;
#define DEBUG_TYPE "loop-simplify"
STATISTIC(NumNested , "Number of nested loops split out");
static void placeSplitBlockCarefully(BasicBlock *NewBB,
SmallVectorImpl<BasicBlock *> &SplitPreds,
Loop *L) {
Function::iterator BBI = --NewBB->getIterator();
for (unsigned i = 0, e = SplitPreds.size(); i != e; ++i) {
if (&*BBI == SplitPreds[i])
return;
}
BasicBlock *FoundBB = nullptr;
for (unsigned i = 0, e = SplitPreds.size(); i != e; ++i) {
Function::iterator BBI = SplitPreds[i]->getIterator();
if (++BBI != NewBB->getParent()->end() && L->contains(&*BBI)) {
FoundBB = SplitPreds[i];
break;
}
}
if (!FoundBB)
FoundBB = SplitPreds[0];
NewBB->moveAfter(FoundBB);
}
BasicBlock *llvm::InsertPreheaderForLoop(Loop *L, DominatorTree *DT,
LoopInfo *LI, MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
BasicBlock *Header = L->getHeader();
SmallVector<BasicBlock*, 8> OutsideBlocks;
for (BasicBlock *P : predecessors(Header)) {
if (!L->contains(P)) { if (isa<IndirectBrInst>(P->getTerminator()))
return nullptr;
OutsideBlocks.push_back(P);
}
}
BasicBlock *PreheaderBB;
PreheaderBB = SplitBlockPredecessors(Header, OutsideBlocks, ".preheader", DT,
LI, MSSAU, PreserveLCSSA);
if (!PreheaderBB)
return nullptr;
LLVM_DEBUG(dbgs() << "LoopSimplify: Creating pre-header "
<< PreheaderBB->getName() << "\n");
placeSplitBlockCarefully(PreheaderBB, OutsideBlocks, L);
return PreheaderBB;
}
static void addBlockAndPredsToSet(BasicBlock *InputBB, BasicBlock *StopBlock,
SmallPtrSetImpl<BasicBlock *> &Blocks) {
SmallVector<BasicBlock *, 8> Worklist;
Worklist.push_back(InputBB);
do {
BasicBlock *BB = Worklist.pop_back_val();
if (Blocks.insert(BB).second && BB != StopBlock)
append_range(Worklist, predecessors(BB));
} while (!Worklist.empty());
}
static PHINode *findPHIToPartitionLoops(Loop *L, DominatorTree *DT,
AssumptionCache *AC) {
const DataLayout &DL = L->getHeader()->getModule()->getDataLayout();
for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ) {
PHINode *PN = cast<PHINode>(I);
++I;
if (Value *V = simplifyInstruction(PN, {DL, nullptr, DT, AC})) {
PN->replaceAllUsesWith(V);
PN->eraseFromParent();
continue;
}
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (PN->getIncomingValue(i) == PN &&
L->contains(PN->getIncomingBlock(i)))
return PN;
}
return nullptr;
}
static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
DominatorTree *DT, LoopInfo *LI,
ScalarEvolution *SE, bool PreserveLCSSA,
AssumptionCache *AC, MemorySSAUpdater *MSSAU) {
if (!Preheader)
return nullptr;
for (auto BB : L->blocks()) {
for (auto &II : *BB) {
if (auto CI = dyn_cast<CallBase>(&II)) {
if (CI->isConvergent()) {
return nullptr;
}
}
}
}
BasicBlock *Header = L->getHeader();
assert(!Header->isEHPad() && "Can't insert backedge to EH pad");
PHINode *PN = findPHIToPartitionLoops(L, DT, AC);
if (!PN) return nullptr;
SmallVector<BasicBlock*, 8> OuterLoopPreds;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
if (PN->getIncomingValue(i) != PN ||
!L->contains(PN->getIncomingBlock(i))) {
if (isa<IndirectBrInst>(PN->getIncomingBlock(i)->getTerminator()))
return nullptr;
OuterLoopPreds.push_back(PN->getIncomingBlock(i));
}
}
LLVM_DEBUG(dbgs() << "LoopSimplify: Splitting out a new outer loop\n");
if (SE)
SE->forgetLoop(L);
BasicBlock *NewBB = SplitBlockPredecessors(Header, OuterLoopPreds, ".outer",
DT, LI, MSSAU, PreserveLCSSA);
placeSplitBlockCarefully(NewBB, OuterLoopPreds, L);
Loop *NewOuter = LI->AllocateLoop();
if (Loop *Parent = L->getParentLoop())
Parent->replaceChildLoopWith(L, NewOuter);
else
LI->changeTopLevelLoop(L, NewOuter);
NewOuter->addChildLoop(L);
for (BasicBlock *BB : L->blocks())
NewOuter->addBlockEntry(BB);
L->moveToHeader(Header);
SmallPtrSet<BasicBlock *, 4> BlocksInL;
for (BasicBlock *P : predecessors(Header)) {
if (DT->dominates(Header, P))
addBlockAndPredsToSet(P, Header, BlocksInL);
}
const std::vector<Loop*> &SubLoops = L->getSubLoops();
for (size_t I = 0; I != SubLoops.size(); )
if (BlocksInL.count(SubLoops[I]->getHeader()))
++I; else
NewOuter->addChildLoop(L->removeChildLoop(SubLoops.begin() + I));
SmallVector<BasicBlock *, 8> OuterLoopBlocks;
OuterLoopBlocks.push_back(NewBB);
for (unsigned i = 0; i != L->getBlocks().size(); ++i) {
BasicBlock *BB = L->getBlocks()[i];
if (!BlocksInL.count(BB)) {
L->removeBlockFromLoop(BB);
if ((*LI)[BB] == L) {
LI->changeLoopFor(BB, NewOuter);
OuterLoopBlocks.push_back(BB);
}
--i;
}
}
formDedicatedExitBlocks(L, DT, LI, MSSAU, PreserveLCSSA);
if (PreserveLCSSA) {
formLCSSA(*L, *DT, LI, SE);
assert(NewOuter->isRecursivelyLCSSAForm(*DT, *LI) &&
"LCSSA is broken after separating nested loops!");
}
return NewOuter;
}
static BasicBlock *insertUniqueBackedgeBlock(Loop *L, BasicBlock *Preheader,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU) {
assert(L->getNumBackEdges() > 1 && "Must have > 1 backedge!");
BasicBlock *Header = L->getHeader();
Function *F = Header->getParent();
if (!Preheader)
return nullptr;
assert(!Header->isEHPad() && "Can't insert backedge to EH pad");
std::vector<BasicBlock*> BackedgeBlocks;
for (BasicBlock *P : predecessors(Header)) {
if (isa<IndirectBrInst>(P->getTerminator()))
return nullptr;
if (P != Preheader) BackedgeBlocks.push_back(P);
}
BasicBlock *BEBlock = BasicBlock::Create(Header->getContext(),
Header->getName() + ".backedge", F);
BranchInst *BETerminator = BranchInst::Create(Header, BEBlock);
BETerminator->setDebugLoc(Header->getFirstNonPHI()->getDebugLoc());
LLVM_DEBUG(dbgs() << "LoopSimplify: Inserting unique backedge block "
<< BEBlock->getName() << "\n");
Function::iterator InsertPos = ++BackedgeBlocks.back()->getIterator();
F->getBasicBlockList().splice(InsertPos, F->getBasicBlockList(), BEBlock);
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
PHINode *PN = cast<PHINode>(I);
PHINode *NewPN = PHINode::Create(PN->getType(), BackedgeBlocks.size(),
PN->getName()+".be", BETerminator);
unsigned PreheaderIdx = ~0U;
bool HasUniqueIncomingValue = true;
Value *UniqueValue = nullptr;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
BasicBlock *IBB = PN->getIncomingBlock(i);
Value *IV = PN->getIncomingValue(i);
if (IBB == Preheader) {
PreheaderIdx = i;
} else {
NewPN->addIncoming(IV, IBB);
if (HasUniqueIncomingValue) {
if (!UniqueValue)
UniqueValue = IV;
else if (UniqueValue != IV)
HasUniqueIncomingValue = false;
}
}
}
assert(PreheaderIdx != ~0U && "PHI has no preheader entry??");
if (PreheaderIdx != 0) {
PN->setIncomingValue(0, PN->getIncomingValue(PreheaderIdx));
PN->setIncomingBlock(0, PN->getIncomingBlock(PreheaderIdx));
}
for (unsigned i = 0, e = PN->getNumIncomingValues()-1; i != e; ++i)
PN->removeIncomingValue(e-i, false);
PN->addIncoming(NewPN, BEBlock);
if (HasUniqueIncomingValue) {
NewPN->replaceAllUsesWith(UniqueValue);
BEBlock->getInstList().erase(NewPN);
}
}
unsigned LoopMDKind = BEBlock->getContext().getMDKindID("llvm.loop");
MDNode *LoopMD = nullptr;
for (unsigned i = 0, e = BackedgeBlocks.size(); i != e; ++i) {
Instruction *TI = BackedgeBlocks[i]->getTerminator();
if (!LoopMD)
LoopMD = TI->getMetadata(LoopMDKind);
TI->setMetadata(LoopMDKind, nullptr);
TI->replaceSuccessorWith(Header, BEBlock);
}
BEBlock->getTerminator()->setMetadata(LoopMDKind, LoopMD);
L->addBasicBlockToLoop(BEBlock, *LI);
DT->splitBlock(BEBlock);
if (MSSAU)
MSSAU->updatePhisWhenInsertingUniqueBackedgeBlock(Header, Preheader,
BEBlock);
return BEBlock;
}
static bool simplifyOneLoop(Loop *L, SmallVectorImpl<Loop *> &Worklist,
DominatorTree *DT, LoopInfo *LI,
ScalarEvolution *SE, AssumptionCache *AC,
MemorySSAUpdater *MSSAU, bool PreserveLCSSA) {
bool Changed = false;
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
ReprocessLoop:
for (BasicBlock *BB : L->blocks()) {
if (BB == L->getHeader())
continue;
SmallPtrSet<BasicBlock*, 4> BadPreds;
for (BasicBlock *P : predecessors(BB))
if (!L->contains(P))
BadPreds.insert(P);
for (BasicBlock *P : BadPreds) {
LLVM_DEBUG(dbgs() << "LoopSimplify: Deleting edge from dead predecessor "
<< P->getName() << "\n");
Instruction *TI = P->getTerminator();
changeToUnreachable(TI, PreserveLCSSA,
nullptr, MSSAU);
Changed = true;
}
}
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
SmallVector<BasicBlock*, 8> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
for (BasicBlock *ExitingBlock : ExitingBlocks)
if (BranchInst *BI = dyn_cast<BranchInst>(ExitingBlock->getTerminator()))
if (BI->isConditional()) {
if (UndefValue *Cond = dyn_cast<UndefValue>(BI->getCondition())) {
LLVM_DEBUG(dbgs()
<< "LoopSimplify: Resolving \"br i1 undef\" to exit in "
<< ExitingBlock->getName() << "\n");
BI->setCondition(ConstantInt::get(Cond->getType(),
!L->contains(BI->getSuccessor(0))));
Changed = true;
}
}
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader) {
Preheader = InsertPreheaderForLoop(L, DT, LI, MSSAU, PreserveLCSSA);
if (Preheader)
Changed = true;
}
if (formDedicatedExitBlocks(L, DT, LI, MSSAU, PreserveLCSSA))
Changed = true;
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
BasicBlock *LoopLatch = L->getLoopLatch();
if (!LoopLatch) {
if (L->getNumBackEdges() < 8) {
if (Loop *OuterL = separateNestedLoop(L, Preheader, DT, LI, SE,
PreserveLCSSA, AC, MSSAU)) {
++NumNested;
Worklist.push_back(OuterL);
Changed = true;
goto ReprocessLoop;
}
}
LoopLatch = insertUniqueBackedgeBlock(L, Preheader, DT, LI, MSSAU);
if (LoopLatch)
Changed = true;
}
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
const DataLayout &DL = L->getHeader()->getModule()->getDataLayout();
PHINode *PN;
for (BasicBlock::iterator I = L->getHeader()->begin();
(PN = dyn_cast<PHINode>(I++)); )
if (Value *V = simplifyInstruction(PN, {DL, nullptr, DT, AC})) {
if (SE) SE->forgetValue(PN);
if (!PreserveLCSSA || LI->replacementPreservesLCSSAForm(PN, V)) {
PN->replaceAllUsesWith(V);
PN->eraseFromParent();
Changed = true;
}
}
auto HasUniqueExitBlock = [&]() {
BasicBlock *UniqueExit = nullptr;
for (auto *ExitingBB : ExitingBlocks)
for (auto *SuccBB : successors(ExitingBB)) {
if (L->contains(SuccBB))
continue;
if (!UniqueExit)
UniqueExit = SuccBB;
else if (UniqueExit != SuccBB)
return false;
}
return true;
};
if (HasUniqueExitBlock()) {
for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
BasicBlock *ExitingBlock = ExitingBlocks[i];
if (!ExitingBlock->getSinglePredecessor()) continue;
BranchInst *BI = dyn_cast<BranchInst>(ExitingBlock->getTerminator());
if (!BI || !BI->isConditional()) continue;
CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition());
if (!CI || CI->getParent() != ExitingBlock) continue;
bool AllInvariant = true;
bool AnyInvariant = false;
for (auto I = ExitingBlock->instructionsWithoutDebug().begin(); &*I != BI; ) {
Instruction *Inst = &*I++;
if (Inst == CI)
continue;
if (!L->makeLoopInvariant(
Inst, AnyInvariant,
Preheader ? Preheader->getTerminator() : nullptr, MSSAU)) {
AllInvariant = false;
break;
}
}
if (AnyInvariant) {
Changed = true;
if (SE)
SE->forgetLoopDispositions(L);
}
if (!AllInvariant) continue;
if (!FoldBranchToCommonDest(BI, nullptr, MSSAU))
continue;
LLVM_DEBUG(dbgs() << "LoopSimplify: Eliminating exiting block "
<< ExitingBlock->getName() << "\n");
assert(pred_empty(ExitingBlock));
Changed = true;
LI->removeBlock(ExitingBlock);
DomTreeNode *Node = DT->getNode(ExitingBlock);
while (!Node->isLeaf()) {
DomTreeNode *Child = Node->back();
DT->changeImmediateDominator(Child, Node->getIDom());
}
DT->eraseNode(ExitingBlock);
if (MSSAU) {
SmallSetVector<BasicBlock *, 8> ExitBlockSet;
ExitBlockSet.insert(ExitingBlock);
MSSAU->removeBlocks(ExitBlockSet);
}
BI->getSuccessor(0)->removePredecessor(
ExitingBlock, PreserveLCSSA);
BI->getSuccessor(1)->removePredecessor(
ExitingBlock, PreserveLCSSA);
ExitingBlock->eraseFromParent();
}
}
if (Changed && SE)
SE->forgetTopmostLoop(L);
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
return Changed;
}
bool llvm::simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI,
ScalarEvolution *SE, AssumptionCache *AC,
MemorySSAUpdater *MSSAU, bool PreserveLCSSA) {
bool Changed = false;
#ifndef NDEBUG
if (PreserveLCSSA) {
assert(DT && "DT not available.");
assert(LI && "LI not available.");
assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
"Requested to preserve LCSSA, but it's already broken.");
}
#endif
SmallVector<Loop *, 4> Worklist;
Worklist.push_back(L);
for (unsigned Idx = 0; Idx != Worklist.size(); ++Idx) {
Loop *L2 = Worklist[Idx];
Worklist.append(L2->begin(), L2->end());
}
while (!Worklist.empty())
Changed |= simplifyOneLoop(Worklist.pop_back_val(), Worklist, DT, LI, SE,
AC, MSSAU, PreserveLCSSA);
return Changed;
}
namespace {
struct LoopSimplify : public FunctionPass {
static char ID; LoopSimplify() : FunctionPass(ID) {
initializeLoopSimplifyPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<AssumptionCacheTracker>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addPreserved<DominatorTreeWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
AU.addPreserved<LoopInfoWrapperPass>();
AU.addPreserved<BasicAAWrapperPass>();
AU.addPreserved<AAResultsWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
AU.addPreserved<ScalarEvolutionWrapperPass>();
AU.addPreserved<SCEVAAWrapperPass>();
AU.addPreservedID(LCSSAID);
AU.addPreserved<DependenceAnalysisWrapperPass>();
AU.addPreservedID(BreakCriticalEdgesID); AU.addPreserved<BranchProbabilityInfoWrapperPass>();
AU.addPreserved<MemorySSAWrapperPass>();
}
void verifyAnalysis() const override;
};
}
char LoopSimplify::ID = 0;
INITIALIZE_PASS_BEGIN(LoopSimplify, "loop-simplify",
"Canonicalize natural loops", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_END(LoopSimplify, "loop-simplify",
"Canonicalize natural loops", false, false)
char &llvm::LoopSimplifyID = LoopSimplify::ID;
Pass *llvm::createLoopSimplifyPass() { return new LoopSimplify(); }
bool LoopSimplify::runOnFunction(Function &F) {
bool Changed = false;
LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto *SEWP = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>();
ScalarEvolution *SE = SEWP ? &SEWP->getSE() : nullptr;
AssumptionCache *AC =
&getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
MemorySSA *MSSA = nullptr;
std::unique_ptr<MemorySSAUpdater> MSSAU;
auto *MSSAAnalysis = getAnalysisIfAvailable<MemorySSAWrapperPass>();
if (MSSAAnalysis) {
MSSA = &MSSAAnalysis->getMSSA();
MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
}
bool PreserveLCSSA = mustPreserveAnalysisID(LCSSAID);
for (auto *L : *LI)
Changed |= simplifyLoop(L, DT, LI, SE, AC, MSSAU.get(), PreserveLCSSA);
#ifndef NDEBUG
if (PreserveLCSSA) {
bool InLCSSA = all_of(
*LI, [&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT, *LI); });
assert(InLCSSA && "LCSSA is broken after loop-simplify.");
}
#endif
return Changed;
}
PreservedAnalyses LoopSimplifyPass::run(Function &F,
FunctionAnalysisManager &AM) {
bool Changed = false;
LoopInfo *LI = &AM.getResult<LoopAnalysis>(F);
DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F);
ScalarEvolution *SE = AM.getCachedResult<ScalarEvolutionAnalysis>(F);
AssumptionCache *AC = &AM.getResult<AssumptionAnalysis>(F);
auto *MSSAAnalysis = AM.getCachedResult<MemorySSAAnalysis>(F);
std::unique_ptr<MemorySSAUpdater> MSSAU;
if (MSSAAnalysis) {
auto *MSSA = &MSSAAnalysis->getMSSA();
MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
}
for (auto *L : *LI)
Changed |=
simplifyLoop(L, DT, LI, SE, AC, MSSAU.get(), false);
if (!Changed)
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<LoopAnalysis>();
PA.preserve<ScalarEvolutionAnalysis>();
PA.preserve<DependenceAnalysis>();
if (MSSAAnalysis)
PA.preserve<MemorySSAAnalysis>();
PA.preserve<BranchProbabilityAnalysis>();
return PA;
}
#if 0#endif
void LoopSimplify::verifyAnalysis() const {
#if 0#endif
}