Move widenable branch formation into makeGuardControlFlowExplicit helper

This is mostly NFC, but I removed the setting of the guard's calling convention onto the WC call.  Why?  Because it was untested, and was producing an ill defined output as the declaration's convention wasn't been changed leaving a mismatch which is UB.
This commit is contained in:
Philip Reames 2019-11-20 12:51:37 -08:00
parent 0f5aabb91a
commit 8ba56f322a
4 changed files with 21 additions and 19 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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");
}
}