Skip to content

Commit 52388ca

Browse files
committed
[Propeller] Match the hash value of BB to adapt to source drift
Add the BB Hash to the generated `.llvm_bb_addr_map` section. The Propeller tool reads it and write to the output file. When building updated code, llvm matches the file with the current BB Hash and generates BBCluster based on the Hash matching results. This feature is controlled by the `bbsections-match-hash` option and is disabled by default.
1 parent d3687c1 commit 52388ca

29 files changed

+323
-59
lines changed

llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@
2828
#include "llvm/Support/LineIterator.h"
2929
#include "llvm/Support/MemoryBuffer.h"
3030
#include "llvm/Target/TargetMachine.h"
31+
#include "llvm/Support/CommandLine.h"
3132

3233
using namespace llvm;
3334

3435
namespace llvm {
3536

37+
extern cl::opt<bool> BBSectionsMatchHash;
38+
3639
// This struct represents the cluster information for a machine basic block,
3740
// which is specifed by a unique ID (`MachineBasicBlock::BBID`).
3841
struct BBClusterInfo {
@@ -65,13 +68,22 @@ template <> struct DenseMapInfo<UniqueBBID> {
6568
return UniqueBBID{TombstoneKey, TombstoneKey};
6669
}
6770
static unsigned getHashValue(const UniqueBBID &Val) {
71+
if (BBSectionsMatchHash) {
72+
std::pair<uint64_t, unsigned> PairVal =
73+
std::make_pair(Val.Hash, Val.CloneID);
74+
return DenseMapInfo<std::pair<uint64_t, unsigned>>::getHashValue(PairVal);
75+
}
6876
std::pair<unsigned, unsigned> PairVal =
6977
std::make_pair(Val.BaseID, Val.CloneID);
7078
return DenseMapInfo<std::pair<unsigned, unsigned>>::getHashValue(PairVal);
7179
}
7280
static bool isEqual(const UniqueBBID &LHS, const UniqueBBID &RHS) {
81+
if (BBSectionsMatchHash) {
82+
return DenseMapInfo<uint64_t>::isEqual(LHS.Hash, RHS.Hash) &&
83+
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
84+
}
7385
return DenseMapInfo<unsigned>::isEqual(LHS.BaseID, RHS.BaseID) &&
74-
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
86+
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
7587
}
7688
};
7789

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ template <> struct DenseMapInfo<MBBSectionID> {
100100
// the basic block sections profile.
101101
struct UniqueBBID {
102102
unsigned BaseID;
103+
uint64_t Hash;
103104
unsigned CloneID;
104105
};
105106

@@ -677,9 +678,13 @@ class MachineBasicBlock
677678

678679
std::optional<UniqueBBID> getBBID() const { return BBID; }
679680

681+
uint64_t getHash() const { return BBID->Hash; }
682+
680683
/// Returns the section ID of this basic block.
681684
MBBSectionID getSectionID() const { return SectionID; }
682685

686+
void setHash(uint64_t Hash) { BBID->Hash = Hash; }
687+
683688
/// Sets the fixed BBID of this basic block.
684689
void setBBID(const UniqueBBID &V) {
685690
assert(!BBID.has_value() && "Cannot change BBID.");

llvm/include/llvm/Object/ELFTypes.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -910,9 +910,11 @@ struct BBAddrMap {
910910
uint32_t Size = 0; // Size of the basic block.
911911
Metadata MD = {false, false, false, false,
912912
false}; // Metdata for this basic block.
913+
uint64_t Hash = 0; // Hash value of the basic block.
913914

914-
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD)
915-
: ID(ID), Offset(Offset), Size(Size), MD(MD){};
915+
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD,
916+
uint64_t Hash)
917+
: ID(ID), Offset(Offset), Size(Size), MD(MD), Hash(Hash){};
916918

917919
bool operator==(const BBEntry &Other) const {
918920
return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&

llvm/include/llvm/ObjectYAML/ELFYAML.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ struct BBAddrMapEntry {
162162
llvm::yaml::Hex64 AddressOffset;
163163
llvm::yaml::Hex64 Size;
164164
llvm::yaml::Hex64 Metadata;
165+
llvm::yaml::Hex64 Hash;
165166
};
166167
uint8_t Version;
167168
llvm::yaml::Hex8 Feature;

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
14251425
emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol);
14261426
// Emit the Metadata.
14271427
OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
1428+
OutStreamer->AddComment("hash value");
1429+
OutStreamer->emitULEB128IntValue(MBB.getHash());
14281430
PrevMBBEndSymbol = MBB.getEndSymbol();
14291431
}
14301432

llvm/lib/CodeGen/BasicBlockPathCloning.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ MachineBasicBlock *CloneMachineBasicBlock(MachineBasicBlock &OrigBB,
5656
auto TII = MF.getSubtarget().getInstrInfo();
5757
// Create the clone block and set its BBID based on the original block.
5858
MachineBasicBlock *CloneBB = MF.CreateMachineBasicBlock(
59-
OrigBB.getBasicBlock(), UniqueBBID{OrigBB.getBBID()->BaseID, CloneID});
59+
OrigBB.getBasicBlock(), UniqueBBID{OrigBB.getBBID()->BaseID,
60+
OrigBB.getBBID()->Hash, CloneID});
6061
MF.push_back(CloneBB);
6162

6263
// Copy the instructions.

llvm/lib/CodeGen/BasicBlockSections.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@
7070

7171
#include "llvm/ADT/SmallVector.h"
7272
#include "llvm/ADT/StringRef.h"
73+
#include "llvm/ADT/Hashing.h"
7374
#include "llvm/CodeGen/BasicBlockSectionUtils.h"
7475
#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
7576
#include "llvm/CodeGen/MachineFunction.h"
7677
#include "llvm/CodeGen/MachineFunctionPass.h"
7778
#include "llvm/CodeGen/Passes.h"
7879
#include "llvm/CodeGen/TargetInstrInfo.h"
7980
#include "llvm/InitializePasses.h"
81+
#include "llvm/IR/Constants.h"
8082
#include "llvm/Target/TargetMachine.h"
8183
#include <optional>
8284

@@ -289,12 +291,43 @@ bool llvm::hasInstrProfHashMismatch(MachineFunction &MF) {
289291
return false;
290292
}
291293

294+
void computeBBHash(MachineFunction &MF) {
295+
for (auto &MBB : MF) {
296+
llvm::hash_code Hash = llvm::hash_value(0);
297+
for (const MachineInstr &MI : MBB) {
298+
if (MI.isPseudo() || MI.isDebugOrPseudoInstr())
299+
continue;
300+
if (MI.isUnconditionalBranch())
301+
continue;
302+
Hash = llvm::hash_combine(Hash, MI.getOpcode());
303+
304+
for (const MachineOperand &MO : MI.operands()) {
305+
if (MO.isReg()) {
306+
Hash = llvm::hash_combine(Hash, MO.getReg());
307+
} else if (MO.isImm()) {
308+
Hash = llvm::hash_combine(Hash, MO.getImm());
309+
} else if (MO.isCImm()) {
310+
Hash = llvm::hash_combine(Hash, MO.getCImm()->getZExtValue());
311+
} else if (MO.isFPImm()) {
312+
Hash = llvm::hash_combine(Hash, MO.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
313+
} else if (MO.isGlobal()) {
314+
Hash = llvm::hash_combine(Hash, MO.getGlobal()->getName());
315+
} else if (MO.isSymbol()) {
316+
Hash = llvm::hash_combine(Hash, MO.getSymbolName());
317+
}
318+
}
319+
}
320+
MBB.setHash(Hash);
321+
}
322+
}
323+
292324
// Identify, arrange, and modify basic blocks which need separate sections
293325
// according to the specification provided by the -fbasic-block-sections flag.
294326
bool BasicBlockSections::handleBBSections(MachineFunction &MF) {
295327
auto BBSectionsType = MF.getTarget().getBBSectionsType();
296328
if (BBSectionsType == BasicBlockSection::None)
297329
return false;
330+
computeBBHash(MF);
298331

299332
// Check for source drift. If the source has changed since the profiles
300333
// were obtained, optimizing basic blocks might be sub-optimal.
@@ -384,6 +417,7 @@ bool BasicBlockSections::handleBBAddrMap(MachineFunction &MF) {
384417
return false;
385418
if (!MF.getTarget().Options.BBAddrMap)
386419
return false;
420+
computeBBHash(MF);
387421
MF.RenumberBlocks();
388422
return true;
389423
}

llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030

3131
using namespace llvm;
3232

33+
namespace llvm {
34+
cl::opt<bool> BBSectionsMatchHash(
35+
"bbsections-match-hash",
36+
cl::desc("This matches basic blocks by hash to fit source drift"),
37+
cl::init(false), cl::Hidden);
38+
}
39+
3340
char BasicBlockSectionsProfileReaderWrapperPass::ID = 0;
3441
INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass,
3542
"bbsections-profile-reader",
@@ -41,18 +48,29 @@ BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const {
4148
SmallVector<StringRef, 2> Parts;
4249
S.split(Parts, '.');
4350
if (Parts.size() > 2)
44-
return createProfileParseError(Twine("unable to parse basic block id: '") +
51+
return createProfileParseError(Twine("unable to parse unique basic block id: '") +
4552
S + "'");
46-
unsigned long long BaseBBID;
47-
if (getAsUnsignedInteger(Parts[0], 10, BaseBBID))
53+
SmallVector<StringRef, 2> IdAndHash;
54+
Parts[0].split(IdAndHash, '-');
55+
if (IdAndHash.size() > 2)
56+
return createProfileParseError(Twine("unable to parse basic block id and hash: '") +
57+
Parts[0] + "'");
58+
unsigned long long BaseBBID = 0;
59+
if (getAsUnsignedInteger(IdAndHash[0], 10, BaseBBID))
4860
return createProfileParseError(
49-
Twine("unable to parse BB id: '" + Parts[0]) +
61+
Twine("unable to parse BB id: '" + IdAndHash[0]) +
5062
"': unsigned integer expected");
63+
unsigned long long BBHash = 0;
64+
if (IdAndHash.size() > 1 && getAsUnsignedInteger(IdAndHash[1], 16, BBHash))
65+
return createProfileParseError(
66+
Twine("unable to parse BB hash: '" + IdAndHash[1]) +
67+
"': hex unsigned integer expected");
5168
unsigned long long CloneID = 0;
5269
if (Parts.size() > 1 && getAsUnsignedInteger(Parts[1], 10, CloneID))
5370
return createProfileParseError(Twine("unable to parse clone id: '") +
5471
Parts[1] + "': unsigned integer expected");
5572
return UniqueBBID{static_cast<unsigned>(BaseBBID),
73+
static_cast<uint64_t>(BBHash),
5674
static_cast<unsigned>(CloneID)};
5775
}
5876

llvm/lib/Object/ELF.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
858858
uint32_t Offset = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
859859
uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
860860
uint32_t MD = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
861+
uint64_t Hash = readULEB128As<uint64_t>(Data, Cur, ULEBSizeErr);
861862
if (Version >= 1) {
862863
// Offset is calculated relative to the end of the previous BB.
863864
Offset += PrevBBEndOffset;
@@ -869,7 +870,7 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
869870
MetadataDecodeErr = MetadataOrErr.takeError();
870871
break;
871872
}
872-
BBEntries.push_back({ID, Offset, Size, *MetadataOrErr});
873+
BBEntries.push_back({ID, Offset, Size, *MetadataOrErr, Hash});
873874
}
874875
TotalNumBlocks += BBEntries.size();
875876
BBRangeEntries.push_back({RangeBaseAddress, std::move(BBEntries)});

llvm/lib/ObjectYAML/ELFEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,7 @@ void ELFState<ELFT>::writeSectionContent(
15091509
SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset);
15101510
SHeader.sh_size += CBA.writeULEB128(BBE.Size);
15111511
SHeader.sh_size += CBA.writeULEB128(BBE.Metadata);
1512+
SHeader.sh_size += CBA.writeULEB128(BBE.Hash);
15121513
}
15131514
}
15141515
if (!PGOAnalyses)

0 commit comments

Comments
 (0)