]> granicus.if.org Git - llvm/commitdiff
[NFC] Add detector for guards expressed as branch by widenable conditions
authorMax Kazantsev <max.kazantsev@azul.com>
Tue, 22 Jan 2019 09:36:22 +0000 (09:36 +0000)
committerMax Kazantsev <max.kazantsev@azul.com>
Tue, 22 Jan 2019 09:36:22 +0000 (09:36 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351791 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/GuardUtils.h
lib/Analysis/GuardUtils.cpp

index 4c755eac824e754eb7afd00ead5f84cc8fe0c50f..62ae09a4f8fd1ba68ca0723d682b7c7f92055d3b 100644 (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
-
index 2cee473e28998bcfd15c6e3df968a9db043a88b9..36ae954ed8b6c3f0aa6efba8e9f301721f4b0d76 100644 (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;
+}