Index: include/llvm/Transforms/Utils/LoopUtils.h =================================================================== --- include/llvm/Transforms/Utils/LoopUtils.h +++ include/llvm/Transforms/Utils/LoopUtils.h @@ -25,6 +25,7 @@ class AliasSetTracker; class AssumptionCache; class BasicBlock; +class BlockFrequencyInfo; class DataLayout; class DominatorTree; class Loop; @@ -357,9 +358,9 @@ /// Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, DataLayout, /// TargetLibraryInfo, Loop, AliasSet information for all instructions of the /// loop and loop safety information as arguments. It returns changed status. -bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, - TargetLibraryInfo *, Loop *, AliasSetTracker *, - LICMSafetyInfo *); +bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, + BlockFrequencyInfo *, DominatorTree *, TargetLibraryInfo *, + Loop *, AliasSetTracker *, LICMSafetyInfo *); /// \brief Try to promote memory values to scalars by sinking stores out of /// the loop and moving loads to before the loop. We do this by looping over Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/CaptureTracking.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/GlobalsModRef.h" @@ -121,6 +122,7 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); AU.addRequired(); + AU.addRequired(); getLoopAnalysisUsage(AU); } @@ -135,6 +137,7 @@ AliasAnalysis *AA; // Current AliasAnalysis information LoopInfo *LI; // Current LoopInfo DominatorTree *DT; // Dominator Tree for the current Loop. + BlockFrequencyInfo *BFI; TargetLibraryInfo *TLI; // TargetLibraryInfo for constant folding. @@ -164,6 +167,7 @@ INITIALIZE_PASS_BEGIN(LICM, "licm", "Loop Invariant Code Motion", false, false) INITIALIZE_PASS_DEPENDENCY(LoopPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) INITIALIZE_PASS_END(LICM, "licm", "Loop Invariant Code Motion", false, false) Pass *llvm::createLICMPass() { return new LICM(); } @@ -182,6 +186,7 @@ LI = &getAnalysis().getLoopInfo(); AA = &getAnalysis().getAAResults(); DT = &getAnalysis().getDomTree(); + BFI = &getAnalysis().getBFI(); TLI = &getAnalysis().getTLI(); @@ -212,7 +217,7 @@ Changed |= sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, TLI, CurLoop, CurAST, &SafetyInfo); if (Preheader) - Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, DT, TLI, + Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, BFI, DT, TLI, CurLoop, CurAST, &SafetyInfo); // Now that all loop invariants have been removed from the loop, promote any @@ -328,7 +333,8 @@ /// uses, allowing us to hoist a loop body in one pass without iteration. /// bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI, - DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop, + BlockFrequencyInfo *BFI, DominatorTree *DT, + TargetLibraryInfo *TLI, Loop *CurLoop, AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) { // Verify inputs. assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr && @@ -337,6 +343,10 @@ BasicBlock *BB = N->getBlock(); + bool ShouldHoist = true; + if (BFI->getBlockFreq(BB) < BFI->getBlockFreq(CurLoop->getLoopPreheader())) + ShouldHoist = false; + // If this subregion is not in the top level loop at all, exit. if (!CurLoop->contains(BB)) return false; @@ -359,6 +369,8 @@ I.eraseFromParent(); continue; } + if (!ShouldHoist) + continue; // Try hoisting the instruction out to the preheader. We can only do this // if all of the operands of the instruction are loop invariant and if it @@ -374,7 +386,8 @@ const std::vector &Children = N->getChildren(); for (DomTreeNode *Child : Children) - Changed |= hoistRegion(Child, AA, LI, DT, TLI, CurLoop, CurAST, SafetyInfo); + Changed |= + hoistRegion(Child, AA, LI, BFI, DT, TLI, CurLoop, CurAST, SafetyInfo); return Changed; } Index: test/Other/pass-pipelines.ll =================================================================== --- test/Other/pass-pipelines.ll +++ test/Other/pass-pipelines.ll @@ -37,6 +37,12 @@ ; CHECK-O2-NEXT: FunctionPass Manager ; CHECK-O2-NOT: Manager ; CHECK-O2: Loop Pass Manager +; CHECK-O2: Branch Probability Analysis +; CHECK-O2: Block Frequency Analysis +; CHECK-O2: Loop Pass Manager +; CHECK-O2: Loop Invariant Code Motion +; CHECK-O2: Loop Pass Manager +; CHECK-O2: Unswitch loops ; CHECK-O2-NOT: Manager ; FIXME: We shouldn't be pulling out to simplify-cfg and instcombine and ; causing new loop pass managers.