diff options
author | Aleksandr Popov <a.popov.tmb@gmail.com> | 2023-08-10 09:29:18 +0200 |
---|---|---|
committer | Aleksandr Popov <a.popov.tmb@gmail.com> | 2023-08-10 10:00:42 +0200 |
commit | 7a0debebde5de629b091c0c099d2ef89131cea04 (patch) | |
tree | e1450f2f9a2675b7b2499eaffd9e7f547edc6a0b | |
parent | bc2b1193b5a205c288d6f2e1f6562f311fba77f4 (diff) | |
download | llvm-7a0debebde5de629b091c0c099d2ef89131cea04.zip llvm-7a0debebde5de629b091c0c099d2ef89131cea04.tar.gz llvm-7a0debebde5de629b091c0c099d2ef89131cea04.tar.bz2 |
[NFC][LoopPredication] Extract guard parsing to GuardUtils
Extract logic of parsing guards and widenable branches in order to reuse
it in the GuardWidening
Reviewed By: anna
Differential Revision: https://reviews.llvm.org/D157276
-rw-r--r-- | llvm/include/llvm/Analysis/GuardUtils.h | 13 | ||||
-rw-r--r-- | llvm/lib/Analysis/GuardUtils.cpp | 35 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/LoopPredication.cpp | 70 |
3 files changed, 63 insertions, 55 deletions
diff --git a/llvm/include/llvm/Analysis/GuardUtils.h b/llvm/include/llvm/Analysis/GuardUtils.h index b832115..3ac6c8e 100644 --- a/llvm/include/llvm/Analysis/GuardUtils.h +++ b/llvm/include/llvm/Analysis/GuardUtils.h @@ -18,11 +18,16 @@ class BasicBlock; class Use; class User; class Value; +template <typename T> class SmallVectorImpl; /// Returns true iff \p U has semantics of a guard expressed in a form of call /// of llvm.experimental.guard intrinsic. bool isGuard(const User *U); +/// Returns true iff \p V has semantics of llvm.experimental.widenable.condition +/// call +bool isWidenableCondition(const Value *V); + /// Returns true iff \p U is a widenable branch (that is, parseWidenableBranch /// returns true). bool isWidenableBranch(const User *U); @@ -48,7 +53,13 @@ bool parseWidenableBranch(const User *U, Value *&Condition, /// modified. Unlike previous version, Condition is optional and may be null. bool parseWidenableBranch(User *U, Use *&Cond, Use *&WC, BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB); - + +// The guard condition is expected to be in form of: +// cond1 && cond2 && cond3 ... +// or in case of widenable branch: +// cond1 && cond2 && cond3 && widenable_contidion ... +// Method collects the list of checks, but skips widenable_condition. +void parseWidenableGuard(const User *U, llvm::SmallVectorImpl<Value *> &Checks); } // llvm #endif // LLVM_ANALYSIS_GUARDUTILS_H diff --git a/llvm/lib/Analysis/GuardUtils.cpp b/llvm/lib/Analysis/GuardUtils.cpp index 40b898e..1239ee6 100644 --- a/llvm/lib/Analysis/GuardUtils.cpp +++ b/llvm/lib/Analysis/GuardUtils.cpp @@ -19,6 +19,10 @@ bool llvm::isGuard(const User *U) { return match(U, m_Intrinsic<Intrinsic::experimental_guard>()); } +bool llvm::isWidenableCondition(const Value *V) { + return match(V, m_Intrinsic<Intrinsic::experimental_widenable_condition>()); +} + bool llvm::isWidenableBranch(const User *U) { Value *Condition, *WidenableCondition; BasicBlock *GuardedBB, *DeoptBB; @@ -111,3 +115,34 @@ bool llvm::parseWidenableBranch(User *U, Use *&C,Use *&WC, } return false; } + +template <typename CallbackType> +static void parseCondition(Value *Condition, CallbackType Callback) { + SmallVector<Value *, 4> Worklist(1, Condition); + SmallPtrSet<Value *, 4> Visited; + Visited.insert(Condition); + do { + Value *Check = Worklist.pop_back_val(); + Value *LHS, *RHS; + if (match(Check, m_And(m_Value(LHS), m_Value(RHS)))) { + if (Visited.insert(LHS).second) + Worklist.push_back(LHS); + if (Visited.insert(RHS).second) + Worklist.push_back(RHS); + continue; + } + Callback(Check); + } while (!Worklist.empty()); +} + +void llvm::parseWidenableGuard(const User *U, + llvm::SmallVectorImpl<Value *> &Checks) { + assert((isGuard(U) || isWidenableBranch(U)) && "Should be"); + Value *Condition = isGuard(U) ? cast<IntrinsicInst>(U)->getArgOperand(0) + : cast<BranchInst>(U)->getCondition(); + + parseCondition(Condition, [&](Value *Check) { + if (!isWidenableCondition(Check)) + Checks.push_back(Check); + }); +} diff --git a/llvm/lib/Transforms/Scalar/LoopPredication.cpp b/llvm/lib/Transforms/Scalar/LoopPredication.cpp index 12852ae..79a3da9 100644 --- a/llvm/lib/Transforms/Scalar/LoopPredication.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPredication.cpp @@ -307,8 +307,8 @@ class LoopPredication { widenICmpRangeCheckDecrementingLoop(LoopICmp LatchCheck, LoopICmp RangeCheck, SCEVExpander &Expander, Instruction *Guard); - unsigned collectChecks(SmallVectorImpl<Value *> &Checks, Value *Condition, - SCEVExpander &Expander, Instruction *Guard); + unsigned widenChecks(SmallVectorImpl<Value *> &Checks, SCEVExpander &Expander, + Instruction *Guard); bool widenGuardConditions(IntrinsicInst *II, SCEVExpander &Expander); bool widenWidenableBranchGuardConditions(BranchInst *Guard, SCEVExpander &Expander); // If the loop always exits through another block in the loop, we should not @@ -754,57 +754,16 @@ LoopPredication::widenICmpRangeCheck(ICmpInst *ICI, SCEVExpander &Expander, } } -unsigned LoopPredication::collectChecks(SmallVectorImpl<Value *> &Checks, - Value *Condition, - SCEVExpander &Expander, - Instruction *Guard) { +unsigned LoopPredication::widenChecks(SmallVectorImpl<Value *> &Checks, + SCEVExpander &Expander, + Instruction *Guard) { unsigned NumWidened = 0; - // The guard condition is expected to be in form of: - // cond1 && cond2 && cond3 ... - // Iterate over subconditions looking for icmp conditions which can be - // widened across loop iterations. Widening these conditions remember the - // resulting list of subconditions in Checks vector. - SmallVector<Value *, 4> Worklist(1, Condition); - SmallPtrSet<Value *, 4> Visited; - Visited.insert(Condition); - Value *WideableCond = nullptr; - do { - Value *Condition = Worklist.pop_back_val(); - Value *LHS, *RHS; - using namespace llvm::PatternMatch; - if (match(Condition, m_And(m_Value(LHS), m_Value(RHS)))) { - if (Visited.insert(LHS).second) - Worklist.push_back(LHS); - if (Visited.insert(RHS).second) - Worklist.push_back(RHS); - continue; - } - - if (match(Condition, - m_Intrinsic<Intrinsic::experimental_widenable_condition>())) { - // Pick any, we don't care which - WideableCond = Condition; - continue; - } - - if (ICmpInst *ICI = dyn_cast<ICmpInst>(Condition)) { - if (auto NewRangeCheck = widenICmpRangeCheck(ICI, Expander, - Guard)) { - Checks.push_back(*NewRangeCheck); + for (auto &Check : Checks) + if (ICmpInst *ICI = dyn_cast<ICmpInst>(Check)) + if (auto NewRangeCheck = widenICmpRangeCheck(ICI, Expander, Guard)) { NumWidened++; - continue; + Check = *NewRangeCheck; } - } - - // Save the condition as is if we can't widen it - Checks.push_back(Condition); - } while (!Worklist.empty()); - // At the moment, our matching logic for wideable conditions implicitly - // assumes we preserve the form: (br (and Cond, WC())). FIXME - // Note that if there were multiple calls to wideable condition in the - // traversal, we only need to keep one, and which one is arbitrary. - if (WideableCond) - Checks.push_back(WideableCond); return NumWidened; } @@ -815,8 +774,8 @@ bool LoopPredication::widenGuardConditions(IntrinsicInst *Guard, TotalConsidered++; SmallVector<Value *, 4> Checks; - unsigned NumWidened = collectChecks(Checks, Guard->getOperand(0), Expander, - Guard); + parseWidenableGuard(Guard, Checks); + unsigned NumWidened = widenChecks(Checks, Expander, Guard); if (NumWidened == 0) return false; @@ -851,8 +810,11 @@ bool LoopPredication::widenWidenableBranchGuardConditions( TotalConsidered++; SmallVector<Value *, 4> Checks; - unsigned NumWidened = collectChecks(Checks, BI->getCondition(), - Expander, BI); + parseWidenableGuard(BI, Checks); + // At the moment, our matching logic for wideable conditions implicitly + // assumes we preserve the form: (br (and Cond, WC())). FIXME + Checks.push_back(WC); + unsigned NumWidened = widenChecks(Checks, Expander, BI); if (NumWidened == 0) return false; |