diff options
-rw-r--r-- | llvm/include/llvm/Transforms/Utils/GuardUtils.h | 7 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/LowerGuardIntrinsic.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/GuardUtils.cpp | 14 |
4 files changed, 21 insertions, 19 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/GuardUtils.h b/llvm/include/llvm/Transforms/Utils/GuardUtils.h index 43cd267f59b..7ab5d9ef4f2 100644 --- a/llvm/include/llvm/Transforms/Utils/GuardUtils.h +++ b/llvm/include/llvm/Transforms/Utils/GuardUtils.h @@ -23,8 +23,11 @@ class Value; /// by the condition of guard's first argument. The taken branch then goes to /// the block that contains \p Guard's successors, and the non-taken branch /// goes to a newly-created deopt block that contains a sole call of the -/// deoptimize function \p DeoptIntrinsic. -void makeGuardControlFlowExplicit(Function *DeoptIntrinsic, CallInst *Guard); +/// deoptimize function \p DeoptIntrinsic. If 'UseWC' is set, preserve the +/// widenable nature of the guard by lowering to equivelent form. If not set, +/// lower to a form without widenable semantics. +void makeGuardControlFlowExplicit(Function *DeoptIntrinsic, CallInst *Guard, + bool UseWC); /// Given a branch we know is widenable (defined per Analysis/GuardUtils.h), /// widen it such that condition 'NewCond' is also known to hold on the taken diff --git a/llvm/lib/Transforms/Scalar/LowerGuardIntrinsic.cpp b/llvm/lib/Transforms/Scalar/LowerGuardIntrinsic.cpp index f8aa2802cce..45f5929e3b9 100644 --- a/llvm/lib/Transforms/Scalar/LowerGuardIntrinsic.cpp +++ b/llvm/lib/Transforms/Scalar/LowerGuardIntrinsic.cpp @@ -61,7 +61,7 @@ static bool lowerGuardIntrinsic(Function &F) { DeoptIntrinsic->setCallingConv(GuardDecl->getCallingConv()); for (auto *CI : ToLower) { - makeGuardControlFlowExplicit(DeoptIntrinsic, CI); + makeGuardControlFlowExplicit(DeoptIntrinsic, CI, false); CI->eraseFromParent(); } diff --git a/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp b/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp index fd8a3643cff..0e3fcf0eb77 100644 --- a/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp +++ b/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp @@ -58,22 +58,9 @@ struct MakeGuardsExplicitLegacyPass : public FunctionPass { static void turnToExplicitForm(CallInst *Guard, Function *DeoptIntrinsic) { // Replace the guard with an explicit branch (just like in GuardWidening). BasicBlock *BB = Guard->getParent(); - makeGuardControlFlowExplicit(DeoptIntrinsic, Guard); - BranchInst *ExplicitGuard = cast<BranchInst>(BB->getTerminator()); - assert(ExplicitGuard->isConditional() && "Must be!"); + makeGuardControlFlowExplicit(DeoptIntrinsic, Guard, true); + assert(isWidenableBranch(BB->getTerminator()) && "should hold"); - // We want the guard to be expressed as explicit control flow, but still be - // widenable. For that, we add Widenable Condition intrinsic call to the - // guard's condition. - IRBuilder<> B(ExplicitGuard); - auto *WidenableCondition = - B.CreateIntrinsic(Intrinsic::experimental_widenable_condition, - {}, {}, nullptr, "widenable_cond"); - WidenableCondition->setCallingConv(Guard->getCallingConv()); - auto *NewCond = - B.CreateAnd(ExplicitGuard->getCondition(), WidenableCondition); - NewCond->setName("exiplicit_guard_cond"); - ExplicitGuard->setCondition(NewCond); Guard->eraseFromParent(); } diff --git a/llvm/lib/Transforms/Utils/GuardUtils.cpp b/llvm/lib/Transforms/Utils/GuardUtils.cpp index 37fca0d129b..b8c4c764e74 100644 --- a/llvm/lib/Transforms/Utils/GuardUtils.cpp +++ b/llvm/lib/Transforms/Utils/GuardUtils.cpp @@ -26,7 +26,7 @@ static cl::opt<uint32_t> PredicatePassBranchWeight( "reciprocal of this value (default = 1 << 20)")); void llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic, - CallInst *Guard) { + CallInst *Guard, bool UseWC) { OperandBundleDef DeoptOB(*Guard->getOperandBundle(LLVMContext::OB_deopt)); SmallVector<Value *, 4> Args(std::next(Guard->arg_begin()), Guard->arg_end()); @@ -62,6 +62,18 @@ void llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic, DeoptCall->setCallingConv(Guard->getCallingConv()); DeoptBlockTerm->eraseFromParent(); + + if (UseWC) { + // We want the guard to be expressed as explicit control flow, but still be + // widenable. For that, we add Widenable Condition intrinsic call to the + // guard's condition. + IRBuilder<> B(CheckBI); + auto *WC = B.CreateIntrinsic(Intrinsic::experimental_widenable_condition, + {}, {}, nullptr, "widenable_cond"); + CheckBI->setCondition(B.CreateAnd(CheckBI->getCondition(), WC, + "exiplicit_guard_cond")); + assert(isWidenableBranch(CheckBI) && "sanity check"); + } } |