1 | //=== ValueProfilePlugins.inc - set of plugins used by ValueProfileCollector =// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains a set of plugin classes used in ValueProfileCollectorImpl. |
10 | // Each plugin is responsible for collecting Value Profiling candidates for a |
11 | // particular optimization. |
12 | // Each plugin must satisfy the interface described in ValueProfileCollector.cpp |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #include "ValueProfileCollector.h" |
17 | #include "llvm/Analysis/IndirectCallVisitor.h" |
18 | #include "llvm/Analysis/TargetLibraryInfo.h" |
19 | #include "llvm/IR/InstVisitor.h" |
20 | |
21 | using namespace llvm; |
22 | using CandidateInfo = ValueProfileCollector::CandidateInfo; |
23 | |
24 | extern cl::opt<bool> MemOPOptMemcmpBcmp; |
25 | |
26 | ///--------------------------- MemIntrinsicPlugin ------------------------------ |
27 | class MemIntrinsicPlugin : public InstVisitor<MemIntrinsicPlugin> { |
28 | Function &F; |
29 | TargetLibraryInfo &TLI; |
30 | std::vector<CandidateInfo> *Candidates; |
31 | |
32 | public: |
33 | static constexpr InstrProfValueKind Kind = IPVK_MemOPSize; |
34 | |
35 | MemIntrinsicPlugin(Function &Fn, TargetLibraryInfo &TLI) |
36 | : F(Fn), TLI(TLI), Candidates(nullptr) {} |
37 | |
38 | void run(std::vector<CandidateInfo> &Cs) { |
39 | Candidates = &Cs; |
40 | visit(F); |
41 | Candidates = nullptr; |
42 | } |
43 | void visitMemIntrinsic(MemIntrinsic &MI) { |
44 | Value *Length = MI.getLength(); |
45 | // Not instrument constant length calls. |
46 | if (isa<ConstantInt>(Val: Length)) |
47 | return; |
48 | |
49 | Instruction *InsertPt = &MI; |
50 | Instruction *AnnotatedInst = &MI; |
51 | Candidates->emplace_back(args: CandidateInfo{.V: Length, .InsertPt: InsertPt, .AnnotatedInst: AnnotatedInst}); |
52 | } |
53 | void visitCallInst(CallInst &CI) { |
54 | if (!MemOPOptMemcmpBcmp) |
55 | return; |
56 | auto *F = CI.getCalledFunction(); |
57 | if (!F) |
58 | return; |
59 | LibFunc Func; |
60 | if (TLI.getLibFunc(CB: CI, F&: Func) && |
61 | (Func == LibFunc_memcmp || Func == LibFunc_bcmp)) { |
62 | Value *Length = CI.getArgOperand(i: 2); |
63 | // Not instrument constant length calls. |
64 | if (isa<ConstantInt>(Val: Length)) |
65 | return; |
66 | Instruction *InsertPt = &CI; |
67 | Instruction *AnnotatedInst = &CI; |
68 | Candidates->emplace_back(args: CandidateInfo{.V: Length, .InsertPt: InsertPt, .AnnotatedInst: AnnotatedInst}); |
69 | } |
70 | } |
71 | }; |
72 | |
73 | ///------------------------ IndirectCallPromotionPlugin ------------------------ |
74 | class IndirectCallPromotionPlugin { |
75 | Function &F; |
76 | |
77 | public: |
78 | static constexpr InstrProfValueKind Kind = IPVK_IndirectCallTarget; |
79 | |
80 | IndirectCallPromotionPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} |
81 | |
82 | void run(std::vector<CandidateInfo> &Candidates) { |
83 | std::vector<CallBase *> Result = findIndirectCalls(F); |
84 | for (Instruction *I : Result) { |
85 | Value *Callee = cast<CallBase>(Val: I)->getCalledOperand(); |
86 | Instruction *InsertPt = I; |
87 | Instruction *AnnotatedInst = I; |
88 | Candidates.emplace_back(args: CandidateInfo{.V: Callee, .InsertPt: InsertPt, .AnnotatedInst: AnnotatedInst}); |
89 | } |
90 | } |
91 | }; |
92 | |
93 | ///--------------------- VirtualTableValueProfilingPlugin -------------------- |
94 | class VTableProfilingPlugin { |
95 | Function &F; |
96 | |
97 | public: |
98 | static constexpr InstrProfValueKind Kind = IPVK_VTableTarget; |
99 | |
100 | VTableProfilingPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} |
101 | |
102 | void run(std::vector<CandidateInfo> &Candidates) { |
103 | std::vector<Instruction *> Result = findVTableAddrs(F); |
104 | for (Instruction *I : Result) { |
105 | Instruction *InsertPt = I->getNextNonDebugInstruction(); |
106 | // When finding an insertion point, keep PHI and EH pad instructions |
107 | // before vp intrinsics. This is similar to |
108 | // `BasicBlock::getFirstInsertionPt`. |
109 | while (InsertPt && (dyn_cast<PHINode>(Val: InsertPt) || InsertPt->isEHPad())) |
110 | InsertPt = InsertPt->getNextNonDebugInstruction(); |
111 | // Skip instrumentating the value if InsertPt is the last instruction. |
112 | // FIXME: Set InsertPt to the end of basic block to instrument the value |
113 | // if InsertPt is the last instruction. |
114 | if (InsertPt == nullptr) |
115 | continue; |
116 | |
117 | Instruction *AnnotatedInst = I; |
118 | Candidates.emplace_back(args: CandidateInfo{.V: I, .InsertPt: InsertPt, .AnnotatedInst: AnnotatedInst}); |
119 | } |
120 | } |
121 | }; |
122 | |
123 | ///----------------------- Registration of the plugins ------------------------- |
124 | /// For now, registering a plugin with the ValueProfileCollector is done by |
125 | /// adding the plugin type to the VP_PLUGIN_LIST macro. |
126 | #define VP_PLUGIN_LIST \ |
127 | MemIntrinsicPlugin, IndirectCallPromotionPlugin, VTableProfilingPlugin |
128 | |