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 @@ -803,28 +803,39 @@ uint32_t Offset; // Offset of basic block relative to function start. uint32_t Size; // Size of the 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)){}; + 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 memcmp(this, &Other, sizeof(Metadata)) == 0; + } + // Encodes this struct as an unsigned integer. + unsigned encode() const { + return ((unsigned)HasReturn) | (HasTailCall << 1) | (IsEHPad << 2) | + (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))}; + } + } MD; + + bool hasReturn() const { return MD.HasReturn; } + bool hasTailCall() const { return MD.HasTailCall; } + bool isEHPad() const { return MD.IsEHPad; } + bool canFallThrough() const { return MD.CanFallThrough; } + + 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; + return memcmp(this, &Other, sizeof(BBEntry)) == 0; } - - bool hasReturn() const { return HasReturn; } - bool hasTailCall() const { return HasTailCall; } - bool isEHPad() const { return IsEHPad; } - bool canFallThrough() const { return 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. +/// 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 unsigned 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};