Skip to content

Commit

Permalink
[PGO] IR level instrumentation of indirect call value profiling
Browse files Browse the repository at this point in the history
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
  • Loading branch information
xur-llvm committed Jan 21, 2016
1 parent 4e971da commit ed9fec7
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 4 deletions.
56 changes: 52 additions & 4 deletions llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
Expand Up @@ -45,17 +45,18 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Instrumentation.h"
#include "CFGMST.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#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"
Expand All @@ -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>
Expand All @@ -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.
Expand All @@ -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:
Expand Down Expand Up @@ -225,7 +235,7 @@ template <class Edge, class BBInfo> class FuncPGOInstrumentation {
// 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,
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand All @@ -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.
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/Transforms/PGOProfile/indirect_call_profile.ll
@@ -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
}

0 comments on commit ed9fec7

Please sign in to comment.