diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -799,32 +799,50 @@ uint64_t Addr; // Function address // Struct representing the BBAddrMap information for one basic block. struct BBEntry { + struct Metadata { + bool HasReturn : 1; // If this block ends with a return (or tail call). + bool HasTailCall : 1; // If this block ends with a tail call. + bool IsEHPad : 1; // If this is an exception handling block. + bool CanFallThrough : 1; // If this block can fall through to its next. + bool operator==(const Metadata &Other) const { + return HasReturn == Other.HasReturn && + HasTailCall == Other.HasTailCall && IsEHPad == Other.IsEHPad && + CanFallThrough == Other.CanFallThrough; + } + // Encodes this struct as an unsigned integer. + unsigned encode() const { + return static_cast(HasReturn) | + (static_cast(HasTailCall) << 1) | + (static_cast(IsEHPad) << 2) | + (static_cast(CanFallThrough) << 3); + } + + // Decodes and returns a Metadata struct from an unsigned integer value. + static Metadata decode(unsigned V) { + return Metadata{/*HasReturn=*/static_cast(V & 1), + /*HasTailCall=*/static_cast(V & (1 << 1)), + /*IsEHPad=*/static_cast(V & (1 << 2)), + /*CanFallThrough=*/static_cast(V & (1 << 3))}; + } + }; + 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. + Metadata MD; // Metdata for this basic block. - // The following fields are decoded from the Metadata field. The encoding - // happens in AsmPrinter.cpp:getBBAddrMapMetadata. - bool HasReturn; // If this block ends with a return (or tail call). - bool HasTailCall; // If this block ends with a tail call. - bool IsEHPad; // If this is an exception handling block. - bool CanFallThrough; // If this block can fall through to its next. - - 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)){}; + BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD) + : ID(ID), Offset(Offset), Size(Size), MD(MD){}; bool operator==(const BBEntry &Other) const { return ID == Other.ID && Offset == Other.Offset && Size == Other.Size && - HasReturn == Other.HasReturn && HasTailCall == Other.HasTailCall && - IsEHPad == Other.IsEHPad && CanFallThrough == Other.CanFallThrough; + MD == Other.MD; } - bool hasReturn() const { return HasReturn; } - bool hasTailCall() const { return HasTailCall; } - bool isEHPad() const { return IsEHPad; } - bool canFallThrough() const { return CanFallThrough; } + bool hasReturn() const { return MD.HasReturn; } + bool hasTailCall() const { return MD.HasTailCall; } + bool isEHPad() const { return MD.IsEHPad; } + bool canFallThrough() const { return MD.CanFallThrough; } }; std::vector BBEntries; // Basic block entries for this function. diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -99,6 +99,7 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/SectionKind.h" +#include "llvm/Object/ELFTypes.h" #include "llvm/Pass.h" #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Support/Casting.h" @@ -1329,21 +1330,15 @@ MCConstantExpr::create(FrameOffset, OutContext)); } -/// Returns the BB metadata to be emitted in the .llvm_bb_addr_map section for a -/// given basic block. This can be used to capture more precise profile -/// information. We use the last 4 bits (LSBs) to encode the following -/// information: -/// * (1): set if return block (ret or tail call). -/// * (2): set if ends with a tail call. -/// * (3): set if exception handling (EH) landing pad. -/// * (4): set if the block can fall through to its next. -/// The remaining bits are zero. -static unsigned getBBAddrMapMetadata(const MachineBasicBlock &MBB) { +/// Returns the BB metadata to be emitted in the SHT_LLVM_BB_ADDR_MAP section +/// for a given basic block. This can be used to capture more precise profile +/// information. +static uint32_t getBBAddrMapMetadata(const MachineBasicBlock &MBB) { const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); - return ((unsigned)MBB.isReturnBlock()) | - ((!MBB.empty() && TII->isTailCall(MBB.back())) << 1) | - (MBB.isEHPad() << 2) | - (const_cast(MBB).canFallThrough() << 3); + return object::BBAddrMap::BBEntry::Metadata{ + MBB.isReturnBlock(), !MBB.empty() && TII->isTailCall(MBB.back()), + MBB.isEHPad(), const_cast(MBB).canFallThrough()} + .encode(); } void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -726,13 +726,14 @@ uint32_t ID = Version >= 2 ? ReadULEB128AsUInt32() : BlockIndex; uint32_t Offset = ReadULEB128AsUInt32(); uint32_t Size = ReadULEB128AsUInt32(); - uint32_t Metadata = ReadULEB128AsUInt32(); + uint32_t MD = ReadULEB128AsUInt32(); if (Version >= 1) { // Offset is calculated relative to the end of the previous BB. Offset += PrevBBEndOffset; PrevBBEndOffset = Offset + Size; } - BBEntries.push_back({ID, Offset, Size, Metadata}); + BBEntries.push_back( + {ID, Offset, Size, BBAddrMap::BBEntry::Metadata::decode(MD)}); } FunctionEntries.push_back({Address, std::move(BBEntries)}); } diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -661,10 +661,10 @@ Metadata: 0x8 )"); - 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}}}; + BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, {false, true, false, false}}}}; + BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, {false, false, true, false}}}}; + BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, {false, true, true, false}}}}; + BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, {false, false, false, true}}}}; std::vector Section0BBAddrMaps = {E4}; std::vector Section1BBAddrMaps = {E3}; diff --git a/llvm/unittests/Object/ELFTypesTest.cpp b/llvm/unittests/Object/ELFTypesTest.cpp --- a/llvm/unittests/Object/ELFTypesTest.cpp +++ b/llvm/unittests/Object/ELFTypesTest.cpp @@ -61,3 +61,18 @@ TestData.getElfNote("AMD", ELF::NT_AMDGPU_METADATA, ArrayRef()); EXPECT_EQ(Note3.getDescAsStringRef(), StringRef("")); } + +TEST(ELFTypesTest, BBEntryMetadataEncodingTest) { + static const std::array Decoded = { + {{false, false, false, false}, + {true, false, false, false}, + {false, true, false, false}, + {false, false, true, false}, + {false, false, false, true}, + {true, true, true, true}}}; + static const std::array Encoded = {{0, 1, 2, 4, 8, 15}}; + for (unsigned i = 0; i < Decoded.size(); ++i) + EXPECT_EQ(Decoded[i].encode(), Encoded[i]); + for (unsigned i = 0; i < Encoded.size(); ++i) + EXPECT_EQ(BBAddrMap::BBEntry::Metadata::decode(Encoded[i]), Decoded[i]); +}