[PGO] Add interfaces to annotate instr with VP data

Add interfaces to do value profile data IR annnotation
  and read. Needed by both FE and IR based PGO.





git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259813 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Xinliang David Li 2016-02-04 19:11:43 +00:00
parent 6cced9c3cd
commit f45c13d3a1
3 changed files with 167 additions and 7 deletions

View File

@ -178,8 +178,8 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName);
/// The first field is the legnth of the uncompressed strings, and the
/// the second field is the length of the zlib-compressed string.
/// Both fields are encoded in ULEB128. If \c doCompress is false, the
/// third field is the uncompressed strings; otherwise it is the
/// compressed string. When the string compression is off, the
/// third field is the uncompressed strings; otherwise it is the
/// compressed string. When the string compression is off, the
/// second field will have value zero.
int collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
bool doCompression, std::string &Result);
@ -193,6 +193,29 @@ class InstrProfSymtab;
/// bytes. This method decodes the string and populates the \c Symtab.
int readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab);
enum InstrProfValueKind : uint32_t {
#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
#include "llvm/ProfileData/InstrProfData.inc"
};
struct InstrProfRecord;
/// Extract value profile data for value site \p SiteIdx from \p InstrProfR
/// and annotate the instruction \p Inst with the value profile meta data.
void annotateValueSite(Module &M, Instruction &Inst,
const InstrProfRecord &InstrProfR,
InstrProfValueKind ValueKind, uint32_t SiteIndx);
/// Extract the value profile data from the \p Inst which is annotated with
/// value
/// profile meta data. Return false if there is no value data annotated,
/// otherwise
/// return true.
bool getValueProfDataFromInst(const Instruction &Inst,
InstrProfValueKind ValueKind,
uint32_t MaxNumValueData,
InstrProfValueData ValueData[],
uint32_t &ActualNumValueData, uint64_t &TotalC);
const std::error_category &instrprof_category();
enum class instrprof_error {
@ -227,11 +250,6 @@ inline instrprof_error MergeResult(instrprof_error &Accumulator,
return Accumulator;
}
enum InstrProfValueKind : uint32_t {
#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
#include "llvm/ProfileData/InstrProfData.inc"
};
namespace object {
class SectionRef;
}

View File

@ -17,6 +17,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorHandling.h"
@ -606,6 +607,92 @@ void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
sys::swapByteOrder<uint32_t>(NumValueKinds);
}
void annotateValueSite(Module &M, Instruction &Inst,
const InstrProfRecord &InstrProfR,
InstrProfValueKind ValueKind, uint32_t SiteIdx) {
uint32_t NV = InstrProfR.getNumValueDataForSite(ValueKind, SiteIdx);
uint64_t Sum = 0;
std::unique_ptr<InstrProfValueData[]> VD =
InstrProfR.getValueForSite(ValueKind, SiteIdx, &Sum);
LLVMContext &Ctx = M.getContext();
MDBuilder MDHelper(Ctx);
SmallVector<Metadata *, 3> Vals;
// Tag
Vals.push_back(MDHelper.createString("VP"));
// Value Kind
Vals.push_back(MDHelper.createConstant(
ConstantInt::get(Type::getInt32Ty(Ctx), ValueKind)));
// Total Count
Vals.push_back(
MDHelper.createConstant(ConstantInt::get(Type::getInt64Ty(Ctx), Sum)));
// Value Profile Data
uint32_t MDCount = 3;
for (uint32_t I = 0; I < NV; ++I) {
Vals.push_back(MDHelper.createConstant(
ConstantInt::get(Type::getInt64Ty(Ctx), VD[I].Value)));
Vals.push_back(MDHelper.createConstant(
ConstantInt::get(Type::getInt64Ty(Ctx), VD[I].Count)));
if (--MDCount == 0)
break;
}
Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals));
}
bool getValueProfDataFromInst(const Instruction &Inst,
InstrProfValueKind ValueKind,
uint32_t MaxNumValueData,
InstrProfValueData ValueData[],
uint32_t &ActualNumValueData, uint64_t &TotalC) {
MDNode *MD = Inst.getMetadata(LLVMContext::MD_prof);
if (!MD)
return false;
unsigned NOps = MD->getNumOperands();
if (NOps < 5)
return false;
// Operand 0 is a string tag "VP":
MDString *Tag = cast<MDString>(MD->getOperand(0));
if (!Tag)
return false;
if (!Tag->getString().equals("VP"))
return false;
// Now check kind:
ConstantInt *KindInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
if (!KindInt)
return false;
if (KindInt->getZExtValue() != ValueKind)
return false;
// Get total count
ConstantInt *TotalCInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
if (!TotalCInt)
return false;
TotalC = TotalCInt->getZExtValue();
ActualNumValueData = 0;
for (unsigned I = 3; I < NOps; I += 2) {
if (ActualNumValueData >= MaxNumValueData)
break;
ConstantInt *Value = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I));
ConstantInt *Count =
mdconst::dyn_extract<ConstantInt>(MD->getOperand(I + 1));
if (!Value || !Count)
return false;
ValueData[ActualNumValueData].Value = Value->getZExtValue();
ValueData[ActualNumValueData].Count = Count->getZExtValue();
ActualNumValueData++;
}
return true;
}
// The argument to this method is a vector of cutoff percentages and the return
// value is a vector of (Cutoff, MinBlockCount, NumBlocks) triplets.
void ProfileSummary::computeDetailedSummary() {

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/ProfileData/InstrProfReader.h"
@ -225,6 +226,60 @@ TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
}
TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
InstrProfRecord Record("caller", 0x1234, {1, 2});
Record.reserveSites(IPVK_IndirectCallTarget, 1);
InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}};
Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
Writer.addRecord(std::move(Record));
auto Profile = Writer.writeBuffer();
readProfile(std::move(Profile));
ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
ASSERT_TRUE(NoError(R.getError()));
LLVMContext Ctx;
std::unique_ptr<Module> M(new Module("MyModule", Ctx));
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
/*isVarArg=*/false);
Function *F =
Function::Create(FTy, Function::ExternalLinkage, "caller", M.get());
BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
IRBuilder<> Builder(BB);
BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
// Use branch instruction to annotate with value profile data for simplicity
Instruction *Inst = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
Instruction *Inst2 = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
annotateValueSite(*M.get(), *Inst, R.get(), IPVK_IndirectCallTarget, 0);
InstrProfValueData ValueData[5];
uint32_t N;
uint64_t T;
bool Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
ValueData, N, T);
ASSERT_TRUE(Res);
ASSERT_EQ(3U, N);
ASSERT_EQ(6U, T);
// The result should be sorted already:
ASSERT_EQ(3000U, ValueData[0].Value);
ASSERT_EQ(3U, ValueData[0].Count);
ASSERT_EQ(2000U, ValueData[1].Value);
ASSERT_EQ(2U, ValueData[1].Count);
ASSERT_EQ(1000U, ValueData[2].Value);
ASSERT_EQ(1U, ValueData[2].Count);
Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 1, ValueData,
N, T);
ASSERT_TRUE(Res);
ASSERT_EQ(1U, N);
ASSERT_EQ(6U, T);
Res = getValueProfDataFromInst(*Inst2, IPVK_IndirectCallTarget, 5, ValueData,
N, T);
ASSERT_FALSE(Res);
}
TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
InstrProfRecord Record1("caller", 0x1234, {1, 2});
InstrProfRecord Record2("callee1", 0x1235, {3, 4});