1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[PGO] IR level instrumentation of indirect call value profiling

This patch adds the instrumentation for indirect call value profiling. It finds all the indirect call-sites and generates instrprof_value_profile intrinsic calls. A new opt level option -disable-vp is introduced to disable this instrumentation.

Reviewers: davidxl, betulb, vsk

Differential Revision: http://reviews.llvm.org/D16016

llvm-svn: 258417
This commit is contained in:
Rong Xu 2016-01-21 18:11:44 +00:00
parent 9447739046
commit 6c08b3c582
2 changed files with 69 additions and 4 deletions

View File

@ -45,7 +45,6 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Instrumentation.h"
#include "CFGMST.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
@ -53,9 +52,11 @@
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/MDBuilder.h"
@ -65,6 +66,7 @@
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/JamCRC.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <string>
#include <utility>
@ -81,6 +83,7 @@ STATISTIC(NumOfPGOSplit, "Number of critical edge splits.");
STATISTIC(NumOfPGOFunc, "Number of functions having valid profile counts.");
STATISTIC(NumOfPGOMismatch, "Number of functions having mismatch profile.");
STATISTIC(NumOfPGOMissing, "Number of functions without profile.");
STATISTIC(NumOfPGOICall, "Number of indirect call value instrumentation.");
// Command line option to specify the file to read profile from. This is
// mainly used for testing.
@ -90,6 +93,13 @@ static cl::opt<std::string>
cl::desc("Specify the path of profile data file. This is"
"mainly for test purpose."));
// Command line options to disable value profiling. The default is false:
// i.e. vaule profiling is enabled by default. This is for debug purpose.
static cl::opt<bool>
DisableValueProfiling("disable-vp", cl::init(false),
cl::Hidden,
cl::desc("Disable Value Profiling"));
namespace {
class PGOInstrumentationGen : public ModulePass {
public:
@ -225,7 +235,7 @@ public:
// Dump edges and BB information.
void dumpInfo(std::string Str = "") const {
MST.dumpEdges(dbgs(), Twine("Dump Function ") + FuncName + " Hash: " +
Twine(FunctionHash) + "\t" + Str);
Twine(FunctionHash) + "\t" + Str);
}
FuncPGOInstrumentation(Function &Func, bool CreateGlobalVar = false,
@ -305,7 +315,21 @@ BasicBlock *FuncPGOInstrumentation<Edge, BBInfo>::getInstrBB(Edge *E) {
return InstrBB;
}
// Visit all edge and instrument the edges not in MST.
// Visitor class that finds all indirect call sites.
struct PGOIndirectCallSiteVisitor
: public InstVisitor<PGOIndirectCallSiteVisitor> {
std::vector<CallInst *> IndirectCallInsts;
PGOIndirectCallSiteVisitor() {}
void visitCallInst(CallInst &I) {
CallSite CS(&I);
if (CS.getCalledFunction() || !CS.getCalledValue())
return;
IndirectCallInsts.push_back(&I);
}
};
// Visit all edge and instrument the edges not in MST, and do value profiling.
// Critical edges will be split.
static void instrumentOneFunc(Function &F, Module *M,
BranchProbabilityInfo *BPI,
@ -318,6 +342,7 @@ static void instrumentOneFunc(Function &F, Module *M,
}
uint32_t I = 0;
Type *I8PtrTy = Type::getInt8PtrTy(M->getContext());
for (auto &E : FuncInfo.MST.AllEdges) {
BasicBlock *InstrBB = FuncInfo.getInstrBB(E.get());
if (!InstrBB)
@ -326,13 +351,36 @@ static void instrumentOneFunc(Function &F, Module *M,
IRBuilder<> Builder(InstrBB, InstrBB->getFirstInsertionPt());
assert(Builder.GetInsertPoint() != InstrBB->end() &&
"Cannot get the Instrumentation point");
Type *I8PtrTy = Type::getInt8PtrTy(M->getContext());
Builder.CreateCall(
Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment),
{llvm::ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
Builder.getInt64(FuncInfo.FunctionHash), Builder.getInt32(NumCounters),
Builder.getInt32(I++)});
}
if (DisableValueProfiling)
return;
unsigned NumIndirectCallSites = 0;
PGOIndirectCallSiteVisitor ICV;
ICV.visit(F);
for (auto &I : ICV.IndirectCallInsts) {
CallSite CS(I);
Value *Callee = CS.getCalledValue();
DEBUG(dbgs() << "Instrument one indirect call: CallSite Index = "
<< NumIndirectCallSites << "\n");
IRBuilder<> Builder(I);
assert(Builder.GetInsertPoint() != I->getParent()->end() &&
"Cannot get the Instrumentation point");
Builder.CreateCall(
Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile),
{llvm::ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
Builder.getInt64(FuncInfo.FunctionHash),
Builder.CreatePtrToInt(Callee, Builder.getInt64Ty()),
Builder.getInt32(llvm::InstrProfValueKind::IPVK_IndirectCallTarget),
Builder.getInt32(NumIndirectCallSites++)});
}
NumOfPGOICall += NumIndirectCallSites;
}
// This class represents a CFG edge in profile use compilation.

View File

@ -0,0 +1,17 @@
; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@bar = external global void ()*, align 8
; GEN: @__profn_foo = private constant [3 x i8] c"foo"
define void @foo() {
entry:
; GEN: entry:
; GEN-NEXT: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 12884901887, i32 1, i32 0)
%tmp = load void ()*, void ()** @bar, align 8
; GEN: [[ICALL_TARGET:%[0-9]+]] = ptrtoint void ()* %tmp to i64
; GEN-NEXT: call void @llvm.instrprof.value.profile(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 12884901887, i64 [[ICALL_TARGET]], i32 0, i32 0)
call void %tmp()
ret void
}