1 //===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 // Utils that are used to perform transformations related to guards and their
10 //===----------------------------------------------------------------------===//
12 #include "llvm/Transforms/Utils/GuardUtils.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/IR/MDBuilder.h"
17 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
21 static cl::opt
<uint32_t> PredicatePassBranchWeight(
22 "guards-predicate-pass-branch-weight", cl::Hidden
, cl::init(1 << 20),
23 cl::desc("The probability of a guard failing is assumed to be the "
24 "reciprocal of this value (default = 1 << 20)"));
26 void llvm::makeGuardControlFlowExplicit(Function
*DeoptIntrinsic
,
28 OperandBundleDef
DeoptOB(*Guard
->getOperandBundle(LLVMContext::OB_deopt
));
29 SmallVector
<Value
*, 4> Args(std::next(Guard
->arg_begin()), Guard
->arg_end());
31 auto *CheckBB
= Guard
->getParent();
32 auto *DeoptBlockTerm
=
33 SplitBlockAndInsertIfThen(Guard
->getArgOperand(0), Guard
, true);
35 auto *CheckBI
= cast
<BranchInst
>(CheckBB
->getTerminator());
37 // SplitBlockAndInsertIfThen inserts control flow that branches to
38 // DeoptBlockTerm if the condition is true. We want the opposite.
39 CheckBI
->swapSuccessors();
41 CheckBI
->getSuccessor(0)->setName("guarded");
42 CheckBI
->getSuccessor(1)->setName("deopt");
44 if (auto *MD
= Guard
->getMetadata(LLVMContext::MD_make_implicit
))
45 CheckBI
->setMetadata(LLVMContext::MD_make_implicit
, MD
);
47 MDBuilder
MDB(Guard
->getContext());
48 CheckBI
->setMetadata(LLVMContext::MD_prof
,
49 MDB
.createBranchWeights(PredicatePassBranchWeight
, 1));
51 IRBuilder
<> B(DeoptBlockTerm
);
52 auto *DeoptCall
= B
.CreateCall(DeoptIntrinsic
, Args
, {DeoptOB
}, "");
54 if (DeoptIntrinsic
->getReturnType()->isVoidTy()) {
57 DeoptCall
->setName("deoptcall");
58 B
.CreateRet(DeoptCall
);
61 DeoptCall
->setCallingConv(Guard
->getCallingConv());
62 DeoptBlockTerm
->eraseFromParent();