[llvm] 6015a04 - [Propeller] Use Fixed MBB ID instead of volatile MachineBasicBlock::Number.
Rahman Lavaee via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 6 22:50:14 PST 2022
Author: Rahman Lavaee
Date: 2022-12-06T22:50:09-08:00
New Revision: 6015a045d768feab3bae9ad9c0c81e118df8b04a
URL: https://github.com/llvm/llvm-project/commit/6015a045d768feab3bae9ad9c0c81e118df8b04a
DIFF: https://github.com/llvm/llvm-project/commit/6015a045d768feab3bae9ad9c0c81e118df8b04a.diff
LOG: [Propeller] Use Fixed MBB ID instead of volatile MachineBasicBlock::Number.
Let Propeller use specialized IDs for basic blocks, instead of MBB number.
This allows optimizations not just prior to asm-printer, but throughout the entire codegen.
This patch only implements the functionality under the new `LLVM_BB_ADDR_MAP` version, but the old version is still being used. A later patch will change the used version.
####Background
Today Propeller uses machine basic block (MBB) numbers, which already exist, to map native assembly to machine IR. This is done as follows.
- Basic block addresses are captured and dumped into the `LLVM_BB_ADDR_MAP` section just before the AsmPrinter pass which writes out object files. This ensures that we have a mapping that is close to assembly.
- Profiling mapping works by taking a virtual address of an instruction and looking up the `LLVM_BB_ADDR_MAP` section to find the MBB number it corresponds to.
- While this works well today, we need to do better when we scale Propeller to target other Machine IR optimizations like spill code optimization. Register allocation happens earlier in the Machine IR pipeline and we need an annotation mechanism that is valid at that point.
- The current scheme will not work in this scenario because the MBB number of a particular basic block is not fixed and changes over the course of codegen (via renumbering, adding, and removing the basic blocks).
- In other words, the volatile MBB numbers do not provide a one-to-one correspondence throughout the lifetime of Machine IR. Profile annotation using MBB numbers is restricted to a fixed point; only valid at the exact point where it was dumped.
- Further, the object file can only be dumped before AsmPrinter and cannot be dumped at an arbitrary point in the Machine IR pass pipeline. Hence, MBB numbers are not suitable and we need something else.
####Solution
We propose using fixed unique incremental MBB IDs for basic blocks instead of volatile MBB numbers. These IDs are assigned upon the creation of machine basic blocks. We modify `MachineFunction::CreateMachineBasicBlock` to assign the fixed ID to every newly created basic block. It assigns `MachineFunction::NextMBBID` to the MBB ID and then increments it, which ensures having unique IDs.
To ensure correct profile attribution, multiple equivalent compilations must generate the same Propeller IDs. This is guaranteed as long as the MachineFunction passes run in the same order. Since the `NextBBID` variable is scoped to `MachineFunction`, interleaving of codegen for different functions won't cause any inconsistencies.
The new encoding is generated under the new version number 2 and we keep backward-compatibility with older versions.
####Impact on Size of the `LLVM_BB_ADDR_MAP` Section
Emitting the Propeller ID results in a 23% increase in the size of the `LLVM_BB_ADDR_MAP` section for the clang binary.
Reviewed By: tmsriram
Differential Revision: https://reviews.llvm.org/D100808
Added:
llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir
Modified:
llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
llvm/include/llvm/CodeGen/MachineBasicBlock.h
llvm/include/llvm/CodeGen/MachineFunction.h
llvm/include/llvm/Object/ELFTypes.h
llvm/include/llvm/ObjectYAML/ELFYAML.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/BasicBlockSections.cpp
llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
llvm/lib/CodeGen/MIRParser/MILexer.cpp
llvm/lib/CodeGen/MIRParser/MILexer.h
llvm/lib/CodeGen/MIRParser/MIParser.cpp
llvm/lib/CodeGen/MachineBasicBlock.cpp
llvm/lib/CodeGen/MachineFunction.cpp
llvm/lib/Object/ELF.cpp
llvm/lib/ObjectYAML/ELFEmitter.cpp
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll
llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
llvm/tools/llvm-readobj/ELFDumper.cpp
llvm/tools/obj2yaml/elf2yaml.cpp
llvm/unittests/Object/ELFObjectFileTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
index f19a7293ecc66..b944c6edde553 100644
--- a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
+++ b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
@@ -31,8 +31,8 @@ namespace llvm {
// The cluster information for a machine basic block.
struct BBClusterInfo {
- // MachineBasicBlock ID.
- unsigned MBBNumber;
+ // Unique ID for this basic block.
+ unsigned BBID;
// Cluster ID this basic block belongs to.
unsigned ClusterID;
// Position of basic block within the cluster.
diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index a1c1d0395da4d..44165136e8404 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -169,6 +169,10 @@ class MachineBasicBlock
/// Indicate that this basic block is the entry block of a cleanup funclet.
bool IsCleanupFuncletEntry = false;
+ /// Fixed unique ID assigned to this basic block upon creation. Used with
+ /// basic block sections and basic block labels.
+ Optional<unsigned> BBID;
+
/// With basic block sections, this stores the Section ID of the basic block.
MBBSectionID SectionID{0};
@@ -620,6 +624,14 @@ class MachineBasicBlock
void setIsEndSection(bool V = true) { IsEndSection = V; }
+ Optional<unsigned> getBBID() const { return BBID; }
+
+ /// Returns the BBID of the block when BBAddrMapVersion >= 2, otherwise
+ /// returns `MachineBasicBlock::Number`.
+ /// TODO: Remove this function when version 1 is deprecated and replace its
+ /// uses with `getBBID()`.
+ unsigned getBBIDOrNumber() const;
+
/// Returns the section ID of this basic block.
MBBSectionID getSectionID() const { return SectionID; }
@@ -629,6 +641,12 @@ class MachineBasicBlock
((unsigned)SectionID.Type) + SectionID.Number;
}
+ /// Sets the fixed BBID of this basic block.
+ void setBBID(unsigned V) {
+ assert(!BBID.has_value() && "Cannot change BBID.");
+ BBID = V;
+ }
+
/// Sets the section ID for this basic block.
void setSectionID(MBBSectionID V) { SectionID = V; }
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 4d2e5d38c5a6a..7afa4d5aa1c67 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -374,6 +374,9 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
bool HasEHScopes = false;
bool HasEHFunclets = false;
+ /// BBID to assign to the next basic block of this function.
+ unsigned NextBBID = 0;
+
/// Section Type for basic blocks, only relevant with basic block sections.
BasicBlockSection BBSectionsType = BasicBlockSection::None;
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index 7ebad36e8fa7e..45e57869baceb 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -799,6 +799,7 @@ struct BBAddrMap {
uint64_t Addr; // Function address
// Struct representing the BBAddrMap information for one basic block.
struct BBEntry {
+ uint32_t ID; // Unique ID of this basic block.
uint32_t Offset; // Offset of basic block relative to function start.
uint32_t Size; // Size of the basic block.
@@ -809,13 +810,13 @@ struct BBAddrMap {
bool IsEHPad; // If this is an exception handling block.
bool CanFallThrough; // If this block can fall through to its next.
- BBEntry(uint32_t Offset, uint32_t Size, uint32_t Metadata)
- : Offset(Offset), Size(Size), HasReturn(Metadata & 1),
+ BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, uint32_t Metadata)
+ : ID(ID), Offset(Offset), Size(Size), HasReturn(Metadata & 1),
HasTailCall(Metadata & (1 << 1)), IsEHPad(Metadata & (1 << 2)),
CanFallThrough(Metadata & (1 << 3)){};
bool operator==(const BBEntry &Other) const {
- return Offset == Other.Offset && Size == Other.Size &&
+ return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
HasReturn == Other.HasReturn && HasTailCall == Other.HasTailCall &&
IsEHPad == Other.IsEHPad && CanFallThrough == Other.CanFallThrough;
}
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index cc77971c61cb0..1ba41232f552e 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -158,6 +158,7 @@ struct DynamicEntry {
struct BBAddrMapEntry {
struct BBEntry {
+ uint32_t ID;
llvm::yaml::Hex64 AddressOffset;
llvm::yaml::Hex64 Size;
llvm::yaml::Hex64 Metadata;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index b4b3128db3063..11eff4dd20096 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1347,7 +1347,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
OutStreamer->pushSection();
OutStreamer->switchSection(BBAddrMapSection);
OutStreamer->AddComment("version");
- OutStreamer->emitInt8(OutStreamer->getContext().getBBAddrMapVersion());
+ uint8_t BBAddrMapVersion = OutStreamer->getContext().getBBAddrMapVersion();
+ OutStreamer->emitInt8(BBAddrMapVersion);
OutStreamer->AddComment("feature");
OutStreamer->emitInt8(0);
OutStreamer->AddComment("function address");
@@ -1359,12 +1360,19 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
for (const MachineBasicBlock &MBB : MF) {
const MCSymbol *MBBSymbol =
MBB.isEntryBlock() ? FunctionSymbol : MBB.getSymbol();
+ // TODO: Remove this check when version 1 is deprecated.
+ if (BBAddrMapVersion > 1) {
+ OutStreamer->AddComment("BB id");
+ // Emit the BB ID for this basic block.
+ OutStreamer->emitULEB128IntValue(*MBB.getBBID());
+ }
// Emit the basic block offset relative to the end of the previous block.
// This is zero unless the block is padded due to alignment.
emitLabelDifferenceAsULEB128(MBBSymbol, PrevMBBEndSymbol);
// Emit the basic block size. When BBs have alignments, their size cannot
// always be computed from their offsets.
emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol);
+ // Emit the Metadata.
OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
PrevMBBEndSymbol = MBB.getEndSymbol();
}
diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp
index 3249022107a0e..8b6cf04bab07b 100644
--- a/llvm/lib/CodeGen/BasicBlockSections.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSections.cpp
@@ -71,8 +71,8 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
#include "llvm/CodeGen/BasicBlockSectionUtils.h"
+#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
@@ -131,9 +131,9 @@ INITIALIZE_PASS(BasicBlockSections, "bbsections-prepare",
// This function updates and optimizes the branching instructions of every basic
// block in a given function to account for changes in the layout.
-static void updateBranches(
- MachineFunction &MF,
- const SmallVector<MachineBasicBlock *, 4> &PreLayoutFallThroughs) {
+static void
+updateBranches(MachineFunction &MF,
+ const SmallVector<MachineBasicBlock *> &PreLayoutFallThroughs) {
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
SmallVector<MachineOperand, 4> Cond;
for (auto &MBB : MF) {
@@ -168,7 +168,7 @@ static void updateBranches(
bool getBBClusterInfoForFunction(
const MachineFunction &MF,
BasicBlockSectionsProfileReader *BBSectionsProfileReader,
- std::vector<Optional<BBClusterInfo>> &V) {
+ DenseMap<unsigned, BBClusterInfo> &V) {
// Find the assoicated cluster information.
std::pair<bool, SmallVector<BBClusterInfo, 4>> P =
@@ -183,13 +183,8 @@ bool getBBClusterInfoForFunction(
return true;
}
- V.resize(MF.getNumBlockIDs());
- for (auto bbClusterInfo : P.second) {
- // Bail out if the cluster information contains invalid MBB numbers.
- if (bbClusterInfo.MBBNumber >= MF.getNumBlockIDs())
- return false;
- V[bbClusterInfo.MBBNumber] = bbClusterInfo;
- }
+ for (const BBClusterInfo &BBCI : P.second)
+ V[BBCI.BBID] = BBCI;
return true;
}
@@ -200,11 +195,12 @@ bool getBBClusterInfoForFunction(
// clusters, they are moved into a single "Exception" section. Eventually,
// clusters are ordered in increasing order of their IDs, with the "Exception"
// and "Cold" succeeding all other clusters.
-// FuncBBClusterInfo represent the cluster information for basic blocks. If this
-// is empty, it means unique sections for all basic blocks in the function.
+// FuncBBClusterInfo represent the cluster information for basic blocks. It
+// maps from BBID of basic blocks to their cluster information. If this is
+// empty, it means unique sections for all basic blocks in the function.
static void
assignSections(MachineFunction &MF,
- const std::vector<Optional<BBClusterInfo>> &FuncBBClusterInfo) {
+ const DenseMap<unsigned, BBClusterInfo> &FuncBBClusterInfo) {
assert(MF.hasBBSections() && "BB Sections is not set for function.");
// This variable stores the section ID of the cluster containing eh_pads (if
// all eh_pads are one cluster). If more than one cluster contain eh_pads, we
@@ -219,15 +215,21 @@ assignSections(MachineFunction &MF,
if (MF.getTarget().getBBSectionsType() == llvm::BasicBlockSection::All ||
FuncBBClusterInfo.empty()) {
// If unique sections are desired for all basic blocks of the function, we
- // set every basic block's section ID equal to its number (basic block
- // id). This further ensures that basic blocks are ordered canonically.
- MBB.setSectionID({static_cast<unsigned int>(MBB.getNumber())});
- } else if (FuncBBClusterInfo[MBB.getNumber()])
- MBB.setSectionID(FuncBBClusterInfo[MBB.getNumber()]->ClusterID);
- else {
- // BB goes into the special cold section if it is not specified in the
- // cluster info map.
- MBB.setSectionID(MBBSectionID::ColdSectionID);
+ // set every basic block's section ID equal to its original position in
+ // the layout (which is equal to its number). This ensures that basic
+ // blocks are ordered canonically.
+ MBB.setSectionID(MBB.getNumber());
+ } else {
+ // TODO: Replace `getBBIDOrNumber` with `getBBID` once version 1 is
+ // deprecated.
+ auto I = FuncBBClusterInfo.find(MBB.getBBIDOrNumber());
+ if (I != FuncBBClusterInfo.end()) {
+ MBB.setSectionID(I->second.ClusterID);
+ } else {
+ // BB goes into the special cold section if it is not specified in the
+ // cluster info map.
+ MBB.setSectionID(MBBSectionID::ColdSectionID);
+ }
}
if (MBB.isEHPad() && EHPadsSectionID != MBB.getSectionID() &&
@@ -250,12 +252,14 @@ assignSections(MachineFunction &MF,
void llvm::sortBasicBlocksAndUpdateBranches(
MachineFunction &MF, MachineBasicBlockComparator MBBCmp) {
- SmallVector<MachineBasicBlock *, 4> PreLayoutFallThroughs(
- MF.getNumBlockIDs());
+ [[maybe_unused]] const MachineBasicBlock *EntryBlock = &MF.front();
+ SmallVector<MachineBasicBlock *> PreLayoutFallThroughs(MF.getNumBlockIDs());
for (auto &MBB : MF)
PreLayoutFallThroughs[MBB.getNumber()] = MBB.getFallThrough();
MF.sort(MBBCmp);
+ assert(&MF.front() == EntryBlock &&
+ "Entry block should not be displaced by basic block sections");
// Set IsBeginSection and IsEndSection according to the assigned section IDs.
MF.assignBeginEndSections();
@@ -318,11 +322,14 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
if (BBSectionsType == BasicBlockSection::List &&
hasInstrProfHashMismatch(MF))
return true;
-
- // Renumber blocks before sorting them for basic block sections. This is
- // useful during sorting, basic blocks in the same section will retain the
- // default order. This renumbering should also be done for basic block
- // labels to match the profiles with the correct blocks.
+ // Renumber blocks before sorting them. This is useful during sorting,
+ // basic blocks in the same section will retain the default order.
+ // This renumbering should also be done for basic block labels to match the
+ // profiles with the correct blocks.
+ // For LLVM_BB_ADDR_MAP versions 2 and higher, this renumbering serves
+ // the
diff erent purpose of accessing the original layout positions and
+ // finding the original fallthroughs.
+ // TODO: Change the above comment accordingly when version 1 is deprecated.
MF.RenumberBlocks();
if (BBSectionsType == BasicBlockSection::Labels) {
@@ -332,7 +339,8 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
BBSectionsProfileReader = &getAnalysis<BasicBlockSectionsProfileReader>();
- std::vector<Optional<BBClusterInfo>> FuncBBClusterInfo;
+ // Map from BBID of blocks to their cluster information.
+ DenseMap<unsigned, BBClusterInfo> FuncBBClusterInfo;
if (BBSectionsType == BasicBlockSection::List &&
!getBBClusterInfoForFunction(MF, BBSectionsProfileReader,
FuncBBClusterInfo))
@@ -372,8 +380,8 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
// If the two basic block are in the same section, the order is decided by
// their position within the section.
if (XSectionID.Type == MBBSectionID::SectionType::Default)
- return FuncBBClusterInfo[X.getNumber()]->PositionInCluster <
- FuncBBClusterInfo[Y.getNumber()]->PositionInCluster;
+ return FuncBBClusterInfo.lookup(X.getBBIDOrNumber()).PositionInCluster <
+ FuncBBClusterInfo.lookup(Y.getBBIDOrNumber()).PositionInCluster;
return X.getNumber() < Y.getNumber();
};
diff --git a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
index c2acf115998b6..5bc8d82debc3f 100644
--- a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
@@ -93,23 +93,23 @@ static Error getBBClusterInfo(const MemoryBuffer *MBuf,
if (FI == ProgramBBClusterInfo.end())
return invalidProfileError(
"Cluster list does not follow a function name specifier.");
- SmallVector<StringRef, 4> BBIndexes;
- S.split(BBIndexes, ' ');
+ SmallVector<StringRef, 4> BBIDs;
+ S.split(BBIDs, ' ');
// Reset current cluster position.
CurrentPosition = 0;
- for (auto BBIndexStr : BBIndexes) {
- unsigned long long BBIndex;
- if (getAsUnsignedInteger(BBIndexStr, 10, BBIndex))
+ for (auto BBIDStr : BBIDs) {
+ unsigned long long BBID;
+ if (getAsUnsignedInteger(BBIDStr, 10, BBID))
return invalidProfileError(Twine("Unsigned integer expected: '") +
- BBIndexStr + "'.");
- if (!FuncBBIDs.insert(BBIndex).second)
+ BBIDStr + "'.");
+ if (!FuncBBIDs.insert(BBID).second)
return invalidProfileError(Twine("Duplicate basic block id found '") +
- BBIndexStr + "'.");
- if (!BBIndex && CurrentPosition)
+ BBIDStr + "'.");
+ if (BBID == 0 && CurrentPosition)
return invalidProfileError("Entry BB (0) does not begin a cluster.");
- FI->second.emplace_back(BBClusterInfo{
- ((unsigned)BBIndex), CurrentCluster, CurrentPosition++});
+ FI->second.emplace_back(
+ BBClusterInfo{((unsigned)BBID), CurrentCluster, CurrentPosition++});
}
CurrentCluster++;
} else { // This is a function name specifier.
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index e9cd5fdaa0706..04746105bef01 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -272,11 +272,13 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
.Case("pcsections", MIToken::kw_pcsections)
.Case("cfi-type", MIToken::kw_cfi_type)
.Case("bbsections", MIToken::kw_bbsections)
+ .Case("bb_id", MIToken::kw_bb_id)
.Case("unknown-size", MIToken::kw_unknown_size)
.Case("unknown-address", MIToken::kw_unknown_address)
.Case("distinct", MIToken::kw_distinct)
.Case("ir-block-address-taken", MIToken::kw_ir_block_address_taken)
- .Case("machine-block-address-taken", MIToken::kw_machine_block_address_taken)
+ .Case("machine-block-address-taken",
+ MIToken::kw_machine_block_address_taken)
.Default(MIToken::Identifier);
}
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index b1ffeac865144..8396835554728 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -128,6 +128,7 @@ struct MIToken {
kw_pcsections,
kw_cfi_type,
kw_bbsections,
+ kw_bb_id,
kw_unknown_size,
kw_unknown_address,
kw_ir_block_address_taken,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 7eb701c08ddd9..3935bf92496ce 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -499,6 +499,7 @@ class MIParser {
bool parseAlignment(uint64_t &Alignment);
bool parseAddrspace(unsigned &Addrspace);
bool parseSectionID(Optional<MBBSectionID> &SID);
+ bool parseBBID(Optional<unsigned> &BBID);
bool parseOperandsOffset(MachineOperand &Op);
bool parseIRValue(const Value *&V);
bool parseMemoryOperandFlag(MachineMemOperand::Flags &Flags);
@@ -662,6 +663,18 @@ bool MIParser::parseSectionID(Optional<MBBSectionID> &SID) {
return false;
}
+// Parse Machine Basic Block ID.
+bool MIParser::parseBBID(Optional<unsigned> &BBID) {
+ assert(Token.is(MIToken::kw_bb_id));
+ lex();
+ unsigned Value = 0;
+ if (getUnsigned(Value))
+ return error("Unknown BB ID");
+ BBID = Value;
+ lex();
+ return false;
+}
+
bool MIParser::parseBasicBlockDefinition(
DenseMap<unsigned, MachineBasicBlock *> &MBBSlots) {
assert(Token.is(MIToken::MachineBasicBlockLabel));
@@ -678,6 +691,7 @@ bool MIParser::parseBasicBlockDefinition(
bool IsEHFuncletEntry = false;
Optional<MBBSectionID> SectionID;
uint64_t Alignment = 0;
+ Optional<unsigned> BBID;
BasicBlock *BB = nullptr;
if (consumeIfPresent(MIToken::lparen)) {
do {
@@ -718,6 +732,10 @@ bool MIParser::parseBasicBlockDefinition(
if (parseSectionID(SectionID))
return true;
break;
+ case MIToken::kw_bb_id:
+ if (parseBBID(BBID))
+ return true;
+ break;
default:
break;
}
@@ -755,6 +773,13 @@ bool MIParser::parseBasicBlockDefinition(
MBB->setSectionID(SectionID.value());
MF.setBBSectionsType(BasicBlockSection::List);
}
+ if (BBID.has_value()) {
+ // BBSectionsType is set to `List` if any basic blocks has `SectionID`.
+ // Here, we set it to `Labels` if it hasn't been set above.
+ if (!MF.hasBBSections())
+ MF.setBBSectionsType(BasicBlockSection::Labels);
+ MBB->setBBID(BBID.value());
+ }
return false;
}
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index f7684ae67d38c..a2c955ef12a13 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -558,6 +558,11 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
}
hasAttributes = true;
}
+ if (getBBID().has_value()) {
+ os << (hasAttributes ? ", " : " (");
+ os << "bb_id " << *getBBID();
+ hasAttributes = true;
+ }
}
if (hasAttributes)
@@ -1646,6 +1651,11 @@ bool MachineBasicBlock::sizeWithoutDebugLargerThan(unsigned Limit) const {
return false;
}
+unsigned MachineBasicBlock::getBBIDOrNumber() const {
+ uint8_t BBAddrMapVersion = getParent()->getContext().getBBAddrMapVersion();
+ return BBAddrMapVersion < 2 ? getNumber() : *getBBID();
+}
+
const MBBSectionID MBBSectionID::ColdSectionID(MBBSectionID::SectionType::Cold);
const MBBSectionID
MBBSectionID::ExceptionSectionID(MBBSectionID::SectionType::Exception);
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 78b49c9236629..9defe36cc6b6a 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -437,8 +437,16 @@ void MachineFunction::deleteMachineInstr(MachineInstr *MI) {
/// `new MachineBasicBlock'.
MachineBasicBlock *
MachineFunction::CreateMachineBasicBlock(const BasicBlock *bb) {
- return new (BasicBlockRecycler.Allocate<MachineBasicBlock>(Allocator))
- MachineBasicBlock(*this, bb);
+ MachineBasicBlock *MBB =
+ new (BasicBlockRecycler.Allocate<MachineBasicBlock>(Allocator))
+ MachineBasicBlock(*this, bb);
+ // Set BBID for `-basic-block=sections=labels` and
+ // `-basic-block-sections=list` to allow robust mapping of profiles to basic
+ // blocks.
+ if (Target.getBBSectionsType() == BasicBlockSection::Labels ||
+ Target.getBBSectionsType() == BasicBlockSection::List)
+ MBB->setBBID(NextBBID++);
+ return MBB;
}
/// Delete the given MachineBasicBlock.
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 93d3476ac3e19..80d1fc2227ac8 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -669,7 +669,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
Version = Data.getU8(Cur);
if (!Cur)
break;
- if (Version > 1)
+ if (Version > 2)
return createError("unsupported SHT_LLVM_BB_ADDR_MAP version: " +
Twine(static_cast<int>(Version)));
Data.getU8(Cur); // Feature byte
@@ -678,8 +678,9 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
uint32_t NumBlocks = ReadULEB128AsUInt32();
std::vector<BBAddrMap::BBEntry> BBEntries;
uint32_t PrevBBEndOffset = 0;
- for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks);
- ++BlockID) {
+ for (uint32_t BlockIndex = 0;
+ !ULEBSizeErr && Cur && (BlockIndex < NumBlocks); ++BlockIndex) {
+ uint32_t ID = Version >= 2 ? ReadULEB128AsUInt32() : BlockIndex;
uint32_t Offset = ReadULEB128AsUInt32();
uint32_t Size = ReadULEB128AsUInt32();
uint32_t Metadata = ReadULEB128AsUInt32();
@@ -688,7 +689,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
Offset += PrevBBEndOffset;
PrevBBEndOffset = Offset + Size;
}
- BBEntries.push_back({Offset, Size, Metadata});
+ BBEntries.push_back({ID, Offset, Size, Metadata});
}
FunctionEntries.push_back({Address, std::move(BBEntries)});
}
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 53fee6af0c14d..d9c12f935232d 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -1396,7 +1396,7 @@ void ELFState<ELFT>::writeSectionContent(
for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) {
// Write version and feature values.
if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP) {
- if (E.Version > 1)
+ if (E.Version > 2)
WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: "
<< static_cast<int>(E.Version)
<< "; encoding using the most recent version";
@@ -1414,10 +1414,13 @@ void ELFState<ELFT>::writeSectionContent(
// Write all BBEntries.
if (!E.BBEntries)
continue;
- for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries)
+ for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries) {
+ if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP && E.Version > 1)
+ SHeader.sh_size += CBA.writeULEB128(BBE.ID);
SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) +
CBA.writeULEB128(BBE.Size) +
CBA.writeULEB128(BBE.Metadata);
+ }
}
}
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 5513ce460dbc3..6517fe13feaa4 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1795,6 +1795,7 @@ void MappingTraits<ELFYAML::BBAddrMapEntry>::mapping(
void MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry>::mapping(
IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &E) {
assert(IO.getContext() && "The IO context is not initialized");
+ IO.mapOptional("ID", E.ID);
IO.mapRequired("AddressOffset", E.AddressOffset);
IO.mapRequired("Size", E.Size);
IO.mapRequired("Metadata", E.Metadata);
diff --git a/llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir b/llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir
new file mode 100644
index 0000000000000..74a7bcf3ae82f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir
@@ -0,0 +1,145 @@
+# Start after bbsections0-prepare and check that the BB address map is generated.
+# RUN: llc -mtriple x86_64-unknown-linux-gnu -start-after=bbsections-prepare %s -o - | FileCheck %s -check-prefix=CHECK
+
+# How to generate the input:
+# foo.cc
+# int foo(bool k) {
+# if (k) return 1;
+# return 0;
+# }
+#
+# clang -O0 -S -emit-llvm foo.cc
+# llc < foo.ll -stop-after=bbsections-prepare -basic-block-sections=labels
+
+# CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text
+--- |
+ ; ModuleID = '<stdin>'
+ source_filename = "/tmp/foo.cc"
+ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ target triple = "x86_64-pc-linux-gnu"
+
+ ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+ define dso_local noundef i32 @_Z3foob(i1 noundef zeroext %0) #0 {
+ %2 = alloca i32, align 4
+ %3 = alloca i8, align 1
+ %4 = zext i1 %0 to i8
+ store i8 %4, i8* %3, align 1
+ %5 = load i8, i8* %3, align 1
+ %6 = trunc i8 %5 to i1
+ br i1 %6, label %7, label %8
+
+ 7: ; preds = %1
+ store i32 1, i32* %2, align 4
+ br label %9
+
+ 8: ; preds = %1
+ store i32 0, i32* %2, align 4
+ br label %9
+
+ 9: ; preds = %8, %7
+ %10 = load i32, i32* %2, align 4
+ ret i32 %10
+ }
+
+ attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+
+ !llvm.module.flags = !{!0, !1, !2, !3, !4}
+ !llvm.ident = !{!5}
+
+ !0 = !{i32 1, !"wchar_size", i32 4}
+ !1 = !{i32 7, !"PIC Level", i32 2}
+ !2 = !{i32 7, !"PIE Level", i32 2}
+ !3 = !{i32 7, !"uwtable", i32 1}
+ !4 = !{i32 7, !"frame-pointer", i32 2}
+ !5 = !{!"Debian clang version 14.0.6-2"}
+
+...
+---
+name: _Z3foob
+alignment: 16
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHCatchret: false
+hasEHScopes: false
+hasEHFunclets: false
+failsVerification: false
+tracksDebugUserValues: true
+registers: []
+liveins:
+ - { reg: '$edi', virtual-reg: '' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 8
+ offsetAdjustment: -8
+ maxAlignment: 4
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ functionContext: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: false
+ localFrameSize: 0
+ savePoint: ''
+ restorePoint: ''
+fixedStack:
+ - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16, stack-id: default,
+ callee-saved-register: '', callee-saved-restored: true, debug-info-variable: '',
+ debug-info-expression: '', debug-info-location: '' }
+stack:
+ - { id: 0, name: '', type: default, offset: -24, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 1, name: '', type: default, offset: -17, size: 1, alignment: 1,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+callSites: []
+debugValueSubstitutions: []
+constants: []
+machineFunctionInfo: {}
+body: |
+ bb.0 (%ir-block.1, bb_id 0):
+ successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ liveins: $edi
+
+ frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+ frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ frame-setup CFI_INSTRUCTION offset $rbp, -16
+ $rbp = frame-setup MOV64rr $rsp
+ frame-setup CFI_INSTRUCTION def_cfa_register $rbp
+ renamable $dil = AND8ri renamable $dil, 1, implicit-def dead $eflags, implicit killed $edi, implicit-def $edi
+ MOV8mr $rbp, 1, $noreg, -1, $noreg, renamable $dil, implicit killed $edi :: (store (s8) into %ir.3)
+ TEST8mi $rbp, 1, $noreg, -1, $noreg, 1, implicit-def $eflags :: (load (s8) from %ir.3)
+ JCC_1 %bb.2, 4, implicit killed $eflags
+
+ bb.1 (%ir-block.7, bb_id 1):
+ successors: %bb.3(0x80000000)
+
+ MOV32mi $rbp, 1, $noreg, -8, $noreg, 1 :: (store (s32) into %ir.2)
+ JMP_1 %bb.3
+
+ bb.2 (%ir-block.8, bb_id 2):
+ successors: %bb.3(0x80000000)
+
+ MOV32mi $rbp, 1, $noreg, -8, $noreg, 0 :: (store (s32) into %ir.2)
+
+ bb.3 (%ir-block.9, bb_id 3):
+ renamable $eax = MOV32rm $rbp, 1, $noreg, -8, $noreg :: (load (s32) from %ir.2)
+ $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
+ frame-destroy CFI_INSTRUCTION def_cfa $rsp, 8
+ RET64 implicit $eax
+
+...
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll b/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll
index b37a314ef65cd..1767903561ce1 100644
--- a/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll
+++ b/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll
@@ -1,8 +1,9 @@
; Stop after bbsections-prepare and check MIR output for section type.
+; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=labels -stop-after=bbsections-prepare | FileCheck %s -check-prefix=BBLABELS
; RUN: echo '!_Z3foob' > %t
; RUN: echo '!!1' >> %t
; RUN: echo '!!2' >> %t
-; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -stop-after=bbsections-prepare | FileCheck %s -check-prefix=CHECK
+; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -stop-after=bbsections-prepare | FileCheck %s -check-prefix=BBSECTIONS
@_ZTIb = external constant ptr
define dso_local i32 @_Z3foob(i1 zeroext %0) {
@@ -27,7 +28,12 @@ define dso_local i32 @_Z3foob(i1 zeroext %0) {
ret i32 %10
}
-; CHECK: bb.0 (%ir-block.1, bbsections Cold):
-; CHECK: bb.3 (%ir-block.9, bbsections Cold):
-; CHECK: bb.1 (%ir-block.7)
-; CHECK: bb.2 (%ir-block.8, bbsections 1):
+; BBSECTIONS: bb.0 (%ir-block.1, bbsections Cold, bb_id 0):
+; BBSECTIONS: bb.3 (%ir-block.9, bbsections Cold, bb_id 3):
+; BBSECTIONS: bb.1 (%ir-block.7, bb_id 1)
+; BBSECTIONS: bb.2 (%ir-block.8, bbsections 1, bb_id 2):
+
+; BBLABELS: bb.0 (%ir-block.1, bb_id 0):
+; BBLABELS: bb.1 (%ir-block.7, bb_id 1):
+; BBLABELS: bb.2 (%ir-block.8, bb_id 2):
+; BBLABELS: bb.3 (%ir-block.9, bb_id 3):
diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
index 0f2fa50ccd438..3f6bde333af05 100644
--- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
+++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
@@ -25,6 +25,7 @@
# CHECK-NEXT: Name: <?>
# CHECK-NEXT: BB entries [
# CHECK-NEXT: {
+# CHECK-NEXT: ID: 0
# CHECK-NEXT: Offset: 0x0
# CHECK-NEXT: Size: 0x1
# CHECK-NEXT: HasReturn: No
@@ -33,6 +34,7 @@
# CHECK-NEXT: CanFallThrough: No
# CHECK-NEXT: }
# CHECK-NEXT: {
+# CHECK-NEXT: ID: 2
# CHECK-NEXT: Offset: 0x4
# CHECK-NEXT: Size: 0x4
# CHECK-NEXT: HasReturn: Yes
@@ -47,6 +49,7 @@
# CHECK-NEXT: Name: foo
# CHECK-NEXT: BB entries [
# CHECK-NEXT: {
+# CHECK-NEXT: ID: 4
# CHECK-NEXT: Offset: 0x6
# CHECK-NEXT: Size: 0x7
# CHECK-NEXT: HasReturn: No
@@ -70,6 +73,7 @@
# TRUNCATED-NEXT: Name: bar
# TRUNCATED-NEXT: BB entries [
# TRUNCATED-NEXT: {
+# TRUNCATED-NEXT: ID: 6
# TRUNCATED-NEXT: Offset: 0x9
# TRUNCATED-NEXT: Size: 0xA
# TRUNCATED-NEXT: HasReturn: Yes
@@ -78,6 +82,7 @@
# TRUNCATED-NEXT: CanFallThrough: Yes
# TRUNCATED-NEXT: }
# TRUNCATED-NEXT: {
+# TRUNCATED-NEXT: ID: 7
# TRUNCATED-NEXT: Offset: 0x1F
# TRUNCATED-NEXT: Size: 0xD
# TRUNCATED-NEXT: HasReturn: No
@@ -106,19 +111,22 @@ Sections:
ShSize: [[SIZE=<none>]]
Link: .text
Entries:
- - Version: 1
+ - Version: 2
Address: [[ADDR=0x11111]]
BBEntries:
- - AddressOffset: 0x0
+ - ID: 0
+ AddressOffset: 0x0
Size: 0x1
Metadata: 0xF0000002
- - AddressOffset: 0x3
+ - ID: 2
+ AddressOffset: 0x3
Size: 0x4
Metadata: 0x5
- - Version: 1
+ - Version: 2
Address: 0x22222
BBEntries:
- - AddressOffset: 0x6
+ - ID: 4
+ AddressOffset: 0x6
Size: 0x7
Metadata: 0x8
- Name: dummy_section
@@ -128,13 +136,15 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Link: .text.bar
Entries:
- - Version: 1
+ - Version: 2
Address: 0x33333
BBEntries:
- - AddressOffset: 0x9
+ - ID: 6
+ AddressOffset: 0x9
Size: 0xa
Metadata: 0xb
- - AddressOffset: 0xc
+ - ID: 7
+ AddressOffset: 0xc
Size: 0xd
Metadata: 0xe
Symbols:
@@ -165,6 +175,7 @@ Symbols:
# V0-NEXT: Name: foo
# V0-NEXT: BB entries [
# V0-NEXT: {
+# V0-NEXT: ID: 0
# V0-NEXT: Offset: 0x1
# V0-NEXT: Size: 0x2
# V0-NEXT: HasReturn:
@@ -173,6 +184,7 @@ Symbols:
# V0-NEXT: CanFallThrough:
# V0-NEXT: }
# V0-NEXT: {
+# V0-NEXT: ID: 1
# V0-NEXT: Offset: 0x4
# V0-NEXT: Size: 0x5
# V0-NEXT: HasReturn:
@@ -183,6 +195,36 @@ Symbols:
# V0-NEXT: ]
# V0-NEXT: }
+## Check version 1 (without BB IDs).
+# RUN: yaml2obj --docnum=2 %s -DVERSION=1 -DSECTION_TYPE=SHT_LLVM_BB_ADDR_MAP -o %t3
+# RUN: llvm-readobj %t3 --bb-addr-map 2>&1 | FileCheck %s --check-prefix=V1
+
+# V1: BBAddrMap [
+# V1-NEXT: Function {
+# V1-NEXT: At: 0x11111
+# V1-NEXT: Name: foo
+# V1-NEXT: BB entries [
+# V1-NEXT: {
+# V1-NEXT: ID: 0
+# V1-NEXT: Offset: 0x1
+# V1-NEXT: Size: 0x2
+# V1-NEXT: HasReturn:
+# V1-NEXT: HasTailCall:
+# V1-NEXT: IsEHPad:
+# V1-NEXT: CanFallThrough:
+# V1-NEXT: }
+# V1-NEXT: {
+# V1-NEXT: ID: 1
+# V1-NEXT: Offset: 0x7
+# V1-NEXT: Size: 0x5
+# V1-NEXT: HasReturn:
+# V1-NEXT: HasTailCall:
+# V1-NEXT: IsEHPad:
+# V1-NEXT: CanFallThrough:
+# V1-NEXT: }
+# V1-NEXT: ]
+# V1-NEXT: }
+
--- !ELF
FileHeader:
Class: ELFCLASS64
diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
index fcd650d3331ce..629c29e202aeb 100644
--- a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
@@ -15,23 +15,27 @@
# VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# VALID-NEXT: Entries:
## The 'Address' field is omitted when it's zero.
-# VALID-NEXT: - Version: 1
+# VALID-NEXT: - Version: 2
# VALID-NEXT: Feature: 0xFF
# VALID-NEXT: BBEntries:
-# VALID-NEXT: - AddressOffset: 0x1
+# VALID-NEXT: - ID: 0
+# VALID-NEXT: AddressOffset: 0x1
# VALID-NEXT: Size: 0x2
# VALID-NEXT: Metadata: 0x3
-# VALID-NEXT: - AddressOffset: 0x4
+# VALID-NEXT: - ID: 2
+# VALID-NEXT: AddressOffset: 0x4
# VALID-NEXT: Size: 0x5
# VALID-NEXT: Metadata: 0x6
-# VALID-NEXT: - AddressOffset: 0xFFFFFFFFFFFFFFF7
+# VALID-NEXT: - ID: 4
+# VALID-NEXT: AddressOffset: 0xFFFFFFFFFFFFFFF7
# VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8
# VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9
-# VALID-NEXT: - Version: 1
+# VALID-NEXT: - Version: 2
# VALID-NEXT: Feature: 0xEE
# VALID-NEXT: Address: 0xFFFFFFFFFFFFFF20
# VALID-NEXT: BBEntries:
-# VALID-NEXT: - AddressOffset: 0xA
+# VALID-NEXT: - ID: 6
+# VALID-NEXT: AddressOffset: 0xA
# VALID-NEXT: Size: 0xB
# VALID-NEXT: Metadata: 0xC
@@ -45,25 +49,29 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]]
Entries:
- - Version: 1
+ - Version: 2
Feature: 0xFF
Address: 0x0
BBEntries:
- - AddressOffset: 0x1
+ - ID: 0
+ AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
- - AddressOffset: 0x4
+ - ID: 2
+ AddressOffset: 0x4
Size: 0x5
Metadata: 0x6
- - AddressOffset: 0xFFFFFFFFFFFFFFF7
+ - ID: 4
+ AddressOffset: 0xFFFFFFFFFFFFFFF7
Size: 0xFFFFFFFFFFFFFFF8
Metadata: 0xFFFFFFFFFFFFFFF9
- - Version: 1
+ - Version: 2
Feature: 0xEE
Address: 0xFFFFFFFFFFFFFF20
NumBlocks: [[NUMBLOCKS=<none>]]
BBEntries:
- - AddressOffset: 0xA
+ - ID: 6
+ AddressOffset: 0xA
Size: 0xB
Metadata: 0xC
@@ -109,7 +117,8 @@ Sections:
## Fields 'Address' and 'Feature' are omitted when they are zero.
# MULTI-NEXT: - Version: 0
# MULTI-NEXT: BBEntries:
-# MULTI-NEXT: - AddressOffset: 0x1
+# MULTI-NEXT: - ID: 0
+# MULTI-NEXT: AddressOffset: 0x1
# MULTI-NEXT: Size: 0x2
# MULTI-NEXT: Metadata: 0x3
# MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)'
@@ -180,7 +189,8 @@ Sections:
# V0-NEXT: - Version: 0
# V0-NEXT: Address: 0x1111
# V0-NEXT: BBEntries:
-# V0-NEXT: - AddressOffset: 0x1
+# V0-NEXT: - ID: 0
+# V0-NEXT: AddressOffset: 0x1
# V0-NEXT: Size: 0x2
# V0-NEXT: Metadata: 0x3
@@ -199,3 +209,47 @@ Sections:
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
+
+## Check obj2yaml for version 1.
+# RUN: yaml2obj --docnum=5 %s -o %t7
+# RUN: obj2yaml %t7 | FileCheck %s --check-prefix=V1
+
+# V1: --- !ELF
+# V1-NEXT: FileHeader:
+# V1-NEXT: Class: ELFCLASS64
+# V1-NEXT: Data: ELFDATA2LSB
+# V1-NEXT: Type: ET_EXEC
+# V1-NEXT: Sections:
+# V1-NEXT: - Name: .llvm_bb_addr_map
+# V1-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
+# V1-NEXT: Entries:
+# V1-NEXT: - Version: 1
+# V1-NEXT: Address: 0x1111
+# V1-NEXT: BBEntries:
+# V1-NEXT: - ID: 0
+# V1-NEXT: AddressOffset: 0x1
+# V1-NEXT: Size: 0x2
+# V1-NEXT: Metadata: 0x3
+# V1-NEXT: - ID: 1
+# V1-NEXT: AddressOffset: 0x4
+# V1-NEXT: Size: 0x5
+# V1-NEXT: Metadata: 0x6
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+Sections:
+ - Name: .llvm_bb_addr_map
+ Type: SHT_LLVM_BB_ADDR_MAP
+ Entries:
+ - Version: 1
+ Address: 0x1111
+ BBEntries:
+ - AddressOffset: 0x1
+ Size: 0x2
+ Metadata: 0x3
+ - AddressOffset: 0x4
+ Size: 0x5
+ Metadata: 0x6
diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
index 1ca30f9bb4ba1..2086dc53208b0 100644
--- a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
@@ -12,13 +12,13 @@
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
# CHECK-NEXT: Offset: 0x40
-# CHECK-NEXT: Size: 12
+# CHECK-NEXT: Size: 13
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 0
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: SectionData (
-# CHECK-NEXT: 0000: 00000000 00000000 01010203
+# CHECK-NEXT: 0000: 00000000 00000000 01010203 04
# CHECK-NEXT: )
# CHECK-NEXT: }
@@ -36,7 +36,7 @@
# Case 4: Specify Entries.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 01002000 00000000 00000101 0203
+# CHECK-NEXT: 0000: 02002000 00000000 0000010B 010203
# CHECK-NEXT: )
# Case 5: Specify Entries and omit the Address field.
@@ -44,13 +44,13 @@
# CHECK: Address:
# CHECK-SAME: {{^ 0x0$}}
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 00000000 00000000 00000101 0203
+# CHECK-NEXT: 0000: 02000000 00000000 0000010C 010203
# CHECK-NEXT: )
# Case 6: Override the NumBlocks field.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 01002000 00000000 00000201 0203
+# CHECK-NEXT: 0000: 02002000 00000000 0000020D 010203
# CHECK-NEXT: )
--- !ELF
@@ -67,7 +67,7 @@ Sections:
## Specify Content.
- Name: '.llvm_bb_addr_map (1)'
Type: SHT_LLVM_BB_ADDR_MAP
- Content: "000000000000000001010203"
+ Content: "00000000000000000101020304"
## 2) We can produce an empty .llvm_bb_addr_map section from a description
## with empty section content.
@@ -85,10 +85,11 @@ Sections:
- Name: '.llvm_bb_addr_map (4)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 1
+ - Version: 2
Address: 0x0000000000000020
BBEntries:
- - AddressOffset: 0x00000001
+ - ID: 11
+ AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
@@ -97,9 +98,10 @@ Sections:
- Name: '.llvm_bb_addr_map (5)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 0
+ - Version: 2
BBEntries:
- - AddressOffset: 0x00000001
+ - ID: 12
+ AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
@@ -108,11 +110,12 @@ Sections:
- Name: '.llvm_bb_addr_map (6)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 1
+ - Version: 2
Address: 0x0000000000000020
NumBlocks: 2
BBEntries:
- - AddressOffset: 0x00000001
+ - ID: 13
+ AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
@@ -137,7 +140,7 @@ Sections:
## Check that yaml2obj generates a warning when we use unsupported versions.
# RUN: yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=INVALID-VERSION
-# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 2; encoding using the most recent version
+# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 3; encoding using the most recent version
--- !ELF
FileHeader:
@@ -149,4 +152,4 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
## Specify unsupported version
- - Version: 2
+ - Version: 3
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 7d2b557efd9b3..d730375a8ac5b 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -7135,6 +7135,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
ListScope L(W, "BB entries");
for (const BBAddrMap::BBEntry &BBE : AM.BBEntries) {
DictScope L(W);
+ W.printNumber("ID", BBE.ID);
W.printHex("Offset", BBE.Offset);
W.printHex("Size", BBE.Size);
W.printBoolean("HasReturn", BBE.HasReturn);
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 0c4e841c47467..b55cecebf32c4 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -897,7 +897,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
while (Cur && Cur.tell() < Content.size()) {
if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
Version = Data.getU8(Cur);
- if (Cur && Version > 1)
+ if (Cur && Version > 2)
return createStringError(
errc::invalid_argument,
"invalid SHT_LLVM_BB_ADDR_MAP section version: " +
@@ -908,11 +908,12 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
uint64_t NumBlocks = Data.getULEB128(Cur);
std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries;
// Read the specified number of BB entries, or until decoding fails.
- for (uint64_t BlockID = 0; Cur && BlockID < NumBlocks; ++BlockID) {
+ for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks; ++BlockIndex) {
+ uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex;
uint64_t Offset = Data.getULEB128(Cur);
uint64_t Size = Data.getULEB128(Cur);
uint64_t Metadata = Data.getULEB128(Cur);
- BBEntries.push_back({Offset, Size, Metadata});
+ BBEntries.push_back({ID, Offset, Size, Metadata});
}
Entries.push_back(
{Version, Feature, Address, /*NumBlocks=*/{}, std::move(BBEntries)});
diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp
index 2591a70b3d58b..25b187f60343e 100644
--- a/llvm/unittests/Object/ELFObjectFileTest.cpp
+++ b/llvm/unittests/Object/ELFObjectFileTest.cpp
@@ -528,7 +528,7 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
// Check that we can detect unsupported versions.
SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
UnsupportedVersionYamlString += R"(
- Version: 2
+ Version: 3
BBEntries:
- AddressOffset: 0x0
Size: 0x1
@@ -536,13 +536,14 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
)";
DoCheck(UnsupportedVersionYamlString,
- "unsupported SHT_LLVM_BB_ADDR_MAP version: 2");
+ "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
SmallString<128> CommonVersionedYamlString(CommonYamlString);
CommonVersionedYamlString += R"(
- Version: 1
+ Version: 2
BBEntries:
- - AddressOffset: 0x0
+ - ID: 1
+ AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
)";
@@ -551,9 +552,9 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
// truncated.
SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
TruncatedYamlString += R"(
- ShSize: 0xa
+ ShSize: 0xb
)";
- DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000a: "
+ DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: "
"malformed uleb128, extends past end");
// Check that we can detect when the encoded BB entry fields exceed the UINT32
@@ -561,29 +562,32 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
3, CommonVersionedYamlString);
OverInt32LimitYamlStrings[0] += R"(
- - AddressOffset: 0x100000000
+ - ID: 1
+ AddressOffset: 0x100000000
Size: 0xFFFFFFFF
Metadata: 0xFFFFFFFF
)";
OverInt32LimitYamlStrings[1] += R"(
- - AddressOffset: 0xFFFFFFFF
+ - ID: 2
+ AddressOffset: 0xFFFFFFFF
Size: 0x100000000
Metadata: 0xFFFFFFFF
)";
OverInt32LimitYamlStrings[2] += R"(
- - AddressOffset: 0xFFFFFFFF
+ - ID: 3
+ AddressOffset: 0xFFFFFFFF
Size: 0xFFFFFFFF
Metadata: 0x100000000
)";
DoCheck(OverInt32LimitYamlStrings[0],
- "ULEB128 value at offset 0xe exceeds UINT32_MAX (0x100000000)");
+ "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
DoCheck(OverInt32LimitYamlStrings[1],
- "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
+ "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
DoCheck(OverInt32LimitYamlStrings[2],
- "ULEB128 value at offset 0x18 exceeds UINT32_MAX (0x100000000)");
+ "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
// Check the proper error handling when the section has fields exceeding
// UINT32 and is also truncated. This is for checking that we don't generate
@@ -592,24 +596,24 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
3, OverInt32LimitYamlStrings[1]);
// Truncate before the end of the 5-byte field.
OverInt32LimitAndTruncated[0] += R"(
- ShSize: 0x17
+ ShSize: 0x19
)";
// Truncate at the end of the 5-byte field.
OverInt32LimitAndTruncated[1] += R"(
- ShSize: 0x18
+ ShSize: 0x1a
)";
// Truncate after the end of the 5-byte field.
OverInt32LimitAndTruncated[2] += R"(
- ShSize: 0x19
+ ShSize: 0x1b
)";
DoCheck(OverInt32LimitAndTruncated[0],
- "unable to decode LEB128 at offset 0x00000013: malformed uleb128, "
+ "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
"extends past end");
DoCheck(OverInt32LimitAndTruncated[1],
- "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
+ "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
DoCheck(OverInt32LimitAndTruncated[2],
- "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
+ "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
// Check for proper error handling when the 'NumBlocks' field is overridden
// with an out-of-range value.
@@ -635,41 +639,57 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
Type: SHT_LLVM_BB_ADDR_MAP
Link: 1
Entries:
- - Version: 1
+ - Version: 2
Address: 0x11111
BBEntries:
- - AddressOffset: 0x0
+ - ID: 1
+ AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
- Name: .llvm_bb_addr_map_2
Type: SHT_LLVM_BB_ADDR_MAP
Link: 1
Entries:
- - Version: 1
+ - Version: 2
Address: 0x22222
BBEntries:
- - AddressOffset: 0x0
+ - ID: 2
+ AddressOffset: 0x0
Size: 0x2
Metadata: 0x4
- - Name: .llvm_bb_addr_map
- Type: SHT_LLVM_BB_ADDR_MAP_V0
- # Link: 0 (by default)
+ - Name: .llvm_bb_addr_map_3
+ Type: SHT_LLVM_BB_ADDR_MAP
+ Link: 2
Entries:
- - Version: 0
+ - Version: 1
Address: 0x33333
BBEntries:
- - AddressOffset: 0x0
+ - ID: 0
+ AddressOffset: 0x0
Size: 0x3
Metadata: 0x6
+ - Name: .llvm_bb_addr_map_4
+ Type: SHT_LLVM_BB_ADDR_MAP_V0
+ # Link: 0 (by default, can be overriden)
+ Entries:
+ - Version: 0
+ Address: 0x44444
+ BBEntries:
+ - ID: 0
+ AddressOffset: 0x0
+ Size: 0x4
+ Metadata: 0x8
)");
- BBAddrMap E1 = {0x11111, {{0x0, 0x1, 0x2}}};
- BBAddrMap E2 = {0x22222, {{0x0, 0x2, 0x4}}};
- BBAddrMap E3 = {0x33333, {{0x0, 0x3, 0x6}}};
+ BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, 0x2}}};
+ BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, 0x4}}};
+ BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, 0x6}}};
+ BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, 0x8}}};
- std::vector<BBAddrMap> Section0BBAddrMaps = {E3};
- std::vector<BBAddrMap> Section1BBAddrMaps = {E1, E2};
- std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3};
+ std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
+ std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
+ std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
+ std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};
auto DoCheckSucceeds = [&](StringRef YamlString,
std::optional<unsigned> TextSectionIndex,
@@ -706,10 +726,11 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
AllBBAddrMaps);
DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps);
- DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section1BBAddrMaps);
+ DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps);
+ DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps);
// Check that when no bb-address-map section is found for a text section,
// we return an empty result.
- DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, {});
+ DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {});
// Check that we detect when a bb-addr-map section is linked to an invalid
// (not present) section.
@@ -718,9 +739,9 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
Link: 10
)";
- DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/1,
+ DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,
"unable to get the linked-to section for "
- "SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: invalid section "
+ "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section "
"index: 10");
// Linked sections are not checked when we don't target a specific text
// section.
@@ -734,12 +755,12 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
)";
DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
- "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: "
+ "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: "
"unable to decode LEB128 at offset 0x00000008: malformed "
"uleb128, extends past end");
// Check that we can read the other section's bb-address-maps which are
// valid.
- DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/1,
+ DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
Section1BBAddrMaps);
}
More information about the llvm-commits
mailing list