Index: include/llvm/Analysis/MustExecute.h =================================================================== --- include/llvm/Analysis/MustExecute.h +++ include/llvm/Analysis/MustExecute.h @@ -31,33 +31,47 @@ class Loop; /// Captures loop safety information. -/// It keep information for loop & its header may throw exception or otherwise +/// It keep information for loop blocks may throw exception or otherwise /// exit abnormaly on any iteration of the loop which might actually execute /// at runtime. The primary way to consume this infromation is via /// isGuaranteedToExecute below, but some callers bailout or fallback to /// alternate reasoning if a loop contains any implicit control flow. -struct LoopSafetyInfo { +class LoopSafetyInfo { bool MayThrow = false; // The current loop contains an instruction which // may throw. bool HeaderMayThrow = false; // Same as previous, but specific to loop header + // The current loop this LoopSafetyInfo is working with. It should be set via + // constructor or via the method "reset" to a non-null value before any query + // is done to this LoopSafetyInfo. + Loop *CurLoop = nullptr; + +public: // Used to update funclet bundle operands. DenseMap BlockColors; - LoopSafetyInfo() = default; -}; + LoopSafetyInfo() {} + + LoopSafetyInfo(Loop *L, DominatorTree *DT) { + // TODO: DT will later be used by ICF analysis that will come in a follow-up + // patch. So far we only need it to make signature changes properly. + assert(DT && "Need to pass a valid domination tree!"); + assert(L && "Need to pass a valid loop!"); + (void)DT; + reset(L); + } -/// Computes safety information for a loop checks loop body & header for -/// the possibility of may throw exception, it takes LoopSafetyInfo and loop as -/// argument. Updates safety information in LoopSafetyInfo argument. -/// Note: This is defined to clear and reinitialize an already initialized -/// LoopSafetyInfo. Some callers rely on this fact. -void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *); + bool mayThrow(const BasicBlock *BB); + + bool anyBlockMayThrow(); + + void reset(Loop *L); +}; /// Returns true if the instruction in a loop is guaranteed to execute at least /// once (under the assumption that the loop is entered). bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo); + LoopSafetyInfo *SafetyInfo); } Index: lib/Analysis/MustExecute.cpp =================================================================== --- lib/Analysis/MustExecute.cpp +++ lib/Analysis/MustExecute.cpp @@ -22,20 +22,35 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +/// Returns true if the block \p BB contains an instruction that may throw or +/// otherwise exit abnormally. +bool LoopSafetyInfo::mayThrow(const BasicBlock *BB) { + assert(CurLoop && "Should calculate the info first!"); + assert(CurLoop->getHeader() == BB && "Currently we only support header!"); + return HeaderMayThrow; +} + +/// Returns true if any block in the current loop contains an instruction that +/// may throw or otherwise exit abnormally. +bool LoopSafetyInfo::anyBlockMayThrow() { + assert(CurLoop && "Should calculate the info first!"); + return MayThrow; +} + /// Computes loop safety information, checks loop body & header /// for the possibility of may throw exception. /// -void llvm::computeLoopSafetyInfo(LoopSafetyInfo *SafetyInfo, Loop *CurLoop) { +void LoopSafetyInfo::reset(Loop *CurLoop) { assert(CurLoop != nullptr && "CurLoop can't be null"); + this->CurLoop = CurLoop; BasicBlock *Header = CurLoop->getHeader(); // Setting default safety values. - SafetyInfo->MayThrow = false; - SafetyInfo->HeaderMayThrow = false; + MayThrow = false; + HeaderMayThrow = false; // Iterate over header and compute safety info. - SafetyInfo->HeaderMayThrow = - !isGuaranteedToTransferExecutionToSuccessor(Header); + HeaderMayThrow = !isGuaranteedToTransferExecutionToSuccessor(Header); - SafetyInfo->MayThrow = SafetyInfo->HeaderMayThrow; + MayThrow = HeaderMayThrow; // Iterate over loop instructions and compute safety info. // Skip header as it has been computed and stored in HeaderMayThrow. // The first block in loopinfo.Blocks is guaranteed to be the header. @@ -43,9 +58,8 @@ "First block must be header"); for (Loop::block_iterator BB = std::next(CurLoop->block_begin()), BBE = CurLoop->block_end(); - (BB != BBE) && !SafetyInfo->MayThrow; ++BB) - SafetyInfo->MayThrow |= - !isGuaranteedToTransferExecutionToSuccessor(*BB); + (BB != BBE) && !MayThrow; ++BB) + MayThrow |= !isGuaranteedToTransferExecutionToSuccessor(*BB); // Compute funclet colors if we might sink/hoist in a function with a funclet // personality routine. @@ -53,7 +67,7 @@ if (Fn->hasPersonalityFn()) if (Constant *PersonalityFn = Fn->getPersonalityFn()) if (isScopedEHPersonality(classifyEHPersonality(PersonalityFn))) - SafetyInfo->BlockColors = colorEHFunclets(*Fn); + BlockColors = colorEHFunclets(*Fn); } /// Return true if we can prove that the given ExitBlock is not reached on the @@ -103,7 +117,7 @@ /// once. bool llvm::isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo) { + LoopSafetyInfo *SafetyInfo) { // We have to check to make sure that the instruction dominates all // of the exit blocks. If it doesn't, then there is a path out of the loop // which does not execute this instruction, so we can't hoist it. @@ -116,12 +130,12 @@ // Inst unless we can prove that Inst comes before the potential implicit // exit. At the moment, we use a (cheap) hack for the common case where // the instruction of interest is the first one in the block. - return !SafetyInfo->HeaderMayThrow || + return !SafetyInfo->mayThrow(CurLoop->getHeader()) || Inst.getParent()->getFirstNonPHIOrDbg() == &Inst; // Somewhere in this loop there is an instruction which may throw and make us // exit the loop. - if (SafetyInfo->MayThrow) + if (SafetyInfo->anyBlockMayThrow()) return false; // Note: There are two styles of reasoning intermixed below for @@ -195,8 +209,7 @@ // TODO: merge these two routines. For the moment, we display the best // result obtained by *either* implementation. This is a bit unfair since no // caller actually gets the full power at the moment. - LoopSafetyInfo LSI; - computeLoopSafetyInfo(&LSI, L); + LoopSafetyInfo LSI(L, DT); return isGuaranteedToExecute(I, DT, L, &LSI) || isGuaranteedToExecuteForEveryIteration(&I, L); } Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -94,7 +94,7 @@ const LoopSafetyInfo *SafetyInfo, TargetTransformInfo *TTI, bool &FreeInLoop); static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo, + LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE); static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, const Loop *CurLoop, LoopSafetyInfo *SafetyInfo, @@ -102,7 +102,7 @@ static bool isSafeToExecuteUnconditionally(Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo, + LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE, const Instruction *CtxI = nullptr); static bool pointerInvalidatedByLoop(Value *V, uint64_t Size, @@ -260,8 +260,7 @@ BasicBlock *Preheader = L->getLoopPreheader(); // Compute loop safety information. - LoopSafetyInfo SafetyInfo; - computeLoopSafetyInfo(&SafetyInfo, L); + LoopSafetyInfo SafetyInfo(L, DT); // 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 @@ -1064,7 +1063,7 @@ /// is safe to hoist, this instruction is called to do the dirty work. /// static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo, + LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE) { auto *Preheader = CurLoop->getLoopPreheader(); LLVM_DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": " << I @@ -1110,7 +1109,7 @@ static bool isSafeToExecuteUnconditionally(Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo, + LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE, const Instruction *CtxI) { if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT)) @@ -1310,7 +1309,7 @@ const DataLayout &MDL = Preheader->getModule()->getDataLayout(); bool IsKnownThreadLocalObject = false; - if (SafetyInfo->MayThrow) { + if (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 Index: lib/Transforms/Scalar/LoopIdiomRecognize.cpp =================================================================== --- lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -319,9 +319,8 @@ // The following transforms hoist stores/memsets into the loop pre-header. // Give up if the loop has instructions may throw. - LoopSafetyInfo SafetyInfo; - computeLoopSafetyInfo(&SafetyInfo, CurLoop); - if (SafetyInfo.MayThrow) + LoopSafetyInfo SafetyInfo(CurLoop, DT); + if (SafetyInfo.anyBlockMayThrow()) return MadeChange; // Scan all the blocks in the loop that are not in subloops. Index: lib/Transforms/Scalar/LoopUnswitch.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnswitch.cpp +++ lib/Transforms/Scalar/LoopUnswitch.cpp @@ -199,7 +199,7 @@ static char ID; // Pass ID, replacement for typeid explicit LoopUnswitch(bool Os = false, bool hasBranchDivergence = false) - : LoopPass(ID), OptimizeForSize(Os), + : LoopPass(ID), OptimizeForSize(Os), SafetyInfo(), hasBranchDivergence(hasBranchDivergence) { initializeLoopUnswitchPass(*PassRegistry::getPassRegistry()); } @@ -520,7 +520,7 @@ SanitizeMemory = F->hasFnAttribute(Attribute::SanitizeMemory); if (SanitizeMemory) - computeLoopSafetyInfo(&SafetyInfo, L); + SafetyInfo.reset(L); bool Changed = false; do { Index: lib/Transforms/Utils/LoopUnrollAndJam.cpp =================================================================== --- lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -761,9 +761,8 @@ } // Check the loop safety info for exceptions. - LoopSafetyInfo LSI; - computeLoopSafetyInfo(&LSI, L); - if (LSI.MayThrow) { + LoopSafetyInfo LSI(L, &DT); + if (LSI.anyBlockMayThrow()) { LLVM_DEBUG(dbgs() << "Won't unroll-and-jam; Something may throw\n"); return false; }