Files
gps/tools/local/circt/include/llvm/Object/BBAddrMap.h
T
2026-07-12 11:01:51 +03:00

290 lines
10 KiB
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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares common types and utilities for basic-block address maps.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_BBADDRMAP_H
#define LLVM_OBJECT_BBADDRMAP_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/UniqueBBID.h"
namespace llvm {
namespace object {
// Struct representing the BBAddrMap for one function.
struct BBAddrMap {
// Bitfield of optional features to control the extra information
// emitted/encoded in the section. The feature list lives in BBAddrMap.def.
struct Features {
enum {
#define HANDLE_BB_ADDR_MAP_FEATURE(Name) Name##Bit,
#include "llvm/Object/BBAddrMap.def"
NumBits,
};
static_assert(NumBits <= 16,
"BBAddrMap::Features is encoded as a uint16_t");
#define HANDLE_BB_ADDR_MAP_FEATURE(Name) bool Name : 1;
#include "llvm/Object/BBAddrMap.def"
static constexpr uint16_t KnownMask =
(static_cast<uint16_t>(1) << NumBits) - 1;
bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; }
bool hasPGOAnalysisBBData() const { return BBFreq || BrProb; }
// Encodes to minimum bit width representation.
uint16_t encode() const {
uint16_t V = 0;
#define HANDLE_BB_ADDR_MAP_FEATURE(Name) \
V |= static_cast<uint16_t>(Name) << Name##Bit;
#include "llvm/Object/BBAddrMap.def"
return V;
}
// Decodes from minimum bit width representation and validates no
// unnecessary bits are used.
static Expected<Features> decode(uint16_t Val) {
Features Feat{
#define HANDLE_BB_ADDR_MAP_FEATURE(Name) \
static_cast<bool>(Val & (uint16_t{1} << Name##Bit)),
#include "llvm/Object/BBAddrMap.def"
};
if (Feat.encode() != Val)
return createStringError(
"invalid encoding for BBAddrMap::Features: 0x%x", Val);
return Feat;
}
bool operator==(const Features &Other) const {
return encode() == Other.encode();
}
};
// Struct representing the BBAddrMap information for one basic block.
struct BBEntry {
struct Metadata {
enum {
#define HANDLE_BB_ADDR_MAP_BB_METADATA(Name) Name##Bit,
#include "llvm/Object/BBAddrMap.def"
NumBits,
};
static_assert(NumBits <= 32,
"BBAddrMap::BBEntry::Metadata is encoded as a uint32_t");
#define HANDLE_BB_ADDR_MAP_BB_METADATA(Name) bool Name : 1;
#include "llvm/Object/BBAddrMap.def"
bool operator==(const Metadata &Other) const {
return encode() == Other.encode();
}
// Encodes this struct as a uint32_t value.
uint32_t encode() const {
uint32_t V = 0;
#define HANDLE_BB_ADDR_MAP_BB_METADATA(Name) \
V |= static_cast<uint32_t>(Name) << Name##Bit;
#include "llvm/Object/BBAddrMap.def"
return V;
}
// Decodes and returns a Metadata struct from a uint32_t value.
static Expected<Metadata> decode(uint32_t V) {
Metadata MD{
#define HANDLE_BB_ADDR_MAP_BB_METADATA(Name) \
static_cast<bool>(V & (uint32_t{1} << Name##Bit)),
#include "llvm/Object/BBAddrMap.def"
};
if (MD.encode() != V)
return createStringError(
"invalid encoding for BBEntry::Metadata: 0x%x", V);
return MD;
}
};
uint32_t ID = 0; // Unique ID of this basic block.
uint32_t Offset = 0; // Offset of basic block relative to the base address.
uint32_t Size = 0; // Size of the basic block.
Metadata MD = {false, false, false, false,
false}; // Metadata for this basic block.
// Offsets of end of call instructions, relative to the basic block start.
SmallVector<uint32_t, 1> CallsiteEndOffsets;
uint64_t Hash = 0; // Hash for this basic block.
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD,
SmallVector<uint32_t, 1> CallsiteEndOffsets, uint64_t Hash)
: ID(ID), Offset(Offset), Size(Size), MD(MD),
CallsiteEndOffsets(std::move(CallsiteEndOffsets)), Hash(Hash) {}
UniqueBBID getID() const { return {ID, 0}; }
bool operator==(const BBEntry &Other) const {
return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
MD == Other.MD && CallsiteEndOffsets == Other.CallsiteEndOffsets &&
Hash == Other.Hash;
}
bool hasReturn() const { return MD.HasReturn; }
bool hasTailCall() const { return MD.HasTailCall; }
bool isEHPad() const { return MD.IsEHPad; }
bool canFallThrough() const { return MD.CanFallThrough; }
bool hasIndirectBranch() const { return MD.HasIndirectBranch; }
};
// Struct representing the BBAddrMap information for a contiguous range of
// basic blocks (a function or a basic block section).
struct BBRangeEntry {
uint64_t BaseAddress = 0; // Base address of the range.
std::vector<BBEntry> BBEntries; // Basic block entries for this range.
// Equality operator for unit testing.
bool operator==(const BBRangeEntry &Other) const {
return BaseAddress == Other.BaseAddress && BBEntries == Other.BBEntries;
}
};
// All ranges for this function. Cannot be empty. The first range always
// corresponds to the function entry.
std::vector<BBRangeEntry> BBRanges;
// Returns the function address associated with this BBAddrMap, which is
// stored as the `BaseAddress` of its first BBRangeEntry.
uint64_t getFunctionAddress() const {
assert(!BBRanges.empty());
return BBRanges.front().BaseAddress;
}
// Returns the total number of bb entries in all bb ranges.
size_t getNumBBEntries() const {
size_t NumBBEntries = 0;
for (const auto &BBR : BBRanges)
NumBBEntries += BBR.BBEntries.size();
return NumBBEntries;
}
// Returns the index of the bb range with the given base address, or
// `std::nullopt` if no such range exists.
std::optional<size_t>
getBBRangeIndexForBaseAddress(uint64_t BaseAddress) const {
for (size_t I = 0; I < BBRanges.size(); ++I)
if (BBRanges[I].BaseAddress == BaseAddress)
return I;
return {};
}
// Returns bb entries in the first range.
const std::vector<BBEntry> &getBBEntries() const {
return BBRanges.front().BBEntries;
}
const std::vector<BBRangeEntry> &getBBRanges() const { return BBRanges; }
// Equality operator for unit testing.
bool operator==(const BBAddrMap &Other) const {
return BBRanges == Other.BBRanges;
}
};
/// A feature extension of BBAddrMap that holds information relevant to PGO.
struct PGOAnalysisMap {
/// Extra basic block data with fields for block frequency and branch
/// probability.
struct PGOBBEntry {
/// Single successor of a given basic block that contains the tag and branch
/// probability associated with it.
struct SuccessorEntry {
/// Unique ID of this successor basic block.
uint32_t ID = 0;
/// Branch Probability of the edge to this successor taken from MBPI.
BranchProbability Prob;
/// Raw edge count from the post link profile (e.g., from bolt or
/// propeller).
uint64_t PostLinkFreq = 0;
bool operator==(const SuccessorEntry &Other) const {
return std::tie(ID, Prob, PostLinkFreq) ==
std::tie(Other.ID, Other.Prob, Other.PostLinkFreq);
}
};
/// Block frequency taken from MBFI
BlockFrequency BlockFreq;
/// Raw block count taken from the post link profile (e.g., from bolt or
/// propeller).
uint64_t PostLinkBlockFreq = 0;
/// List of successors of the current block
llvm::SmallVector<SuccessorEntry, 2> Successors;
bool operator==(const PGOBBEntry &Other) const {
return std::tie(BlockFreq, PostLinkBlockFreq, Successors) ==
std::tie(Other.BlockFreq, Other.PostLinkBlockFreq,
Other.Successors);
}
};
uint64_t FuncEntryCount; // Prof count from IR function
std::vector<PGOBBEntry> BBEntries; // Extended basic block entries
// Flags to indicate if each PGO related info was enabled in this function
BBAddrMap::Features FeatEnable;
bool operator==(const PGOAnalysisMap &Other) const {
return std::tie(FuncEntryCount, BBEntries, FeatEnable) ==
std::tie(Other.FuncEntryCount, Other.BBEntries, Other.FeatEnable);
}
};
/// Extracts addresses from a data stream.
/// The base implementation reads the address directly.
/// Subclasses can override to handle format-specific details such as relocation
/// resolution.
class AddressExtractor {
const DataExtractor &Data;
unsigned AddressSize;
public:
AddressExtractor(const DataExtractor &Data, unsigned AddressSize)
: Data(Data), AddressSize(AddressSize) {}
virtual ~AddressExtractor() = default;
const DataExtractor &getDataExtractor() const { return Data; }
/// Extract and resolve an address at the current \p Cur position.
virtual Expected<uint64_t> extractAddress(DataExtractor::Cursor &Cur) {
uint64_t Address = Data.getUnsigned(Cur, AddressSize);
if (!Cur)
return Cur.takeError();
return Address;
}
};
/// Decodes one BB address map section payload.
///
/// \p Extractor provides address extraction and the underlying DataExtractor.
/// \p PGOAnalyses if non-null, receives the decoded PGO analysis data. On
/// error, \p PGOAnalyses may be partially populated.
LLVM_ABI Expected<std::vector<BBAddrMap>>
decodeBBAddrMapPayload(AddressExtractor &Extractor,
std::vector<PGOAnalysisMap> *PGOAnalyses = nullptr);
} // end namespace object.
} // end namespace llvm.
#endif // LLVM_OBJECT_BBADDRMAP_H