Skip to content

Commit 5ac48ef

Browse files
committed
[Propeller] Use a bit-field struct for the metdata fields of BBEntry.
This patch encapsulates the encoding and decoding logic of basic block metadata into the Metadata struct, and also reduces the decoded size of `SHT_LLVM_BB_ADDR_MAP` section. The patch would've looked more readable if we could use designated initializer, but that is a c++20 feature. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D148360
1 parent 7fbfcc6 commit 5ac48ef

File tree

6 files changed

+113
-44
lines changed

6 files changed

+113
-44
lines changed

llvm/include/llvm/Object/ELFTypes.h

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -799,32 +799,57 @@ struct BBAddrMap {
799799
uint64_t Addr; // Function address
800800
// Struct representing the BBAddrMap information for one basic block.
801801
struct BBEntry {
802+
struct Metadata {
803+
bool HasReturn : 1; // If this block ends with a return (or tail call).
804+
bool HasTailCall : 1; // If this block ends with a tail call.
805+
bool IsEHPad : 1; // If this is an exception handling block.
806+
bool CanFallThrough : 1; // If this block can fall through to its next.
807+
808+
bool operator==(const Metadata &Other) const {
809+
return HasReturn == Other.HasReturn &&
810+
HasTailCall == Other.HasTailCall && IsEHPad == Other.IsEHPad &&
811+
CanFallThrough == Other.CanFallThrough;
812+
}
813+
814+
// Encodes this struct as a uint32_t value.
815+
uint32_t encode() const {
816+
return static_cast<uint32_t>(HasReturn) |
817+
(static_cast<uint32_t>(HasTailCall) << 1) |
818+
(static_cast<uint32_t>(IsEHPad) << 2) |
819+
(static_cast<uint32_t>(CanFallThrough) << 3);
820+
}
821+
822+
// Decodes and returns a Metadata struct from a uint32_t value.
823+
static Expected<Metadata> decode(uint32_t V) {
824+
Metadata MD{/*HasReturn=*/static_cast<bool>(V & 1),
825+
/*HasTailCall=*/static_cast<bool>(V & (1 << 1)),
826+
/*IsEHPad=*/static_cast<bool>(V & (1 << 2)),
827+
/*CanFallThrough=*/static_cast<bool>(V & (1 << 3))};
828+
if (MD.encode() != V)
829+
return createStringError(
830+
std::error_code(), "invalid encoding for BBEntry::Metadata: 0x%x",
831+
V);
832+
return MD;
833+
}
834+
};
835+
802836
uint32_t ID; // Unique ID of this basic block.
803837
uint32_t Offset; // Offset of basic block relative to function start.
804838
uint32_t Size; // Size of the basic block.
839+
Metadata MD; // Metdata for this basic block.
805840

806-
// The following fields are decoded from the Metadata field. The encoding
807-
// happens in AsmPrinter.cpp:getBBAddrMapMetadata.
808-
bool HasReturn; // If this block ends with a return (or tail call).
809-
bool HasTailCall; // If this block ends with a tail call.
810-
bool IsEHPad; // If this is an exception handling block.
811-
bool CanFallThrough; // If this block can fall through to its next.
812-
813-
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, uint32_t Metadata)
814-
: ID(ID), Offset(Offset), Size(Size), HasReturn(Metadata & 1),
815-
HasTailCall(Metadata & (1 << 1)), IsEHPad(Metadata & (1 << 2)),
816-
CanFallThrough(Metadata & (1 << 3)){};
841+
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD)
842+
: ID(ID), Offset(Offset), Size(Size), MD(MD){};
817843

818844
bool operator==(const BBEntry &Other) const {
819845
return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
820-
HasReturn == Other.HasReturn && HasTailCall == Other.HasTailCall &&
821-
IsEHPad == Other.IsEHPad && CanFallThrough == Other.CanFallThrough;
846+
MD == Other.MD;
822847
}
823848

824-
bool hasReturn() const { return HasReturn; }
825-
bool hasTailCall() const { return HasTailCall; }
826-
bool isEHPad() const { return IsEHPad; }
827-
bool canFallThrough() const { return CanFallThrough; }
849+
bool hasReturn() const { return MD.HasReturn; }
850+
bool hasTailCall() const { return MD.HasTailCall; }
851+
bool isEHPad() const { return MD.IsEHPad; }
852+
bool canFallThrough() const { return MD.CanFallThrough; }
828853
};
829854
std::vector<BBEntry> BBEntries; // Basic block entries for this function.
830855

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
#include "llvm/MC/MCTargetOptions.h"
100100
#include "llvm/MC/MCValue.h"
101101
#include "llvm/MC/SectionKind.h"
102+
#include "llvm/Object/ELFTypes.h"
102103
#include "llvm/Pass.h"
103104
#include "llvm/Remarks/RemarkStreamer.h"
104105
#include "llvm/Support/Casting.h"
@@ -1330,21 +1331,15 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
13301331
MCConstantExpr::create(FrameOffset, OutContext));
13311332
}
13321333

1333-
/// Returns the BB metadata to be emitted in the .llvm_bb_addr_map section for a
1334-
/// given basic block. This can be used to capture more precise profile
1335-
/// information. We use the last 4 bits (LSBs) to encode the following
1336-
/// information:
1337-
/// * (1): set if return block (ret or tail call).
1338-
/// * (2): set if ends with a tail call.
1339-
/// * (3): set if exception handling (EH) landing pad.
1340-
/// * (4): set if the block can fall through to its next.
1341-
/// The remaining bits are zero.
1342-
static unsigned getBBAddrMapMetadata(const MachineBasicBlock &MBB) {
1334+
/// Returns the BB metadata to be emitted in the SHT_LLVM_BB_ADDR_MAP section
1335+
/// for a given basic block. This can be used to capture more precise profile
1336+
/// information.
1337+
static uint32_t getBBAddrMapMetadata(const MachineBasicBlock &MBB) {
13431338
const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
1344-
return ((unsigned)MBB.isReturnBlock()) |
1345-
((!MBB.empty() && TII->isTailCall(MBB.back())) << 1) |
1346-
(MBB.isEHPad() << 2) |
1347-
(const_cast<MachineBasicBlock &>(MBB).canFallThrough() << 3);
1339+
return object::BBAddrMap::BBEntry::Metadata{
1340+
MBB.isReturnBlock(), !MBB.empty() && TII->isTailCall(MBB.back()),
1341+
MBB.isEHPad(), const_cast<MachineBasicBlock &>(MBB).canFallThrough()}
1342+
.encode();
13481343
}
13491344

13501345
void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {

llvm/lib/Object/ELF.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec,
674674

675675
DataExtractor::Cursor Cur(0);
676676
Error ULEBSizeErr = Error::success();
677+
Error MetadataDecodeErr = Error::success();
677678
// Helper to extract and decode the next ULEB128 value as uint32_t.
678679
// Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the uint32_t
679680
// limit.
@@ -694,7 +695,8 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec,
694695
};
695696

696697
uint8_t Version = 0;
697-
while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) {
698+
while (!ULEBSizeErr && !MetadataDecodeErr && Cur &&
699+
Cur.tell() < Content.size()) {
698700
if (Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
699701
Version = Data.getU8(Cur);
700702
if (!Cur)
@@ -722,24 +724,32 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec,
722724
std::vector<BBAddrMap::BBEntry> BBEntries;
723725
uint32_t PrevBBEndOffset = 0;
724726
for (uint32_t BlockIndex = 0;
725-
!ULEBSizeErr && Cur && (BlockIndex < NumBlocks); ++BlockIndex) {
727+
!MetadataDecodeErr && !ULEBSizeErr && Cur && (BlockIndex < NumBlocks);
728+
++BlockIndex) {
726729
uint32_t ID = Version >= 2 ? ReadULEB128AsUInt32() : BlockIndex;
727730
uint32_t Offset = ReadULEB128AsUInt32();
728731
uint32_t Size = ReadULEB128AsUInt32();
729-
uint32_t Metadata = ReadULEB128AsUInt32();
732+
uint32_t MD = ReadULEB128AsUInt32();
730733
if (Version >= 1) {
731734
// Offset is calculated relative to the end of the previous BB.
732735
Offset += PrevBBEndOffset;
733736
PrevBBEndOffset = Offset + Size;
734737
}
735-
BBEntries.push_back({ID, Offset, Size, Metadata});
738+
Expected<BBAddrMap::BBEntry::Metadata> MetadataOrErr =
739+
BBAddrMap::BBEntry::Metadata::decode(MD);
740+
if (!MetadataOrErr) {
741+
MetadataDecodeErr = MetadataOrErr.takeError();
742+
break;
743+
}
744+
BBEntries.push_back({ID, Offset, Size, *MetadataOrErr});
736745
}
737746
FunctionEntries.push_back({Address, std::move(BBEntries)});
738747
}
739-
// Either Cur is in the error state, or ULEBSizeError is set (not both), but
740-
// we join the two errors here to be safe.
741-
if (!Cur || ULEBSizeErr)
742-
return joinErrors(Cur.takeError(), std::move(ULEBSizeErr));
748+
// Either Cur is in the error state, or we have an error in ULEBSizeErr or
749+
// MetadataDecodeErr (but not both), but we join all errors here to be safe.
750+
if (!Cur || ULEBSizeErr || MetadataDecodeErr)
751+
return joinErrors(joinErrors(Cur.takeError(), std::move(ULEBSizeErr)),
752+
std::move(MetadataDecodeErr));
743753
return FunctionEntries;
744754
}
745755

llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DSIZE=6 -o %t2.o
2222
# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED
2323

24+
## Check that invalid metadata can be handled.
25+
# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DMETADATA=0xF000002 -o %t3.o
26+
# RUN: llvm-readobj %t3.o --bb-addr-map 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALIDMD
27+
2428
# CHECK: BBAddrMap [
2529
# CHECK-NEXT: Function {
2630
# CHECK-NEXT: At: [[ADDR]]
@@ -97,6 +101,9 @@
97101
# TRUNCATED-NEXT: }
98102
# TRUNCATED-NEXT: ]
99103

104+
# INVALIDMD: BBAddrMap [
105+
# INVALIDMD-NEXT: warning: '[[FILE]]': unable to dump SHT_LLVM_BB_ADDR_MAP section with index 3: invalid encoding for BBEntry::Metadata: 0xf000002
106+
100107
--- !ELF
101108
FileHeader:
102109
Class: ELFCLASS[[BITS]]
@@ -120,7 +127,7 @@ Sections:
120127
- ID: 0
121128
AddressOffset: 0x0
122129
Size: 0x1
123-
Metadata: 0xF0000002
130+
Metadata: [[METADATA=0x2]]
124131
- ID: 2
125132
AddressOffset: 0x3
126133
Size: 0x4

llvm/unittests/Object/ELFObjectFileTest.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -661,10 +661,10 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
661661
Metadata: 0x8
662662
)");
663663

664-
BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, 0x2}}};
665-
BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, 0x4}}};
666-
BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, 0x6}}};
667-
BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, 0x8}}};
664+
BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, {false, true, false, false}}}};
665+
BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, {false, false, true, false}}}};
666+
BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, {false, true, true, false}}}};
667+
BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, {false, false, false, true}}}};
668668

669669
std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
670670
std::vector<BBAddrMap> Section1BBAddrMaps = {E3};

llvm/unittests/Object/ELFTypesTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88
#include "llvm/Object/ELFTypes.h"
9+
#include "llvm/Testing/Support/Error.h"
910
#include "gtest/gtest.h"
1011
#include <iostream>
1112

@@ -61,3 +62,34 @@ TEST(ELFTypesTest, NoteTest) {
6162
TestData.getElfNote("AMD", ELF::NT_AMDGPU_METADATA, ArrayRef<uint8_t>());
6263
EXPECT_EQ(Note3.getDescAsStringRef(4), StringRef(""));
6364
}
65+
66+
TEST(ELFTypesTest, BBEntryMetadataEncodingTest) {
67+
const std::array<BBAddrMap::BBEntry::Metadata, 6> Decoded = {
68+
{{false, false, false, false},
69+
{true, false, false, false},
70+
{false, true, false, false},
71+
{false, false, true, false},
72+
{false, false, false, true},
73+
{true, true, true, true}}};
74+
const std::array<uint32_t, 6> Encoded = {{0, 1, 2, 4, 8, 15}};
75+
for (size_t i = 0; i < Decoded.size(); ++i)
76+
EXPECT_EQ(Decoded[i].encode(), Encoded[i]);
77+
for (size_t i = 0; i < Encoded.size(); ++i) {
78+
Expected<BBAddrMap::BBEntry::Metadata> MetadataOrError =
79+
BBAddrMap::BBEntry::Metadata::decode(Encoded[i]);
80+
ASSERT_THAT_EXPECTED(MetadataOrError, Succeeded());
81+
EXPECT_EQ(*MetadataOrError, Decoded[i]);
82+
}
83+
}
84+
85+
TEST(ELFTypesTest, BBEntryMetadataInvalidEncodingTest) {
86+
const std::array<std::string, 2> Errors = {
87+
"invalid encoding for BBEntry::Metadata: 0xffff",
88+
"invalid encoding for BBEntry::Metadata: 0x100001"};
89+
const std::array<uint32_t, 2> Values = {{0xFFFF, 0x100001}};
90+
for (size_t i = 0; i < Values.size(); ++i) {
91+
EXPECT_THAT_ERROR(
92+
BBAddrMap::BBEntry::Metadata::decode(Values[i]).takeError(),
93+
FailedWithMessage(Errors[i]));
94+
}
95+
}

0 commit comments

Comments
 (0)