1*b5893f02SDimitry Andric //===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===//
2*b5893f02SDimitry Andric //
3*b5893f02SDimitry Andric // The LLVM Compiler Infrastructure
4*b5893f02SDimitry Andric //
5*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
7*b5893f02SDimitry Andric //
8*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
9*b5893f02SDimitry Andric // Utils that are used to perform transformations related to guards and their
10*b5893f02SDimitry Andric // conditions.
11*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
12*b5893f02SDimitry Andric
13*b5893f02SDimitry Andric #include "llvm/Transforms/Utils/GuardUtils.h"
14*b5893f02SDimitry Andric #include "llvm/IR/Function.h"
15*b5893f02SDimitry Andric #include "llvm/IR/Instructions.h"
16*b5893f02SDimitry Andric #include "llvm/IR/IRBuilder.h"
17*b5893f02SDimitry Andric #include "llvm/IR/MDBuilder.h"
18*b5893f02SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
19*b5893f02SDimitry Andric
20*b5893f02SDimitry Andric using namespace llvm;
21*b5893f02SDimitry Andric
22*b5893f02SDimitry Andric static cl::opt<uint32_t> PredicatePassBranchWeight(
23*b5893f02SDimitry Andric "guards-predicate-pass-branch-weight", cl::Hidden, cl::init(1 << 20),
24*b5893f02SDimitry Andric cl::desc("The probability of a guard failing is assumed to be the "
25*b5893f02SDimitry Andric "reciprocal of this value (default = 1 << 20)"));
26*b5893f02SDimitry Andric
makeGuardControlFlowExplicit(Function * DeoptIntrinsic,CallInst * Guard)27*b5893f02SDimitry Andric void llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic,
28*b5893f02SDimitry Andric CallInst *Guard) {
29*b5893f02SDimitry Andric OperandBundleDef DeoptOB(*Guard->getOperandBundle(LLVMContext::OB_deopt));
30*b5893f02SDimitry Andric SmallVector<Value *, 4> Args(std::next(Guard->arg_begin()), Guard->arg_end());
31*b5893f02SDimitry Andric
32*b5893f02SDimitry Andric auto *CheckBB = Guard->getParent();
33*b5893f02SDimitry Andric auto *DeoptBlockTerm =
34*b5893f02SDimitry Andric SplitBlockAndInsertIfThen(Guard->getArgOperand(0), Guard, true);
35*b5893f02SDimitry Andric
36*b5893f02SDimitry Andric auto *CheckBI = cast<BranchInst>(CheckBB->getTerminator());
37*b5893f02SDimitry Andric
38*b5893f02SDimitry Andric // SplitBlockAndInsertIfThen inserts control flow that branches to
39*b5893f02SDimitry Andric // DeoptBlockTerm if the condition is true. We want the opposite.
40*b5893f02SDimitry Andric CheckBI->swapSuccessors();
41*b5893f02SDimitry Andric
42*b5893f02SDimitry Andric CheckBI->getSuccessor(0)->setName("guarded");
43*b5893f02SDimitry Andric CheckBI->getSuccessor(1)->setName("deopt");
44*b5893f02SDimitry Andric
45*b5893f02SDimitry Andric if (auto *MD = Guard->getMetadata(LLVMContext::MD_make_implicit))
46*b5893f02SDimitry Andric CheckBI->setMetadata(LLVMContext::MD_make_implicit, MD);
47*b5893f02SDimitry Andric
48*b5893f02SDimitry Andric MDBuilder MDB(Guard->getContext());
49*b5893f02SDimitry Andric CheckBI->setMetadata(LLVMContext::MD_prof,
50*b5893f02SDimitry Andric MDB.createBranchWeights(PredicatePassBranchWeight, 1));
51*b5893f02SDimitry Andric
52*b5893f02SDimitry Andric IRBuilder<> B(DeoptBlockTerm);
53*b5893f02SDimitry Andric auto *DeoptCall = B.CreateCall(DeoptIntrinsic, Args, {DeoptOB}, "");
54*b5893f02SDimitry Andric
55*b5893f02SDimitry Andric if (DeoptIntrinsic->getReturnType()->isVoidTy()) {
56*b5893f02SDimitry Andric B.CreateRetVoid();
57*b5893f02SDimitry Andric } else {
58*b5893f02SDimitry Andric DeoptCall->setName("deoptcall");
59*b5893f02SDimitry Andric B.CreateRet(DeoptCall);
60*b5893f02SDimitry Andric }
61*b5893f02SDimitry Andric
62*b5893f02SDimitry Andric DeoptCall->setCallingConv(Guard->getCallingConv());
63*b5893f02SDimitry Andric DeoptBlockTerm->eraseFromParent();
64*b5893f02SDimitry Andric }
65