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