Index: include/llvm/Analysis/GuardUtils.h =================================================================== --- include/llvm/Analysis/GuardUtils.h +++ include/llvm/Analysis/GuardUtils.h @@ -20,6 +20,9 @@ /// Returns true iff \p U has semantics of a guard. bool isGuard(const User *U); +/// Returns true iff \p U is a branch that has semantics of a guard. +bool isExplicitGuard(const User *U); + } // llvm #endif // LLVM_ANALYSIS_GUARDUTILS_H Index: lib/Analysis/GuardUtils.cpp =================================================================== --- lib/Analysis/GuardUtils.cpp +++ lib/Analysis/GuardUtils.cpp @@ -19,3 +19,30 @@ using namespace llvm::PatternMatch; return match(U, m_Intrinsic()); } + +bool llvm::isExplicitGuard(const User *U) { + using namespace llvm::PatternMatch; + const BranchInst *BI = dyn_cast(U); + + // We are looking for the following pattern: + // br i1 %cond & widenable_condition(), label %guarded, label %deopt + // deopt: + // + // deoptimize() + if (!BI || !BI->isConditional()) + return false; + + if (!match(BI->getCondition(), + m_And(m_Value(), + m_Intrinsic()))) + return false; + + const BasicBlock *DeoptBlock = BI->getSuccessor(1); + for (auto &Insn : *DeoptBlock) { + if (match(&Insn, m_Intrinsic())) + return true; + if (Insn.mayHaveSideEffects()) + return false; + } + return false; +}