mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[PGO] Refactor Value Profiling into a plugin based oracle and create a well defined API for the plugins.
Summary: This PR creates a utility class called ValueProfileCollector that tells PGOInstrumentationGen and PGOInstrumentationUse what to value-profile and where to attach the profile metadata. It then refactors logic scattered in PGOInstrumentation.cpp into two plugins that plug into the ValueProfileCollector. Authored By: Wael Yehia <wyehia@ca.ibm.com> Reviewer: davidxl, tejohnson, xur Reviewed By: davidxl, tejohnson, xur Subscribers: llvm-commits Tag: #llvm Differential Revision: https://reviews.llvm.org/D67920 Patch By Wael Yehia <wyehia@ca.ibm.com> llvm-svn: 373601
This commit is contained in:
parent
e03c5f1b6b
commit
729f819c81
@ -14,6 +14,7 @@ add_llvm_library(LLVMInstrumentation
|
||||
PGOMemOPSizeOpt.cpp
|
||||
PoisonChecking.cpp
|
||||
SanitizerCoverage.cpp
|
||||
ValueProfileCollector.cpp
|
||||
ThreadSanitizer.cpp
|
||||
HWAddressSanitizer.cpp
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CFGMST.h"
|
||||
#include "ValueProfileCollector.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -61,7 +62,6 @@
|
||||
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
||||
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/IndirectCallVisitor.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||
@ -121,6 +121,7 @@
|
||||
|
||||
using namespace llvm;
|
||||
using ProfileCount = Function::ProfileCount;
|
||||
using VPCandidateInfo = ValueProfileCollector::CandidateInfo;
|
||||
|
||||
#define DEBUG_TYPE "pgo-instrumentation"
|
||||
|
||||
@ -287,6 +288,11 @@ static std::string getBranchCondString(Instruction *TI) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *ValueProfKindDescr[] = {
|
||||
#define VALUE_PROF_KIND(Enumerator, Value, Descr) Descr,
|
||||
#include "llvm/ProfileData/InstrProfData.inc"
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
/// The select instruction visitor plays three roles specified
|
||||
@ -349,50 +355,6 @@ struct SelectInstVisitor : public InstVisitor<SelectInstVisitor> {
|
||||
unsigned getNumOfSelectInsts() const { return NSIs; }
|
||||
};
|
||||
|
||||
/// Instruction Visitor class to visit memory intrinsic calls.
|
||||
struct MemIntrinsicVisitor : public InstVisitor<MemIntrinsicVisitor> {
|
||||
Function &F;
|
||||
unsigned NMemIs = 0; // Number of memIntrinsics instrumented.
|
||||
VisitMode Mode = VM_counting; // Visiting mode.
|
||||
unsigned CurCtrId = 0; // Current counter index.
|
||||
unsigned TotalNumCtrs = 0; // Total number of counters
|
||||
GlobalVariable *FuncNameVar = nullptr;
|
||||
uint64_t FuncHash = 0;
|
||||
PGOUseFunc *UseFunc = nullptr;
|
||||
std::vector<Instruction *> Candidates;
|
||||
|
||||
MemIntrinsicVisitor(Function &Func) : F(Func) {}
|
||||
|
||||
void countMemIntrinsics(Function &Func) {
|
||||
NMemIs = 0;
|
||||
Mode = VM_counting;
|
||||
visit(Func);
|
||||
}
|
||||
|
||||
void instrumentMemIntrinsics(Function &Func, unsigned TotalNC,
|
||||
GlobalVariable *FNV, uint64_t FHash) {
|
||||
Mode = VM_instrument;
|
||||
TotalNumCtrs = TotalNC;
|
||||
FuncHash = FHash;
|
||||
FuncNameVar = FNV;
|
||||
visit(Func);
|
||||
}
|
||||
|
||||
std::vector<Instruction *> findMemIntrinsics(Function &Func) {
|
||||
Candidates.clear();
|
||||
Mode = VM_annotate;
|
||||
visit(Func);
|
||||
return Candidates;
|
||||
}
|
||||
|
||||
// Visit the IR stream and annotate all mem intrinsic call instructions.
|
||||
void instrumentOneMemIntrinsic(MemIntrinsic &MI);
|
||||
|
||||
// Visit \p MI instruction and perform tasks according to visit mode.
|
||||
void visitMemIntrinsic(MemIntrinsic &SI);
|
||||
|
||||
unsigned getNumOfMemIntrinsics() const { return NMemIs; }
|
||||
};
|
||||
|
||||
class PGOInstrumentationGenLegacyPass : public ModulePass {
|
||||
public:
|
||||
@ -564,13 +526,14 @@ private:
|
||||
// A map that stores the Comdat group in function F.
|
||||
std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers;
|
||||
|
||||
ValueProfileCollector VPC;
|
||||
|
||||
void computeCFGHash();
|
||||
void renameComdatFunction();
|
||||
|
||||
public:
|
||||
std::vector<std::vector<Instruction *>> ValueSites;
|
||||
std::vector<std::vector<VPCandidateInfo>> ValueSites;
|
||||
SelectInstVisitor SIVisitor;
|
||||
MemIntrinsicVisitor MIVisitor;
|
||||
std::string FuncName;
|
||||
GlobalVariable *FuncNameVar;
|
||||
|
||||
@ -605,23 +568,21 @@ public:
|
||||
std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
|
||||
bool CreateGlobalVar = false, BranchProbabilityInfo *BPI = nullptr,
|
||||
BlockFrequencyInfo *BFI = nullptr, bool IsCS = false)
|
||||
: F(Func), IsCS(IsCS), ComdatMembers(ComdatMembers),
|
||||
ValueSites(IPVK_Last + 1), SIVisitor(Func), MIVisitor(Func),
|
||||
MST(F, BPI, BFI) {
|
||||
: F(Func), IsCS(IsCS), ComdatMembers(ComdatMembers), VPC(Func),
|
||||
ValueSites(IPVK_Last + 1), SIVisitor(Func), MST(F, BPI, BFI) {
|
||||
// This should be done before CFG hash computation.
|
||||
SIVisitor.countSelects(Func);
|
||||
MIVisitor.countMemIntrinsics(Func);
|
||||
ValueSites[IPVK_MemOPSize] = VPC.get(IPVK_MemOPSize);
|
||||
if (!IsCS) {
|
||||
NumOfPGOSelectInsts += SIVisitor.getNumOfSelectInsts();
|
||||
NumOfPGOMemIntrinsics += MIVisitor.getNumOfMemIntrinsics();
|
||||
NumOfPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size();
|
||||
NumOfPGOBB += MST.BBInfos.size();
|
||||
ValueSites[IPVK_IndirectCallTarget] = findIndirectCalls(Func);
|
||||
ValueSites[IPVK_IndirectCallTarget] = VPC.get(IPVK_IndirectCallTarget);
|
||||
} else {
|
||||
NumOfCSPGOSelectInsts += SIVisitor.getNumOfSelectInsts();
|
||||
NumOfCSPGOMemIntrinsics += MIVisitor.getNumOfMemIntrinsics();
|
||||
NumOfCSPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size();
|
||||
NumOfCSPGOBB += MST.BBInfos.size();
|
||||
}
|
||||
ValueSites[IPVK_MemOPSize] = MIVisitor.findMemIntrinsics(Func);
|
||||
|
||||
FuncName = getPGOFuncName(F);
|
||||
computeCFGHash();
|
||||
@ -875,28 +836,36 @@ static void instrumentOneFunc(
|
||||
if (DisableValueProfiling)
|
||||
return;
|
||||
|
||||
unsigned NumIndirectCalls = 0;
|
||||
for (auto &I : FuncInfo.ValueSites[IPVK_IndirectCallTarget]) {
|
||||
CallSite CS(I);
|
||||
Value *Callee = CS.getCalledValue();
|
||||
LLVM_DEBUG(dbgs() << "Instrument one indirect call: CallSite Index = "
|
||||
<< NumIndirectCalls << "\n");
|
||||
IRBuilder<> Builder(I);
|
||||
assert(Builder.GetInsertPoint() != I->getParent()->end() &&
|
||||
"Cannot get the Instrumentation point");
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile),
|
||||
{ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncInfo.FunctionHash),
|
||||
Builder.CreatePtrToInt(Callee, Builder.getInt64Ty()),
|
||||
Builder.getInt32(IPVK_IndirectCallTarget),
|
||||
Builder.getInt32(NumIndirectCalls++)});
|
||||
}
|
||||
NumOfPGOICall += NumIndirectCalls;
|
||||
NumOfPGOICall += FuncInfo.ValueSites[IPVK_IndirectCallTarget].size();
|
||||
|
||||
// Now instrument memop intrinsic calls.
|
||||
FuncInfo.MIVisitor.instrumentMemIntrinsics(
|
||||
F, NumCounters, FuncInfo.FuncNameVar, FuncInfo.FunctionHash);
|
||||
// For each VP Kind, walk the VP candidates and instrument each one.
|
||||
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
|
||||
unsigned SiteIndex = 0;
|
||||
if (Kind == IPVK_MemOPSize && !PGOInstrMemOP)
|
||||
continue;
|
||||
|
||||
for (VPCandidateInfo Cand : FuncInfo.ValueSites[Kind]) {
|
||||
LLVM_DEBUG(dbgs() << "Instrument one VP " << ValueProfKindDescr[Kind]
|
||||
<< " site: CallSite Index = " << SiteIndex << "\n");
|
||||
|
||||
IRBuilder<> Builder(Cand.InsertPt);
|
||||
assert(Builder.GetInsertPoint() != Cand.InsertPt->getParent()->end() &&
|
||||
"Cannot get the Instrumentation point");
|
||||
|
||||
Value *ToProfile = nullptr;
|
||||
if (Cand.V->getType()->isIntegerTy())
|
||||
ToProfile = Builder.CreateZExtOrTrunc(Cand.V, Builder.getInt64Ty());
|
||||
else if (Cand.V->getType()->isPointerTy())
|
||||
ToProfile = Builder.CreatePtrToInt(Cand.V, Builder.getInt64Ty());
|
||||
assert(ToProfile && "value profiling Value is of unexpected type");
|
||||
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile),
|
||||
{ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncInfo.FunctionHash), ToProfile,
|
||||
Builder.getInt32(Kind), Builder.getInt32(SiteIndex++)});
|
||||
}
|
||||
} // IPVK_First <= Kind <= IPVK_Last
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1429,43 +1398,6 @@ void SelectInstVisitor::visitSelectInst(SelectInst &SI) {
|
||||
llvm_unreachable("Unknown visiting mode");
|
||||
}
|
||||
|
||||
void MemIntrinsicVisitor::instrumentOneMemIntrinsic(MemIntrinsic &MI) {
|
||||
Module *M = F.getParent();
|
||||
IRBuilder<> Builder(&MI);
|
||||
Type *Int64Ty = Builder.getInt64Ty();
|
||||
Type *I8PtrTy = Builder.getInt8PtrTy();
|
||||
Value *Length = MI.getLength();
|
||||
assert(!isa<ConstantInt>(Length));
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile),
|
||||
{ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncHash), Builder.CreateZExtOrTrunc(Length, Int64Ty),
|
||||
Builder.getInt32(IPVK_MemOPSize), Builder.getInt32(CurCtrId)});
|
||||
++CurCtrId;
|
||||
}
|
||||
|
||||
void MemIntrinsicVisitor::visitMemIntrinsic(MemIntrinsic &MI) {
|
||||
if (!PGOInstrMemOP)
|
||||
return;
|
||||
Value *Length = MI.getLength();
|
||||
// Not instrument constant length calls.
|
||||
if (dyn_cast<ConstantInt>(Length))
|
||||
return;
|
||||
|
||||
switch (Mode) {
|
||||
case VM_counting:
|
||||
NMemIs++;
|
||||
return;
|
||||
case VM_instrument:
|
||||
instrumentOneMemIntrinsic(MI);
|
||||
return;
|
||||
case VM_annotate:
|
||||
Candidates.push_back(&MI);
|
||||
return;
|
||||
}
|
||||
llvm_unreachable("Unknown visiting mode");
|
||||
}
|
||||
|
||||
// Traverse all valuesites and annotate the instructions for all value kind.
|
||||
void PGOUseFunc::annotateValueSites() {
|
||||
if (DisableValueProfiling)
|
||||
@ -1478,11 +1410,6 @@ void PGOUseFunc::annotateValueSites() {
|
||||
annotateValueSites(Kind);
|
||||
}
|
||||
|
||||
static const char *ValueProfKindDescr[] = {
|
||||
#define VALUE_PROF_KIND(Enumerator, Value, Descr) Descr,
|
||||
#include "llvm/ProfileData/InstrProfData.inc"
|
||||
};
|
||||
|
||||
// Annotate the instructions for a specific value kind.
|
||||
void PGOUseFunc::annotateValueSites(uint32_t Kind) {
|
||||
assert(Kind <= IPVK_Last);
|
||||
@ -1501,11 +1428,11 @@ void PGOUseFunc::annotateValueSites(uint32_t Kind) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &I : ValueSites) {
|
||||
for (VPCandidateInfo &I : ValueSites) {
|
||||
LLVM_DEBUG(dbgs() << "Read one value site profile (kind = " << Kind
|
||||
<< "): Index = " << ValueSiteIndex << " out of "
|
||||
<< NumValueSites << "\n");
|
||||
annotateValueSite(*M, *I, ProfileRecord,
|
||||
annotateValueSite(*M, *I.AnnotatedInst, ProfileRecord,
|
||||
static_cast<InstrProfValueKind>(Kind), ValueSiteIndex,
|
||||
Kind == IPVK_MemOPSize ? MaxNumMemOPAnnotations
|
||||
: MaxNumAnnotations);
|
||||
|
78
lib/Transforms/Instrumentation/ValueProfileCollector.cpp
Normal file
78
lib/Transforms/Instrumentation/ValueProfileCollector.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
//===- ValueProfileCollector.cpp - determine what to value profile --------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The implementation of the ValueProfileCollector via ValueProfileCollectorImpl
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ValueProfilePlugins.inc"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
/// A plugin-based class that takes an arbitrary number of Plugin types.
|
||||
/// Each plugin type must satisfy the following API:
|
||||
/// 1) the constructor must take a `Function &f`. Typically, the plugin would
|
||||
/// scan the function looking for candidates.
|
||||
/// 2) contain a member function with the following signature and name:
|
||||
/// void run(std::vector<CandidateInfo> &Candidates);
|
||||
/// such that the plugin would append its result into the vector parameter.
|
||||
///
|
||||
/// Plugins are defined in ValueProfilePlugins.inc
|
||||
template <class... Ts> class PluginChain;
|
||||
|
||||
/// The type PluginChainFinal is the final chain of plugins that will be used by
|
||||
/// ValueProfileCollectorImpl.
|
||||
using PluginChainFinal = PluginChain<VP_PLUGIN_LIST>;
|
||||
|
||||
template <> class PluginChain<> {
|
||||
public:
|
||||
PluginChain(Function &F) {}
|
||||
void get(InstrProfValueKind K, std::vector<CandidateInfo> &Candidates) {}
|
||||
};
|
||||
|
||||
template <class PluginT, class... Ts>
|
||||
class PluginChain<PluginT, Ts...> : public PluginChain<Ts...> {
|
||||
PluginT Plugin;
|
||||
using Base = PluginChain<Ts...>;
|
||||
|
||||
public:
|
||||
PluginChain(Function &F) : PluginChain<Ts...>(F), Plugin(F) {}
|
||||
|
||||
void get(InstrProfValueKind K, std::vector<CandidateInfo> &Candidates) {
|
||||
if (K == PluginT::Kind)
|
||||
Plugin.run(Candidates);
|
||||
Base::get(K, Candidates);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// ValueProfileCollectorImpl inherits the API of PluginChainFinal.
|
||||
class ValueProfileCollector::ValueProfileCollectorImpl : public PluginChainFinal {
|
||||
public:
|
||||
using PluginChainFinal::PluginChainFinal;
|
||||
};
|
||||
|
||||
ValueProfileCollector::ValueProfileCollector(Function &F)
|
||||
: PImpl(new ValueProfileCollectorImpl(F)) {}
|
||||
|
||||
ValueProfileCollector::~ValueProfileCollector() = default;
|
||||
|
||||
std::vector<CandidateInfo>
|
||||
ValueProfileCollector::get(InstrProfValueKind Kind) const {
|
||||
std::vector<CandidateInfo> Result;
|
||||
PImpl->get(Kind, Result);
|
||||
return Result;
|
||||
}
|
79
lib/Transforms/Instrumentation/ValueProfileCollector.h
Normal file
79
lib/Transforms/Instrumentation/ValueProfileCollector.h
Normal file
@ -0,0 +1,79 @@
|
||||
//===- ValueProfileCollector.h - determine what to value profile ----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a utility class, ValueProfileCollector, that is used to
|
||||
// determine what kind of llvm::Value's are worth value-profiling, at which
|
||||
// point in the program, and which instruction holds the Value Profile metadata.
|
||||
// Currently, the only users of this utility is the PGOInstrumentation[Gen|Use]
|
||||
// passes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILE_GEN_ANALYSIS_H
|
||||
#define LLVM_ANALYSIS_PROFILE_GEN_ANALYSIS_H
|
||||
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Utility analysis that determines what values are worth profiling.
|
||||
/// The actual logic is inside the ValueProfileCollectorImpl, whose job is to
|
||||
/// populate the Candidates vector.
|
||||
///
|
||||
/// Value profiling an expression means to track the values that this expression
|
||||
/// takes at runtime and the frequency of each value.
|
||||
/// It is important to distinguish between two sets of value profiles for a
|
||||
/// particular expression:
|
||||
/// 1) The set of values at the point of evaluation.
|
||||
/// 2) The set of values at the point of use.
|
||||
/// In some cases, the two sets are identical, but it's not unusual for the two
|
||||
/// to differ.
|
||||
///
|
||||
/// To elaborate more, consider this C code, and focus on the expression `nn`:
|
||||
/// void foo(int nn, bool b) {
|
||||
/// if (b) memcpy(x, y, nn);
|
||||
/// }
|
||||
/// The point of evaluation can be as early as the start of the function, and
|
||||
/// let's say the value profile for `nn` is:
|
||||
/// total=100; (value,freq) set = {(8,10), (32,50)}
|
||||
/// The point of use is right before we call memcpy, and since we execute the
|
||||
/// memcpy conditionally, the value profile of `nn` can be:
|
||||
/// total=15; (value,freq) set = {(8,10), (4,5)}
|
||||
///
|
||||
/// For this reason, a plugin is responsible for computing the insertion point
|
||||
/// for each value to be profiled. The `CandidateInfo` structure encapsulates
|
||||
/// all the information needed for each value profile site.
|
||||
class ValueProfileCollector {
|
||||
public:
|
||||
struct CandidateInfo {
|
||||
Value *V; // The value to profile.
|
||||
Instruction *InsertPt; // Insert the VP lib call before this instr.
|
||||
Instruction *AnnotatedInst; // Where metadata is attached.
|
||||
};
|
||||
|
||||
ValueProfileCollector(Function &Fn);
|
||||
ValueProfileCollector(ValueProfileCollector &&) = delete;
|
||||
ValueProfileCollector &operator=(ValueProfileCollector &&) = delete;
|
||||
|
||||
ValueProfileCollector(const ValueProfileCollector &) = delete;
|
||||
ValueProfileCollector &operator=(const ValueProfileCollector &) = delete;
|
||||
~ValueProfileCollector();
|
||||
|
||||
/// returns a list of value profiling candidates of the given kind
|
||||
std::vector<CandidateInfo> get(InstrProfValueKind Kind) const;
|
||||
|
||||
private:
|
||||
class ValueProfileCollectorImpl;
|
||||
std::unique_ptr<ValueProfileCollectorImpl> PImpl;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
75
lib/Transforms/Instrumentation/ValueProfilePlugins.inc
Normal file
75
lib/Transforms/Instrumentation/ValueProfilePlugins.inc
Normal file
@ -0,0 +1,75 @@
|
||||
//=== ValueProfilePlugins.inc - set of plugins used by ValueProfileCollector =//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a set of plugin classes used in ValueProfileCollectorImpl.
|
||||
// Each plugin is responsible for collecting Value Profiling candidates for a
|
||||
// particular optimization.
|
||||
// Each plugin must satisfy the interface described in ValueProfileCollector.cpp
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ValueProfileCollector.h"
|
||||
#include "llvm/Analysis/IndirectCallVisitor.h"
|
||||
#include "llvm/IR/InstVisitor.h"
|
||||
|
||||
using namespace llvm;
|
||||
using CandidateInfo = ValueProfileCollector::CandidateInfo;
|
||||
|
||||
///--------------------------- MemIntrinsicPlugin ------------------------------
|
||||
class MemIntrinsicPlugin : public InstVisitor<MemIntrinsicPlugin> {
|
||||
Function &F;
|
||||
std::vector<CandidateInfo> *Candidates;
|
||||
|
||||
public:
|
||||
static constexpr InstrProfValueKind Kind = IPVK_MemOPSize;
|
||||
|
||||
MemIntrinsicPlugin(Function &Fn) : F(Fn), Candidates(nullptr) {}
|
||||
|
||||
void run(std::vector<CandidateInfo> &Cs) {
|
||||
Candidates = &Cs;
|
||||
visit(F);
|
||||
Candidates = nullptr;
|
||||
}
|
||||
void visitMemIntrinsic(MemIntrinsic &MI) {
|
||||
Value *Length = MI.getLength();
|
||||
// Not instrument constant length calls.
|
||||
if (dyn_cast<ConstantInt>(Length))
|
||||
return;
|
||||
|
||||
Instruction *InsertPt = &MI;
|
||||
Instruction *AnnotatedInst = &MI;
|
||||
Candidates->emplace_back(CandidateInfo{Length, InsertPt, AnnotatedInst});
|
||||
}
|
||||
};
|
||||
|
||||
///------------------------ IndirectCallPromotionPlugin ------------------------
|
||||
class IndirectCallPromotionPlugin {
|
||||
Function &F;
|
||||
|
||||
public:
|
||||
static constexpr InstrProfValueKind Kind = IPVK_IndirectCallTarget;
|
||||
|
||||
IndirectCallPromotionPlugin(Function &Fn) : F(Fn) {}
|
||||
|
||||
void run(std::vector<CandidateInfo> &Candidates) {
|
||||
std::vector<Instruction *> Result = findIndirectCalls(F);
|
||||
for (Instruction *I : Result) {
|
||||
Value *Callee = CallSite(I).getCalledValue();
|
||||
Instruction *InsertPt = I;
|
||||
Instruction *AnnotatedInst = I;
|
||||
Candidates.emplace_back(CandidateInfo{Callee, InsertPt, AnnotatedInst});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///----------------------- Registration of the plugins -------------------------
|
||||
/// For now, registering a plugin with the ValueProfileCollector is done by
|
||||
/// adding the plugin type to the VP_PLUGIN_LIST macro.
|
||||
#define VP_PLUGIN_LIST \
|
||||
MemIntrinsicPlugin, \
|
||||
IndirectCallPromotionPlugin
|
Loading…
Reference in New Issue
Block a user