Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Transforms/Scalar/LowerGuardIntrinsic.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- LowerGuardIntrinsic.cpp - Lower the guard intrinsic ---------------===//
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
//
10
// This pass lowers the llvm.experimental.guard intrinsic to a conditional call
11
// to @llvm.experimental.deoptimize.  Once this happens, the guard can no longer
12
// be widened.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/IR/BasicBlock.h"
19
#include "llvm/IR/Function.h"
20
#include "llvm/IR/IRBuilder.h"
21
#include "llvm/IR/InstIterator.h"
22
#include "llvm/IR/Instructions.h"
23
#include "llvm/IR/Intrinsics.h"
24
#include "llvm/IR/MDBuilder.h"
25
#include "llvm/IR/Module.h"
26
#include "llvm/Pass.h"
27
#include "llvm/Transforms/Scalar.h"
28
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
29
30
using namespace llvm;
31
32
static cl::opt<uint32_t> PredicatePassBranchWeight(
33
    "guards-predicate-pass-branch-weight", cl::Hidden, cl::init(1 << 20),
34
    cl::desc("The probability of a guard failing is assumed to be the "
35
             "reciprocal of this value (default = 1 << 20)"));
36
37
namespace {
38
struct LowerGuardIntrinsicLegacyPass : public FunctionPass {
39
  static char ID;
40
2
  LowerGuardIntrinsicLegacyPass() : FunctionPass(ID) {
41
2
    initializeLowerGuardIntrinsicLegacyPassPass(
42
2
        *PassRegistry::getPassRegistry());
43
2
  }
44
45
  bool runOnFunction(Function &F) override;
46
};
47
}
48
49
static void MakeGuardControlFlowExplicit(Function *DeoptIntrinsic,
50
11
                                         CallInst *CI) {
51
11
  OperandBundleDef DeoptOB(*CI->getOperandBundle(LLVMContext::OB_deopt));
52
11
  SmallVector<Value *, 4> Args(std::next(CI->arg_begin()), CI->arg_end());
53
11
54
11
  auto *CheckBB = CI->getParent();
55
11
  auto *DeoptBlockTerm =
56
11
      SplitBlockAndInsertIfThen(CI->getArgOperand(0), CI, true);
57
11
58
11
  auto *CheckBI = cast<BranchInst>(CheckBB->getTerminator());
59
11
60
11
  // SplitBlockAndInsertIfThen inserts control flow that branches to
61
11
  // DeoptBlockTerm if the condition is true.  We want the opposite.
62
11
  CheckBI->swapSuccessors();
63
11
64
11
  CheckBI->getSuccessor(0)->setName("guarded");
65
11
  CheckBI->getSuccessor(1)->setName("deopt");
66
11
67
11
  if (auto *MD = CI->getMetadata(LLVMContext::MD_make_implicit))
68
2
    CheckBI->setMetadata(LLVMContext::MD_make_implicit, MD);
69
11
70
11
  MDBuilder MDB(CI->getContext());
71
11
  CheckBI->setMetadata(LLVMContext::MD_prof,
72
11
                       MDB.createBranchWeights(PredicatePassBranchWeight, 1));
73
11
74
11
  IRBuilder<> B(DeoptBlockTerm);
75
11
  auto *DeoptCall = B.CreateCall(DeoptIntrinsic, Args, {DeoptOB}, "");
76
11
77
11
  if (
DeoptIntrinsic->getReturnType()->isVoidTy()11
) {
78
4
    B.CreateRetVoid();
79
11
  } else {
80
7
    DeoptCall->setName("deoptcall");
81
7
    B.CreateRet(DeoptCall);
82
7
  }
83
11
84
11
  DeoptCall->setCallingConv(CI->getCallingConv());
85
11
  DeoptBlockTerm->eraseFromParent();
86
11
}
87
88
11
static bool lowerGuardIntrinsic(Function &F) {
89
11
  // Check if we can cheaply rule out the possibility of not having any work to
90
11
  // do.
91
11
  auto *GuardDecl = F.getParent()->getFunction(
92
11
      Intrinsic::getName(Intrinsic::experimental_guard));
93
11
  if (
!GuardDecl || 11
GuardDecl->use_empty()11
)
94
0
    return false;
95
11
96
11
  SmallVector<CallInst *, 8> ToLower;
97
11
  for (auto &I : instructions(F))
98
33
    
if (auto *33
CI33
= dyn_cast<CallInst>(&I))
99
11
      
if (auto *11
F11
= CI->getCalledFunction())
100
11
        
if (11
F->getIntrinsicID() == Intrinsic::experimental_guard11
)
101
11
          ToLower.push_back(CI);
102
11
103
11
  if (ToLower.empty())
104
0
    return false;
105
11
106
11
  auto *DeoptIntrinsic = Intrinsic::getDeclaration(
107
11
      F.getParent(), Intrinsic::experimental_deoptimize, {F.getReturnType()});
108
11
  DeoptIntrinsic->setCallingConv(GuardDecl->getCallingConv());
109
11
110
11
  for (auto *CI : ToLower) {
111
11
    MakeGuardControlFlowExplicit(DeoptIntrinsic, CI);
112
11
    CI->eraseFromParent();
113
11
  }
114
11
115
11
  return true;
116
11
}
117
118
6
bool LowerGuardIntrinsicLegacyPass::runOnFunction(Function &F) {
119
6
  return lowerGuardIntrinsic(F);
120
6
}
121
122
char LowerGuardIntrinsicLegacyPass::ID = 0;
123
INITIALIZE_PASS(LowerGuardIntrinsicLegacyPass, "lower-guard-intrinsic",
124
                "Lower the guard intrinsic to normal control flow", false,
125
                false)
126
127
0
Pass *llvm::createLowerGuardIntrinsicPass() {
128
0
  return new LowerGuardIntrinsicLegacyPass();
129
0
}
130
131
PreservedAnalyses LowerGuardIntrinsicPass::run(Function &F,
132
5
                                               FunctionAnalysisManager &AM) {
133
5
  if (lowerGuardIntrinsic(F))
134
5
    return PreservedAnalyses::none();
135
0
136
0
  return PreservedAnalyses::all();
137
0
}