Files
clang-r547379/include/llvm/Analysis/CtxProfAnalysis.h
Ryan Prichard 6024e5c395 Update prebuilt Clang to r547379 (20.0.0).
clang 20.0.0 (based on r547379) from build 12806354.

Bug: http://b/379133546
Test: N/A
Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b

Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
2025-11-26 14:59:46 -05:00

140 lines
4.8 KiB
C++

//===- CtxProfAnalysis.h - maintain contextual profile info -*- C++ ---*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
#ifndef LLVM_ANALYSIS_CTXPROFANALYSIS_H
#define LLVM_ANALYSIS_CTXPROFANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PassManager.h"
#include "llvm/ProfileData/PGOCtxProfReader.h"
namespace llvm {
class CtxProfAnalysis;
// Setting initial capacity to 1 because all contexts must have at least 1
// counter, and then, because all contexts belonging to a function have the same
// size, there'll be at most one other heap allocation.
using CtxProfFlatProfile =
DenseMap<GlobalValue::GUID, SmallVector<uint64_t, 1>>;
/// The instrumented contextual profile, produced by the CtxProfAnalysis.
class PGOContextualProfile {
friend class CtxProfAnalysis;
friend class CtxProfAnalysisPrinterPass;
struct FunctionInfo {
uint32_t NextCounterIndex = 0;
uint32_t NextCallsiteIndex = 0;
const std::string Name;
FunctionInfo(StringRef Name) : Name(Name) {}
};
std::optional<PGOCtxProfContext::CallTargetMapTy> Profiles;
// For the GUIDs in this module, associate metadata about each function which
// we'll need when we maintain the profiles during IPO transformations.
DenseMap<GlobalValue::GUID, FunctionInfo> FuncInfo;
/// Get the GUID of this Function if it's defined in this module.
GlobalValue::GUID getDefinedFunctionGUID(const Function &F) const;
// This is meant to be constructed from CtxProfAnalysis, which will also set
// its state piecemeal.
PGOContextualProfile() = default;
public:
PGOContextualProfile(const PGOContextualProfile &) = delete;
PGOContextualProfile(PGOContextualProfile &&) = default;
operator bool() const { return Profiles.has_value(); }
const PGOCtxProfContext::CallTargetMapTy &profiles() const {
return *Profiles;
}
bool isFunctionKnown(const Function &F) const {
return getDefinedFunctionGUID(F) != 0;
}
uint32_t allocateNextCounterIndex(const Function &F) {
assert(isFunctionKnown(F));
return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex++;
}
uint32_t allocateNextCallsiteIndex(const Function &F) {
assert(isFunctionKnown(F));
return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex++;
}
const CtxProfFlatProfile flatten() const;
bool invalidate(Module &, const PreservedAnalyses &PA,
ModuleAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise,
// it's stateless and remains preserved.
auto PAC = PA.getChecker<CtxProfAnalysis>();
return !PAC.preservedWhenStateless();
}
};
class CtxProfAnalysis : public AnalysisInfoMixin<CtxProfAnalysis> {
StringRef Profile;
public:
static AnalysisKey Key;
explicit CtxProfAnalysis(StringRef Profile = "");
using Result = PGOContextualProfile;
PGOContextualProfile run(Module &M, ModuleAnalysisManager &MAM);
/// Get the instruction instrumenting a callsite, or nullptr if that cannot be
/// found.
static InstrProfCallsite *getCallsiteInstrumentation(CallBase &CB);
/// Get the instruction instrumenting a BB, or nullptr if not present.
static InstrProfIncrementInst *getBBInstrumentation(BasicBlock &BB);
};
class CtxProfAnalysisPrinterPass
: public PassInfoMixin<CtxProfAnalysisPrinterPass> {
raw_ostream &OS;
public:
explicit CtxProfAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
static bool isRequired() { return true; }
};
/// Assign a GUID to functions as metadata. GUID calculation takes linkage into
/// account, which may change especially through and after thinlto. By
/// pre-computing and assigning as metadata, this mechanism is resilient to such
/// changes (as well as name changes e.g. suffix ".llvm." additions).
// FIXME(mtrofin): we can generalize this mechanism to calculate a GUID early in
// the pass pipeline, associate it with any Global Value, and then use it for
// PGO and ThinLTO.
// At that point, this should be moved elsewhere.
class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
public:
explicit AssignGUIDPass() = default;
/// Assign a GUID *if* one is not already assign, as a function metadata named
/// `GUIDMetadataName`.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
static const char *GUIDMetadataName;
// This should become GlobalValue::getGUID
static uint64_t getGUID(const Function &F);
};
} // namespace llvm
#endif // LLVM_ANALYSIS_CTXPROFANALYSIS_H