[llvm] r259813 - [PGO] Add interfaces to annotate instr with VP data

Xinliang David Li via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 4 11:11:43 PST 2016


Author: davidxl
Date: Thu Feb  4 13:11:43 2016
New Revision: 259813

URL: http://llvm.org/viewvc/llvm-project?rev=259813&view=rev
Log:
[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.




Modified:
    llvm/trunk/include/llvm/ProfileData/InstrProf.h
    llvm/trunk/lib/ProfileData/InstrProf.cpp
    llvm/trunk/unittests/ProfileData/InstrProfTest.cpp

Modified: llvm/trunk/include/llvm/ProfileData/InstrProf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=259813&r1=259812&r2=259813&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/InstrProf.h (original)
+++ llvm/trunk/include/llvm/ProfileData/InstrProf.h Thu Feb  4 13:11:43 2016
@@ -178,8 +178,8 @@ StringRef getFuncNameWithoutPrefix(Strin
 /// 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(instr
   return Accumulator;
 }
 
-enum InstrProfValueKind : uint32_t {
-#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
-#include "llvm/ProfileData/InstrProfData.inc"
-};
-
 namespace object {
 class SectionRef;
 }

Modified: llvm/trunk/lib/ProfileData/InstrProf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProf.cpp?rev=259813&r1=259812&r2=259813&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/InstrProf.cpp (original)
+++ llvm/trunk/lib/ProfileData/InstrProf.cpp Thu Feb  4 13:11:43 2016
@@ -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(su
   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() {

Modified: llvm/trunk/unittests/ProfileData/InstrProfTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/InstrProfTest.cpp?rev=259813&r1=259812&r2=259813&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/InstrProfTest.cpp (original)
+++ llvm/trunk/unittests/ProfileData/InstrProfTest.cpp Thu Feb  4 13:11:43 2016
@@ -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_ica
   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});




More information about the llvm-commits mailing list