[llvm] 98c1ba4 - [InstrProf] Add vtables with type metadata into symtab (#81051)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 9 10:41:26 PDT 2024
Author: Mingming Liu
Date: 2024-05-09T10:41:23-07:00
New Revision: 98c1ba460a697110c64f6d1dd362dcf7088a13ca
URL: https://github.com/llvm/llvm-project/commit/98c1ba460a697110c64f6d1dd362dcf7088a13ca
DIFF: https://github.com/llvm/llvm-project/commit/98c1ba460a697110c64f6d1dd362dcf7088a13ca.diff
LOG: [InstrProf] Add vtables with type metadata into symtab (#81051)
The indirect-call-promotion pass will look up the vtable to find out
the virtual function [1],
and add vtable-derived information in icall
candidate [2] for cost-benefit analysis.
[1] https://github.com/llvm/llvm-project/pull/81442/files#diff-a95d1ac8a0da69713fcb3346135d4b219f0a73920318d2549495620ea215191bR395-R416
[2] https://github.com/llvm/llvm-project/pull/81442/files#diff-a95d1ac8a0da69713fcb3346135d4b219f0a73920318d2549495620ea215191bR195-R199
Added:
Modified:
llvm/include/llvm/ProfileData/InstrProf.h
llvm/lib/ProfileData/InstrProf.cpp
llvm/unittests/ProfileData/InstrProfTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index d5c1ba62911f7..88c7fe425b5a5 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -470,6 +471,12 @@ class InstrProfSymtab {
// A map from MD5 keys to function define. We only populate this map
// when build the Symtab from a Module.
std::vector<std::pair<uint64_t, Function *>> MD5FuncMap;
+ // A map from MD5 to the global variable. This map is only populated when
+ // building the symtab from a module. Use separate container instances for
+ // `MD5FuncMap` and `MD5VTableMap`.
+ // TODO: Unify the container type and the lambda function 'mapName' inside
+ // add{Func,VTable}WithName.
+ DenseMap<uint64_t, GlobalVariable *> MD5VTableMap;
// A map from function runtime address to function name MD5 hash.
// This map is only populated and used by raw instr profile reader.
AddrHashMap AddrToMD5Map;
@@ -488,12 +495,18 @@ class InstrProfSymtab {
// Add the function into the symbol table, by creating the following
// map entries:
- // name-set = {PGOFuncName} + {getCanonicalName(PGOFuncName)} if the canonical
- // name is
diff erent from pgo name
+ // name-set = {PGOFuncName} union {getCanonicalName(PGOFuncName)}
// - In MD5NameMap: <MD5Hash(name), name> for name in name-set
// - In MD5FuncMap: <MD5Hash(name), &F> for name in name-set
Error addFuncWithName(Function &F, StringRef PGOFuncName);
+ // Add the vtable into the symbol table, by creating the following
+ // map entries:
+ // name-set = {PGOName} union {getCanonicalName(PGOName)}
+ // - In MD5NameMap: <MD5Hash(name), name> for name in name-set
+ // - In MD5VTableMap: <MD5Hash(name), name> for name in name-set
+ Error addVTableWithName(GlobalVariable &V, StringRef PGOVTableName);
+
// If the symtab is created by a series of calls to \c addFuncName, \c
// finalizeSymtab needs to be called before looking up function names.
// This is required because the underlying map is a vector (for space
@@ -555,6 +568,7 @@ class InstrProfSymtab {
Error create(const FuncNameIterRange &FuncIterRange,
const VTableNameIterRange &VTableIterRange);
+ // Map the MD5 of the symbol name to the name.
Error addSymbolName(StringRef SymbolName) {
if (SymbolName.empty())
return make_error<InstrProfError>(instrprof_error::malformed,
@@ -630,6 +644,10 @@ class InstrProfSymtab {
/// Return function from the name's md5 hash. Return nullptr if not found.
inline Function *getFunction(uint64_t FuncMD5Hash);
+ /// Return the global variable corresponding to md5 hash. Return nullptr if
+ /// not found.
+ inline GlobalVariable *getGlobalVariable(uint64_t MD5Hash);
+
/// Return the name section data.
inline StringRef getNameData() const { return Data; }
@@ -709,6 +727,12 @@ Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
return nullptr;
}
+GlobalVariable *InstrProfSymtab::getGlobalVariable(uint64_t MD5Hash) {
+ if (auto Iter = MD5VTableMap.find(MD5Hash); Iter != MD5VTableMap.end())
+ return Iter->second;
+ return nullptr;
+}
+
// To store the sums of profile count values, or the percentage of
// the sums of the total count values.
struct CountSumOrPercent {
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 1e3ca47b3d5aa..806d01de1ada5 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -476,11 +476,43 @@ Error InstrProfSymtab::create(Module &M, bool InLTO) {
return E;
}
+ SmallVector<MDNode *, 2> Types;
+ for (GlobalVariable &G : M.globals()) {
+ if (!G.hasName() || !G.hasMetadata(LLVMContext::MD_type))
+ continue;
+ if (Error E = addVTableWithName(
+ G, getIRPGOObjectName(G, InLTO, /* PGONameMetadata */ nullptr)))
+ return E;
+ }
+
Sorted = false;
finalizeSymtab();
return Error::success();
}
+Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
+ StringRef VTablePGOName) {
+ auto mapName = [&](StringRef Name) -> Error {
+ if (Error E = addSymbolName(Name))
+ return E;
+
+ bool Inserted = true;
+ std::tie(std::ignore, Inserted) =
+ MD5VTableMap.try_emplace(GlobalValue::getGUID(Name), &VTable);
+ if (!Inserted)
+ LLVM_DEBUG(dbgs() << "GUID conflict within one module");
+ return Error::success();
+ };
+ if (Error E = mapName(VTablePGOName))
+ return E;
+
+ StringRef CanonicalName = getCanonicalName(VTablePGOName);
+ if (CanonicalName != VTablePGOName)
+ return mapName(CanonicalName);
+
+ return Error::success();
+}
+
/// \c NameStrings is a string composed of one of more possibly encoded
/// sub-strings. The substrings are separated by 0 or more zero bytes. This
/// method decodes the string and calls `NameCallback` for each substring.
diff --git a/llvm/unittests/ProfileData/InstrProfTest.cpp b/llvm/unittests/ProfileData/InstrProfTest.cpp
index 402de64fe99bb..8f2c5aee1819d 100644
--- a/llvm/unittests/ProfileData/InstrProfTest.cpp
+++ b/llvm/unittests/ProfileData/InstrProfTest.cpp
@@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
@@ -1730,6 +1732,34 @@ TEST(SymtabTest, instr_prof_symtab_module_test) {
Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get());
Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
+ // [ptr, ptr, ptr]
+ ArrayType *VTableArrayType = ArrayType::get(
+ PointerType::get(Ctx, M->getDataLayout().getDefaultGlobalsAddressSpace()),
+ 3);
+ Constant *Int32TyNull =
+ llvm::ConstantExpr::getNullValue(PointerType::getUnqual(Ctx));
+ SmallVector<llvm::Type *, 1> tys = {VTableArrayType};
+ StructType *VTableType = llvm::StructType::get(Ctx, tys);
+
+ // Create two vtables in the module, one with external linkage and the other
+ // with local linkage.
+ for (auto [Name, Linkage] :
+ {std::pair{"ExternalGV", GlobalValue::ExternalLinkage},
+ {"LocalGV", GlobalValue::InternalLinkage}}) {
+ llvm::Twine FuncName(Name, StringRef("VFunc"));
+ Function *VFunc = Function::Create(FTy, Linkage, FuncName, M.get());
+ GlobalVariable *GV = new llvm::GlobalVariable(
+ *M, VTableType, /* isConstant= */ true, Linkage,
+ llvm::ConstantStruct::get(
+ VTableType,
+ {llvm::ConstantArray::get(VTableArrayType,
+ {Int32TyNull, Int32TyNull, VFunc})}),
+ Name);
+ // Add type metadata for the test data, since vtables with type metadata
+ // are added to symtab.
+ GV->addTypeMetadata(16, MDString::get(Ctx, Name));
+ }
+
InstrProfSymtab ProfSymtab;
EXPECT_THAT_ERROR(ProfSymtab.create(*M), Succeeded());
@@ -1751,6 +1781,23 @@ TEST(SymtabTest, instr_prof_symtab_module_test) {
EXPECT_EQ(PGOName, PGOFuncName);
EXPECT_THAT(PGOFuncName.str(), EndsWith(Funcs[I].str()));
}
+
+ StringRef VTables[] = {"ExternalGV", "LocalGV"};
+ for (auto [VTableName, PGOName] : {std::pair{"ExternalGV", "ExternalGV"},
+ {"LocalGV", "MyModule.cpp;LocalGV"}}) {
+ GlobalVariable *GV =
+ M->getGlobalVariable(VTableName, /* AllowInternal=*/true);
+
+ // Test that ProfSymtab returns the expected name given a hash.
+ std::string IRPGOName = getPGOName(*GV);
+ EXPECT_STREQ(IRPGOName.c_str(), PGOName);
+ uint64_t GUID = IndexedInstrProf::ComputeHash(IRPGOName);
+ EXPECT_EQ(IRPGOName, ProfSymtab.getFuncOrVarName(GUID));
+ EXPECT_EQ(VTableName, getParsedIRPGOName(IRPGOName).second);
+
+ // Test that ProfSymtab returns the expected global variable
+ EXPECT_EQ(GV, ProfSymtab.getGlobalVariable(GUID));
+ }
}
// Testing symtab serialization and creator/deserialization interface
More information about the llvm-commits
mailing list