annotate lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp @ 124:4fa72497ed5d

fix
author mir3636
date Thu, 30 Nov 2017 20:04:56 +0900
parents 803732b1fca8
children c2174574ed3a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
121
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
1 //===-- PGOMemOPSizeOpt.cpp - Optimizations based on value profiling ===//
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
2 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
3 // The LLVM Compiler Infrastructure
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
4 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
5 // This file is distributed under the University of Illinois Open Source
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
6 // License. See LICENSE.TXT for details.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
7 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
8 //===----------------------------------------------------------------------===//
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
9 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
10 // This file implements the transformation that optimizes memory intrinsics
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
11 // such as memcpy using the size value profile. When memory intrinsic size
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
12 // value profile metadata is available, a single memory intrinsic is expanded
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
13 // to a sequence of guarded specialized versions that are called with the
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
14 // hottest size(s), for later expansion into more optimal inline sequences.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
15 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
16 //===----------------------------------------------------------------------===//
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
17
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
18 #include "llvm/ADT/ArrayRef.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
19 #include "llvm/ADT/Statistic.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
20 #include "llvm/ADT/StringRef.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
21 #include "llvm/ADT/Twine.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
22 #include "llvm/Analysis/BlockFrequencyInfo.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
23 #include "llvm/Analysis/GlobalsModRef.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
24 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
25 #include "llvm/IR/BasicBlock.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
26 #include "llvm/IR/CallSite.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
27 #include "llvm/IR/DerivedTypes.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
28 #include "llvm/IR/Function.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
29 #include "llvm/IR/IRBuilder.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
30 #include "llvm/IR/InstVisitor.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
31 #include "llvm/IR/InstrTypes.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
32 #include "llvm/IR/Instruction.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
33 #include "llvm/IR/Instructions.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
34 #include "llvm/IR/LLVMContext.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
35 #include "llvm/IR/PassManager.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
36 #include "llvm/IR/Type.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
37 #include "llvm/Pass.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
38 #include "llvm/PassRegistry.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
39 #include "llvm/PassSupport.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
40 #include "llvm/ProfileData/InstrProf.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
41 #include "llvm/Support/Casting.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
42 #include "llvm/Support/CommandLine.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
43 #include "llvm/Support/Debug.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
44 #include "llvm/Support/ErrorHandling.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
45 #include "llvm/Support/MathExtras.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
46 #include "llvm/Transforms/Instrumentation.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
47 #include "llvm/Transforms/PGOInstrumentation.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
48 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
49 #include <cassert>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
50 #include <cstdint>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
51 #include <vector>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
52
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
53 using namespace llvm;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
54
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
55 #define DEBUG_TYPE "pgo-memop-opt"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
56
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
57 STATISTIC(NumOfPGOMemOPOpt, "Number of memop intrinsics optimized.");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
58 STATISTIC(NumOfPGOMemOPAnnotate, "Number of memop intrinsics annotated.");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
59
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
60 // The minimum call count to optimize memory intrinsic calls.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
61 static cl::opt<unsigned>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
62 MemOPCountThreshold("pgo-memop-count-threshold", cl::Hidden, cl::ZeroOrMore,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
63 cl::init(1000),
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
64 cl::desc("The minimum count to optimize memory "
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
65 "intrinsic calls"));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
66
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
67 // Command line option to disable memory intrinsic optimization. The default is
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
68 // false. This is for debug purpose.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
69 static cl::opt<bool> DisableMemOPOPT("disable-memop-opt", cl::init(false),
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
70 cl::Hidden, cl::desc("Disable optimize"));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
71
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
72 // The percent threshold to optimize memory intrinsic calls.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
73 static cl::opt<unsigned>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
74 MemOPPercentThreshold("pgo-memop-percent-threshold", cl::init(40),
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
75 cl::Hidden, cl::ZeroOrMore,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
76 cl::desc("The percentage threshold for the "
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
77 "memory intrinsic calls optimization"));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
78
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
79 // Maximum number of versions for optimizing memory intrinsic call.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
80 static cl::opt<unsigned>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
81 MemOPMaxVersion("pgo-memop-max-version", cl::init(3), cl::Hidden,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
82 cl::ZeroOrMore,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
83 cl::desc("The max version for the optimized memory "
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
84 " intrinsic calls"));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
85
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
86 // Scale the counts from the annotation using the BB count value.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
87 static cl::opt<bool>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
88 MemOPScaleCount("pgo-memop-scale-count", cl::init(true), cl::Hidden,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
89 cl::desc("Scale the memop size counts using the basic "
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
90 " block count value"));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
91
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
92 // This option sets the rangge of precise profile memop sizes.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
93 extern cl::opt<std::string> MemOPSizeRange;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
94
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
95 // This option sets the value that groups large memop sizes
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
96 extern cl::opt<unsigned> MemOPSizeLarge;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
97
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
98 namespace {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
99 class PGOMemOPSizeOptLegacyPass : public FunctionPass {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
100 public:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
101 static char ID;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
102
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
103 PGOMemOPSizeOptLegacyPass() : FunctionPass(ID) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
104 initializePGOMemOPSizeOptLegacyPassPass(*PassRegistry::getPassRegistry());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
105 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
106
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
107 StringRef getPassName() const override { return "PGOMemOPSize"; }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
108
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
109 private:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
110 bool runOnFunction(Function &F) override;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
111 void getAnalysisUsage(AnalysisUsage &AU) const override {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
112 AU.addRequired<BlockFrequencyInfoWrapperPass>();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
113 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
114 AU.addPreserved<GlobalsAAWrapperPass>();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
115 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
116 };
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
117 } // end anonymous namespace
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
118
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
119 char PGOMemOPSizeOptLegacyPass::ID = 0;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
120 INITIALIZE_PASS_BEGIN(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt",
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
121 "Optimize memory intrinsic using its size value profile",
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
122 false, false)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
123 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
124 INITIALIZE_PASS_END(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt",
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
125 "Optimize memory intrinsic using its size value profile",
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
126 false, false)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
127
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
128 FunctionPass *llvm::createPGOMemOPSizeOptLegacyPass() {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
129 return new PGOMemOPSizeOptLegacyPass();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
130 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
131
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
132 namespace {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
133 class MemOPSizeOpt : public InstVisitor<MemOPSizeOpt> {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
134 public:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
135 MemOPSizeOpt(Function &Func, BlockFrequencyInfo &BFI,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
136 OptimizationRemarkEmitter &ORE)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
137 : Func(Func), BFI(BFI), ORE(ORE), Changed(false) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
138 ValueDataArray =
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
139 llvm::make_unique<InstrProfValueData[]>(MemOPMaxVersion + 2);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
140 // Get the MemOPSize range information from option MemOPSizeRange,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
141 getMemOPSizeRangeFromOption(MemOPSizeRange, PreciseRangeStart,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
142 PreciseRangeLast);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
143 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
144 bool isChanged() const { return Changed; }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
145 void perform() {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
146 WorkList.clear();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
147 visit(Func);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
148
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
149 for (auto &MI : WorkList) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
150 ++NumOfPGOMemOPAnnotate;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
151 if (perform(MI)) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
152 Changed = true;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
153 ++NumOfPGOMemOPOpt;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
154 DEBUG(dbgs() << "MemOP call: " << MI->getCalledFunction()->getName()
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
155 << "is Transformed.\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
156 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
157 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
158 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
159
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
160 void visitMemIntrinsic(MemIntrinsic &MI) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
161 Value *Length = MI.getLength();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
162 // Not perform on constant length calls.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
163 if (dyn_cast<ConstantInt>(Length))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
164 return;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
165 WorkList.push_back(&MI);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
166 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
167
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
168 private:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
169 Function &Func;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
170 BlockFrequencyInfo &BFI;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
171 OptimizationRemarkEmitter &ORE;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
172 bool Changed;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
173 std::vector<MemIntrinsic *> WorkList;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
174 // Start of the previse range.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
175 int64_t PreciseRangeStart;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
176 // Last value of the previse range.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
177 int64_t PreciseRangeLast;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
178 // The space to read the profile annotation.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
179 std::unique_ptr<InstrProfValueData[]> ValueDataArray;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
180 bool perform(MemIntrinsic *MI);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
181
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
182 // This kind shows which group the value falls in. For PreciseValue, we have
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
183 // the profile count for that value. LargeGroup groups the values that are in
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
184 // range [LargeValue, +inf). NonLargeGroup groups the rest of values.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
185 enum MemOPSizeKind { PreciseValue, NonLargeGroup, LargeGroup };
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
186
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
187 MemOPSizeKind getMemOPSizeKind(int64_t Value) const {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
188 if (Value == MemOPSizeLarge && MemOPSizeLarge != 0)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
189 return LargeGroup;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
190 if (Value == PreciseRangeLast + 1)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
191 return NonLargeGroup;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
192 return PreciseValue;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
193 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
194 };
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
195
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
196 static const char *getMIName(const MemIntrinsic *MI) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
197 switch (MI->getIntrinsicID()) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
198 case Intrinsic::memcpy:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
199 return "memcpy";
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
200 case Intrinsic::memmove:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
201 return "memmove";
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
202 case Intrinsic::memset:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
203 return "memset";
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
204 default:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
205 return "unknown";
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
206 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
207 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
208
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
209 static bool isProfitable(uint64_t Count, uint64_t TotalCount) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
210 assert(Count <= TotalCount);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
211 if (Count < MemOPCountThreshold)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
212 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
213 if (Count < TotalCount * MemOPPercentThreshold / 100)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
214 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
215 return true;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
216 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
217
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
218 static inline uint64_t getScaledCount(uint64_t Count, uint64_t Num,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
219 uint64_t Denom) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
220 if (!MemOPScaleCount)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
221 return Count;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
222 bool Overflowed;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
223 uint64_t ScaleCount = SaturatingMultiply(Count, Num, &Overflowed);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
224 return ScaleCount / Denom;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
225 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
226
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
227 bool MemOPSizeOpt::perform(MemIntrinsic *MI) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
228 assert(MI);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
229 if (MI->getIntrinsicID() == Intrinsic::memmove)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
230 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
231
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
232 uint32_t NumVals, MaxNumPromotions = MemOPMaxVersion + 2;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
233 uint64_t TotalCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
234 if (!getValueProfDataFromInst(*MI, IPVK_MemOPSize, MaxNumPromotions,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
235 ValueDataArray.get(), NumVals, TotalCount))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
236 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
237
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
238 uint64_t ActualCount = TotalCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
239 uint64_t SavedTotalCount = TotalCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
240 if (MemOPScaleCount) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
241 auto BBEdgeCount = BFI.getBlockProfileCount(MI->getParent());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
242 if (!BBEdgeCount)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
243 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
244 ActualCount = *BBEdgeCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
245 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
246
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
247 ArrayRef<InstrProfValueData> VDs(ValueDataArray.get(), NumVals);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
248 DEBUG(dbgs() << "Read one memory intrinsic profile with count " << ActualCount
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
249 << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
250 DEBUG(
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
251 for (auto &VD
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
252 : VDs) { dbgs() << " (" << VD.Value << "," << VD.Count << ")\n"; });
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
253
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
254 if (ActualCount < MemOPCountThreshold)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
255 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
256 // Skip if the total value profiled count is 0, in which case we can't
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
257 // scale up the counts properly (and there is no profitable transformation).
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
258 if (TotalCount == 0)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
259 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
260
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
261 TotalCount = ActualCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
262 if (MemOPScaleCount)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
263 DEBUG(dbgs() << "Scale counts: numerator = " << ActualCount
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
264 << " denominator = " << SavedTotalCount << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
265
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
266 // Keeping track of the count of the default case:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
267 uint64_t RemainCount = TotalCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
268 uint64_t SavedRemainCount = SavedTotalCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
269 SmallVector<uint64_t, 16> SizeIds;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
270 SmallVector<uint64_t, 16> CaseCounts;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
271 uint64_t MaxCount = 0;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
272 unsigned Version = 0;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
273 // Default case is in the front -- save the slot here.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
274 CaseCounts.push_back(0);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
275 for (auto &VD : VDs) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
276 int64_t V = VD.Value;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
277 uint64_t C = VD.Count;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
278 if (MemOPScaleCount)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
279 C = getScaledCount(C, ActualCount, SavedTotalCount);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
280
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
281 // Only care precise value here.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
282 if (getMemOPSizeKind(V) != PreciseValue)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
283 continue;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
284
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
285 // ValueCounts are sorted on the count. Break at the first un-profitable
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
286 // value.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
287 if (!isProfitable(C, RemainCount))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
288 break;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
289
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
290 SizeIds.push_back(V);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
291 CaseCounts.push_back(C);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
292 if (C > MaxCount)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
293 MaxCount = C;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
294
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
295 assert(RemainCount >= C);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
296 RemainCount -= C;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
297 assert(SavedRemainCount >= VD.Count);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
298 SavedRemainCount -= VD.Count;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
299
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
300 if (++Version > MemOPMaxVersion && MemOPMaxVersion != 0)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
301 break;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
302 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
303
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
304 if (Version == 0)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
305 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
306
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
307 CaseCounts[0] = RemainCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
308 if (RemainCount > MaxCount)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
309 MaxCount = RemainCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
310
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
311 uint64_t SumForOpt = TotalCount - RemainCount;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
312
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
313 DEBUG(dbgs() << "Optimize one memory intrinsic call to " << Version
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
314 << " Versions (covering " << SumForOpt << " out of "
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
315 << TotalCount << ")\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
316
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
317 // mem_op(..., size)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
318 // ==>
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
319 // switch (size) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
320 // case s1:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
321 // mem_op(..., s1);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
322 // goto merge_bb;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
323 // case s2:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
324 // mem_op(..., s2);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
325 // goto merge_bb;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
326 // ...
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
327 // default:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
328 // mem_op(..., size);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
329 // goto merge_bb;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
330 // }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
331 // merge_bb:
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
332
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
333 BasicBlock *BB = MI->getParent();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
334 DEBUG(dbgs() << "\n\n== Basic Block Before ==\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
335 DEBUG(dbgs() << *BB << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
336 auto OrigBBFreq = BFI.getBlockFreq(BB);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
337
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
338 BasicBlock *DefaultBB = SplitBlock(BB, MI);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
339 BasicBlock::iterator It(*MI);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
340 ++It;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
341 assert(It != DefaultBB->end());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
342 BasicBlock *MergeBB = SplitBlock(DefaultBB, &(*It));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
343 MergeBB->setName("MemOP.Merge");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
344 BFI.setBlockFreq(MergeBB, OrigBBFreq.getFrequency());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
345 DefaultBB->setName("MemOP.Default");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
346
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
347 auto &Ctx = Func.getContext();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
348 IRBuilder<> IRB(BB);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
349 BB->getTerminator()->eraseFromParent();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
350 Value *SizeVar = MI->getLength();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
351 SwitchInst *SI = IRB.CreateSwitch(SizeVar, DefaultBB, SizeIds.size());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
352
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
353 // Clear the value profile data.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
354 MI->setMetadata(LLVMContext::MD_prof, nullptr);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
355 // If all promoted, we don't need the MD.prof metadata.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
356 if (SavedRemainCount > 0 || Version != NumVals)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
357 // Otherwise we need update with the un-promoted records back.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
358 annotateValueSite(*Func.getParent(), *MI, VDs.slice(Version),
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
359 SavedRemainCount, IPVK_MemOPSize, NumVals);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
360
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
361 DEBUG(dbgs() << "\n\n== Basic Block After==\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
362
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
363 for (uint64_t SizeId : SizeIds) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
364 BasicBlock *CaseBB = BasicBlock::Create(
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
365 Ctx, Twine("MemOP.Case.") + Twine(SizeId), &Func, DefaultBB);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
366 Instruction *NewInst = MI->clone();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
367 // Fix the argument.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
368 MemIntrinsic * MemI = dyn_cast<MemIntrinsic>(NewInst);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
369 IntegerType *SizeType = dyn_cast<IntegerType>(MemI->getLength()->getType());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
370 assert(SizeType && "Expected integer type size argument.");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
371 ConstantInt *CaseSizeId = ConstantInt::get(SizeType, SizeId);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
372 MemI->setLength(CaseSizeId);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
373 CaseBB->getInstList().push_back(NewInst);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
374 IRBuilder<> IRBCase(CaseBB);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
375 IRBCase.CreateBr(MergeBB);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
376 SI->addCase(CaseSizeId, CaseBB);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
377 DEBUG(dbgs() << *CaseBB << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
378 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
379 setProfMetadata(Func.getParent(), SI, CaseCounts, MaxCount);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
380
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
381 DEBUG(dbgs() << *BB << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
382 DEBUG(dbgs() << *DefaultBB << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
383 DEBUG(dbgs() << *MergeBB << "\n");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
384
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
385 ORE.emit([&]() {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
386 using namespace ore;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
387 return OptimizationRemark(DEBUG_TYPE, "memopt-opt", MI)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
388 << "optimized " << NV("Intrinsic", StringRef(getMIName(MI)))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
389 << " with count " << NV("Count", SumForOpt) << " out of "
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
390 << NV("Total", TotalCount) << " for " << NV("Versions", Version)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
391 << " versions";
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
392 });
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
393
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
394 return true;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
395 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
396 } // namespace
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
397
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
398 static bool PGOMemOPSizeOptImpl(Function &F, BlockFrequencyInfo &BFI,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
399 OptimizationRemarkEmitter &ORE) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
400 if (DisableMemOPOPT)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
401 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
402
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
403 if (F.hasFnAttribute(Attribute::OptimizeForSize))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
404 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
405 MemOPSizeOpt MemOPSizeOpt(F, BFI, ORE);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
406 MemOPSizeOpt.perform();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
407 return MemOPSizeOpt.isChanged();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
408 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
409
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
410 bool PGOMemOPSizeOptLegacyPass::runOnFunction(Function &F) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
411 BlockFrequencyInfo &BFI =
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
412 getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
413 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
414 return PGOMemOPSizeOptImpl(F, BFI, ORE);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
415 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
416
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
417 namespace llvm {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
418 char &PGOMemOPSizeOptID = PGOMemOPSizeOptLegacyPass::ID;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
419
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
420 PreservedAnalyses PGOMemOPSizeOpt::run(Function &F,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
421 FunctionAnalysisManager &FAM) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
422 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
423 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
424 bool Changed = PGOMemOPSizeOptImpl(F, BFI, ORE);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
425 if (!Changed)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
426 return PreservedAnalyses::all();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
427 auto PA = PreservedAnalyses();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
428 PA.preserve<GlobalsAA>();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
429 return PA;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
430 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
431 } // namespace llvm