diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp b/contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp index 40b898e96f3b..b872286fb939 100644 --- a/contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp +++ b/contrib/llvm-project/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; @@ -27,11 +31,9 @@ bool llvm::isWidenableBranch(const User *U) { } bool llvm::isGuardAsWidenableBranch(const User *U) { - Value *Condition, *WidenableCondition; - BasicBlock *GuardedBB, *DeoptBB; - if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB, - DeoptBB)) + if (!isWidenableBranch(U)) return false; + BasicBlock *DeoptBB = cast<BranchInst>(U)->getSuccessor(1); SmallPtrSet<const BasicBlock *, 2> Visited; Visited.insert(DeoptBB); do { @@ -111,3 +113,59 @@ bool llvm::parseWidenableBranch(User *U, Use *&C,Use *&WC, } return false; } + +template <typename CallbackType> +static void parseCondition(Value *Condition, + CallbackType RecordCheckOrWidenableCond) { + 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; + } + if (!RecordCheckOrWidenableCond(Check)) + break; + } 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); + return true; + }); +} + +Value *llvm::extractWidenableCondition(const User *U) { + auto *BI = dyn_cast<BranchInst>(U); + if (!BI || !BI->isConditional()) + return nullptr; + + auto Condition = BI->getCondition(); + if (!Condition->hasOneUse()) + return nullptr; + + Value *WidenableCondition = nullptr; + parseCondition(Condition, [&](Value *Check) { + // We require widenable_condition has only one use, otherwise we don't + // consider appropriate branch as widenable. + if (isWidenableCondition(Check) && Check->hasOneUse()) { + WidenableCondition = Check; + return false; + } + return true; + }); + return WidenableCondition; +} |
