aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Analysis/GuardUtils.cpp66
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;
+}