| //===-- LICM.cpp - Loop Invariant Code Motion Pass ------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This pass performs loop invariant code motion, attempting to remove as much | |
| // code from the body of a loop as possible. It does this by either hoisting | |
| // code into the preheader block, or by sinking code to the exit blocks if it is | |
| // safe. This pass also promotes must-aliased memory locations in the loop to | |
| // live in registers, thus hoisting and sinking "invariant" loads and stores. | |
| // | |
| // Hoisting operations out of loops is a canonicalization transform. It | |
| // enables and simplifies subsequent optimizations in the middle-end. | |
| // Rematerialization of hoisted instructions to reduce register pressure is the | |
| // responsibility of the back-end, which has more accurate information about | |
| // register pressure and also handles other optimizations than LICM that | |
| // increase live-ranges. | |
| // | |
| // This pass uses alias analysis for two purposes: | |
| // | |
| // 1. Moving loop invariant loads and calls out of loops. If we can determine | |
| // that a load or call inside of a loop never aliases anything stored to, | |
| // we can hoist it or sink it like any other instruction. | |
| // 2. Scalar Promotion of Memory - If there is a store instruction inside of | |
| // the loop, we try to move the store to happen AFTER the loop instead of | |
| // inside of the loop. This can only happen if a few conditions are true: | |
| // A. The pointer stored through is loop invariant | |
| // B. There are no stores or loads in the loop which _may_ alias the | |
| // pointer. There are no calls in the loop which mod/ref the pointer. | |
| // If these conditions are true, we can promote the loads and stores in the | |
| // loop of the pointer to use a temporary alloca'd variable. We then use | |
| // the SSAUpdater to construct the appropriate SSA form for the value. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Transforms/Scalar/LICM.h" | |
| #include "ScalarOptions.h" | |
| #include "llvm/ADT/DenseMap.h" | |
| #include "llvm/ADT/PriorityWorklist.h" | |
| #include "llvm/ADT/Statistic.h" | |
| #include "llvm/Analysis/AliasAnalysis.h" | |
| #include "llvm/Analysis/AliasSetTracker.h" | |
| #include "llvm/Analysis/AssumptionCache.h" | |
| #include "llvm/Analysis/CaptureTracking.h" | |
| #include "llvm/Analysis/DomTreeUpdater.h" | |
| #include "llvm/Analysis/GuardUtils.h" | |
| #include "llvm/Analysis/LazyBlockFrequencyInfo.h" | |
| #include "llvm/Analysis/Loads.h" | |
| #include "llvm/Analysis/LoopInfo.h" | |
| #include "llvm/Analysis/LoopIterator.h" | |
| #include "llvm/Analysis/LoopNestAnalysis.h" | |
| #include "llvm/Analysis/LoopPass.h" | |
| #include "llvm/Analysis/MemoryLocation.h" | |
| #include "llvm/Analysis/MemorySSA.h" | |
| #include "llvm/Analysis/MemorySSAUpdater.h" | |
| #include "llvm/Analysis/MustExecute.h" | |
| #include "llvm/Analysis/OptimizationRemarkEmitter.h" | |
| #include "llvm/Analysis/ScalarEvolution.h" | |
| #include "llvm/Analysis/TargetLibraryInfo.h" | |
| #include "llvm/Analysis/TargetTransformInfo.h" | |
| #include "llvm/Analysis/ValueTracking.h" | |
| #include "llvm/IR/CFG.h" | |
| #include "llvm/IR/Constants.h" | |
| #include "llvm/IR/DataLayout.h" | |
| #include "llvm/IR/DebugInfoMetadata.h" | |
| #include "llvm/IR/DerivedTypes.h" | |
| #include "llvm/IR/Dominators.h" | |
| #include "llvm/IR/IRBuilder.h" | |
| #include "llvm/IR/Instructions.h" | |
| #include "llvm/IR/IntrinsicInst.h" | |
| #include "llvm/IR/LLVMContext.h" | |
| #include "llvm/IR/Metadata.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/IR/PatternMatch.h" | |
| #include "llvm/IR/PredIteratorCache.h" | |
| #include "llvm/InitializePasses.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include "llvm/Transforms/Scalar.h" | |
| #include "llvm/Transforms/Utils/AssumeBundleBuilder.h" | |
| #include "llvm/Transforms/Utils/BasicBlockUtils.h" | |
| #include "llvm/Transforms/Utils/Local.h" | |
| #include "llvm/Transforms/Utils/LoopUtils.h" | |
| #include "llvm/Transforms/Utils/SSAUpdater.h" | |
| #include <algorithm> | |
| #include <utility> | |
| using namespace llvm; | |
| namespace llvm { | |
| class LPMUpdater; | |
| } // namespace llvm | |
| #define DEBUG_TYPE "licm" | |
| STATISTIC(NumSunk, "Number of instructions sunk out of loop"); | |
| STATISTIC(NumHoisted, "Number of instructions hoisted out of loop"); | |
| STATISTIC(NumMovedLoads, "Number of load insts hoisted or sunk"); | |
| STATISTIC(NumMovedCalls, "Number of call insts hoisted or sunk"); | |
| STATISTIC(NumPromotionCandidates, "Number of promotion candidates"); | |
| STATISTIC(NumLoadPromoted, "Number of load-only promotions"); | |
| STATISTIC(NumLoadStorePromoted, "Number of load and store promotions"); | |
| STATISTIC(NumMinMaxHoisted, | |
| "Number of min/max expressions hoisted out of the loop"); | |
| STATISTIC(NumGEPsHoisted, | |
| "Number of geps reassociated and hoisted out of the loop"); | |
| STATISTIC(NumAddSubHoisted, "Number of add/subtract expressions reassociated " | |
| "and hoisted out of the loop"); | |
| STATISTIC(NumFPAssociationsHoisted, "Number of invariant FP expressions " | |
| "reassociated and hoisted out of the loop"); | |
| STATISTIC(NumIntAssociationsHoisted, | |
| "Number of invariant int expressions " | |
| "reassociated and hoisted out of the loop"); | |
| STATISTIC(NumBOAssociationsHoisted, "Number of invariant BinaryOp expressions " | |
| "reassociated and hoisted out of the loop"); | |
| unsigned | |
| llvm::getLicmMssaOptCap(const cl::LibraryOptionsContext *LibraryOptions) { | |
| return cl::LibraryOptionsContext::get<ScalarOptions>(LibraryOptions) | |
| .licm_mssa_optimization_cap; | |
| } | |
| unsigned llvm::getLicmMssaNoAccForPromotionCap( | |
| const cl::LibraryOptionsContext *LibraryOptions) { | |
| return cl::LibraryOptionsContext::get<ScalarOptions>(LibraryOptions) | |
| .licm_mssa_max_acc_promotion; | |
| } | |
| static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI); | |
| static bool isNotUsedOrFoldableInLoop(const Instruction &I, const Loop *CurLoop, | |
| const LoopSafetyInfo *SafetyInfo, | |
| TargetTransformInfo *TTI, | |
| bool &FoldableInLoop, bool LoopNestMode); | |
| static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, | |
| BasicBlock *Dest, ICFLoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater &MSSAU, ScalarEvolution *SE, | |
| OptimizationRemarkEmitter *ORE); | |
| static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, | |
| const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE); | |
| static bool isSafeToExecuteUnconditionally( | |
| Instruction &Inst, const DominatorTree *DT, const TargetLibraryInfo *TLI, | |
| const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, | |
| OptimizationRemarkEmitter *ORE, const Instruction *CtxI, | |
| AssumptionCache *AC, bool AllowSpeculation); | |
| static bool noConflictingReadWrites(Instruction *I, MemorySSA *MSSA, | |
| AAResults *AA, Loop *CurLoop, | |
| SinkAndHoistLICMFlags &Flags); | |
| static bool pointerInvalidatedByLoop(MemorySSA *MSSA, MemoryUse *MU, | |
| Loop *CurLoop, Instruction &I, | |
| SinkAndHoistLICMFlags &Flags, | |
| bool InvariantGroup); | |
| static bool pointerInvalidatedByBlock(BasicBlock &BB, MemorySSA &MSSA, | |
| MemoryUse &MU); | |
| /// Aggregates various functions for hoisting computations out of loop. | |
| static bool hoistArithmetics(const ScalarOptions &Opts, Instruction &I, Loop &L, | |
| ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT); | |
| static bool hoistInsertPastInsert(InsertElementInst *Ins, Loop *CurLoop, | |
| DominatorTree *DT, BasicBlock *HoistDest, | |
| ICFLoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater &MSSAU, ScalarEvolution *SE, | |
| OptimizationRemarkEmitter *ORE); | |
| static Instruction *cloneInstructionInExitBlock( | |
| Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI, | |
| const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU); | |
| static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU); | |
| static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest, | |
| ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, ScalarEvolution *SE); | |
| static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L, | |
| function_ref<void(Instruction *)> Fn); | |
| using PointersAndHasReadsOutsideSet = | |
| std::pair<SmallSetVector<Value *, 8>, bool>; | |
| static SmallVector<PointersAndHasReadsOutsideSet, 0> collectPromotionCandidates( | |
| MemorySSA *MSSA, AliasAnalysis *AA, DominatorTree *DT, | |
| ICFLoopSafetyInfo *SafetyInfo, | |
| const SmallPtrSetImpl<const MDNode *> &LoopLocalAliasScopes, Loop *L); | |
| static const ScalarOptions &getScalarOptions(const Loop &L) { | |
| return L.getHeader()->getContext().getLibraryOptions().get<ScalarOptions>(); | |
| } | |
| namespace { | |
| struct LoopInvariantCodeMotion { | |
| bool runOnLoop(Loop *L, AAResults *AA, LoopInfo *LI, DominatorTree *DT, | |
| AssumptionCache *AC, TargetLibraryInfo *TLI, | |
| TargetTransformInfo *TTI, ScalarEvolution *SE, MemorySSA *MSSA, | |
| OptimizationRemarkEmitter *ORE, bool LoopNestMode = false); | |
| LoopInvariantCodeMotion(const ScalarOptions &Opts, const LICMOptions &LO) | |
| : Opts(Opts), | |
| LicmMssaOptCap(LO.MssaOptCap.value_or(Opts.licm_mssa_optimization_cap)), | |
| LicmMssaNoAccForPromotionCap(LO.MssaNoAccForPromotionCap.value_or( | |
| Opts.licm_mssa_max_acc_promotion)), | |
| LicmAllowSpeculation(LO.AllowSpeculation) {} | |
| private: | |
| const ScalarOptions &Opts; | |
| unsigned LicmMssaOptCap; | |
| unsigned LicmMssaNoAccForPromotionCap; | |
| bool LicmAllowSpeculation; | |
| }; | |
| struct LegacyLICMPass : public LoopPass { | |
| static char ID; // Pass identification, replacement for typeid | |
| LegacyLICMPass() : LoopPass(ID) { | |
| initializeLegacyLICMPassPass(*PassRegistry::getPassRegistry()); | |
| } | |
| bool runOnLoop(Loop *L, LPPassManager &LPM) override { | |
| if (skipLoop(L)) | |
| return false; | |
| LLVM_DEBUG(dbgs() << "Perform LICM on Loop with header at block " | |
| << L->getHeader()->getNameOrAsOperand() << "\n"); | |
| Function *F = L->getHeader()->getParent(); | |
| auto *SE = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>(); | |
| MemorySSA *MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA(); | |
| // For the old PM, we can't use OptimizationRemarkEmitter as an analysis | |
| // pass. Function analyses need to be preserved across loop transformations | |
| // but ORE cannot be preserved (see comment before the pass definition). | |
| OptimizationRemarkEmitter ORE(L->getHeader()->getParent()); | |
| const ScalarOptions &Opts = | |
| F->getContext().getLibraryOptions().get<ScalarOptions>(); | |
| LoopInvariantCodeMotion LICM(Opts, LICMOptions()); | |
| return LICM.runOnLoop( | |
| L, &getAnalysis<AAResultsWrapperPass>().getAAResults(), | |
| &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(), | |
| &getAnalysis<DominatorTreeWrapperPass>().getDomTree(), | |
| &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F), | |
| &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(*F), | |
| &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*F), | |
| SE ? &SE->getSE() : nullptr, MSSA, &ORE); | |
| } | |
| /// This transformation requires natural loop information & requires that | |
| /// loop preheaders be inserted into the CFG... | |
| /// | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.addPreserved<DominatorTreeWrapperPass>(); | |
| AU.addPreserved<LoopInfoWrapperPass>(); | |
| AU.addRequired<TargetLibraryInfoWrapperPass>(); | |
| AU.addRequired<MemorySSAWrapperPass>(); | |
| AU.addPreserved<MemorySSAWrapperPass>(); | |
| AU.addRequired<TargetTransformInfoWrapperPass>(); | |
| AU.addRequired<AssumptionCacheTracker>(); | |
| getLoopAnalysisUsage(AU); | |
| LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU); | |
| AU.addPreserved<LazyBlockFrequencyInfoPass>(); | |
| AU.addPreserved<LazyBranchProbabilityInfoPass>(); | |
| } | |
| }; | |
| } // namespace | |
| PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM, | |
| LoopStandardAnalysisResults &AR, LPMUpdater &) { | |
| if (!AR.MSSA) | |
| reportFatalUsageError("LICM requires MemorySSA (loop-mssa)"); | |
| // For the new PM, we also can't use OptimizationRemarkEmitter as an analysis | |
| // pass. Function analyses need to be preserved across loop transformations | |
| // but ORE cannot be preserved (see comment before the pass definition). | |
| OptimizationRemarkEmitter ORE(L.getHeader()->getParent()); | |
| LoopInvariantCodeMotion LICM(getScalarOptions(L), Opts); | |
| if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, &AR.AC, &AR.TLI, &AR.TTI, | |
| &AR.SE, AR.MSSA, &ORE)) | |
| return PreservedAnalyses::all(); | |
| auto PA = getLoopPassPreservedAnalyses(); | |
| PA.preserve<MemorySSAAnalysis>(); | |
| return PA; | |
| } | |
| void LICMPass::printPipeline( | |
| raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { | |
| static_cast<PassInfoMixin<LICMPass> *>(this)->printPipeline( | |
| OS, MapClassName2PassName); | |
| OS << '<'; | |
| OS << (Opts.AllowSpeculation ? "" : "no-") << "allowspeculation"; | |
| OS << '>'; | |
| } | |
| PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM, | |
| LoopStandardAnalysisResults &AR, | |
| LPMUpdater &) { | |
| if (!AR.MSSA) | |
| reportFatalUsageError("LNICM requires MemorySSA (loop-mssa)"); | |
| // For the new PM, we also can't use OptimizationRemarkEmitter as an analysis | |
| // pass. Function analyses need to be preserved across loop transformations | |
| // but ORE cannot be preserved (see comment before the pass definition). | |
| OptimizationRemarkEmitter ORE(LN.getParent()); | |
| Loop &OutermostLoop = LN.getOutermostLoop(); | |
| LoopInvariantCodeMotion LICM(getScalarOptions(OutermostLoop), Opts); | |
| bool Changed = LICM.runOnLoop(&OutermostLoop, &AR.AA, &AR.LI, &AR.DT, &AR.AC, | |
| &AR.TLI, &AR.TTI, &AR.SE, AR.MSSA, &ORE, true); | |
| if (!Changed) | |
| return PreservedAnalyses::all(); | |
| auto PA = getLoopPassPreservedAnalyses(); | |
| PA.preserve<DominatorTreeAnalysis>(); | |
| PA.preserve<LoopAnalysis>(); | |
| PA.preserve<MemorySSAAnalysis>(); | |
| return PA; | |
| } | |
| void LNICMPass::printPipeline( | |
| raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { | |
| static_cast<PassInfoMixin<LNICMPass> *>(this)->printPipeline( | |
| OS, MapClassName2PassName); | |
| OS << '<'; | |
| OS << (Opts.AllowSpeculation ? "" : "no-") << "allowspeculation"; | |
| OS << '>'; | |
| } | |
| char LegacyLICMPass::ID = 0; | |
| INITIALIZE_PASS_BEGIN(LegacyLICMPass, "licm", "Loop Invariant Code Motion", | |
| false, false) | |
| INITIALIZE_PASS_DEPENDENCY(LoopPass) | |
| INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | |
| INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) | |
| INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass) | |
| INITIALIZE_PASS_DEPENDENCY(LazyBFIPass) | |
| INITIALIZE_PASS_END(LegacyLICMPass, "licm", "Loop Invariant Code Motion", false, | |
| false) | |
| Pass *llvm::createLICMPass() { return new LegacyLICMPass(); } | |
| llvm::SinkAndHoistLICMFlags::SinkAndHoistLICMFlags(bool IsSink, Loop &L, | |
| MemorySSA &MSSA) | |
| : SinkAndHoistLICMFlags(getScalarOptions(L).licm_mssa_optimization_cap, | |
| getScalarOptions(L).licm_mssa_max_acc_promotion, | |
| IsSink, L, MSSA) {} | |
| llvm::SinkAndHoistLICMFlags::SinkAndHoistLICMFlags( | |
| unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap, bool IsSink, | |
| Loop &L, MemorySSA &MSSA) | |
| : LicmMssaOptCap(LicmMssaOptCap), | |
| LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap), | |
| IsSink(IsSink) { | |
| unsigned AccessCapCount = 0; | |
| for (auto *BB : L.getBlocks()) | |
| if (const auto *Accesses = MSSA.getBlockAccesses(BB)) | |
| for (const auto &MA : *Accesses) { | |
| (void)MA; | |
| ++AccessCapCount; | |
| if (AccessCapCount > LicmMssaNoAccForPromotionCap) { | |
| NoOfMemAccTooLarge = true; | |
| return; | |
| } | |
| } | |
| } | |
| /// Hoist expressions out of the specified loop. Note, alias info for inner | |
| /// loop is not preserved so it is not a good idea to run LICM multiple | |
| /// times on one loop. | |
| bool LoopInvariantCodeMotion::runOnLoop(Loop *L, AAResults *AA, LoopInfo *LI, | |
| DominatorTree *DT, AssumptionCache *AC, | |
| TargetLibraryInfo *TLI, | |
| TargetTransformInfo *TTI, | |
| ScalarEvolution *SE, MemorySSA *MSSA, | |
| OptimizationRemarkEmitter *ORE, | |
| bool LoopNestMode) { | |
| bool Changed = false; | |
| assert(L->isLCSSAForm(*DT) && "Loop is not in LCSSA form."); | |
| // If this loop has metadata indicating that LICM is not to be performed then | |
| // just exit. | |
| if (hasDisableLICMTransformsHint(L)) { | |
| return false; | |
| } | |
| // Don't sink stores from loops with coroutine suspend instructions. | |
| // LICM would sink instructions into the default destination of | |
| // the coroutine switch. The default destination of the switch is to | |
| // handle the case where the coroutine is suspended, by which point the | |
| // coroutine frame may have been destroyed. No instruction can be sunk there. | |
| // FIXME: This would unfortunately hurt the performance of coroutines, however | |
| // there is currently no general solution for this. Similar issues could also | |
| // potentially happen in other passes where instructions are being moved | |
| // across that edge. | |
| bool HasCoroSuspendInst = false; | |
| // AA metadata declared to be local to each iteration cannot be used to infer | |
| // alias information when promoting stores. | |
| SmallPtrSet<const MDNode *, 4> LoopLocalAliasScopes; | |
| for (BasicBlock *BB : L->getBlocks()) { | |
| for (Instruction &I : *BB) { | |
| using namespace PatternMatch; | |
| HasCoroSuspendInst |= match(&I, m_Intrinsic<Intrinsic::coro_suspend>()); | |
| if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I)) | |
| for (const MDOperand &Op : Decl->getScopeList()->operands()) | |
| LoopLocalAliasScopes.insert(cast<MDNode>(Op.get())); | |
| } | |
| } | |
| MemorySSAUpdater MSSAU(MSSA); | |
| SinkAndHoistLICMFlags Flags(LicmMssaOptCap, LicmMssaNoAccForPromotionCap, | |
| /*IsSink=*/true, *L, *MSSA); | |
| // Get the preheader block to move instructions into... | |
| BasicBlock *Preheader = L->getLoopPreheader(); | |
| // Compute loop safety information. | |
| ICFLoopSafetyInfo SafetyInfo(L); | |
| // We want to visit all of the instructions in this loop... that are not parts | |
| // of our subloops (they have already had their invariants hoisted out of | |
| // their loop, into this loop, so there is no need to process the BODIES of | |
| // the subloops). | |
| // | |
| // Traverse the body of the loop in depth first order on the dominator tree so | |
| // that we are guaranteed to see definitions before we see uses. This allows | |
| // us to sink instructions in one pass, without iteration. After sinking | |
| // instructions, we perform another pass to hoist them out of the loop. | |
| if (L->hasDedicatedExits()) | |
| Changed |= | |
| LoopNestMode | |
| ? sinkRegionForLoopNest(DT->getNode(L->getHeader()), AA, LI, DT, | |
| TLI, TTI, L, MSSAU, &SafetyInfo, Flags, ORE) | |
| : sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, TLI, TTI, L, | |
| MSSAU, &SafetyInfo, Flags, ORE); | |
| Flags.setIsSink(false); | |
| if (Preheader) | |
| Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, DT, AC, TLI, L, | |
| MSSAU, SE, &SafetyInfo, Flags, ORE, LoopNestMode, | |
| LicmAllowSpeculation); | |
| // Now that all loop invariants have been removed from the loop, promote any | |
| // memory references to scalars that we can. | |
| // Don't sink stores from loops without dedicated block exits. Exits | |
| // containing indirect branches are not transformed by loop simplify, | |
| // make sure we catch that. An additional load may be generated in the | |
| // preheader for SSA updater, so also avoid sinking when no preheader | |
| // is available. | |
| if (!Opts.disable_licm_promotion && Preheader && L->hasDedicatedExits() && | |
| !Flags.tooManyMemoryAccesses() && !HasCoroSuspendInst) { | |
| // Figure out the loop exits and their insertion points | |
| SmallVector<BasicBlock *, 8> ExitBlocks; | |
| L->getUniqueExitBlocks(ExitBlocks); | |
| // We can't insert into a catchswitch. | |
| bool HasCatchSwitch = llvm::any_of(ExitBlocks, [](BasicBlock *Exit) { | |
| return isa<CatchSwitchInst>(Exit->getTerminator()); | |
| }); | |
| if (!HasCatchSwitch) { | |
| SmallVector<BasicBlock::iterator, 8> InsertPts; | |
| SmallVector<MemoryAccess *, 8> MSSAInsertPts; | |
| InsertPts.reserve(ExitBlocks.size()); | |
| MSSAInsertPts.reserve(ExitBlocks.size()); | |
| PredIteratorCache PIC; | |
| // Promoting one set of accesses may make the pointers for another set | |
| // loop invariant, so run this in a loop. | |
| bool Promoted = false; | |
| bool LocalPromoted; | |
| do { | |
| LocalPromoted = false; | |
| // Recompute the insertion points each time we compute the promotion | |
| // candidates, so we don't sink past a store which was promoted in a | |
| // previous iteration. | |
| InsertPts.clear(); | |
| MSSAInsertPts.clear(); | |
| for (BasicBlock *ExitBlock : ExitBlocks) { | |
| InsertPts.push_back(ExitBlock->getFirstInsertionPt()); | |
| MSSAInsertPts.push_back(nullptr); | |
| } | |
| for (auto [PointerMustAliases, HasReadsOutsideSet] : | |
| collectPromotionCandidates(MSSA, AA, DT, &SafetyInfo, | |
| LoopLocalAliasScopes, L)) { | |
| LocalPromoted |= promoteLoopAccessesToScalars( | |
| PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI, | |
| DT, AC, TLI, TTI, L, MSSAU, &SafetyInfo, ORE, | |
| LicmAllowSpeculation, HasReadsOutsideSet); | |
| } | |
| Promoted |= LocalPromoted; | |
| } while (LocalPromoted); | |
| // Once we have promoted values across the loop body we have to | |
| // recursively reform LCSSA as any nested loop may now have values defined | |
| // within the loop used in the outer loop. | |
| // FIXME: This is really heavy handed. It would be a bit better to use an | |
| // SSAUpdater strategy during promotion that was LCSSA aware and reformed | |
| // it as it went. | |
| if (Promoted) | |
| formLCSSARecursively(*L, *DT, LI, SE); | |
| Changed |= Promoted; | |
| } | |
| } | |
| // Check that neither this loop nor its parent have had LCSSA broken. LICM is | |
| // specifically moving instructions across the loop boundary and so it is | |
| // especially in need of basic functional correctness checking here. | |
| assert(L->isLCSSAForm(*DT) && "Loop not left in LCSSA form after LICM!"); | |
| assert((L->isOutermost() || L->getParentLoop()->isLCSSAForm(*DT)) && | |
| "Parent loop not left in LCSSA form after LICM!"); | |
| if (VerifyMemorySSA) | |
| MSSA->verifyMemorySSA(); | |
| if (Changed && SE) | |
| SE->forgetLoopDispositions(); | |
| return Changed; | |
| } | |
| /// Walk the specified region of the CFG (defined by all blocks dominated by | |
| /// the specified block, and that are in the current loop) in reverse depth | |
| /// first order w.r.t the DominatorTree. This allows us to visit uses before | |
| /// definitions, allowing us to sink a loop body in one pass without iteration. | |
| /// | |
| bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI, | |
| DominatorTree *DT, TargetLibraryInfo *TLI, | |
| TargetTransformInfo *TTI, Loop *CurLoop, | |
| MemorySSAUpdater &MSSAU, ICFLoopSafetyInfo *SafetyInfo, | |
| SinkAndHoistLICMFlags &Flags, | |
| OptimizationRemarkEmitter *ORE, Loop *OutermostLoop) { | |
| // Verify inputs. | |
| assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr && | |
| CurLoop != nullptr && SafetyInfo != nullptr && | |
| "Unexpected input to sinkRegion."); | |
| // We want to visit children before parents. We will enqueue all the parents | |
| // before their children in the worklist and process the worklist in reverse | |
| // order. | |
| SmallVector<BasicBlock *, 16> Worklist = | |
| collectChildrenInLoop(DT, N, CurLoop); | |
| bool Changed = false; | |
| for (BasicBlock *BB : reverse(Worklist)) { | |
| // subloop (which would already have been processed). | |
| if (inSubLoop(BB, CurLoop, LI)) | |
| continue; | |
| for (BasicBlock::iterator II = BB->end(); II != BB->begin();) { | |
| Instruction &I = *--II; | |
| // The instruction is not used in the loop if it is dead. In this case, | |
| // we just delete it instead of sinking it. | |
| if (isInstructionTriviallyDead(&I, TLI)) { | |
| LLVM_DEBUG(dbgs() << "LICM deleting dead inst: " << I << '\n'); | |
| salvageKnowledge(&I); | |
| salvageDebugInfo(I); | |
| ++II; | |
| eraseInstruction(I, *SafetyInfo, MSSAU); | |
| Changed = true; | |
| continue; | |
| } | |
| // Check to see if we can sink this instruction to the exit blocks | |
| // of the loop. We can do this if the all users of the instruction are | |
| // outside of the loop. In this case, it doesn't even matter if the | |
| // operands of the instruction are loop invariant. | |
| // | |
| bool FoldableInLoop = false; | |
| bool LoopNestMode = OutermostLoop != nullptr; | |
| if (!I.mayHaveSideEffects() && | |
| isNotUsedOrFoldableInLoop(I, LoopNestMode ? OutermostLoop : CurLoop, | |
| SafetyInfo, TTI, FoldableInLoop, | |
| LoopNestMode) && | |
| canSinkOrHoistInst(I, AA, DT, CurLoop, MSSAU, true, Flags, ORE)) { | |
| if (sink(I, LI, DT, CurLoop, SafetyInfo, MSSAU, ORE)) { | |
| if (!FoldableInLoop) { | |
| ++II; | |
| salvageDebugInfo(I); | |
| eraseInstruction(I, *SafetyInfo, MSSAU); | |
| } | |
| Changed = true; | |
| } | |
| } | |
| } | |
| } | |
| if (VerifyMemorySSA) | |
| MSSAU.getMemorySSA()->verifyMemorySSA(); | |
| return Changed; | |
| } | |
| bool llvm::sinkRegionForLoopNest(DomTreeNode *N, AAResults *AA, LoopInfo *LI, | |
| DominatorTree *DT, TargetLibraryInfo *TLI, | |
| TargetTransformInfo *TTI, Loop *CurLoop, | |
| MemorySSAUpdater &MSSAU, | |
| ICFLoopSafetyInfo *SafetyInfo, | |
| SinkAndHoistLICMFlags &Flags, | |
| OptimizationRemarkEmitter *ORE) { | |
| bool Changed = false; | |
| SmallPriorityWorklist<Loop *, 4> Worklist; | |
| Worklist.insert(CurLoop); | |
| appendLoopsToWorklist(*CurLoop, Worklist); | |
| while (!Worklist.empty()) { | |
| Loop *L = Worklist.pop_back_val(); | |
| Changed |= sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, TLI, TTI, L, | |
| MSSAU, SafetyInfo, Flags, ORE, CurLoop); | |
| } | |
| return Changed; | |
| } | |
| /// Walk the specified region of the CFG (defined by all blocks dominated by | |
| /// the specified block, and that are in the current loop) in depth first | |
| /// order w.r.t the DominatorTree. This allows us to visit definitions before | |
| /// uses, allowing us to hoist a loop body in one pass without iteration. | |
| /// | |
| bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI, | |
| DominatorTree *DT, AssumptionCache *AC, | |
| TargetLibraryInfo *TLI, Loop *CurLoop, | |
| MemorySSAUpdater &MSSAU, ScalarEvolution *SE, | |
| ICFLoopSafetyInfo *SafetyInfo, | |
| SinkAndHoistLICMFlags &Flags, | |
| OptimizationRemarkEmitter *ORE, bool LoopNestMode, | |
| bool AllowSpeculation) { | |
| // Verify inputs. | |
| assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr && | |
| CurLoop != nullptr && SafetyInfo != nullptr && | |
| "Unexpected input to hoistRegion."); | |
| const ScalarOptions &Opts = getScalarOptions(*CurLoop); | |
| LoopBlocksRPO Worklist(CurLoop); | |
| Worklist.perform(LI); | |
| bool Changed = false; | |
| BasicBlock *Preheader = CurLoop->getLoopPreheader(); | |
| for (BasicBlock *BB : Worklist) { | |
| // Only need to process the contents of this block if it is not part of a | |
| // subloop (which would already have been processed). | |
| if (!LoopNestMode && inSubLoop(BB, CurLoop, LI)) | |
| continue; | |
| for (Instruction &I : llvm::make_early_inc_range(*BB)) { | |
| // 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 is safe to hoist the instruction. | |
| if (CurLoop->hasLoopInvariantOperands(&I) && | |
| canSinkOrHoistInst(I, AA, DT, CurLoop, MSSAU, true, Flags, ORE) && | |
| isSafeToExecuteUnconditionally(I, DT, TLI, CurLoop, SafetyInfo, ORE, | |
| Preheader->getTerminator(), AC, | |
| AllowSpeculation)) { | |
| hoist(I, DT, CurLoop, Preheader, SafetyInfo, MSSAU, SE, ORE); | |
| Changed = true; | |
| continue; | |
| } | |
| if (auto *Ins = dyn_cast<InsertElementInst>(&I)) | |
| if (hoistInsertPastInsert(Ins, CurLoop, DT, Preheader, SafetyInfo, | |
| MSSAU, SE, ORE)) { | |
| Changed = true; | |
| continue; | |
| } | |
| // Attempt to remove floating point division out of the loop by | |
| // converting it to a reciprocal multiplication. | |
| if (I.getOpcode() == Instruction::FDiv && I.hasAllowReciprocal() && | |
| CurLoop->isLoopInvariant(I.getOperand(1))) { | |
| auto Divisor = I.getOperand(1); | |
| auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0); | |
| auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor); | |
| ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags()); | |
| SafetyInfo->insertInstructionTo(ReciprocalDivisor, I.getParent()); | |
| ReciprocalDivisor->insertBefore(I.getIterator()); | |
| ReciprocalDivisor->setDebugLoc(I.getDebugLoc()); | |
| auto Product = | |
| BinaryOperator::CreateFMul(I.getOperand(0), ReciprocalDivisor); | |
| Product->setFastMathFlags(I.getFastMathFlags()); | |
| SafetyInfo->insertInstructionTo(Product, I.getParent()); | |
| Product->insertAfter(I.getIterator()); | |
| Product->setDebugLoc(I.getDebugLoc()); | |
| I.replaceAllUsesWith(Product); | |
| eraseInstruction(I, *SafetyInfo, MSSAU); | |
| hoist(*ReciprocalDivisor, DT, CurLoop, Preheader, SafetyInfo, MSSAU, SE, | |
| ORE); | |
| Changed = true; | |
| continue; | |
| } | |
| auto IsInvariantStart = [&](Instruction &I) { | |
| using namespace PatternMatch; | |
| return I.use_empty() && | |
| match(&I, m_Intrinsic<Intrinsic::invariant_start>()); | |
| }; | |
| auto MustExecuteWithoutWritesBefore = [&](Instruction &I) { | |
| return SafetyInfo->isGuaranteedToExecute(I, DT) && | |
| SafetyInfo->doesNotWriteMemoryBefore(I); | |
| }; | |
| if ((IsInvariantStart(I) || isGuard(&I)) && | |
| CurLoop->hasLoopInvariantOperands(&I) && | |
| MustExecuteWithoutWritesBefore(I)) { | |
| hoist(I, DT, CurLoop, Preheader, SafetyInfo, MSSAU, SE, ORE); | |
| Changed = true; | |
| continue; | |
| } | |
| // Try to reassociate instructions so that part of computations can be | |
| // done out of loop. | |
| if (hoistArithmetics(Opts, I, *CurLoop, *SafetyInfo, MSSAU, AC, DT)) { | |
| Changed = true; | |
| continue; | |
| } | |
| } | |
| } | |
| if (VerifyMemorySSA) | |
| MSSAU.getMemorySSA()->verifyMemorySSA(); | |
| // Now that we've finished hoisting make sure that LI and DT are still | |
| // valid. | |
| #ifdef EXPENSIVE_CHECKS | |
| if (Changed) { | |
| assert(DT->verify(DominatorTree::VerificationLevel::Fast) && | |
| "Dominator tree verification failed"); | |
| LI->verify(); | |
| } | |
| #endif | |
| return Changed; | |
| } | |
| static std::optional<uint64_t> | |
| getConstantInsertionIndex(InsertElementInst *Ins) { | |
| // Must have constant insertion lane. | |
| auto *InsertedIdxCI = dyn_cast<ConstantInt>(Ins->getOperand(2)); | |
| if (!InsertedIdxCI) | |
| return std::nullopt; | |
| auto *VecTy = cast<VectorType>(Ins->getType()); | |
| // Avoid hoisting past out of bounds inserts. | |
| if (InsertedIdxCI->isNegative() || | |
| InsertedIdxCI->getValue().uge( | |
| VecTy->getElementCount().getKnownMinValue())) | |
| return std::nullopt; | |
| return InsertedIdxCI->getValue().getLimitedValue(); | |
| } | |
| static bool hoistInsertPastInsert(InsertElementInst *Ins, Loop *CurLoop, | |
| DominatorTree *DT, BasicBlock *HoistDest, | |
| ICFLoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater &MSSAU, ScalarEvolution *SE, | |
| OptimizationRemarkEmitter *ORE) { | |
| // Canonicalize: | |
| // %inner = insertelement %base, %variant, C1 | |
| // %outer = insertelement %inner, %invariant, C2 | |
| // into: | |
| // %outer = insertelement %base, %invariant, C2 | |
| // %inner = insertelement %outer, %variant, C1 | |
| // so we can hoist %outer | |
| // The instruction we are hoisting must have invariant insertion data | |
| Value *InsertedElt = Ins->getOperand(1); | |
| if (!CurLoop->isLoopInvariant(InsertedElt)) | |
| return false; | |
| std::optional<uint64_t> HoistIdx = getConstantInsertionIndex(Ins); | |
| if (!HoistIdx) | |
| return false; | |
| InsertElementInst *Inner = Ins; | |
| while (!CurLoop->isLoopInvariant(Inner->getOperand(0))) { | |
| // If the inner value isn't invariant, check to see if it is another insert | |
| // All instructions in the chain must be in the same basic block | |
| auto *InnerIns = dyn_cast<InsertElementInst>(Inner->getOperand(0)); | |
| if (!InnerIns || InnerIns->getParent() != Ins->getParent()) | |
| return false; | |
| // Make sure not hoisting past insertions into the same lane | |
| std::optional<uint64_t> InsertIdx = getConstantInsertionIndex(InnerIns); | |
| if (!InsertIdx || *InsertIdx == *HoistIdx) | |
| return false; | |
| // Instruction being hoisted past must only have one use | |
| if (!InnerIns->hasOneUse()) | |
| return false; | |
| Inner = InnerIns; | |
| } | |
| // Base case of `insertelement <4 x i8> %invar0, i8 %invar1, i32 2` handled in | |
| // base LICM logic | |
| if (Inner == Ins) | |
| return false; | |
| Ins->replaceAllUsesWith(Ins->getOperand(0)); | |
| Ins->moveBefore(Inner->getIterator()); | |
| Ins->setOperand(0, Inner->getOperand(0)); | |
| Inner->setOperand(0, Ins); | |
| hoist(*Ins, DT, CurLoop, HoistDest, SafetyInfo, MSSAU, SE, ORE); | |
| return true; | |
| } | |
| // Return true if LI is invariant within scope of the loop. LI is invariant if | |
| // CurLoop is dominated by an invariant.start representing the same memory | |
| // location and size as the memory location LI loads from, and also the | |
| // invariant.start has no uses. | |
| static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT, | |
| Loop *CurLoop) { | |
| Value *Addr = LI->getPointerOperand(); | |
| const DataLayout &DL = LI->getDataLayout(); | |
| const TypeSize LocSizeInBits = DL.getTypeSizeInBits(LI->getType()); | |
| // It is not currently possible for clang to generate an invariant.start | |
| // intrinsic with scalable vector types because we don't support thread local | |
| // sizeless types and we don't permit sizeless types in structs or classes. | |
| // Furthermore, even if support is added for this in future the intrinsic | |
| // itself is defined to have a size of -1 for variable sized objects. This | |
| // makes it impossible to verify if the intrinsic envelops our region of | |
| // interest. For example, both <vscale x 32 x i8> and <vscale x 16 x i8> | |
| // types would have a -1 parameter, but the former is clearly double the size | |
| // of the latter. | |
| if (LocSizeInBits.isScalable()) | |
| return false; | |
| // If we've ended up at a global/constant, bail. We shouldn't be looking at | |
| // uselists for non-local Values in a loop pass. | |
| if (isa<Constant>(Addr)) | |
| return false; | |
| const ScalarOptions &Opts = | |
| LI->getContext().getLibraryOptions().get<ScalarOptions>(); | |
| unsigned UsesVisited = 0; | |
| // Traverse all uses of the load operand value, to see if invariant.start is | |
| // one of the uses, and whether it dominates the load instruction. | |
| for (auto *U : Addr->users()) { | |
| // Avoid traversing for Load operand with high number of users. | |
| if (++UsesVisited > Opts.licm_max_num_uses_traversed) | |
| return false; | |
| IntrinsicInst *II = dyn_cast<IntrinsicInst>(U); | |
| // If there are escaping uses of invariant.start instruction, the load maybe | |
| // non-invariant. | |
| if (!II || II->getIntrinsicID() != Intrinsic::invariant_start || | |
| !II->use_empty()) | |
| continue; | |
| ConstantInt *InvariantSize = cast<ConstantInt>(II->getArgOperand(0)); | |
| // The intrinsic supports having a -1 argument for variable sized objects | |
| // so we should check for that here. | |
| if (InvariantSize->isNegative()) | |
| continue; | |
| uint64_t InvariantSizeInBits = InvariantSize->getSExtValue() * 8; | |
| // Confirm the invariant.start location size contains the load operand size | |
| // in bits. Also, the invariant.start should dominate the load, and we | |
| // should not hoist the load out of a loop that contains this dominating | |
| // invariant.start. | |
| if (LocSizeInBits.getFixedValue() <= InvariantSizeInBits && | |
| DT->properlyDominates(II->getParent(), CurLoop->getHeader())) | |
| return true; | |
| } | |
| return false; | |
| } | |
| /// Return true if-and-only-if we know how to (mechanically) both hoist and | |
| /// sink a given instruction out of a loop. Does not address legality | |
| /// concerns such as aliasing or speculation safety. | |
| static bool isHoistableAndSinkableInst(Instruction &I) { | |
| // Only these instructions are hoistable/sinkable. | |
| return (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || | |
| isa<FenceInst>(I) || isa<CastInst>(I) || isa<UnaryOperator>(I) || | |
| isa<BinaryOperator>(I) || isa<SelectInst>(I) || | |
| isa<GetElementPtrInst>(I) || isa<CmpInst>(I) || | |
| isa<InsertElementInst>(I) || isa<ExtractElementInst>(I) || | |
| isa<ShuffleVectorInst>(I) || isa<ExtractValueInst>(I) || | |
| isa<InsertValueInst>(I) || isa<FreezeInst>(I)); | |
| } | |
| /// Return true if I is the only Instruction with a MemoryAccess in L. | |
| static bool isOnlyMemoryAccess(const Instruction *I, const Loop *L, | |
| const MemorySSAUpdater &MSSAU) { | |
| for (auto *BB : L->getBlocks()) | |
| if (auto *Accs = MSSAU.getMemorySSA()->getBlockAccesses(BB)) { | |
| int NotAPhi = 0; | |
| for (const auto &Acc : *Accs) { | |
| if (isa<MemoryPhi>(&Acc)) | |
| continue; | |
| const auto *MUD = cast<MemoryUseOrDef>(&Acc); | |
| if (MUD->getMemoryInst() != I || NotAPhi++ == 1) | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| static MemoryAccess *getClobberingMemoryAccess(MemorySSA &MSSA, | |
| BatchAAResults &BAA, | |
| SinkAndHoistLICMFlags &Flags, | |
| MemoryUseOrDef *MA) { | |
| // See declaration of SetLicmMssaOptCap for usage details. | |
| if (Flags.tooManyClobberingCalls()) | |
| return MA->getDefiningAccess(); | |
| MemoryAccess *Source = | |
| MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(MA, BAA); | |
| Flags.incrementClobberingCalls(); | |
| return Source; | |
| } | |
| bool llvm::canHoistLoad(LoadInst &LI, AAResults *AA, DominatorTree *DT, | |
| Loop *CurLoop, MemorySSA &MSSA, | |
| bool TargetExecutesOncePerLoop, | |
| SinkAndHoistLICMFlags &Flags, | |
| OptimizationRemarkEmitter *ORE) { | |
| if (!LI.isUnordered()) | |
| return false; // Don't sink/hoist volatile or ordered atomic loads! | |
| // Loads from constant memory are always safe to move, even if they end up | |
| // in the same alias set as something that ends up being modified. | |
| if (!isModSet(AA->getModRefInfoMask(LI.getOperand(0)))) | |
| return true; | |
| if (LI.hasMetadata(LLVMContext::MD_invariant_load)) | |
| return true; | |
| if (LI.isAtomic() && !TargetExecutesOncePerLoop) | |
| return false; // Don't risk duplicating unordered loads | |
| // This checks for an invariant.start dominating the load. | |
| if (isLoadInvariantInLoop(&LI, DT, CurLoop)) | |
| return true; | |
| auto *MU = cast<MemoryUse>(MSSA.getMemoryAccess(&LI)); | |
| bool InvariantGroup = LI.hasMetadata(LLVMContext::MD_invariant_group); | |
| bool Invalidated = | |
| pointerInvalidatedByLoop(&MSSA, MU, CurLoop, LI, Flags, InvariantGroup); | |
| // Check loop-invariant address because this may also be a sinkable load | |
| // whose address is not necessarily loop-invariant. | |
| if (ORE && Invalidated && CurLoop->isLoopInvariant(LI.getPointerOperand())) | |
| ORE->emit([&]() { | |
| return OptimizationRemarkMissed( | |
| DEBUG_TYPE, "LoadWithLoopInvariantAddressInvalidated", &LI) | |
| << "failed to move load with loop-invariant address " | |
| "because the loop may invalidate its value"; | |
| }); | |
| return !Invalidated; | |
| } | |
| bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, | |
| Loop *CurLoop, MemorySSAUpdater &MSSAU, | |
| bool TargetExecutesOncePerLoop, | |
| SinkAndHoistLICMFlags &Flags, | |
| OptimizationRemarkEmitter *ORE) { | |
| // If we don't understand the instruction, bail early. | |
| if (!isHoistableAndSinkableInst(I)) | |
| return false; | |
| MemorySSA *MSSA = MSSAU.getMemorySSA(); | |
| // Loads have extra constraints we have to verify before we can hoist them. | |
| if (LoadInst *LI = dyn_cast<LoadInst>(&I)) { | |
| return canHoistLoad(*LI, AA, DT, CurLoop, *MSSA, TargetExecutesOncePerLoop, | |
| Flags, ORE); | |
| } else if (CallInst *CI = dyn_cast<CallInst>(&I)) { | |
| // Don't sink calls which can throw. | |
| if (CI->mayThrow()) | |
| return false; | |
| // Convergent attribute has been used on operations that involve | |
| // inter-thread communication which results are implicitly affected by the | |
| // enclosing control flows. It is not safe to hoist or sink such operations | |
| // across control flow. | |
| if (CI->isConvergent()) | |
| return false; | |
| // FIXME: Current LLVM IR semantics don't work well with coroutines and | |
| // thread local globals. We currently treat getting the address of a thread | |
| // local global as not accessing memory, even though it may not be a | |
| // constant throughout a function with coroutines. Remove this check after | |
| // we better model semantics of thread local globals. | |
| if (CI->getFunction()->isPresplitCoroutine()) | |
| return false; | |
| using namespace PatternMatch; | |
| if (match(CI, m_Intrinsic<Intrinsic::assume>())) | |
| // Assumes don't actually alias anything or throw | |
| return true; | |
| // Handle simple cases by querying alias analysis. | |
| MemoryEffects Behavior = AA->getMemoryEffects(CI); | |
| if (Behavior.doesNotAccessMemory()) | |
| return true; | |
| if (Behavior.onlyReadsMemory()) { | |
| // Might have stale MemoryDef for call that was later inferred to be | |
| // read-only. | |
| auto *MU = dyn_cast<MemoryUse>(MSSA->getMemoryAccess(CI)); | |
| if (!MU) | |
| return false; | |
| // If we can prove there are no writes to the memory read by the call, we | |
| // can hoist or sink. | |
| return !pointerInvalidatedByLoop( | |
| MSSA, MU, CurLoop, I, Flags, /*InvariantGroup=*/false); | |
| } | |
| if (Behavior.onlyWritesMemory()) { | |
| // can hoist or sink if there are no conflicting read/writes to the | |
| // memory location written to by the call. | |
| return noConflictingReadWrites(CI, MSSA, AA, CurLoop, Flags); | |
| } | |
| return false; | |
| } else if (auto *FI = dyn_cast<FenceInst>(&I)) { | |
| // Fences alias (most) everything to provide ordering. For the moment, | |
| // just give up if there are any other memory operations in the loop. | |
| return isOnlyMemoryAccess(FI, CurLoop, MSSAU); | |
| } else if (auto *SI = dyn_cast<StoreInst>(&I)) { | |
| if (!SI->isUnordered()) | |
| return false; // Don't sink/hoist volatile or ordered atomic store! | |
| // We can only hoist a store that we can prove writes a value which is not | |
| // read or overwritten within the loop. For those cases, we fallback to | |
| // load store promotion instead. TODO: We can extend this to cases where | |
| // there is exactly one write to the location and that write dominates an | |
| // arbitrary number of reads in the loop. | |
| if (isOnlyMemoryAccess(SI, CurLoop, MSSAU)) | |
| return true; | |
| return noConflictingReadWrites(SI, MSSA, AA, CurLoop, Flags); | |
| } | |
| assert(!I.mayReadOrWriteMemory() && "unhandled aliasing"); | |
| // We've established mechanical ability and aliasing, it's up to the caller | |
| // to check fault safety | |
| return true; | |
| } | |
| /// Returns true if a PHINode is a trivially replaceable with an | |
| /// Instruction. | |
| /// This is true when all incoming values are that instruction. | |
| /// This pattern occurs most often with LCSSA PHI nodes. | |
| /// | |
| static bool isTriviallyReplaceablePHI(const PHINode &PN, const Instruction &I) { | |
| for (const Value *IncValue : PN.incoming_values()) | |
| if (IncValue != &I) | |
| return false; | |
| return true; | |
| } | |
| /// Return true if the instruction is foldable in the loop. | |
| static bool isFoldableInLoop(const Instruction &I, const Loop *CurLoop, | |
| const TargetTransformInfo *TTI) { | |
| if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) { | |
| InstructionCost CostI = | |
| TTI->getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency); | |
| if (CostI != TargetTransformInfo::TCC_Free) | |
| return false; | |
| // For a GEP, we cannot simply use getInstructionCost because currently | |
| // it optimistically assumes that a GEP will fold into addressing mode | |
| // regardless of its users. | |
| const BasicBlock *BB = GEP->getParent(); | |
| for (const User *U : GEP->users()) { | |
| const Instruction *UI = cast<Instruction>(U); | |
| if (CurLoop->contains(UI) && | |
| (BB != UI->getParent() || | |
| (!isa<StoreInst>(UI) && !isa<LoadInst>(UI)))) | |
| return false; | |
| } | |
| return true; | |
| } | |
| return false; | |
| } | |
| /// Return true if the only users of this instruction are outside of | |
| /// the loop. If this is true, we can sink the instruction to the exit | |
| /// blocks of the loop. | |
| /// | |
| /// We also return true if the instruction could be folded away in lowering. | |
| /// (e.g., a GEP can be folded into a load as an addressing mode in the loop). | |
| static bool isNotUsedOrFoldableInLoop(const Instruction &I, const Loop *CurLoop, | |
| const LoopSafetyInfo *SafetyInfo, | |
| TargetTransformInfo *TTI, | |
| bool &FoldableInLoop, bool LoopNestMode) { | |
| bool IsFoldable = isFoldableInLoop(I, CurLoop, TTI); | |
| for (const User *U : I.users()) { | |
| const Instruction *UI = cast<Instruction>(U); | |
| if (const PHINode *PN = dyn_cast<PHINode>(UI)) { | |
| const BasicBlock *BB = PN->getParent(); | |
| // We cannot sink uses in catchswitches. | |
| if (isa<CatchSwitchInst>(BB->getTerminator())) | |
| return false; | |
| // We need to sink a callsite to a unique funclet. Avoid sinking if the | |
| // phi use is too muddled. | |
| if (isa<CallInst>(I)) { | |
| const auto &BlockColors = SafetyInfo->getBlockColors(); | |
| if (!BlockColors.empty() && | |
| BlockColors.find(const_cast<BasicBlock *>(BB))->second.size() != 1) | |
| return false; | |
| } | |
| if (LoopNestMode) { | |
| while (isa<PHINode>(UI) && UI->hasOneUser() && | |
| UI->getNumOperands() == 1) { | |
| if (!CurLoop->contains(UI)) | |
| break; | |
| UI = cast<Instruction>(UI->user_back()); | |
| } | |
| } | |
| } | |
| if (CurLoop->contains(UI)) { | |
| if (IsFoldable) { | |
| FoldableInLoop = true; | |
| continue; | |
| } | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| static Instruction *cloneInstructionInExitBlock( | |
| Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI, | |
| const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU) { | |
| Instruction *New; | |
| if (auto *CI = dyn_cast<CallInst>(&I)) { | |
| const auto &BlockColors = SafetyInfo->getBlockColors(); | |
| // Sinking call-sites need to be handled differently from other | |
| // instructions. The cloned call-site needs a funclet bundle operand | |
| // appropriate for its location in the CFG. | |
| SmallVector<OperandBundleDef, 1> OpBundles; | |
| for (unsigned BundleIdx = 0, BundleEnd = CI->getNumOperandBundles(); | |
| BundleIdx != BundleEnd; ++BundleIdx) { | |
| OperandBundleUse Bundle = CI->getOperandBundleAt(BundleIdx); | |
| if (Bundle.getTagID() == LLVMContext::OB_funclet) | |
| continue; | |
| OpBundles.emplace_back(Bundle); | |
| } | |
| if (!BlockColors.empty()) { | |
| const ColorVector &CV = BlockColors.find(&ExitBlock)->second; | |
| assert(CV.size() == 1 && "non-unique color for exit block!"); | |
| BasicBlock *BBColor = CV.front(); | |
| BasicBlock::iterator EHPad = BBColor->getFirstNonPHIIt(); | |
| if (EHPad->isEHPad()) | |
| OpBundles.emplace_back("funclet", &*EHPad); | |
| } | |
| New = CallInst::Create(CI, OpBundles); | |
| New->copyMetadata(*CI); | |
| } else { | |
| New = I.clone(); | |
| } | |
| New->insertInto(&ExitBlock, ExitBlock.getFirstInsertionPt()); | |
| if (!I.getName().empty()) | |
| New->setName(I.getName() + ".le"); | |
| if (MSSAU.getMemorySSA()->getMemoryAccess(&I)) { | |
| // Create a new MemoryAccess and let MemorySSA set its defining access. | |
| // After running some passes, MemorySSA might be outdated, and the | |
| // instruction `I` may have become a non-memory touching instruction. | |
| MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB( | |
| New, nullptr, New->getParent(), MemorySSA::Beginning, | |
| /*CreationMustSucceed=*/false); | |
| if (NewMemAcc) { | |
| if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc)) | |
| MSSAU.insertDef(MemDef, /*RenameUses=*/true); | |
| else { | |
| auto *MemUse = cast<MemoryUse>(NewMemAcc); | |
| MSSAU.insertUse(MemUse, /*RenameUses=*/true); | |
| } | |
| } | |
| } | |
| // Build LCSSA PHI nodes for any in-loop operands (if legal). Note that | |
| // this is particularly cheap because we can rip off the PHI node that we're | |
| // replacing for the number and blocks of the predecessors. | |
| // OPT: If this shows up in a profile, we can instead finish sinking all | |
| // invariant instructions, and then walk their operands to re-establish | |
| // LCSSA. That will eliminate creating PHI nodes just to nuke them when | |
| // sinking bottom-up. | |
| for (Use &Op : New->operands()) | |
| if (LI->wouldBeOutOfLoopUseRequiringLCSSA(Op.get(), PN.getParent())) { | |
| auto *OInst = cast<Instruction>(Op.get()); | |
| PHINode *OpPN = | |
| PHINode::Create(OInst->getType(), PN.getNumIncomingValues(), | |
| OInst->getName() + ".lcssa"); | |
| OpPN->insertBefore(ExitBlock.begin()); | |
| for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) | |
| OpPN->addIncoming(OInst, PN.getIncomingBlock(i)); | |
| Op = OpPN; | |
| } | |
| return New; | |
| } | |
| static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU) { | |
| MSSAU.removeMemoryAccess(&I); | |
| SafetyInfo.removeInstruction(&I); | |
| I.eraseFromParent(); | |
| } | |
| static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest, | |
| ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, | |
| ScalarEvolution *SE) { | |
| SafetyInfo.removeInstruction(&I); | |
| SafetyInfo.insertInstructionTo(&I, Dest->getParent()); | |
| I.moveBefore(*Dest->getParent(), Dest); | |
| if (MemoryUseOrDef *OldMemAcc = cast_or_null<MemoryUseOrDef>( | |
| MSSAU.getMemorySSA()->getMemoryAccess(&I))) | |
| MSSAU.moveToPlace(OldMemAcc, Dest->getParent(), | |
| MemorySSA::BeforeTerminator); | |
| if (SE) | |
| SE->forgetBlockAndLoopDispositions(&I); | |
| } | |
| static Instruction *sinkThroughTriviallyReplaceablePHI( | |
| PHINode *TPN, Instruction *I, LoopInfo *LI, | |
| SmallDenseMap<BasicBlock *, Instruction *, 32> &SunkCopies, | |
| const LoopSafetyInfo *SafetyInfo, const Loop *CurLoop, | |
| MemorySSAUpdater &MSSAU) { | |
| assert(isTriviallyReplaceablePHI(*TPN, *I) && | |
| "Expect only trivially replaceable PHI"); | |
| BasicBlock *ExitBlock = TPN->getParent(); | |
| auto [It, Inserted] = SunkCopies.try_emplace(ExitBlock); | |
| if (Inserted) | |
| It->second = cloneInstructionInExitBlock(*I, *ExitBlock, *TPN, LI, | |
| SafetyInfo, MSSAU); | |
| return It->second; | |
| } | |
| static bool canSplitPredecessors(PHINode *PN, LoopSafetyInfo *SafetyInfo) { | |
| BasicBlock *BB = PN->getParent(); | |
| if (!BB->canSplitPredecessors()) | |
| return false; | |
| // It's not impossible to split EHPad blocks, but if BlockColors already exist | |
| // it require updating BlockColors for all offspring blocks accordingly. By | |
| // skipping such corner case, we can make updating BlockColors after splitting | |
| // predecessor fairly simple. | |
| if (!SafetyInfo->getBlockColors().empty() && | |
| BB->getFirstNonPHIIt()->isEHPad()) | |
| return false; | |
| for (BasicBlock *BBPred : predecessors(BB)) { | |
| if (isa<IndirectBrInst>(BBPred->getTerminator())) | |
| return false; | |
| } | |
| return true; | |
| } | |
| static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT, | |
| LoopInfo *LI, const Loop *CurLoop, | |
| LoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater *MSSAU) { | |
| #ifndef NDEBUG | |
| SmallVector<BasicBlock *, 32> ExitBlocks; | |
| CurLoop->getUniqueExitBlocks(ExitBlocks); | |
| SmallPtrSet<BasicBlock *, 32> ExitBlockSet(llvm::from_range, ExitBlocks); | |
| #endif | |
| BasicBlock *ExitBB = PN->getParent(); | |
| assert(ExitBlockSet.count(ExitBB) && "Expect the PHI is in an exit block."); | |
| // Split predecessors of the loop exit to make instructions in the loop are | |
| // exposed to exit blocks through trivially replaceable PHIs while keeping the | |
| // loop in the canonical form where each predecessor of each exit block should | |
| // be contained within the loop. For example, this will convert the loop below | |
| // from | |
| // | |
| // LB1: | |
| // %v1 = | |
| // br %LE, %LB2 | |
| // LB2: | |
| // %v2 = | |
| // br %LE, %LB1 | |
| // LE: | |
| // %p = phi [%v1, %LB1], [%v2, %LB2] <-- non-trivially replaceable | |
| // | |
| // to | |
| // | |
| // LB1: | |
| // %v1 = | |
| // br %LE.split, %LB2 | |
| // LB2: | |
| // %v2 = | |
| // br %LE.split2, %LB1 | |
| // LE.split: | |
| // %p1 = phi [%v1, %LB1] <-- trivially replaceable | |
| // br %LE | |
| // LE.split2: | |
| // %p2 = phi [%v2, %LB2] <-- trivially replaceable | |
| // br %LE | |
| // LE: | |
| // %p = phi [%p1, %LE.split], [%p2, %LE.split2] | |
| // | |
| const auto &BlockColors = SafetyInfo->getBlockColors(); | |
| SmallSetVector<BasicBlock *, 8> PredBBs(pred_begin(ExitBB), pred_end(ExitBB)); | |
| DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); | |
| while (!PredBBs.empty()) { | |
| BasicBlock *PredBB = *PredBBs.begin(); | |
| assert(CurLoop->contains(PredBB) && | |
| "Expect all predecessors are in the loop"); | |
| if (PN->getBasicBlockIndex(PredBB) >= 0) { | |
| BasicBlock *NewPred = SplitBlockPredecessors( | |
| ExitBB, PredBB, ".split.loop.exit", &DTU, LI, MSSAU, true); | |
| // Since we do not allow splitting EH-block with BlockColors in | |
| // canSplitPredecessors(), we can simply assign predecessor's color to | |
| // the new block. | |
| if (!BlockColors.empty()) | |
| // Grab a reference to the ColorVector to be inserted before getting the | |
| // reference to the vector we are copying because inserting the new | |
| // element in BlockColors might cause the map to be reallocated. | |
| SafetyInfo->copyColors(NewPred, PredBB); | |
| } | |
| PredBBs.remove(PredBB); | |
| } | |
| } | |
| /// When an instruction is found to only be used outside of the loop, this | |
| /// function moves it to the exit blocks and patches up SSA form as needed. | |
| /// This method is guaranteed to remove the original instruction from its | |
| /// position, and may either delete it or move it to outside of the loop. | |
| /// | |
| static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, | |
| const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE) { | |
| bool Changed = false; | |
| LLVM_DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n"); | |
| // Iterate over users to be ready for actual sinking. Replace users via | |
| // unreachable blocks with undef and make all user PHIs trivially replaceable. | |
| SmallPtrSet<Instruction *, 8> VisitedUsers; | |
| for (Instruction::user_iterator UI = I.user_begin(), UE = I.user_end(); | |
| UI != UE;) { | |
| auto *User = cast<Instruction>(*UI); | |
| Use &U = UI.getUse(); | |
| ++UI; | |
| if (VisitedUsers.count(User) || CurLoop->contains(User)) | |
| continue; | |
| if (!DT->isReachableFromEntry(User->getParent())) { | |
| U = PoisonValue::get(I.getType()); | |
| Changed = true; | |
| continue; | |
| } | |
| // The user must be a PHI node. | |
| PHINode *PN = cast<PHINode>(User); | |
| // Surprisingly, instructions can be used outside of loops without any | |
| // exits. This can only happen in PHI nodes if the incoming block is | |
| // unreachable. | |
| BasicBlock *BB = PN->getIncomingBlock(U); | |
| if (!DT->isReachableFromEntry(BB)) { | |
| U = PoisonValue::get(I.getType()); | |
| Changed = true; | |
| continue; | |
| } | |
| VisitedUsers.insert(PN); | |
| if (isTriviallyReplaceablePHI(*PN, I)) | |
| continue; | |
| if (!canSplitPredecessors(PN, SafetyInfo)) | |
| return Changed; | |
| // Split predecessors of the PHI so that we can make users trivially | |
| // replaceable. | |
| splitPredecessorsOfLoopExit(PN, DT, LI, CurLoop, SafetyInfo, &MSSAU); | |
| // Should rebuild the iterators, as they may be invalidated by | |
| // splitPredecessorsOfLoopExit(). | |
| UI = I.user_begin(); | |
| UE = I.user_end(); | |
| } | |
| if (VisitedUsers.empty()) | |
| return Changed; | |
| ORE->emit([&]() { | |
| return OptimizationRemark(DEBUG_TYPE, "InstSunk", &I) | |
| << "sinking " << ore::NV("Inst", &I); | |
| }); | |
| if (isa<LoadInst>(I)) | |
| ++NumMovedLoads; | |
| else if (isa<CallInst>(I)) | |
| ++NumMovedCalls; | |
| ++NumSunk; | |
| #ifndef NDEBUG | |
| SmallVector<BasicBlock *, 32> ExitBlocks; | |
| CurLoop->getUniqueExitBlocks(ExitBlocks); | |
| SmallPtrSet<BasicBlock *, 32> ExitBlockSet(llvm::from_range, ExitBlocks); | |
| #endif | |
| // Clones of this instruction. Don't create more than one per exit block! | |
| SmallDenseMap<BasicBlock *, Instruction *, 32> SunkCopies; | |
| // If this instruction is only used outside of the loop, then all users are | |
| // PHI nodes in exit blocks due to LCSSA form. Just RAUW them with clones of | |
| // the instruction. | |
| // First check if I is worth sinking for all uses. Sink only when it is worth | |
| // across all uses. | |
| SmallSetVector<User*, 8> Users(I.user_begin(), I.user_end()); | |
| for (auto *UI : Users) { | |
| auto *User = cast<Instruction>(UI); | |
| if (CurLoop->contains(User)) | |
| continue; | |
| PHINode *PN = cast<PHINode>(User); | |
| assert(ExitBlockSet.count(PN->getParent()) && | |
| "The LCSSA PHI is not in an exit block!"); | |
| // The PHI must be trivially replaceable. | |
| Instruction *New = sinkThroughTriviallyReplaceablePHI( | |
| PN, &I, LI, SunkCopies, SafetyInfo, CurLoop, MSSAU); | |
| // As we sink the instruction out of the BB, drop its debug location. | |
| New->dropLocation(); | |
| PN->replaceAllUsesWith(New); | |
| eraseInstruction(*PN, *SafetyInfo, MSSAU); | |
| Changed = true; | |
| } | |
| return Changed; | |
| } | |
| /// When an instruction is found to only use loop invariant operands that | |
| /// is safe to hoist, this instruction is called to do the dirty work. | |
| /// | |
| static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, | |
| BasicBlock *Dest, ICFLoopSafetyInfo *SafetyInfo, | |
| MemorySSAUpdater &MSSAU, ScalarEvolution *SE, | |
| OptimizationRemarkEmitter *ORE) { | |
| LLVM_DEBUG(dbgs() << "LICM hoisting to " << Dest->getNameOrAsOperand() << ": " | |
| << I << "\n"); | |
| ORE->emit([&]() { | |
| return OptimizationRemark(DEBUG_TYPE, "Hoisted", &I) << "hoisting " | |
| << ore::NV("Inst", &I); | |
| }); | |
| // Metadata can be dependent on conditions we are hoisting above. | |
| // Conservatively strip all metadata on the instruction unless we were | |
| // guaranteed to execute I if we entered the loop, in which case the metadata | |
| // is valid in the loop preheader. | |
| // Similarly, If I is a call and it is not guaranteed to execute in the loop, | |
| // then moving to the preheader means we should strip attributes on the call | |
| // that can cause UB since we may be hoisting above conditions that allowed | |
| // inferring those attributes. They may not be valid at the preheader. | |
| if ((I.hasMetadataOtherThanDebugLoc() || isa<CallInst>(I)) && | |
| // The check on hasMetadataOtherThanDebugLoc is to prevent us from burning | |
| // time in isGuaranteedToExecute if we don't actually have anything to | |
| // drop. It is a compile time optimization, not required for correctness. | |
| !SafetyInfo->isGuaranteedToExecute(I, DT)) { | |
| I.dropUBImplyingAttrsAndMetadata(); | |
| } | |
| if (isa<PHINode>(I)) | |
| // Move the new node to the end of the phi list in the destination block. | |
| moveInstructionBefore(I, Dest->getFirstNonPHIIt(), *SafetyInfo, MSSAU, SE); | |
| else | |
| // Move the new node to the destination block, before its terminator. | |
| moveInstructionBefore(I, Dest->getTerminator()->getIterator(), *SafetyInfo, | |
| MSSAU, SE); | |
| I.updateLocationAfterHoist(); | |
| if (isa<LoadInst>(I)) | |
| ++NumMovedLoads; | |
| else if (isa<CallInst>(I)) | |
| ++NumMovedCalls; | |
| ++NumHoisted; | |
| } | |
| /// Only sink or hoist an instruction if it is not a trapping instruction, | |
| /// or if the instruction is known not to trap when moved to the preheader. | |
| /// or if it is a trapping instruction and is guaranteed to execute. | |
| static bool isSafeToExecuteUnconditionally( | |
| Instruction &Inst, const DominatorTree *DT, const TargetLibraryInfo *TLI, | |
| const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, | |
| OptimizationRemarkEmitter *ORE, const Instruction *CtxI, | |
| AssumptionCache *AC, bool AllowSpeculation) { | |
| if (AllowSpeculation && | |
| isSafeToSpeculativelyExecute(&Inst, CtxI, AC, DT, TLI)) | |
| return true; | |
| bool GuaranteedToExecute = SafetyInfo->isGuaranteedToExecute(Inst, DT); | |
| if (!GuaranteedToExecute) { | |
| auto *LI = dyn_cast<LoadInst>(&Inst); | |
| if (LI && CurLoop->isLoopInvariant(LI->getPointerOperand())) | |
| ORE->emit([&]() { | |
| return OptimizationRemarkMissed( | |
| DEBUG_TYPE, "LoadWithLoopInvariantAddressCondExecuted", LI) | |
| << "failed to hoist load with loop-invariant address " | |
| "because load is conditionally executed"; | |
| }); | |
| } | |
| return GuaranteedToExecute; | |
| } | |
| namespace { | |
| class LoopPromoter : public LoadAndStorePromoter { | |
| Value *SomePtr; // Designated pointer to store to. | |
| SmallVectorImpl<BasicBlock *> &LoopExitBlocks; | |
| SmallVectorImpl<BasicBlock::iterator> &LoopInsertPts; | |
| SmallVectorImpl<MemoryAccess *> &MSSAInsertPts; | |
| PredIteratorCache &PredCache; | |
| MemorySSAUpdater &MSSAU; | |
| LoopInfo &LI; | |
| DebugLoc DL; | |
| Align Alignment; | |
| bool UnorderedAtomic; | |
| AAMDNodes AATags; | |
| ICFLoopSafetyInfo &SafetyInfo; | |
| bool CanInsertStoresInExitBlocks; | |
| ArrayRef<const Instruction *> Uses; | |
| // We're about to add a use of V in a loop exit block. Insert an LCSSA phi | |
| // (if legal) if doing so would add an out-of-loop use to an instruction | |
| // defined in-loop. | |
| Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const { | |
| if (!LI.wouldBeOutOfLoopUseRequiringLCSSA(V, BB)) | |
| return V; | |
| Instruction *I = cast<Instruction>(V); | |
| // We need to create an LCSSA PHI node for the incoming value and | |
| // store that. | |
| PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB), | |
| I->getName() + ".lcssa"); | |
| PN->insertBefore(BB->begin()); | |
| for (BasicBlock *Pred : PredCache.get(BB)) | |
| PN->addIncoming(I, Pred); | |
| return PN; | |
| } | |
| public: | |
| LoopPromoter(Value *SP, ArrayRef<const Instruction *> Insts, SSAUpdater &S, | |
| SmallVectorImpl<BasicBlock *> &LEB, | |
| SmallVectorImpl<BasicBlock::iterator> &LIP, | |
| SmallVectorImpl<MemoryAccess *> &MSSAIP, PredIteratorCache &PIC, | |
| MemorySSAUpdater &MSSAU, LoopInfo &li, DebugLoc dl, | |
| Align Alignment, bool UnorderedAtomic, const AAMDNodes &AATags, | |
| ICFLoopSafetyInfo &SafetyInfo, bool CanInsertStoresInExitBlocks) | |
| : LoadAndStorePromoter(Insts, S), SomePtr(SP), LoopExitBlocks(LEB), | |
| LoopInsertPts(LIP), MSSAInsertPts(MSSAIP), PredCache(PIC), MSSAU(MSSAU), | |
| LI(li), DL(std::move(dl)), Alignment(Alignment), | |
| UnorderedAtomic(UnorderedAtomic), AATags(AATags), | |
| SafetyInfo(SafetyInfo), | |
| CanInsertStoresInExitBlocks(CanInsertStoresInExitBlocks), Uses(Insts) {} | |
| void insertStoresInLoopExitBlocks() { | |
| // Insert stores after in the loop exit blocks. Each exit block gets a | |
| // store of the live-out values that feed them. Since we've already told | |
| // the SSA updater about the defs in the loop and the preheader | |
| // definition, it is all set and we can start using it. | |
| DIAssignID *NewID = nullptr; | |
| for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) { | |
| BasicBlock *ExitBlock = LoopExitBlocks[i]; | |
| Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock); | |
| LiveInValue = maybeInsertLCSSAPHI(LiveInValue, ExitBlock); | |
| Value *Ptr = maybeInsertLCSSAPHI(SomePtr, ExitBlock); | |
| BasicBlock::iterator InsertPos = LoopInsertPts[i]; | |
| StoreInst *NewSI = new StoreInst(LiveInValue, Ptr, InsertPos); | |
| if (UnorderedAtomic) | |
| NewSI->setOrdering(AtomicOrdering::Unordered); | |
| NewSI->setAlignment(Alignment); | |
| NewSI->setDebugLoc(DL); | |
| // Attach DIAssignID metadata to the new store, generating it on the | |
| // first loop iteration. | |
| if (i == 0) { | |
| // NewSI will have its DIAssignID set here if there are any stores in | |
| // Uses with a DIAssignID attachment. This merged ID will then be | |
| // attached to the other inserted stores (in the branch below). | |
| NewSI->mergeDIAssignID(Uses); | |
| NewID = cast_or_null<DIAssignID>( | |
| NewSI->getMetadata(LLVMContext::MD_DIAssignID)); | |
| } else { | |
| // Attach the DIAssignID (or nullptr) merged from Uses in the branch | |
| // above. | |
| NewSI->setMetadata(LLVMContext::MD_DIAssignID, NewID); | |
| } | |
| if (AATags) | |
| NewSI->setAAMetadata(AATags); | |
| MemoryAccess *MSSAInsertPoint = MSSAInsertPts[i]; | |
| MemoryAccess *NewMemAcc; | |
| if (!MSSAInsertPoint) { | |
| NewMemAcc = MSSAU.createMemoryAccessInBB( | |
| NewSI, nullptr, NewSI->getParent(), MemorySSA::Beginning); | |
| } else { | |
| NewMemAcc = | |
| MSSAU.createMemoryAccessAfter(NewSI, nullptr, MSSAInsertPoint); | |
| } | |
| MSSAInsertPts[i] = NewMemAcc; | |
| MSSAU.insertDef(cast<MemoryDef>(NewMemAcc), true); | |
| // FIXME: true for safety, false may still be correct. | |
| } | |
| } | |
| void doExtraRewritesBeforeFinalDeletion() override { | |
| if (CanInsertStoresInExitBlocks) | |
| insertStoresInLoopExitBlocks(); | |
| } | |
| void instructionDeleted(Instruction *I) const override { | |
| SafetyInfo.removeInstruction(I); | |
| MSSAU.removeMemoryAccess(I); | |
| } | |
| bool shouldDelete(Instruction *I) const override { | |
| if (isa<StoreInst>(I)) | |
| return CanInsertStoresInExitBlocks; | |
| return true; | |
| } | |
| }; | |
| bool isNotCapturedBeforeOrInLoop(const Value *V, const Loop *L, | |
| DominatorTree *DT) { | |
| // We can perform the captured-before check against any instruction in the | |
| // loop header, as the loop header is reachable from any instruction inside | |
| // the loop. | |
| // TODO: ReturnCaptures=true shouldn't be necessary here. | |
| return capturesNothing(PointerMayBeCapturedBefore( | |
| V, /*ReturnCaptures=*/true, L->getHeader()->getTerminator(), DT, | |
| /*IncludeI=*/false, CaptureComponents::Provenance)); | |
| } | |
| /// Return true if we can prove that a caller cannot inspect the object if an | |
| /// unwind occurs inside the loop. | |
| bool isNotVisibleOnUnwindInLoop(const Value *Object, const Loop *L, | |
| DominatorTree *DT) { | |
| bool RequiresNoCaptureBeforeUnwind; | |
| if (!isNotVisibleOnUnwind(Object, RequiresNoCaptureBeforeUnwind)) | |
| return false; | |
| return !RequiresNoCaptureBeforeUnwind || | |
| isNotCapturedBeforeOrInLoop(Object, L, DT); | |
| } | |
| bool isThreadLocalObject(const Value *Object, const Loop *L, | |
| DominatorTree *DT) { | |
| // The object must be function-local to start with, and then not captured | |
| // before/in the loop. | |
| if (isIdentifiedFunctionLocal(Object) && | |
| isNotCapturedBeforeOrInLoop(Object, L, DT)) | |
| return true; | |
| // In a single-threaded environment, all objects are effectively thread-local. | |
| const Module *M = L->getHeader()->getModule(); | |
| return M->getThreadModel() == ThreadModel::Single; | |
| } | |
| } // namespace | |
| /// 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 | |
| /// the stores in the loop, looking for stores to Must pointers which are | |
| /// loop invariant. | |
| /// | |
| bool llvm::promoteLoopAccessesToScalars( | |
| const SmallSetVector<Value *, 8> &PointerMustAliases, | |
| SmallVectorImpl<BasicBlock *> &ExitBlocks, | |
| SmallVectorImpl<BasicBlock::iterator> &InsertPts, | |
| SmallVectorImpl<MemoryAccess *> &MSSAInsertPts, PredIteratorCache &PIC, | |
| LoopInfo *LI, DominatorTree *DT, AssumptionCache *AC, | |
| const TargetLibraryInfo *TLI, TargetTransformInfo *TTI, Loop *CurLoop, | |
| MemorySSAUpdater &MSSAU, ICFLoopSafetyInfo *SafetyInfo, | |
| OptimizationRemarkEmitter *ORE, bool AllowSpeculation, | |
| bool HasReadsOutsideSet) { | |
| // Verify inputs. | |
| assert(LI != nullptr && DT != nullptr && CurLoop != nullptr && | |
| SafetyInfo != nullptr && | |
| "Unexpected Input to promoteLoopAccessesToScalars"); | |
| LLVM_DEBUG({ | |
| dbgs() << "Trying to promote set of must-aliased pointers:\n"; | |
| for (Value *Ptr : PointerMustAliases) | |
| dbgs() << " " << *Ptr << "\n"; | |
| }); | |
| ++NumPromotionCandidates; | |
| Value *SomePtr = *PointerMustAliases.begin(); | |
| BasicBlock *Preheader = CurLoop->getLoopPreheader(); | |
| // It is not safe to promote a load/store from the loop if the load/store is | |
| // conditional. For example, turning: | |
| // | |
| // for () { if (c) *P += 1; } | |
| // | |
| // into: | |
| // | |
| // tmp = *P; for () { if (c) tmp +=1; } *P = tmp; | |
| // | |
| // is not safe, because *P may only be valid to access if 'c' is true. | |
| // | |
| // The safety property divides into two parts: | |
| // p1) The memory may not be dereferenceable on entry to the loop. In this | |
| // case, we can't insert the required load in the preheader. | |
| // p2) The memory model does not allow us to insert a store along any dynamic | |
| // path which did not originally have one. | |
| // | |
| // If at least one store is guaranteed to execute, both properties are | |
| // satisfied, and promotion is legal. | |
| // | |
| // This, however, is not a necessary condition. Even if no store/load is | |
| // guaranteed to execute, we can still establish these properties. | |
| // We can establish (p1) by proving that hoisting the load into the preheader | |
| // is safe (i.e. proving dereferenceability on all paths through the loop). We | |
| // can use any access within the alias set to prove dereferenceability, | |
| // since they're all must alias. | |
| // | |
| // There are two ways establish (p2): | |
| // a) Prove the location is thread-local. In this case the memory model | |
| // requirement does not apply, and stores are safe to insert. | |
| // b) Prove a store dominates every exit block. In this case, if an exit | |
| // blocks is reached, the original dynamic path would have taken us through | |
| // the store, so inserting a store into the exit block is safe. Note that this | |
| // is different from the store being guaranteed to execute. For instance, | |
| // if an exception is thrown on the first iteration of the loop, the original | |
| // store is never executed, but the exit blocks are not executed either. | |
| bool DereferenceableInPH = false; | |
| bool StoreIsGuaranteedToExecute = false; | |
| bool LoadIsGuaranteedToExecute = false; | |
| bool FoundLoadToPromote = false; | |
| // Goes from Unknown to either Safe or Unsafe, but can't switch between them. | |
| enum { | |
| StoreSafe, | |
| StoreUnsafe, | |
| StoreSafetyUnknown, | |
| } StoreSafety = StoreSafetyUnknown; | |
| SmallVector<Instruction *, 64> LoopUses; | |
| // We start with an alignment of one and try to find instructions that allow | |
| // us to prove better alignment. | |
| Align Alignment; | |
| // Keep track of which types of access we see | |
| bool SawUnorderedAtomic = false; | |
| bool SawNotAtomic = false; | |
| AAMDNodes AATags; | |
| const DataLayout &MDL = Preheader->getDataLayout(); | |
| // If there are reads outside the promoted set, then promoting stores is | |
| // definitely not safe. | |
| if (HasReadsOutsideSet) | |
| StoreSafety = StoreUnsafe; | |
| if (StoreSafety == StoreSafetyUnknown && SafetyInfo->anyBlockMayThrow()) { | |
| // If a loop can throw, we have to insert a store along each unwind edge. | |
| // That said, we can't actually make the unwind edge explicit. Therefore, | |
| // we have to prove that the store is dead along the unwind edge. We do | |
| // this by proving that the caller can't have a reference to the object | |
| // after return and thus can't possibly load from the object. | |
| Value *Object = getUnderlyingObject(SomePtr); | |
| if (!isNotVisibleOnUnwindInLoop(Object, CurLoop, DT)) | |
| StoreSafety = StoreUnsafe; | |
| } | |
| // Check that all accesses to pointers in the alias set use the same type. | |
| // We cannot (yet) promote a memory location that is loaded and stored in | |
| // different sizes. While we are at it, collect alignment and AA info. | |
| Type *AccessTy = nullptr; | |
| for (Value *ASIV : PointerMustAliases) { | |
| for (Use &U : ASIV->uses()) { | |
| // Ignore instructions that are outside the loop. | |
| Instruction *UI = dyn_cast<Instruction>(U.getUser()); | |
| if (!UI || !CurLoop->contains(UI)) | |
| continue; | |
| // If there is an non-load/store instruction in the loop, we can't promote | |
| // it. | |
| if (LoadInst *Load = dyn_cast<LoadInst>(UI)) { | |
| if (!Load->isUnordered()) | |
| return false; | |
| SawUnorderedAtomic |= Load->isAtomic(); | |
| SawNotAtomic |= !Load->isAtomic(); | |
| FoundLoadToPromote = true; | |
| Align InstAlignment = Load->getAlign(); | |
| if (!LoadIsGuaranteedToExecute) | |
| LoadIsGuaranteedToExecute = | |
| SafetyInfo->isGuaranteedToExecute(*UI, DT); | |
| // Note that proving a load safe to speculate requires proving | |
| // sufficient alignment at the target location. Proving it guaranteed | |
| // to execute does as well. Thus we can increase our guaranteed | |
| // alignment as well. | |
| if (!DereferenceableInPH || (InstAlignment > Alignment)) | |
| if (isSafeToExecuteUnconditionally( | |
| *Load, DT, TLI, CurLoop, SafetyInfo, ORE, | |
| Preheader->getTerminator(), AC, AllowSpeculation)) { | |
| DereferenceableInPH = true; | |
| Alignment = std::max(Alignment, InstAlignment); | |
| } | |
| } else if (const StoreInst *Store = dyn_cast<StoreInst>(UI)) { | |
| // Stores *of* the pointer are not interesting, only stores *to* the | |
| // pointer. | |
| if (U.getOperandNo() != StoreInst::getPointerOperandIndex()) | |
| continue; | |
| if (!Store->isUnordered()) | |
| return false; | |
| SawUnorderedAtomic |= Store->isAtomic(); | |
| SawNotAtomic |= !Store->isAtomic(); | |
| // If the store is guaranteed to execute, both properties are satisfied. | |
| // We may want to check if a store is guaranteed to execute even if we | |
| // already know that promotion is safe, since it may have higher | |
| // alignment than any other guaranteed stores, in which case we can | |
| // raise the alignment on the promoted store. | |
| Align InstAlignment = Store->getAlign(); | |
| bool GuaranteedToExecute = SafetyInfo->isGuaranteedToExecute(*UI, DT); | |
| StoreIsGuaranteedToExecute |= GuaranteedToExecute; | |
| if (GuaranteedToExecute) { | |
| DereferenceableInPH = true; | |
| if (StoreSafety == StoreSafetyUnknown) | |
| StoreSafety = StoreSafe; | |
| Alignment = std::max(Alignment, InstAlignment); | |
| } | |
| // If a store dominates all exit blocks, it is safe to sink. | |
| // As explained above, if an exit block was executed, a dominating | |
| // store must have been executed at least once, so we are not | |
| // introducing stores on paths that did not have them. | |
| // Note that this only looks at explicit exit blocks. If we ever | |
| // start sinking stores into unwind edges (see above), this will break. | |
| if (StoreSafety == StoreSafetyUnknown && | |
| llvm::all_of(ExitBlocks, [&](BasicBlock *Exit) { | |
| return DT->dominates(Store->getParent(), Exit); | |
| })) | |
| StoreSafety = StoreSafe; | |
| // If the store is not guaranteed to execute, we may still get | |
| // deref info through it. | |
| if (!DereferenceableInPH) { | |
| DereferenceableInPH = isDereferenceableAndAlignedPointer( | |
| Store->getPointerOperand(), Store->getValueOperand()->getType(), | |
| Store->getAlign(), | |
| SimplifyQuery(MDL, TLI, DT, AC, Preheader->getTerminator())); | |
| } | |
| } else | |
| continue; // Not a load or store. | |
| if (!AccessTy) | |
| AccessTy = getLoadStoreType(UI); | |
| else if (AccessTy != getLoadStoreType(UI)) | |
| return false; | |
| // Merge the AA tags. | |
| if (LoopUses.empty()) { | |
| // On the first load/store, just take its AA tags. | |
| AATags = UI->getAAMetadata(); | |
| } else if (AATags) { | |
| AATags = AATags.merge(UI->getAAMetadata()); | |
| } | |
| LoopUses.push_back(UI); | |
| } | |
| } | |
| // If we found both an unordered atomic instruction and a non-atomic memory | |
| // access, bail. We can't blindly promote non-atomic to atomic since we | |
| // might not be able to lower the result. We can't downgrade since that | |
| // would violate memory model. Also, align 0 is an error for atomics. | |
| if (SawUnorderedAtomic && SawNotAtomic) | |
| return false; | |
| // If we're inserting an atomic load in the preheader, we must be able to | |
| // lower it. We're only guaranteed to be able to lower naturally aligned | |
| // atomics. | |
| if (SawUnorderedAtomic && Alignment < MDL.getTypeStoreSize(AccessTy)) | |
| return false; | |
| // If we couldn't prove we can hoist the load, bail. | |
| if (!DereferenceableInPH) { | |
| LLVM_DEBUG(dbgs() << "Not promoting: Not dereferenceable in preheader\n"); | |
| return false; | |
| } | |
| // We know we can hoist the load, but don't have a guaranteed store. | |
| // Check whether the location is writable and thread-local. If it is, then we | |
| // can insert stores along paths which originally didn't have them without | |
| // violating the memory model. | |
| if (StoreSafety == StoreSafetyUnknown) { | |
| Value *Object = getUnderlyingObject(SomePtr); | |
| bool ExplicitlyDereferenceableOnly; | |
| // The dereferenceability query here is only required to satisfy the | |
| // writable contract, actual dereferenceability has already been proven | |
| // above. As such, we can ignore frees. | |
| if (isWritableObject(Object, ExplicitlyDereferenceableOnly) && | |
| (!ExplicitlyDereferenceableOnly || | |
| isDereferenceablePointer(SomePtr, AccessTy, MDL, | |
| /*IgnoreFree=*/true)) && | |
| isThreadLocalObject(Object, CurLoop, DT)) | |
| StoreSafety = StoreSafe; | |
| } | |
| // If we've still failed to prove we can sink the store, hoist the load | |
| // only, if possible. | |
| if (StoreSafety != StoreSafe && !FoundLoadToPromote) | |
| // If we cannot hoist the load either, give up. | |
| return false; | |
| // Lets do the promotion! | |
| if (StoreSafety == StoreSafe) { | |
| LLVM_DEBUG(dbgs() << "LICM: Promoting load/store of the value: " << *SomePtr | |
| << '\n'); | |
| ++NumLoadStorePromoted; | |
| } else { | |
| LLVM_DEBUG(dbgs() << "LICM: Promoting load of the value: " << *SomePtr | |
| << '\n'); | |
| ++NumLoadPromoted; | |
| } | |
| ORE->emit([&]() { | |
| return OptimizationRemark(DEBUG_TYPE, "PromoteLoopAccessesToScalar", | |
| LoopUses[0]) | |
| << "Moving accesses to memory location out of the loop"; | |
| }); | |
| // Look at all the loop uses, and try to merge their locations. | |
| std::vector<DebugLoc> LoopUsesLocs; | |
| for (auto U : LoopUses) | |
| LoopUsesLocs.push_back(U->getDebugLoc()); | |
| auto DL = DebugLoc::getMergedLocations(LoopUsesLocs); | |
| // We use the SSAUpdater interface to insert phi nodes as required. | |
| SmallVector<PHINode *, 16> NewPHIs; | |
| SSAUpdater SSA(&NewPHIs); | |
| LoopPromoter Promoter(SomePtr, LoopUses, SSA, ExitBlocks, InsertPts, | |
| MSSAInsertPts, PIC, MSSAU, *LI, DL, Alignment, | |
| SawUnorderedAtomic, | |
| StoreIsGuaranteedToExecute ? AATags : AAMDNodes(), | |
| *SafetyInfo, StoreSafety == StoreSafe); | |
| // Set up the preheader to have a definition of the value. It is the live-out | |
| // value from the preheader that uses in the loop will use. | |
| LoadInst *PreheaderLoad = nullptr; | |
| if (FoundLoadToPromote || !StoreIsGuaranteedToExecute) { | |
| PreheaderLoad = | |
| new LoadInst(AccessTy, SomePtr, SomePtr->getName() + ".promoted", | |
| Preheader->getTerminator()->getIterator()); | |
| if (SawUnorderedAtomic) | |
| PreheaderLoad->setOrdering(AtomicOrdering::Unordered); | |
| PreheaderLoad->setAlignment(Alignment); | |
| PreheaderLoad->setDebugLoc(DebugLoc::getDropped()); | |
| if (AATags && LoadIsGuaranteedToExecute) | |
| PreheaderLoad->setAAMetadata(AATags); | |
| MemoryAccess *PreheaderLoadMemoryAccess = MSSAU.createMemoryAccessInBB( | |
| PreheaderLoad, nullptr, PreheaderLoad->getParent(), MemorySSA::End); | |
| MemoryUse *NewMemUse = cast<MemoryUse>(PreheaderLoadMemoryAccess); | |
| MSSAU.insertUse(NewMemUse, /*RenameUses=*/true); | |
| SSA.AddAvailableValue(Preheader, PreheaderLoad); | |
| } else { | |
| SSA.AddAvailableValue(Preheader, PoisonValue::get(AccessTy)); | |
| } | |
| if (VerifyMemorySSA) | |
| MSSAU.getMemorySSA()->verifyMemorySSA(); | |
| // Rewrite all the loads in the loop and remember all the definitions from | |
| // stores in the loop. | |
| Promoter.run(LoopUses); | |
| if (VerifyMemorySSA) | |
| MSSAU.getMemorySSA()->verifyMemorySSA(); | |
| // If the SSAUpdater didn't use the load in the preheader, just zap it now. | |
| if (PreheaderLoad && PreheaderLoad->use_empty()) | |
| eraseInstruction(*PreheaderLoad, *SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L, | |
| function_ref<void(Instruction *)> Fn) { | |
| for (const BasicBlock *BB : L->blocks()) | |
| if (const auto *Accesses = MSSA->getBlockAccesses(BB)) | |
| for (const auto &Access : *Accesses) | |
| if (const auto *MUD = dyn_cast<MemoryUseOrDef>(&Access)) | |
| Fn(MUD->getMemoryInst()); | |
| } | |
| /// Returns whether \p I is a memory access that may be a candidate for | |
| /// promotion out of the loop \p L. | |
| static bool isPotentiallyPromotable(const Instruction *I, const Loop *L) { | |
| if (const auto *SI = dyn_cast<StoreInst>(I)) { | |
| const Value *PtrOp = SI->getPointerOperand(); | |
| if (isStrongerThanMonotonic(SI->getOrdering())) | |
| return false; | |
| return !isa<ConstantData>(PtrOp) && L->isLoopInvariant(PtrOp); | |
| } | |
| if (const auto *LI = dyn_cast<LoadInst>(I)) { | |
| const Value *PtrOp = LI->getPointerOperand(); | |
| if (isStrongerThanMonotonic(LI->getOrdering())) | |
| return false; | |
| return !isa<ConstantData>(PtrOp) && L->isLoopInvariant(PtrOp); | |
| } | |
| return false; | |
| } | |
| /// Returns whether \p N has any operand from the set \p Operands. | |
| static bool | |
| hasAnyMDOperandsFrom(const MDNode *N, | |
| const SmallPtrSetImpl<const MDNode *> &Operands) { | |
| return N && llvm::any_of(N->operands(), [&](const MDOperand &Op) { | |
| return Operands.contains(cast<MDNode>(Op.get())); | |
| }); | |
| } | |
| /// Returns the potentially promotable stores with AA tags that are valid along | |
| /// all non-unwinding execution paths of the loop \p L, which allows for the AA | |
| /// tags to be used when deciding promotions. | |
| static SmallPtrSet<const StoreInst *, 8> collectStoresWithInvariantAATags( | |
| MemorySSA *MSSA, DominatorTree *DT, | |
| const SmallPtrSetImpl<const MDNode *> &LoopLocalAliasScopes, Loop *L) { | |
| SmallDenseMap<MemoryLocation, SmallVector<const StoreInst *, 1>, 4> | |
| StoresByLoc; | |
| foreachMemoryAccess(MSSA, L, [&](Instruction *I) { | |
| const auto *SI = dyn_cast<StoreInst>(I); | |
| if (SI && SI->getAAMetadata() && isPotentiallyPromotable(SI, L)) | |
| StoresByLoc[MemoryLocation::get(SI)].push_back(SI); | |
| }); | |
| // This only looks at explicit exiting blocks. If we ever start sinking | |
| // stores into unwind edges, this will break. | |
| SmallVector<BasicBlock *, 4> ExitingBlocks; | |
| L->getExitingBlocks(ExitingBlocks); | |
| SmallPtrSet<const StoreInst *, 8> StoresWithInvariantAATags; | |
| for (const auto &Pair : StoresByLoc) { | |
| const MemoryLocation &Loc = Pair.first; | |
| const SmallVector<const StoreInst *, 1> &Stores = Pair.second; | |
| // A scope declared inside the loop denotes a different scope on each | |
| // iteration, and thus should not be preserved. | |
| if (hasAnyMDOperandsFrom(Loc.AATags.Scope, LoopLocalAliasScopes) || | |
| hasAnyMDOperandsFrom(Loc.AATags.NoAlias, LoopLocalAliasScopes)) | |
| continue; | |
| // Without exiting blocks the loop is never left, and promotion has no | |
| // exit block to insert a store into either. | |
| if (llvm::all_of(ExitingBlocks, [&](BasicBlock *ExitingBB) { | |
| return llvm::any_of(Stores, [&](const StoreInst *SI) { | |
| return DT->dominates(SI->getParent(), ExitingBB); | |
| }); | |
| })) | |
| StoresWithInvariantAATags.insert_range(Stores); | |
| } | |
| return StoresWithInvariantAATags; | |
| } | |
| // The bool indicates whether there might be reads outside the set, in which | |
| // case only loads may be promoted. | |
| static SmallVector<PointersAndHasReadsOutsideSet, 0> collectPromotionCandidates( | |
| MemorySSA *MSSA, AliasAnalysis *AA, DominatorTree *DT, | |
| ICFLoopSafetyInfo *SafetyInfo, | |
| const SmallPtrSetImpl<const MDNode *> &LoopLocalAliasScopes, Loop *L) { | |
| BatchAAResults BatchAA(*AA); | |
| AliasSetTracker AST(BatchAA); | |
| // Only conditionally executed stores need this, so compute it on demand to | |
| // keep the common case free. | |
| std::optional<SmallPtrSet<const StoreInst *, 8>> StoresWithInvariantAATags; | |
| auto HasInvariantAATags = [&](const StoreInst *SI) { | |
| if (!StoresWithInvariantAATags) | |
| StoresWithInvariantAATags = | |
| collectStoresWithInvariantAATags(MSSA, DT, LoopLocalAliasScopes, L); | |
| return StoresWithInvariantAATags->contains(SI); | |
| }; | |
| // Populate AST with potentially promotable accesses. | |
| SmallPtrSet<Value *, 16> AttemptingPromotion; | |
| foreachMemoryAccess(MSSA, L, [&](Instruction *I) { | |
| if (isPotentiallyPromotable(I, L)) { | |
| AttemptingPromotion.insert(I); | |
| if (StoreInst *SI = dyn_cast<StoreInst>(I); | |
| SI && SI->getAAMetadata() && | |
| !SafetyInfo->isGuaranteedToExecute(*SI, DT) && | |
| !HasInvariantAATags(SI)) { | |
| // Promotion requires inserting a new store at the loop exits; we need | |
| // to prove that store doesn't alias anything, in addition to proving | |
| // aliasing for the stores we're removing. The new store is executed | |
| // unconditionally, so when we're proving aliasing for that store, we | |
| // can only rely on AA tags that likewise hold unconditionally. | |
| AST.addWithoutAATags(SI); | |
| } else { | |
| AST.add(I); | |
| } | |
| } | |
| }); | |
| // We're only interested in must-alias sets that contain a mod. | |
| SmallVector<PointerIntPair<const AliasSet *, 1, bool>, 8> Sets; | |
| for (AliasSet &AS : AST) | |
| if (!AS.isForwardingAliasSet() && AS.isMod() && AS.isMustAlias()) | |
| Sets.push_back({&AS, false}); | |
| if (Sets.empty()) | |
| return {}; // Nothing to promote... | |
| // Discard any sets for which there is an aliasing non-promotable access. | |
| foreachMemoryAccess(MSSA, L, [&](Instruction *I) { | |
| if (AttemptingPromotion.contains(I)) | |
| return; | |
| llvm::erase_if(Sets, [&](PointerIntPair<const AliasSet *, 1, bool> &Pair) { | |
| ModRefInfo MR = Pair.getPointer()->aliasesUnknownInst(I, BatchAA); | |
| // Cannot promote if there are writes outside the set. | |
| if (isModSet(MR)) | |
| return true; | |
| if (isRefSet(MR)) { | |
| // Remember reads outside the set. | |
| Pair.setInt(true); | |
| // If this is a mod-only set and there are reads outside the set, | |
| // we will not be able to promote, so bail out early. | |
| return !Pair.getPointer()->isRef(); | |
| } | |
| return false; | |
| }); | |
| }); | |
| SmallVector<std::pair<SmallSetVector<Value *, 8>, bool>, 0> Result; | |
| for (auto [Set, HasReadsOutsideSet] : Sets) { | |
| SmallSetVector<Value *, 8> PointerMustAliases; | |
| for (const auto &MemLoc : *Set) | |
| PointerMustAliases.insert(const_cast<Value *>(MemLoc.Ptr)); | |
| Result.emplace_back(std::move(PointerMustAliases), HasReadsOutsideSet); | |
| } | |
| return Result; | |
| } | |
| // For a given store instruction or writeonly call instruction, this function | |
| // checks that there are no read or writes that conflict with the memory | |
| // access in the instruction | |
| static bool noConflictingReadWrites(Instruction *I, MemorySSA *MSSA, | |
| AAResults *AA, Loop *CurLoop, | |
| SinkAndHoistLICMFlags &Flags) { | |
| assert(isa<CallInst>(*I) || isa<StoreInst>(*I)); | |
| // If there are more accesses than the Promotion cap, then give up as we're | |
| // not walking a list that long. | |
| if (Flags.tooManyMemoryAccesses()) | |
| return false; | |
| auto *IMD = MSSA->getMemoryAccess(I); | |
| BatchAAResults BAA(*AA); | |
| auto *Source = getClobberingMemoryAccess(*MSSA, BAA, Flags, IMD); | |
| // Make sure there are no clobbers inside the loop. | |
| if (!MSSA->isLiveOnEntryDef(Source) && CurLoop->contains(Source->getBlock())) | |
| return false; | |
| // If there are interfering Uses don't move this store. | |
| // TODO: Cache set of Uses on the first walk in runOnLoop, update when | |
| // moving accesses. Can also extend to dominating uses. | |
| for (auto *BB : CurLoop->getBlocks()) { | |
| auto *Accesses = MSSA->getBlockAccesses(BB); | |
| if (!Accesses) | |
| continue; | |
| for (const auto &MA : *Accesses) { | |
| // Accesses are ordered. If we find one that I dominates we can stop. | |
| if (!Flags.getIsSink() && MSSA->dominates(IMD, &MA)) | |
| break; | |
| if (const auto *MemUseOrDef = dyn_cast<MemoryUseOrDef>(&MA)) { | |
| // Skip unrelated accesses. | |
| if (isNoModRef(BAA.getModRefInfo(MemUseOrDef->getMemoryInst(), I))) | |
| continue; | |
| return false; | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| static bool pointerInvalidatedByLoop(MemorySSA *MSSA, MemoryUse *MU, | |
| Loop *CurLoop, Instruction &I, | |
| SinkAndHoistLICMFlags &Flags, | |
| bool InvariantGroup) { | |
| // For hoisting, use the walker to determine safety | |
| if (!Flags.getIsSink()) { | |
| // If hoisting an invariant group, we only need to check that there | |
| // is no store to the loaded pointer between the start of the loop, | |
| // and the load (since all values must be the same). | |
| // This can be checked in two conditions: | |
| // 1) if the memoryaccess is outside the loop | |
| // 2) the earliest access is at the loop header, | |
| // if the memory loaded is the phi node | |
| BatchAAResults BAA(MSSA->getAA()); | |
| MemoryAccess *Source = getClobberingMemoryAccess(*MSSA, BAA, Flags, MU); | |
| return !MSSA->isLiveOnEntryDef(Source) && | |
| CurLoop->contains(Source->getBlock()) && | |
| !(InvariantGroup && Source->getBlock() == CurLoop->getHeader() && isa<MemoryPhi>(Source)); | |
| } | |
| // For sinking, we'd need to check all Defs below this use. The getClobbering | |
| // call will look on the backedge of the loop, but will check aliasing with | |
| // the instructions on the previous iteration. | |
| // For example: | |
| // for (i ... ) | |
| // load a[i] ( Use (LoE) | |
| // store a[i] ( 1 = Def (2), with 2 = Phi for the loop. | |
| // i++; | |
| // The load sees no clobbering inside the loop, as the backedge alias check | |
| // does phi translation, and will check aliasing against store a[i-1]. | |
| // However sinking the load outside the loop, below the store is incorrect. | |
| // For now, only sink if there are no Defs in the loop, and the existing ones | |
| // precede the use and are in the same block. | |
| // FIXME: Increase precision: Safe to sink if Use post dominates the Def; | |
| // needs PostDominatorTreeAnalysis. | |
| // FIXME: More precise: no Defs that alias this Use. | |
| if (Flags.tooManyMemoryAccesses()) | |
| return true; | |
| for (auto *BB : CurLoop->getBlocks()) | |
| if (pointerInvalidatedByBlock(*BB, *MSSA, *MU)) | |
| return true; | |
| // When sinking, the source block may not be part of the loop so check it. | |
| if (!CurLoop->contains(&I)) | |
| return pointerInvalidatedByBlock(*I.getParent(), *MSSA, *MU); | |
| return false; | |
| } | |
| bool pointerInvalidatedByBlock(BasicBlock &BB, MemorySSA &MSSA, MemoryUse &MU) { | |
| if (const auto *Accesses = MSSA.getBlockDefs(&BB)) | |
| for (const auto &MA : *Accesses) | |
| if (const auto *MD = dyn_cast<MemoryDef>(&MA)) | |
| if (MU.getBlock() != MD->getBlock() || !MSSA.locallyDominates(MD, &MU)) | |
| return true; | |
| return false; | |
| } | |
| /// Try to simplify things like (A < INV_1 AND icmp A < INV_2) into (A < | |
| /// min(INV_1, INV_2)), if INV_1 and INV_2 are both loop invariants and their | |
| /// minimun can be computed outside of loop, and X is not a loop-invariant. | |
| static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU) { | |
| bool Inverse = false; | |
| using namespace PatternMatch; | |
| Value *Cond1, *Cond2; | |
| if (match(&I, m_LogicalOr(m_Value(Cond1), m_Value(Cond2)))) { | |
| Inverse = true; | |
| } else if (match(&I, m_LogicalAnd(m_Value(Cond1), m_Value(Cond2)))) { | |
| // Do nothing | |
| } else | |
| return false; | |
| auto MatchICmpAgainstInvariant = [&](Value *C, CmpPredicate &P, Value *&LHS, | |
| Value *&RHS) { | |
| if (!match(C, m_OneUse(m_ICmp(P, m_Value(LHS), m_Value(RHS))))) | |
| return false; | |
| if (!LHS->getType()->isIntegerTy()) | |
| return false; | |
| if (!ICmpInst::isRelational(P)) | |
| return false; | |
| if (L.isLoopInvariant(LHS)) { | |
| std::swap(LHS, RHS); | |
| P = ICmpInst::getSwappedPredicate(P); | |
| } | |
| if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS)) | |
| return false; | |
| if (Inverse) | |
| P = ICmpInst::getInversePredicate(P); | |
| return true; | |
| }; | |
| CmpPredicate P1, P2; | |
| Value *LHS1, *LHS2, *RHS1, *RHS2; | |
| if (!MatchICmpAgainstInvariant(Cond1, P1, LHS1, RHS1) || | |
| !MatchICmpAgainstInvariant(Cond2, P2, LHS2, RHS2)) | |
| return false; | |
| auto MatchingPred = CmpPredicate::getMatching(P1, P2); | |
| if (!MatchingPred || LHS1 != LHS2) | |
| return false; | |
| // Everything is fine, we can do the transform. | |
| bool UseMin = ICmpInst::isLT(*MatchingPred) || ICmpInst::isLE(*MatchingPred); | |
| assert( | |
| (UseMin || ICmpInst::isGT(*MatchingPred) || | |
| ICmpInst::isGE(*MatchingPred)) && | |
| "Relational predicate is either less (or equal) or greater (or equal)!"); | |
| Intrinsic::ID id = ICmpInst::isSigned(*MatchingPred) | |
| ? (UseMin ? Intrinsic::smin : Intrinsic::smax) | |
| : (UseMin ? Intrinsic::umin : Intrinsic::umax); | |
| auto *Preheader = L.getLoopPreheader(); | |
| assert(Preheader && "Loop is not in simplify form?"); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| // We are about to create a new guaranteed use for RHS2 which might not exist | |
| // before (if it was a non-taken input of logical and/or instruction). If it | |
| // was poison, we need to freeze it. Note that no new use for LHS and RHS1 are | |
| // introduced, so they don't need this. | |
| if (isa<SelectInst>(I)) | |
| RHS2 = Builder.CreateFreeze(RHS2, RHS2->getName() + ".fr"); | |
| Value *NewRHS = Builder.CreateBinaryIntrinsic( | |
| id, RHS1, RHS2, nullptr, | |
| StringRef("invariant.") + | |
| (ICmpInst::isSigned(*MatchingPred) ? "s" : "u") + | |
| (UseMin ? "min" : "max")); | |
| Builder.SetInsertPoint(&I); | |
| ICmpInst::Predicate P = *MatchingPred; | |
| if (Inverse) | |
| P = ICmpInst::getInversePredicate(P); | |
| Value *NewCond = Builder.CreateICmp(P, LHS1, NewRHS); | |
| NewCond->takeName(&I); | |
| I.replaceAllUsesWith(NewCond); | |
| eraseInstruction(I, SafetyInfo, MSSAU); | |
| Instruction &CondI1 = *cast<Instruction>(Cond1); | |
| Instruction &CondI2 = *cast<Instruction>(Cond2); | |
| salvageDebugInfo(CondI1); | |
| salvageDebugInfo(CondI2); | |
| eraseInstruction(CondI1, SafetyInfo, MSSAU); | |
| eraseInstruction(CondI2, SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| /// Reassociate gep (gep ptr, idx1), idx2 to gep (gep ptr, idx2), idx1 if | |
| /// this allows hoisting the inner GEP. | |
| static bool hoistGEP(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT) { | |
| auto *GEP = dyn_cast<GetElementPtrInst>(&I); | |
| if (!GEP) | |
| return false; | |
| // Do not try to hoist a constant GEP out of the loop via reassociation. | |
| // Constant GEPs can often be folded into addressing modes, and reassociating | |
| // them may inhibit CSE of a common base. | |
| if (GEP->hasAllConstantIndices()) | |
| return false; | |
| auto *Src = dyn_cast<GetElementPtrInst>(GEP->getPointerOperand()); | |
| if (!Src || !Src->hasOneUse() || !L.contains(Src)) | |
| return false; | |
| Value *SrcPtr = Src->getPointerOperand(); | |
| auto LoopInvariant = [&](Value *V) { return L.isLoopInvariant(V); }; | |
| if (!L.isLoopInvariant(SrcPtr) || !all_of(GEP->indices(), LoopInvariant)) | |
| return false; | |
| // This can only happen if !AllowSpeculation, otherwise this would already be | |
| // handled. | |
| // FIXME: Should we respect AllowSpeculation in these reassociation folds? | |
| // The flag exists to prevent metadata dropping, which is not relevant here. | |
| if (all_of(Src->indices(), LoopInvariant)) | |
| return false; | |
| // The swapped GEPs are inbounds if both original GEPs are inbounds | |
| // and the sign of the offsets is the same. For simplicity, only | |
| // handle both offsets being non-negative. | |
| const DataLayout &DL = GEP->getDataLayout(); | |
| auto NonNegative = [&](Value *V) { | |
| return isKnownNonNegative(V, SimplifyQuery(DL, DT, AC, GEP)); | |
| }; | |
| bool IsInBounds = Src->isInBounds() && GEP->isInBounds() && | |
| all_of(Src->indices(), NonNegative) && | |
| all_of(GEP->indices(), NonNegative); | |
| BasicBlock *Preheader = L.getLoopPreheader(); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| Value *NewSrc = Builder.CreateGEP(GEP->getSourceElementType(), SrcPtr, | |
| SmallVector<Value *>(GEP->indices()), | |
| "invariant.gep", IsInBounds); | |
| Builder.SetInsertPoint(GEP); | |
| Value *NewGEP = Builder.CreateGEP(Src->getSourceElementType(), NewSrc, | |
| SmallVector<Value *>(Src->indices()), "gep", | |
| IsInBounds); | |
| GEP->replaceAllUsesWith(NewGEP); | |
| eraseInstruction(*GEP, SafetyInfo, MSSAU); | |
| salvageDebugInfo(*Src); | |
| eraseInstruction(*Src, SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| /// Try to turn things like "LV + C1 < C2" into "LV < C2 - C1". Here | |
| /// C1 and C2 are loop invariants and LV is a loop-variant. | |
| static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS, | |
| Value *InvariantRHS, ICmpInst &ICmp, Loop &L, | |
| ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, | |
| AssumptionCache *AC, DominatorTree *DT) { | |
| assert(!L.isLoopInvariant(VariantLHS) && "Precondition."); | |
| assert(L.isLoopInvariant(InvariantRHS) && "Precondition."); | |
| bool IsSigned = ICmpInst::isSigned(Pred); | |
| // Try to represent VariantLHS as sum of invariant and variant operands. | |
| using namespace PatternMatch; | |
| Value *VariantOp, *InvariantOp; | |
| if (IsSigned && !match(VariantLHS, m_NSWAddLike(m_Value(VariantOp), | |
| m_Value(InvariantOp)))) | |
| return false; | |
| if (!IsSigned && !match(VariantLHS, m_NUWAddLike(m_Value(VariantOp), | |
| m_Value(InvariantOp)))) | |
| return false; | |
| // LHS itself is a loop-variant, try to represent it in the form: | |
| // "VariantOp + InvariantOp". If it is possible, then we can reassociate. | |
| if (L.isLoopInvariant(VariantOp)) | |
| std::swap(VariantOp, InvariantOp); | |
| if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) | |
| return false; | |
| // In order to turn "LV + C1 < C2" into "LV < C2 - C1", we need to be able to | |
| // freely move values from left side of inequality to right side (just as in | |
| // normal linear arithmetics). Overflows make things much more complicated, so | |
| // we want to avoid this. | |
| auto &DL = L.getHeader()->getDataLayout(); | |
| SimplifyQuery SQ(DL, DT, AC, &ICmp); | |
| if (IsSigned && computeOverflowForSignedSub(InvariantRHS, InvariantOp, SQ) != | |
| llvm::OverflowResult::NeverOverflows) | |
| return false; | |
| if (!IsSigned && | |
| computeOverflowForUnsignedSub(InvariantRHS, InvariantOp, SQ) != | |
| llvm::OverflowResult::NeverOverflows) | |
| return false; | |
| auto *Preheader = L.getLoopPreheader(); | |
| assert(Preheader && "Loop is not in simplify form?"); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| Value *NewCmpOp = | |
| Builder.CreateSub(InvariantRHS, InvariantOp, "invariant.op", | |
| /*HasNUW*/ !IsSigned, /*HasNSW*/ IsSigned); | |
| ICmp.setPredicate(Pred); | |
| ICmp.setOperand(0, VariantOp); | |
| ICmp.setOperand(1, NewCmpOp); | |
| // The new LHS is a different value, so a samesign (or any other | |
| // poison-generating) flag asserted about the old operands may no longer hold. | |
| ICmp.dropPoisonGeneratingFlags(); | |
| Instruction &DeadI = cast<Instruction>(*VariantLHS); | |
| salvageDebugInfo(DeadI); | |
| eraseInstruction(DeadI, SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| /// Try to reassociate and hoist the following two patterns: | |
| /// LV - C1 < C2 --> LV < C1 + C2, | |
| /// C1 - LV < C2 --> LV > C1 - C2. | |
| static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS, | |
| Value *InvariantRHS, ICmpInst &ICmp, Loop &L, | |
| ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, | |
| AssumptionCache *AC, DominatorTree *DT) { | |
| assert(!L.isLoopInvariant(VariantLHS) && "Precondition."); | |
| assert(L.isLoopInvariant(InvariantRHS) && "Precondition."); | |
| bool IsSigned = ICmpInst::isSigned(Pred); | |
| // Try to represent VariantLHS as sum of invariant and variant operands. | |
| using namespace PatternMatch; | |
| Value *VariantOp, *InvariantOp; | |
| if (IsSigned && | |
| !match(VariantLHS, m_NSWSub(m_Value(VariantOp), m_Value(InvariantOp)))) | |
| return false; | |
| if (!IsSigned && | |
| !match(VariantLHS, m_NUWSub(m_Value(VariantOp), m_Value(InvariantOp)))) | |
| return false; | |
| bool VariantSubtracted = false; | |
| // LHS itself is a loop-variant, try to represent it in the form: | |
| // "VariantOp + InvariantOp". If it is possible, then we can reassociate. If | |
| // the variant operand goes with minus, we use a slightly different scheme. | |
| if (L.isLoopInvariant(VariantOp)) { | |
| std::swap(VariantOp, InvariantOp); | |
| VariantSubtracted = true; | |
| Pred = ICmpInst::getSwappedPredicate(Pred); | |
| } | |
| if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) | |
| return false; | |
| // In order to turn "LV - C1 < C2" into "LV < C2 + C1", we need to be able to | |
| // freely move values from left side of inequality to right side (just as in | |
| // normal linear arithmetics). Overflows make things much more complicated, so | |
| // we want to avoid this. Likewise, for "C1 - LV < C2" we need to prove that | |
| // "C1 - C2" does not overflow. | |
| auto &DL = L.getHeader()->getDataLayout(); | |
| SimplifyQuery SQ(DL, DT, AC, &ICmp); | |
| if (VariantSubtracted && IsSigned) { | |
| // C1 - LV < C2 --> LV > C1 - C2 | |
| if (computeOverflowForSignedSub(InvariantOp, InvariantRHS, SQ) != | |
| llvm::OverflowResult::NeverOverflows) | |
| return false; | |
| } else if (VariantSubtracted && !IsSigned) { | |
| // C1 - LV < C2 --> LV > C1 - C2 | |
| if (computeOverflowForUnsignedSub(InvariantOp, InvariantRHS, SQ) != | |
| llvm::OverflowResult::NeverOverflows) | |
| return false; | |
| } else if (!VariantSubtracted && IsSigned) { | |
| // LV - C1 < C2 --> LV < C1 + C2 | |
| if (computeOverflowForSignedAdd(InvariantOp, InvariantRHS, SQ) != | |
| llvm::OverflowResult::NeverOverflows) | |
| return false; | |
| } else { // !VariantSubtracted && !IsSigned | |
| // LV - C1 < C2 --> LV < C1 + C2 | |
| if (computeOverflowForUnsignedAdd(InvariantOp, InvariantRHS, SQ) != | |
| llvm::OverflowResult::NeverOverflows) | |
| return false; | |
| } | |
| auto *Preheader = L.getLoopPreheader(); | |
| assert(Preheader && "Loop is not in simplify form?"); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| Value *NewCmpOp = | |
| VariantSubtracted | |
| ? Builder.CreateSub(InvariantOp, InvariantRHS, "invariant.op", | |
| /*HasNUW*/ !IsSigned, /*HasNSW*/ IsSigned) | |
| : Builder.CreateAdd(InvariantOp, InvariantRHS, "invariant.op", | |
| /*HasNUW*/ !IsSigned, /*HasNSW*/ IsSigned); | |
| ICmp.setPredicate(Pred); | |
| ICmp.setOperand(0, VariantOp); | |
| ICmp.setOperand(1, NewCmpOp); | |
| // The new LHS is a different value, so a samesign (or any other | |
| // poison-generating) flag asserted about the old operands may no longer hold. | |
| ICmp.dropPoisonGeneratingFlags(); | |
| Instruction &DeadI = cast<Instruction>(*VariantLHS); | |
| salvageDebugInfo(DeadI); | |
| eraseInstruction(DeadI, SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| /// Reassociate and hoist add/sub expressions. | |
| static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT) { | |
| using namespace PatternMatch; | |
| CmpPredicate Pred; | |
| Value *LHS, *RHS; | |
| if (!match(&I, m_ICmp(Pred, m_Value(LHS), m_Value(RHS)))) | |
| return false; | |
| // Put variant operand to LHS position. | |
| if (L.isLoopInvariant(LHS)) { | |
| std::swap(LHS, RHS); | |
| Pred = ICmpInst::getSwappedPredicate(Pred); | |
| } | |
| // We want to delete the initial operation after reassociation, so only do it | |
| // if it has no other uses. | |
| if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS) || !LHS->hasOneUse()) | |
| return false; | |
| // TODO: We could go with smarter context, taking common dominator of all I's | |
| // users instead of I itself. | |
| if (hoistAdd(Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT)) | |
| return true; | |
| if (hoistSub(Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT)) | |
| return true; | |
| return false; | |
| } | |
| static bool isReassociableOp(Instruction *I, unsigned IntOpcode, | |
| unsigned FPOpcode) { | |
| if (I->getOpcode() == IntOpcode) | |
| return true; | |
| if (I->getOpcode() == FPOpcode && I->hasAllowReassoc() && | |
| I->hasNoSignedZeros()) | |
| return true; | |
| return false; | |
| } | |
| /// Try to reassociate expressions like ((A1 * B1) + (A2 * B2) + ...) * C where | |
| /// A1, A2, ... and C are loop invariants into expressions like | |
| /// ((A1 * C * B1) + (A2 * C * B2) + ...) and hoist the (A1 * C), (A2 * C), ... | |
| /// invariant expressions. This functions returns true only if any hoisting has | |
| /// actually occurred. | |
| static bool hoistMulAddAssociation(const ScalarOptions &Opts, Instruction &I, | |
| Loop &L, ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT) { | |
| if (!isReassociableOp(&I, Instruction::Mul, Instruction::FMul)) | |
| return false; | |
| Value *VariantOp = I.getOperand(0); | |
| Value *InvariantOp = I.getOperand(1); | |
| if (L.isLoopInvariant(VariantOp)) | |
| std::swap(VariantOp, InvariantOp); | |
| if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) | |
| return false; | |
| Value *Factor = InvariantOp; | |
| // First, we need to make sure we should do the transformation. | |
| SmallVector<Use *> Changes; | |
| SmallVector<BinaryOperator *> Adds; | |
| SmallVector<BinaryOperator *> Worklist; | |
| if (BinaryOperator *VariantBinOp = dyn_cast<BinaryOperator>(VariantOp)) | |
| Worklist.push_back(VariantBinOp); | |
| while (!Worklist.empty()) { | |
| BinaryOperator *BO = Worklist.pop_back_val(); | |
| if (!BO->hasOneUse()) | |
| return false; | |
| if (isReassociableOp(BO, Instruction::Add, Instruction::FAdd) && | |
| isa<BinaryOperator>(BO->getOperand(0)) && | |
| isa<BinaryOperator>(BO->getOperand(1))) { | |
| Worklist.push_back(cast<BinaryOperator>(BO->getOperand(0))); | |
| Worklist.push_back(cast<BinaryOperator>(BO->getOperand(1))); | |
| Adds.push_back(BO); | |
| continue; | |
| } | |
| if (!isReassociableOp(BO, Instruction::Mul, Instruction::FMul) || | |
| L.isLoopInvariant(BO)) | |
| return false; | |
| Use &U0 = BO->getOperandUse(0); | |
| Use &U1 = BO->getOperandUse(1); | |
| if (L.isLoopInvariant(U0)) | |
| Changes.push_back(&U0); | |
| else if (L.isLoopInvariant(U1)) | |
| Changes.push_back(&U1); | |
| else | |
| return false; | |
| unsigned Limit = I.getType()->isIntOrIntVectorTy() | |
| ? Opts.licm_max_num_int_reassociations | |
| : Opts.licm_max_num_fp_reassociations; | |
| if (Changes.size() > Limit) | |
| return false; | |
| } | |
| if (Changes.empty()) | |
| return false; | |
| // Drop the poison flags for any adds we looked through. | |
| if (I.getType()->isIntOrIntVectorTy()) { | |
| for (auto *Add : Adds) | |
| Add->dropPoisonGeneratingFlags(); | |
| } | |
| // We know we should do it so let's do the transformation. | |
| auto *Preheader = L.getLoopPreheader(); | |
| assert(Preheader && "Loop is not in simplify form?"); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| for (auto *U : Changes) { | |
| assert(L.isLoopInvariant(U->get())); | |
| auto *Ins = cast<BinaryOperator>(U->getUser()); | |
| Value *Mul; | |
| if (I.getType()->isIntOrIntVectorTy()) { | |
| Mul = Builder.CreateMul(U->get(), Factor, "factor.op.mul"); | |
| // Drop the poison flags on the original multiply. | |
| Ins->dropPoisonGeneratingFlags(); | |
| } else | |
| Mul = Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul"); | |
| // Rewrite the reassociable instruction. | |
| unsigned OpIdx = U->getOperandNo(); | |
| auto *LHS = OpIdx == 0 ? Mul : Ins->getOperand(0); | |
| auto *RHS = OpIdx == 1 ? Mul : Ins->getOperand(1); | |
| auto *NewBO = | |
| BinaryOperator::Create(Ins->getOpcode(), LHS, RHS, | |
| Ins->getName() + ".reass", Ins->getIterator()); | |
| NewBO->setDebugLoc(DebugLoc::getDropped()); | |
| NewBO->copyIRFlags(Ins); | |
| if (VariantOp == Ins) | |
| VariantOp = NewBO; | |
| Ins->replaceAllUsesWith(NewBO); | |
| eraseInstruction(*Ins, SafetyInfo, MSSAU); | |
| } | |
| I.replaceAllUsesWith(VariantOp); | |
| eraseInstruction(I, SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| /// Reassociate associative binary expressions of the form | |
| /// | |
| /// 1. "(LV op C1) op C2" ==> "LV op (C1 op C2)" | |
| /// 2. "(C1 op LV) op C2" ==> "LV op (C1 op C2)" | |
| /// 3. "C2 op (C1 op LV)" ==> "LV op (C1 op C2)" | |
| /// 4. "C2 op (LV op C1)" ==> "LV op (C1 op C2)" | |
| /// | |
| /// where op is an associative BinOp, LV is a loop variant, and C1 and C2 are | |
| /// loop invariants that we want to hoist, noting that associativity implies | |
| /// commutativity. | |
| static bool hoistBOAssociation(Instruction &I, Loop &L, | |
| ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT) { | |
| auto *BO = dyn_cast<BinaryOperator>(&I); | |
| if (!BO || !BO->isAssociative()) | |
| return false; | |
| Instruction::BinaryOps Opcode = BO->getOpcode(); | |
| bool LVInRHS = L.isLoopInvariant(BO->getOperand(0)); | |
| auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand(LVInRHS)); | |
| if (!BO0 || BO0->getOpcode() != Opcode || !BO0->isAssociative() || | |
| BO0->hasNUsesOrMore(BO0->getType()->isIntegerTy() ? 2 : 3)) | |
| return false; | |
| Value *LV = BO0->getOperand(0); | |
| Value *C1 = BO0->getOperand(1); | |
| Value *C2 = BO->getOperand(!LVInRHS); | |
| assert(BO->isCommutative() && BO0->isCommutative() && | |
| "Associativity implies commutativity"); | |
| if (L.isLoopInvariant(LV) && !L.isLoopInvariant(C1)) | |
| std::swap(LV, C1); | |
| if (L.isLoopInvariant(LV) || !L.isLoopInvariant(C1) || !L.isLoopInvariant(C2)) | |
| return false; | |
| auto *Preheader = L.getLoopPreheader(); | |
| assert(Preheader && "Loop is not in simplify form?"); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| auto *Inv = Builder.CreateBinOp(Opcode, C1, C2, "invariant.op"); | |
| auto *NewBO = BinaryOperator::Create( | |
| Opcode, LV, Inv, BO->getName() + ".reass", BO->getIterator()); | |
| NewBO->setDebugLoc(DebugLoc::getDropped()); | |
| if (Opcode == Instruction::FAdd || Opcode == Instruction::FMul) { | |
| // Intersect FMF flags for FADD and FMUL. | |
| FastMathFlags Intersect = BO->getFastMathFlags() & BO0->getFastMathFlags(); | |
| if (auto *I = dyn_cast<Instruction>(Inv)) | |
| I->setFastMathFlags(Intersect); | |
| NewBO->setFastMathFlags(Intersect); | |
| } else { | |
| OverflowTracking Flags; | |
| Flags.AllKnownNonNegative = false; | |
| Flags.AllKnownNonZero = false; | |
| Flags.mergeFlags(*BO); | |
| Flags.mergeFlags(*BO0); | |
| // If `Inv` was not constant-folded, a new Instruction has been created. | |
| auto *InvI = dyn_cast<Instruction>(Inv); | |
| if (InvI) | |
| Flags.applyFlags(*InvI); | |
| Flags.applyFlags(*NewBO); | |
| // The original nsw flags guarantee that LV + C1 + C2 is representable. | |
| // If C1 + C2 is representable too, both reassociated adds keep nsw. | |
| SimplifyQuery SQ(L.getHeader()->getDataLayout(), DT, AC, | |
| Preheader->getTerminator()); | |
| if (Opcode == Instruction::Add && Flags.HasNSW && !Flags.HasNUW && | |
| computeOverflowForSignedAdd(C1, C2, SQ) == | |
| OverflowResult::NeverOverflows) { | |
| if (InvI) | |
| InvI->setHasNoSignedWrap(); | |
| NewBO->setHasNoSignedWrap(); | |
| } | |
| } | |
| BO->replaceAllUsesWith(NewBO); | |
| eraseInstruction(*BO, SafetyInfo, MSSAU); | |
| // (LV op C1) might not be erased if it has more uses than the one we just | |
| // replaced. | |
| if (BO0->use_empty()) { | |
| salvageDebugInfo(*BO0); | |
| eraseInstruction(*BO0, SafetyInfo, MSSAU); | |
| } | |
| return true; | |
| } | |
| /// Reassociate add/sub expressions of the form: | |
| /// | |
| /// 1. "(LV + C1) - C2" ==> "LV + (C1 - C2)" | |
| /// 2. "(LV - C1) - C2" ==> "LV - (C1 + C2)" | |
| /// 3. "(LV - C1) + C2" ==> "LV + (C2 - C1)" | |
| /// | |
| /// where LV is a loop variant, and C1 and C2 are loop invariants. | |
| /// Sub is not associative, but these algebraic identities allow hoisting | |
| /// invariant computations out of the loop. | |
| static bool hoistSubAddAssociation(Instruction &I, Loop &L, | |
| ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT) { | |
| using namespace PatternMatch; | |
| Instruction *BO; | |
| Value *LV, *C1, *C2; | |
| Instruction::BinaryOps InvOp, ResultOp; | |
| // Try to match one of three reassociation patterns involving sub. | |
| // | |
| // 1. (LV + C1) - C2 ==> LV + (C1 - C2) | |
| // 2. (LV - C1) - C2 ==> LV - (C1 + C2) | |
| // 3. (LV - C1) + C2 ==> LV + (C2 - C1) | |
| // ^ ^ | |
| // \ \___ InvOp | |
| // \ | |
| // \____ ResultOp | |
| // | |
| if (match(&I, | |
| m_Sub(m_OneUse(m_Instruction(BO, m_Add(m_Value(LV), m_Value(C1)))), | |
| m_Value(C2)))) { | |
| // Case 1. | |
| // | |
| // Depending on which of the addition is invariant, we might need to swap | |
| // the arguments | |
| if (L.isLoopInvariant(LV) && !L.isLoopInvariant(C1)) | |
| std::swap(LV, C1); | |
| InvOp = Instruction::Sub; | |
| ResultOp = Instruction::Add; | |
| } else if (match(&I, m_Sub(m_OneUse(m_Instruction( | |
| BO, m_Sub(m_Value(LV), m_Value(C1)))), | |
| m_Value(C2)))) { | |
| // Case 2. | |
| InvOp = Instruction::Add; | |
| ResultOp = Instruction::Sub; | |
| } else if (match(&I, m_c_Add(m_OneUse(m_Instruction( | |
| BO, m_Sub(m_Value(LV), m_Value(C1)))), | |
| m_Value(C2)))) { | |
| // Case 3. | |
| // | |
| // We use (C2 - C1) as the invariant as opposed to case 1, but instead of | |
| // adding a special case in invariant creation, we can just swap the | |
| // operands here. | |
| std::swap(C1, C2); | |
| InvOp = Instruction::Sub; | |
| ResultOp = Instruction::Add; | |
| } else { | |
| return false; | |
| } | |
| if (L.isLoopInvariant(LV) || !L.isLoopInvariant(C1) || !L.isLoopInvariant(C2)) | |
| return false; | |
| auto *Preheader = L.getLoopPreheader(); | |
| assert(Preheader && "Loop is not in simplify form?"); | |
| IRBuilder<> Builder(Preheader->getTerminator()); | |
| auto *Inv = Builder.CreateBinOp(InvOp, C1, C2, "invariant.op"); | |
| auto *NewBO = BinaryOperator::Create(ResultOp, LV, Inv, | |
| I.getName() + ".reass", I.getIterator()); | |
| NewBO->setDebugLoc(DebugLoc::getDropped()); | |
| // No overflow flags are set on the new instructions -- reassociation | |
| // involving sub does not preserve nsw/nuw in general. | |
| I.replaceAllUsesWith(NewBO); | |
| eraseInstruction(I, SafetyInfo, MSSAU); | |
| salvageDebugInfo(*BO); | |
| eraseInstruction(*BO, SafetyInfo, MSSAU); | |
| return true; | |
| } | |
| static bool hoistArithmetics(const ScalarOptions &Opts, Instruction &I, Loop &L, | |
| ICFLoopSafetyInfo &SafetyInfo, | |
| MemorySSAUpdater &MSSAU, AssumptionCache *AC, | |
| DominatorTree *DT) { | |
| // Optimize complex patterns, such as (x < INV1 && x < INV2), turning them | |
| // into (x < min(INV1, INV2)), and hoisting the invariant part of this | |
| // expression out of the loop. | |
| if (hoistMinMax(I, L, SafetyInfo, MSSAU)) { | |
| ++NumHoisted; | |
| ++NumMinMaxHoisted; | |
| return true; | |
| } | |
| // Try to hoist GEPs by reassociation. | |
| if (hoistGEP(I, L, SafetyInfo, MSSAU, AC, DT)) { | |
| ++NumHoisted; | |
| ++NumGEPsHoisted; | |
| return true; | |
| } | |
| // Try to hoist add/sub's by reassociation. | |
| if (hoistAddSub(I, L, SafetyInfo, MSSAU, AC, DT)) { | |
| ++NumHoisted; | |
| ++NumAddSubHoisted; | |
| return true; | |
| } | |
| bool IsInt = I.getType()->isIntOrIntVectorTy(); | |
| if (hoistMulAddAssociation(Opts, I, L, SafetyInfo, MSSAU, AC, DT)) { | |
| ++NumHoisted; | |
| if (IsInt) | |
| ++NumIntAssociationsHoisted; | |
| else | |
| ++NumFPAssociationsHoisted; | |
| return true; | |
| } | |
| if (hoistBOAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) { | |
| ++NumHoisted; | |
| ++NumBOAssociationsHoisted; | |
| return true; | |
| } | |
| if (hoistSubAddAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) { | |
| ++NumHoisted; | |
| ++NumBOAssociationsHoisted; | |
| return true; | |
| } | |
| return false; | |
| } | |
| /// Little predicate that returns true if the specified basic block is in | |
| /// a subloop of the current one, not the current one itself. | |
| /// | |
| static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI) { | |
| assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop"); | |
| return LI->getLoopFor(BB) != CurLoop; | |
| } |