From 9c90ec2fae508e08b0323db4d1a164cbf64c8bcc Mon Sep 17 00:00:00 2001 From: Max Kazantsev Date: Tue, 16 Oct 2018 08:31:05 +0000 Subject: [PATCH] [NFC] Make LoopSafetyInfo abstract to allow alternative implementations llvm-svn: 344592 --- llvm/include/llvm/Analysis/MustExecute.h | 46 +++++++++++++++---- llvm/lib/Analysis/MustExecute.cpp | 16 +++---- llvm/lib/Transforms/Scalar/LICM.cpp | 2 +- .../Transforms/Scalar/LoopIdiomRecognize.cpp | 2 +- llvm/lib/Transforms/Scalar/LoopUnswitch.cpp | 2 +- .../lib/Transforms/Utils/LoopUnrollAndJam.cpp | 2 +- 6 files changed, 48 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/Analysis/MustExecute.h b/llvm/include/llvm/Analysis/MustExecute.h index d78b38bdeadc..6a6a127b7c3a 100644 --- a/llvm/include/llvm/Analysis/MustExecute.h +++ b/llvm/include/llvm/Analysis/MustExecute.h @@ -45,10 +45,6 @@ class Loop; /// loop were made and the info wasn't recomputed properly, the behavior of all /// methods except for computeLoopSafetyInfo is undefined. 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 - // Used to update funclet bundle operands. DenseMap BlockColors; @@ -73,15 +69,15 @@ public: /// Returns true iff the header block of the loop for which this info is /// calculated contains an instruction that may throw or otherwise exit /// abnormally. - bool headerMayThrow() const; + virtual bool headerMayThrow() const = 0; /// Returns true iff the block \p BB potentially may throw exception. It can /// be false-positive in cases when we want to avoid complex analysis. - bool blockMayThrow(const BasicBlock *BB) const; + virtual bool blockMayThrow(const BasicBlock *BB) const = 0; /// Returns true iff any block of the loop for which this info is contains an /// instruction that may throw or otherwise exit abnormally. - bool anyBlockMayThrow() const; + virtual bool anyBlockMayThrow() const = 0; /// Return true if we must reach the block \p BB under assumption that the /// loop \p CurLoop is entered. @@ -93,14 +89,44 @@ public: /// 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(const Loop *CurLoop); + virtual void computeLoopSafetyInfo(const Loop *CurLoop) = 0; /// 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; + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const = 0; LoopSafetyInfo() = default; + + virtual ~LoopSafetyInfo() = default; +}; + + +/// Simple and conservative implementation of LoopSafetyInfo that can give +/// false-positive answers to its queries in order to avoid complicated +/// analysis. +class SimpleLoopSafetyInfo: public LoopSafetyInfo { + bool MayThrow = false; // The current loop contains an instruction which + // may throw. + bool HeaderMayThrow = false; // Same as previous, but specific to loop header + +public: + virtual bool headerMayThrow() const; + + virtual bool blockMayThrow(const BasicBlock *BB) const; + + virtual bool anyBlockMayThrow() const; + + virtual void computeLoopSafetyInfo(const Loop *CurLoop); + + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const; + + SimpleLoopSafetyInfo() : LoopSafetyInfo() {}; + + virtual ~SimpleLoopSafetyInfo() {}; }; } diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp index bce941be26c4..618e2e3e30d2 100644 --- a/llvm/lib/Analysis/MustExecute.cpp +++ b/llvm/lib/Analysis/MustExecute.cpp @@ -33,20 +33,20 @@ void LoopSafetyInfo::copyColors(BasicBlock *New, BasicBlock *Old) { ColorsForNewBlock = ColorsForOldBlock; } -bool LoopSafetyInfo::headerMayThrow() const { +bool SimpleLoopSafetyInfo::headerMayThrow() const { return HeaderMayThrow; } -bool LoopSafetyInfo::blockMayThrow(const BasicBlock *BB) const { +bool SimpleLoopSafetyInfo::blockMayThrow(const BasicBlock *BB) const { (void)BB; return anyBlockMayThrow(); } -bool LoopSafetyInfo::anyBlockMayThrow() const { +bool SimpleLoopSafetyInfo::anyBlockMayThrow() const { return MayThrow; } -void LoopSafetyInfo::computeLoopSafetyInfo(const Loop *CurLoop) { +void SimpleLoopSafetyInfo::computeLoopSafetyInfo(const Loop *CurLoop) { assert(CurLoop != nullptr && "CurLoop can't be null"); BasicBlock *Header = CurLoop->getHeader(); // Iterate over header and compute safety info. @@ -200,9 +200,9 @@ bool LoopSafetyInfo::allLoopPathsLeadToBlock(const Loop *CurLoop, /// Returns true if the instruction in a loop is guaranteed to execute at least /// once. -bool LoopSafetyInfo::isGuaranteedToExecute(const Instruction &Inst, - const DominatorTree *DT, - const Loop *CurLoop) const { +bool SimpleLoopSafetyInfo::isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const { // 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. @@ -259,7 +259,7 @@ static bool isMustExecuteIn(const Instruction &I, Loop *L, DominatorTree *DT) { // 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; + SimpleLoopSafetyInfo LSI; LSI.computeLoopSafetyInfo(L); return LSI.isGuaranteedToExecute(I, DT, L) || isGuaranteedToExecuteForEveryIteration(&I, L); diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 6c8992895935..e72342b88b6d 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -267,7 +267,7 @@ bool LoopInvariantCodeMotion::runOnLoop( BasicBlock *Preheader = L->getLoopPreheader(); // Compute loop safety information. - LoopSafetyInfo SafetyInfo; + SimpleLoopSafetyInfo SafetyInfo; SafetyInfo.computeLoopSafetyInfo(L); // We want to visit all of the instructions in this loop... that are not parts diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 9a45551f64b2..4b375956a124 100644 --- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -320,7 +320,7 @@ bool LoopIdiomRecognize::runOnCountableLoop() { // The following transforms hoist stores/memsets into the loop pre-header. // Give up if the loop has instructions may throw. - LoopSafetyInfo SafetyInfo; + SimpleLoopSafetyInfo SafetyInfo; SafetyInfo.computeLoopSafetyInfo(CurLoop); if (SafetyInfo.anyBlockMayThrow()) return MadeChange; diff --git a/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp index cd49f51283fa..4a089dfa7dbf 100644 --- a/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -189,7 +189,7 @@ namespace { BasicBlock *loopPreheader = nullptr; bool SanitizeMemory; - LoopSafetyInfo SafetyInfo; + SimpleLoopSafetyInfo SafetyInfo; // LoopBlocks contains all of the basic blocks of the loop, including the // preheader of the loop, the body of the loop, and the exit blocks of the diff --git a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp index c17a64f01877..8949c603a841 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -761,7 +761,7 @@ bool llvm::isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree &DT, } // Check the loop safety info for exceptions. - LoopSafetyInfo LSI; + SimpleLoopSafetyInfo LSI; LSI.computeLoopSafetyInfo(L); if (LSI.anyBlockMayThrow()) { LLVM_DEBUG(dbgs() << "Won't unroll-and-jam; Something may throw\n");