diff options
author | Max Kazantsev <max.kazantsev@azul.com> | 2019-01-22 09:36:22 +0000 |
---|---|---|
committer | Max Kazantsev <max.kazantsev@azul.com> | 2019-01-22 09:36:22 +0000 |
commit | bd374b27cc33567b0a0522ee511fc1ea9f0bb1df (patch) | |
tree | 90c1c6cf66a8be88b3e27b9b9d6d64f87372853f | |
parent | b88d6fd7b8c0f40a919e463b9b8c9193efbc5eaa (diff) | |
download | bcm5719-llvm-bd374b27cc33567b0a0522ee511fc1ea9f0bb1df.tar.gz bcm5719-llvm-bd374b27cc33567b0a0522ee511fc1ea9f0bb1df.zip |
[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
-rw-r--r-- | llvm/include/llvm/Analysis/GuardUtils.h | 8 | ||||
-rw-r--r-- | llvm/lib/Analysis/GuardUtils.cpp | 27 |
2 files changed, 33 insertions, 2 deletions
diff --git a/llvm/include/llvm/Analysis/GuardUtils.h b/llvm/include/llvm/Analysis/GuardUtils.h index 4c755eac824..62ae09a4f8f 100644 --- a/llvm/include/llvm/Analysis/GuardUtils.h +++ b/llvm/include/llvm/Analysis/GuardUtils.h @@ -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 - diff --git a/llvm/lib/Analysis/GuardUtils.cpp b/llvm/lib/Analysis/GuardUtils.cpp index 2cee473e289..36ae954ed8b 100644 --- a/llvm/lib/Analysis/GuardUtils.cpp +++ b/llvm/lib/Analysis/GuardUtils.cpp @@ -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; +} |