Skip to content

Commit d15e3af

Browse files
wdx727lifengxiang1025zcfh
committed
Adding Matching and Inference Functionality to Propeller-PR2: Compute basic block hash and emit to ELF.
Co-authored-by: lifengxiang1025 <[email protected]> Co-authored-by: zcfh <[email protected]>
1 parent 89eef94 commit d15e3af

File tree

8 files changed

+355
-1
lines changed

8 files changed

+355
-1
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
//===- llvm/CodeGen/MachineBlockHashInfo.h ----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Compute the hashes of basic blocks.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CODEGEN_MACHINEBLOCKHASHINFO_H
14+
#define LLVM_CODEGEN_MACHINEBLOCKHASHINFO_H
15+
16+
#include "llvm/CodeGen/MachineFunctionPass.h"
17+
18+
namespace llvm {
19+
20+
/// An object wrapping several components of a basic block hash. The combined
21+
/// (blended) hash is represented and stored as one uint64_t, while individual
22+
/// components are of smaller size (e.g., uint16_t or uint8_t).
23+
struct BlendedBlockHash {
24+
public:
25+
explicit BlendedBlockHash(uint16_t Offset, uint16_t OpcodeHash,
26+
uint16_t InstrHash, uint16_t NeighborHash)
27+
: Offset(Offset), OpcodeHash(OpcodeHash), InstrHash(InstrHash),
28+
NeighborHash(NeighborHash) {}
29+
30+
explicit BlendedBlockHash(uint64_t CombinedHash) {
31+
Offset = CombinedHash & 0xffff;
32+
CombinedHash >>= 16;
33+
OpcodeHash = CombinedHash & 0xffff;
34+
CombinedHash >>= 16;
35+
InstrHash = CombinedHash & 0xffff;
36+
CombinedHash >>= 16;
37+
NeighborHash = CombinedHash & 0xffff;
38+
}
39+
40+
/// Combine the blended hash into uint64_t.
41+
uint64_t combine() const {
42+
43+
uint64_t Hash = 0;
44+
45+
Hash |= uint64_t(NeighborHash);
46+
Hash <<= 16;
47+
48+
Hash |= uint64_t(InstrHash);
49+
Hash <<= 16;
50+
51+
Hash |= uint64_t(OpcodeHash);
52+
Hash <<= 16;
53+
54+
Hash |= uint64_t(Offset);
55+
56+
return Hash;
57+
}
58+
59+
/// Compute a distance between two given blended hashes. The smaller the
60+
/// distance, the more similar two blocks are. For identical basic blocks,
61+
/// the distance is zero.
62+
/// Since OpcodeHash is highly stable, we consider a match good only if
63+
/// the OpcodeHashes are identical. Mismatched OpcodeHashes lead to low
64+
/// matching accuracy, and poor matches undermine the quality of final
65+
/// inference. Notably, during inference, we also consider the matching
66+
/// ratio of basic blocks (BBs). For MachineFunctions with a low matching
67+
/// ratio, we directly skip optimization to reduce the impact of
68+
/// mismatches—this ensures even very poor profiles won’t cause negative
69+
/// optimization.
70+
/// In the context of matching, we consider NeighborHash to be more
71+
/// important. This is especially true when accounting for inlining
72+
/// scenarios, where the position of a basic block (BB) in the control
73+
/// flow graph (CFG) is more critical. Therefore, the matching results
74+
/// from NeighborHash carry greater significance.
75+
uint64_t distance(const BlendedBlockHash &BBH) const {
76+
assert(OpcodeHash == BBH.OpcodeHash &&
77+
"incorrect blended hash distance computation");
78+
uint64_t Dist = 0;
79+
// Account for NeighborHash
80+
Dist += NeighborHash == BBH.NeighborHash ? 0 : 1;
81+
Dist <<= 16;
82+
// Account for InstrHash
83+
Dist += InstrHash == BBH.InstrHash ? 0 : 1;
84+
Dist <<= 16;
85+
// Account for Offset
86+
Dist += (Offset >= BBH.Offset ? Offset - BBH.Offset : BBH.Offset - Offset);
87+
return Dist;
88+
}
89+
90+
private:
91+
/// The offset of the basic block from the function start.
92+
uint16_t Offset{0};
93+
/// Hash of the basic block instructions, excluding operands.
94+
uint16_t OpcodeHash{0};
95+
/// Hash of the basic block instructions, including opcodes and
96+
/// operands.
97+
uint16_t InstrHash{0};
98+
/// OpcodeHash of the basic block together with OpcodeHashes of its
99+
/// successors and predecessors.
100+
uint16_t NeighborHash{0};
101+
};
102+
103+
class MachineBlockHashInfo : public MachineFunctionPass {
104+
DenseMap<const MachineBasicBlock *, uint64_t> MBBHashInfo;
105+
106+
public:
107+
static char ID;
108+
MachineBlockHashInfo();
109+
110+
StringRef getPassName() const override { return "Basic Block Hash Compute"; }
111+
112+
void getAnalysisUsage(AnalysisUsage &AU) const override;
113+
114+
bool runOnMachineFunction(MachineFunction &F) override;
115+
116+
uint64_t getMBBHash(const MachineBasicBlock &MBB);
117+
};
118+
119+
} // end namespace llvm
120+
121+
#endif // LLVM_CODEGEN_MACHINEBLOCKHASHINFO_H

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ LLVM_ABI MachineFunctionPass *createBasicBlockSectionsPass();
6969

7070
LLVM_ABI MachineFunctionPass *createBasicBlockPathCloningPass();
7171

72+
/// createMachineBlockHashInfoPass - This pass computes basic block hashes.
73+
LLVM_ABI MachineFunctionPass *createMachineBlockHashInfoPass();
74+
7275
/// createMachineFunctionSplitterPass - This pass splits machine functions
7376
/// using profile information.
7477
LLVM_ABI MachineFunctionPass *createMachineFunctionSplitterPass();

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ LLVM_ABI void initializeBasicBlockSectionsPass(PassRegistry &);
6262
LLVM_ABI void initializeBarrierNoopPass(PassRegistry &);
6363
LLVM_ABI void initializeBasicAAWrapperPassPass(PassRegistry &);
6464
LLVM_ABI void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry &);
65+
LLVM_ABI void initializeMachineBlockHashInfoPass(PassRegistry &);
6566
LLVM_ABI void initializeBranchFolderLegacyPass(PassRegistry &);
6667
LLVM_ABI void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry &);
6768
LLVM_ABI void initializeBranchRelaxationLegacyPass(PassRegistry &);

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "llvm/CodeGen/GCMetadataPrinter.h"
4242
#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
4343
#include "llvm/CodeGen/MachineBasicBlock.h"
44+
#include "llvm/CodeGen/MachineBlockHashInfo.h"
4445
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
4546
#include "llvm/CodeGen/MachineConstantPool.h"
4647
#include "llvm/CodeGen/MachineDominators.h"
@@ -184,6 +185,8 @@ static cl::opt<bool> PrintLatency(
184185
cl::desc("Print instruction latencies as verbose asm comments"), cl::Hidden,
185186
cl::init(false));
186187

188+
extern cl::opt<bool> EmitBBHash;
189+
187190
STATISTIC(EmittedInsts, "Number of machine instrs printed");
188191

189192
char AsmPrinter::ID = 0;
@@ -474,6 +477,8 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
474477
AU.addRequired<GCModuleInfo>();
475478
AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
476479
AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
480+
if (EmitBBHash)
481+
AU.addRequired<MachineBlockHashInfo>();
477482
}
478483

479484
bool AsmPrinter::doInitialization(Module &M) {
@@ -1440,7 +1445,7 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges,
14401445
MF.hasBBSections() && NumMBBSectionRanges > 1,
14411446
static_cast<bool>(BBAddrMapSkipEmitBBEntries),
14421447
HasCalls,
1443-
false};
1448+
EmitBBHash.getValue()};
14441449
}
14451450

14461451
void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
@@ -1499,6 +1504,9 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
14991504
PrevMBBEndSymbol = MBBSymbol;
15001505
}
15011506

1507+
auto MBHI =
1508+
Features.BBHash ? &getAnalysis<MachineBlockHashInfo>() : nullptr;
1509+
15021510
if (!Features.OmitBBEntries) {
15031511
OutStreamer->AddComment("BB id");
15041512
// Emit the BB ID for this basic block.
@@ -1526,6 +1534,10 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
15261534
emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), CurrentLabel);
15271535
// Emit the Metadata.
15281536
OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
1537+
// Emit the Hash.
1538+
if (MBHI) {
1539+
OutStreamer->emitInt64(MBHI->getMBBHash(MBB));
1540+
}
15291541
}
15301542
PrevMBBEndSymbol = MBB.getEndSymbol();
15311543
}

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ add_llvm_component_library(LLVMCodeGen
108108
LowerEmuTLS.cpp
109109
MachineBasicBlock.cpp
110110
MachineBlockFrequencyInfo.cpp
111+
MachineBlockHashInfo.cpp
111112
MachineBlockPlacement.cpp
112113
MachineBranchProbabilityInfo.cpp
113114
MachineCFGPrinter.cpp
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//===- llvm/CodeGen/MachineBlockHashInfo.cpp---------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Compute the hashes of basic blocks.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "llvm/CodeGen/MachineBlockHashInfo.h"
14+
#include "llvm/CodeGen/Passes.h"
15+
#include "llvm/InitializePasses.h"
16+
#include "llvm/Target/TargetMachine.h"
17+
18+
using namespace llvm;
19+
20+
uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) {
21+
uint64_t Hash = 0;
22+
for (const MachineInstr &MI : MBB) {
23+
if (MI.isMetaInstruction() || MI.isTerminator())
24+
continue;
25+
Hash = hashing::detail::hash_16_bytes(Hash, MI.getOpcode());
26+
if (HashOperands) {
27+
for (unsigned i = 0; i < MI.getNumOperands(); i++) {
28+
Hash =
29+
hashing::detail::hash_16_bytes(Hash, hash_value(MI.getOperand(i)));
30+
}
31+
}
32+
}
33+
return Hash;
34+
}
35+
36+
/// Fold a 64-bit integer to a 16-bit one.
37+
uint16_t fold_64_to_16(const uint64_t Value) {
38+
uint16_t Res = static_cast<uint16_t>(Value);
39+
Res ^= static_cast<uint16_t>(Value >> 16);
40+
Res ^= static_cast<uint16_t>(Value >> 32);
41+
Res ^= static_cast<uint16_t>(Value >> 48);
42+
return Res;
43+
}
44+
45+
INITIALIZE_PASS(MachineBlockHashInfo, "machine-block-hash",
46+
"Machine Block Hash Analysis", true, true)
47+
48+
char MachineBlockHashInfo::ID = 0;
49+
50+
MachineBlockHashInfo::MachineBlockHashInfo() : MachineFunctionPass(ID) {
51+
initializeMachineBlockHashInfoPass(*PassRegistry::getPassRegistry());
52+
}
53+
54+
void MachineBlockHashInfo::getAnalysisUsage(AnalysisUsage &AU) const {
55+
AU.setPreservesAll();
56+
MachineFunctionPass::getAnalysisUsage(AU);
57+
}
58+
59+
struct CollectHashInfo {
60+
uint64_t Offset;
61+
uint64_t OpcodeHash;
62+
uint64_t InstrHash;
63+
uint64_t NeighborHash;
64+
};
65+
66+
bool MachineBlockHashInfo::runOnMachineFunction(MachineFunction &F) {
67+
DenseMap<const MachineBasicBlock *, CollectHashInfo> HashInfos;
68+
uint16_t Offset = 0;
69+
// Initialize hash components
70+
for (const MachineBasicBlock &MBB : F) {
71+
// offset of the machine basic block
72+
HashInfos[&MBB].Offset = Offset;
73+
Offset += MBB.size();
74+
// Hashing opcodes
75+
HashInfos[&MBB].OpcodeHash = hashBlock(MBB, /*HashOperands=*/false);
76+
// Hash complete instructions
77+
HashInfos[&MBB].InstrHash = hashBlock(MBB, /*HashOperands=*/true);
78+
}
79+
80+
// Initialize neighbor hash
81+
for (const MachineBasicBlock &MBB : F) {
82+
uint64_t Hash = HashInfos[&MBB].OpcodeHash;
83+
// Append hashes of successors
84+
for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
85+
uint64_t SuccHash = HashInfos[SuccMBB].OpcodeHash;
86+
Hash = hashing::detail::hash_16_bytes(Hash, SuccHash);
87+
}
88+
// Append hashes of predecessors
89+
for (const MachineBasicBlock *PredMBB : MBB.predecessors()) {
90+
uint64_t PredHash = HashInfos[PredMBB].OpcodeHash;
91+
Hash = hashing::detail::hash_16_bytes(Hash, PredHash);
92+
}
93+
HashInfos[&MBB].NeighborHash = Hash;
94+
}
95+
96+
// Assign hashes
97+
for (const MachineBasicBlock &MBB : F) {
98+
BlendedBlockHash BlendedHash(fold_64_to_16(HashInfos[&MBB].Offset),
99+
fold_64_to_16(HashInfos[&MBB].OpcodeHash),
100+
fold_64_to_16(HashInfos[&MBB].InstrHash),
101+
fold_64_to_16(HashInfos[&MBB].NeighborHash));
102+
MBBHashInfo[&MBB] = BlendedHash.combine();
103+
}
104+
105+
return false;
106+
}
107+
108+
uint64_t MachineBlockHashInfo::getMBBHash(const MachineBasicBlock &MBB) {
109+
return MBBHashInfo[&MBB];
110+
}
111+
112+
MachineFunctionPass *llvm::createMachineBlockHashInfoPass() {
113+
return new MachineBlockHashInfo();
114+
}

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ static cl::opt<bool>
272272
cl::desc("Split static data sections into hot and cold "
273273
"sections using profile information"));
274274

275+
cl::opt<bool> EmitBBHash(
276+
"emit-bb-hash",
277+
cl::desc(
278+
"Emit the hash of basic block in the SHT_LLVM_BB_ADDR_MAP section."),
279+
cl::init(false), cl::Optional);
280+
275281
/// Allow standard passes to be disabled by command line options. This supports
276282
/// simple binary flags that either suppress the pass or do nothing.
277283
/// i.e. -disable-mypass=false has no effect.
@@ -1281,6 +1287,8 @@ void TargetPassConfig::addMachinePasses() {
12811287
// address map (or both).
12821288
if (TM->getBBSectionsType() != llvm::BasicBlockSection::None ||
12831289
TM->Options.BBAddrMap) {
1290+
if (EmitBBHash)
1291+
addPass(llvm::createMachineBlockHashInfoPass());
12841292
if (TM->getBBSectionsType() == llvm::BasicBlockSection::List) {
12851293
addPass(llvm::createBasicBlockSectionsProfileReaderWrapperPass(
12861294
TM->getBBSectionsFuncListBuf()));

0 commit comments

Comments
 (0)