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