[NFC] Add detector for guards expressed as branch by widenable conditions

This patch adds a function to detect guards expressed in explicit control
flow form as branch by `and` with widenable condition intrinsic call:

    %wc = call i1 @llvm.experimental.widenable.condition()
    %guard_cond = and i1, %some_cond, %wc
    br i1 %guard_cond, label %guarded, label %deopt

  deopt:
    <maybe some non-side-effecting instructions>
    deoptimize()

This form can be used as alternative to implicit control flow guard
representation expressed by `experimental_guard` intrinsic.

Differential Revision: https://reviews.llvm.org/D56074
Reviewed By: reames

llvm-svn: 351791
This commit is contained in:
Max Kazantsev 2019-01-22 09:36:22 +00:00
parent ac2839a57d
commit 75db383edd
2 changed files with 33 additions and 2 deletions

View File

@ -16,10 +16,14 @@ namespace llvm {
class User;
/// Returns true iff \p U has semantics of a guard.
/// 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 U has semantics of a guard expressed in a form of a
/// widenable conditional branch to deopt block.
bool isGuardAsWidenableBranch(const User *U);
} // llvm
#endif // LLVM_ANALYSIS_GUARDUTILS_H

View File

@ -18,3 +18,30 @@ bool llvm::isGuard(const User *U) {
using namespace llvm::PatternMatch;
return match(U, m_Intrinsic<Intrinsic::experimental_guard>());
}
bool llvm::isGuardAsWidenableBranch(const User *U) {
using namespace llvm::PatternMatch;
const BranchInst *BI = dyn_cast<BranchInst>(U);
// We are looking for the following pattern:
// br i1 %cond & widenable_condition(), label %guarded, label %deopt
// deopt:
// <non-side-effecting instructions>
// deoptimize()
if (!BI || !BI->isConditional())
return false;
if (!match(BI->getCondition(),
m_And(m_Value(),
m_Intrinsic<Intrinsic::experimental_widenable_condition>())))
return false;
const BasicBlock *DeoptBlock = BI->getSuccessor(1);
for (auto &Insn : *DeoptBlock) {
if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>()))
return true;
if (Insn.mayHaveSideEffects())
return false;
}
return false;
}