[NFC] Add function to parse widenable conditional branches

llvm-svn: 351803
This commit is contained in:
Max Kazantsev 2019-01-22 11:21:32 +00:00
parent 1bf1964a15
commit ca47f1f72a
2 changed files with 29 additions and 17 deletions

View File

@ -14,7 +14,9 @@
namespace llvm { namespace llvm {
class BasicBlock;
class User; class User;
class Value;
/// Returns true iff \p U has semantics of a guard expressed in a form of call /// Returns true iff \p U has semantics of a guard expressed in a form of call
/// of llvm.experimental.guard intrinsic. /// of llvm.experimental.guard intrinsic.
@ -24,6 +26,19 @@ bool isGuard(const User *U);
/// widenable conditional branch to deopt block. /// widenable conditional branch to deopt block.
bool isGuardAsWidenableBranch(const User *U); bool isGuardAsWidenableBranch(const User *U);
/// If U is widenable branch looking like:
/// %cond = ...
/// %wc = call i1 @llvm.experimental.widenable.condition()
/// %branch_cond = and i1 %cond, %wc
/// br i1 %branch_cond, label %if_true_bb, label %if_false_bb ; <--- U
/// The function returns true, and the values %cond and %wc and blocks
/// %if_true_bb, if_false_bb are returned in
/// the parameters (Condition, WidenableCondition, IfTrueBB and IfFalseFF)
/// respectively. If \p U does not match this pattern, return false.
bool parseWidenableBranch(const User *U, Value *&Condition,
Value *&WidenableCondition, BasicBlock *&IfTrueBB,
BasicBlock *&IfFalseBB);
} // llvm } // llvm
#endif // LLVM_ANALYSIS_GUARDUTILS_H #endif // LLVM_ANALYSIS_GUARDUTILS_H

View File

@ -20,24 +20,13 @@ bool llvm::isGuard(const User *U) {
} }
bool llvm::isGuardAsWidenableBranch(const User *U) { bool llvm::isGuardAsWidenableBranch(const User *U) {
Value *Condition, *WidenableCondition;
BasicBlock *GuardedBB, *DeoptBB;
if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
DeoptBB))
return false;
using namespace llvm::PatternMatch; using namespace llvm::PatternMatch;
const BranchInst *BI = dyn_cast<BranchInst>(U); for (auto &Insn : *DeoptBB) {
// 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>())) if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>()))
return true; return true;
if (Insn.mayHaveSideEffects()) if (Insn.mayHaveSideEffects())
@ -45,3 +34,11 @@ bool llvm::isGuardAsWidenableBranch(const User *U) {
} }
return false; return false;
} }
bool llvm::parseWidenableBranch(const User *U, Value *&Condition,
Value *&WidenableCondition,
BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
using namespace llvm::PatternMatch;
return match(U, m_Br(m_And(m_Value(Condition), m_Value(WidenableCondition)),
IfTrueBB, IfFalseBB));
}