Skip to content

Commit bd374b2

Browse files
author
Max Kazantsev
committedJan 22, 2019
[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
1 parent b88d6fd commit bd374b2

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed
 

‎llvm/include/llvm/Analysis/GuardUtils.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ namespace llvm {
1616

1717
class User;
1818

19-
/// Returns true iff \p U has semantics of a guard.
19+
/// Returns true iff \p U has semantics of a guard expressed in a form of call
20+
/// of llvm.experimental.guard intrinsic.
2021
bool isGuard(const User *U);
2122

23+
/// Returns true iff \p U has semantics of a guard expressed in a form of a
24+
/// widenable conditional branch to deopt block.
25+
bool isGuardAsWidenableBranch(const User *U);
26+
2227
} // llvm
2328

2429
#endif // LLVM_ANALYSIS_GUARDUTILS_H
25-

‎llvm/lib/Analysis/GuardUtils.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,30 @@ bool llvm::isGuard(const User *U) {
1818
using namespace llvm::PatternMatch;
1919
return match(U, m_Intrinsic<Intrinsic::experimental_guard>());
2020
}
21+
22+
bool llvm::isGuardAsWidenableBranch(const User *U) {
23+
using namespace llvm::PatternMatch;
24+
const BranchInst *BI = dyn_cast<BranchInst>(U);
25+
26+
// We are looking for the following pattern:
27+
// br i1 %cond & widenable_condition(), label %guarded, label %deopt
28+
// deopt:
29+
// <non-side-effecting instructions>
30+
// deoptimize()
31+
if (!BI || !BI->isConditional())
32+
return false;
33+
34+
if (!match(BI->getCondition(),
35+
m_And(m_Value(),
36+
m_Intrinsic<Intrinsic::experimental_widenable_condition>())))
37+
return false;
38+
39+
const BasicBlock *DeoptBlock = BI->getSuccessor(1);
40+
for (auto &Insn : *DeoptBlock) {
41+
if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>()))
42+
return true;
43+
if (Insn.mayHaveSideEffects())
44+
return false;
45+
}
46+
return false;
47+
}

0 commit comments

Comments
 (0)
Please sign in to comment.