aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authormingmingl <mingmingl@google.com>2025-08-30 20:34:28 -0700
committermingmingl <mingmingl@google.com>2025-09-13 22:26:24 -0700
commitd4e4d958ce165b82f4da2b509bec5a7e4aaec756 (patch)
treed9caa5e5f0864a28c0c8e74adaea215b66cbe0cb /llvm/lib
parent4a7ba1de7100e15d7fb444c0b9868977b16b5494 (diff)
downloadllvm-users/mingmingl-llvm/annotator.zip
llvm-users/mingmingl-llvm/annotator.tar.gz
llvm-users/mingmingl-llvm/annotator.tar.bz2
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/StaticDataProfileInfo.cpp98
-rw-r--r--llvm/lib/CodeGen/StaticDataAnnotator.cpp8
-rw-r--r--llvm/lib/IR/Globals.cpp17
-rw-r--r--llvm/lib/ProfileData/DataAccessProf.cpp4
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemProfUse.cpp11
5 files changed, 90 insertions, 48 deletions
diff --git a/llvm/lib/Analysis/StaticDataProfileInfo.cpp b/llvm/lib/Analysis/StaticDataProfileInfo.cpp
index b7ca654..05b1adf 100644
--- a/llvm/lib/Analysis/StaticDataProfileInfo.cpp
+++ b/llvm/lib/Analysis/StaticDataProfileInfo.cpp
@@ -1,11 +1,17 @@
#include "llvm/Analysis/StaticDataProfileInfo.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/ProfileData/InstrProf.h"
using namespace llvm;
+
+extern cl::opt<bool> AnnotateStaticDataSectionPrefix;
+
void StaticDataProfileInfo::addConstantProfileCount(
const Constant *C, std::optional<uint64_t> Count) {
if (!Count) {
@@ -28,65 +34,79 @@ StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
return I->second;
}
-std::optional<StringRef>
-StaticDataProfileInfo::getDataHotnessBasedOnProfileCount(
- const Constant *C, const ProfileSummaryInfo *PSI) const {
- auto Count = getConstantProfileCount(C);
- // The constant `C` doesn't have a profile count. `C` might be a external
- // linkage global variable, whose PGO-based counter is not tracked within one
- // IR module.
- if (!Count)
- return std::nullopt;
+StaticDataProfileInfo::StaticDataHotness
+StaticDataProfileInfo::getSectionHotnessUsingProfileCount(
+ const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const {
// The accummulated counter shows the constant is hot. Return 'hot' whether
// this variable is seen by unprofiled functions or not.
- if (PSI->isHotCount(*Count))
- return "hot";
+ if (PSI->isHotCount(Count))
+ return StaticDataHotness::Hot;
// The constant is not hot, and seen by unprofiled functions. We don't want to
// assign it to unlikely sections, even if the counter says 'cold'. So return
// an empty prefix before checking whether the counter is cold.
if (ConstantWithoutCounts.count(C))
- return std::nullopt;
+ return StaticDataHotness::LukewarmOrUnknown;
// The accummulated counter shows the constant is cold. Return 'unlikely'.
- if (PSI->isColdCount(*Count)) {
- return "unlikely";
- }
- return "";
-}
+ if (PSI->isColdCount(Count))
+ return StaticDataHotness::Cold;
-static StringRef reconcileHotness(StringRef SectionPrefix, StringRef Hotness) {
- assert((SectionPrefix == "hot" || SectionPrefix == "unlikely") &&
- "Section prefix must be 'hot' or 'unlikely'");
+ return StaticDataHotness::LukewarmOrUnknown;
+}
- if (SectionPrefix == "hot" || Hotness == "hot")
+StringRef StaticDataProfileInfo::hotnessToStr(
+ StaticDataProfileInfo::StaticDataHotness Hotness) const {
+ switch (Hotness) {
+ case StaticDataProfileInfo::StaticDataHotness::Cold:
+ return "unlikely";
+ case StaticDataProfileInfo::StaticDataHotness::Hot:
return "hot";
- assert(SectionPrefix == "unlikely" && "Section prefix must be 'unlikely'.");
- return Hotness;
+ default:
+ return "";
+ }
}
-static StringRef
-reconcileOptionalHotness(std::optional<StringRef> SectionPrefix,
- std::optional<StringRef> Hotness) {
- if (!SectionPrefix)
- return Hotness.value_or("");
- if (!Hotness)
- return SectionPrefix.value_or("");
-
- return reconcileHotness(*SectionPrefix, *Hotness);
+StaticDataProfileInfo::StaticDataHotness
+StaticDataProfileInfo::getSectionHotnessUsingDAP(
+ std::optional<StringRef> MaybeSectionPrefix) const {
+ if (!MaybeSectionPrefix)
+ return StaticDataProfileInfo::StaticDataHotness::LukewarmOrUnknown;
+ StringRef Prefix = *MaybeSectionPrefix;
+ assert((Prefix == "hot" || Prefix == "unlikely") &&
+ "Expect section_prefix to be one of hot or unlikely");
+ return Prefix == "hot" ? StaticDataProfileInfo::StaticDataHotness::Hot
+ : StaticDataProfileInfo::StaticDataHotness::Cold;
}
StringRef StaticDataProfileInfo::getConstantSectionPrefix(
const Constant *C, const ProfileSummaryInfo *PSI) const {
- std::optional<StringRef> HotnessBasedOnCount =
- getDataHotnessBasedOnProfileCount(C, PSI);
- if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
- return reconcileOptionalHotness(GV->getSectionPrefix(),
- HotnessBasedOnCount);
+ auto Count = getConstantProfileCount(C);
- return HotnessBasedOnCount.value_or("");
+ if (HasDataAccessProf) {
+ // Module flag `HasDataAccessProf` is 1 -> empty section prefix means uknown
+ // hotness except for string literals.
+ if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C);
+ GV && !GV->getName().starts_with(".str")) {
+ auto HotnessFromDAP = getSectionHotnessUsingDAP(GV->getSectionPrefix());
+
+ if (!Count)
+ return hotnessToStr(HotnessFromDAP);
+
+ auto HotnessFromPGO = getSectionHotnessUsingProfileCount(C, PSI, *Count);
+ return hotnessToStr(std::max(HotnessFromDAP, HotnessFromPGO));
+ }
+ }
+
+ if (!Count)
+ return "";
+ return hotnessToStr(getSectionHotnessUsingProfileCount(C, PSI, *Count));
}
bool StaticDataProfileInfoWrapperPass::doInitialization(Module &M) {
- Info.reset(new StaticDataProfileInfo());
+ bool HasDataAccessProf = false;
+ if (auto *MD = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("HasDataAccessProf")))
+ HasDataAccessProf = MD->getZExtValue();
+ Info.reset(new StaticDataProfileInfo(HasDataAccessProf));
return false;
}
diff --git a/llvm/lib/CodeGen/StaticDataAnnotator.cpp b/llvm/lib/CodeGen/StaticDataAnnotator.cpp
index fdf48e1..72735d2 100644
--- a/llvm/lib/CodeGen/StaticDataAnnotator.cpp
+++ b/llvm/lib/CodeGen/StaticDataAnnotator.cpp
@@ -31,6 +31,8 @@
#include "llvm/Analysis/StaticDataProfileInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Analysis.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/InitializePasses.h"
@@ -79,11 +81,7 @@ bool StaticDataAnnotator::runOnModule(Module &M) {
continue;
StringRef SectionPrefix = SDPI->getConstantSectionPrefix(&GV, PSI);
- if (SectionPrefix.empty())
- continue;
-
- GV.setSectionPrefix(SectionPrefix);
- Changed = true;
+ Changed |= GV.updateSectionPrefix(SectionPrefix);
}
return Changed;
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 11d33e2..0731fcb 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -289,11 +289,28 @@ void GlobalObject::setSection(StringRef S) {
}
void GlobalObject::setSectionPrefix(StringRef Prefix) {
+ if (Prefix.empty()) {
+ setMetadata(LLVMContext::MD_section_prefix, nullptr);
+ return;
+ }
MDBuilder MDB(getContext());
setMetadata(LLVMContext::MD_section_prefix,
MDB.createGlobalObjectSectionPrefix(Prefix));
}
+bool GlobalObject::updateSectionPrefix(StringRef Prefix) {
+ auto MD = getMetadata(LLVMContext::MD_section_prefix);
+ StringRef ExistingPrefix; // Empty by default.
+ if (MD != nullptr)
+ ExistingPrefix = cast<MDString>(MD->getOperand(1))->getString();
+
+ if (ExistingPrefix != Prefix) {
+ setSectionPrefix(Prefix);
+ return true;
+ }
+ return false;
+}
+
std::optional<StringRef> GlobalObject::getSectionPrefix() const {
if (MDNode *MD = getMetadata(LLVMContext::MD_section_prefix)) {
[[maybe_unused]] StringRef MDName =
diff --git a/llvm/lib/ProfileData/DataAccessProf.cpp b/llvm/lib/ProfileData/DataAccessProf.cpp
index a1e686b..d16d0b6f 100644
--- a/llvm/lib/ProfileData/DataAccessProf.cpp
+++ b/llvm/lib/ProfileData/DataAccessProf.cpp
@@ -1,6 +1,7 @@
#include "llvm/ProfileData/DataAccessProf.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Errc.h"
@@ -9,6 +10,9 @@
#include "llvm/Support/raw_ostream.h"
namespace llvm {
+cl::opt<bool> AnnotateStaticDataSectionPrefix(
+ "memprof-annotate-static-data-prefix", cl::init(false), cl::Hidden,
+ cl::desc("If true, annotate the static data section prefix"));
namespace memprof {
// If `Map` has an entry keyed by `Str`, returns the entry iterator. Otherwise,
diff --git a/llvm/lib/Transforms/Instrumentation/MemProfUse.cpp b/llvm/lib/Transforms/Instrumentation/MemProfUse.cpp
index ecb2f2d..789396c 100644
--- a/llvm/lib/Transforms/Instrumentation/MemProfUse.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemProfUse.cpp
@@ -41,6 +41,7 @@ using namespace llvm::memprof;
#define DEBUG_TYPE "memprof"
namespace llvm {
+extern cl::opt<bool> AnnotateStaticDataSectionPrefix;
extern cl::opt<bool> PGOWarnMissing;
extern cl::opt<bool> NoPGOWarnMismatch;
extern cl::opt<bool> NoPGOWarnMismatchComdatWeak;
@@ -76,10 +77,6 @@ static cl::opt<unsigned> MinMatchedColdBytePercent(
"memprof-matching-cold-threshold", cl::init(100), cl::Hidden,
cl::desc("Min percent of cold bytes matched to hint allocation cold"));
-static cl::opt<bool> AnnotateStaticDataSectionPrefix(
- "memprof-annotate-static-data-prefix", cl::init(false), cl::Hidden,
- cl::desc("If true, annotate the static data section prefix"));
-
// Matching statistics
STATISTIC(NumOfMemProfMissing, "Number of functions without memory profile.");
STATISTIC(NumOfMemProfMismatch,
@@ -797,7 +794,11 @@ bool MemProfUsePass::annotateGlobalVariables(
if (!AnnotateStaticDataSectionPrefix || M.globals().empty())
return false;
+ // The module flag helps codegen passes interpret empty section prefix:
+ // - 0 : empty section prefix is expected for each GV.
+ // - 1 : empty section prefix means the GV has unknown hotness.
if (!DataAccessProf) {
+ M.addModuleFlag(Module::Warning, "HasDataAccessProf", 0U);
M.getContext().diagnose(DiagnosticInfoPGOProfile(
MemoryProfileFileName.data(),
StringRef("Data access profiles not found in memprof. Ignore "
@@ -806,6 +807,8 @@ bool MemProfUsePass::annotateGlobalVariables(
return false;
}
+ M.addModuleFlag(Module::Warning, "HasDataAccessProf", 1);
+
bool Changed = false;
// Iterate all global variables in the module and annotate them based on
// data access profiles. Note it's up to the linker to decide how to map input