Skip to content

Commit 39831a6

Browse files
wdx727lifengxiang1025zcfhrlavaee
authored andcommitted
Adding Matching and Inference Functionality to Propeller-PR2 (llvm#162963)
Adding Matching and Inference Functionality to Propeller. For detailed information, please refer to the following RFC: https://discourse.llvm.org/t/rfc-adding-matching-and-inference-functionality-to-propeller/86238. This is the second PR, which includes the calculation of basic block hashes and their emission to the ELF file. It is associated with the previous PR at llvm#160706. co-authors: lifengxiang1025 [[email protected]](mailto:[email protected]); zcfh [[email protected]](mailto:[email protected]) Co-authored-by: lifengxiang1025 <[email protected]> Co-authored-by: zcfh <[email protected]> Co-authored-by: Rahman Lavaee <[email protected]>
1 parent 96e44b2 commit 39831a6

16 files changed

+390
-16
lines changed

llvm/docs/Extensions.rst

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,36 @@ as offsets relative to prior addresses.
416416
The following versioning schemes are currently supported (newer versions support
417417
features of the older versions).
418418

419-
Version 3 (newest): Capable of encoding callsite offsets. Enabled by the 6th bit
419+
Version 4 (newest): Capable of encoding basic block hashes. This feature is
420+
enabled by the 7th bit of the feature byte.
421+
422+
Example:
423+
424+
.. code-block:: gas
425+
426+
.section ".llvm_bb_addr_map","",@llvm_bb_addr_map
427+
.byte 4 # version number
428+
.byte 96 # feature byte
429+
.quad .Lfunc_begin0 # address of the function
430+
.byte 2 # number of basic blocks
431+
# BB record for BB_0
432+
.byte 0 # BB_0 ID
433+
.uleb128 .Lfunc_begin0-.Lfunc_begin0 # BB_0 offset relative to function entry (always zero)
434+
.byte 0 # number of callsites in this block
435+
.uleb128 .LBB_END0_0-.Lfunc_begin0 # BB_0 size
436+
.byte x # BB_0 metadata
437+
.quad 9080480745856761856 # BB_0 hash
438+
# BB record for BB_1
439+
.byte 1 # BB_1 ID
440+
.uleb128 .LBB0_1-.LBB_END0_0 # BB_1 offset relative to the end of last block (BB_0).
441+
.byte 2 # number of callsites in this block
442+
.uleb128 .LBB0_1_CS0-.LBB0_1 # offset of callsite end relative to the previous offset (.LBB0_1)
443+
.uleb128 .LBB0_1_CS1-.LBB0_1_CS0 # offset of callsite end relative to the previous offset (.LBB0_1_CS0)
444+
.uleb128 .LBB_END0_1-.LBB0_1_CS1 # BB_1 size offset (Offset of the block end relative to the previous offset).
445+
.byte y # BB_1 metadata
446+
.quad 2363478788702666771 # BB_1 hash
447+
448+
Version 3: Capable of encoding callsite offsets. Enabled by the 6th bit
420449
of the feature byte.
421450

422451
Example:
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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+
uint64_t Hash = 0;
43+
Hash |= uint64_t(NeighborHash);
44+
Hash <<= 16;
45+
Hash |= uint64_t(InstrHash);
46+
Hash <<= 16;
47+
Hash |= uint64_t(OpcodeHash);
48+
Hash <<= 16;
49+
Hash |= uint64_t(Offset);
50+
return Hash;
51+
}
52+
53+
/// Compute a distance between two given blended hashes. The smaller the
54+
/// distance, the more similar two blocks are. For identical basic blocks,
55+
/// the distance is zero.
56+
/// Since OpcodeHash is highly stable, we consider a match good only if
57+
/// the OpcodeHashes are identical. Mismatched OpcodeHashes lead to low
58+
/// matching accuracy, and poor matches undermine the quality of final
59+
/// inference. Notably, during inference, we also consider the matching
60+
/// ratio of basic blocks. For MachineFunctions with a low matching
61+
/// ratio, we directly skip optimization to reduce the impact of
62+
/// mismatches. This ensures even very poor profiles won’t cause negative
63+
/// optimization.
64+
/// In the context of matching, we consider NeighborHash to be more
65+
/// important. This is especially true when accounting for inlining
66+
/// scenarios, where the position of a basic block in the control
67+
/// flow graph is more critical.
68+
uint64_t distance(const BlendedBlockHash &BBH) const {
69+
assert(OpcodeHash == BBH.OpcodeHash &&
70+
"incorrect blended hash distance computation");
71+
uint64_t Dist = 0;
72+
// Account for NeighborHash
73+
Dist += NeighborHash == BBH.NeighborHash ? 0 : 1;
74+
Dist <<= 16;
75+
// Account for InstrHash
76+
Dist += InstrHash == BBH.InstrHash ? 0 : 1;
77+
Dist <<= 16;
78+
// Account for Offset
79+
Dist += (Offset >= BBH.Offset ? Offset - BBH.Offset : BBH.Offset - Offset);
80+
return Dist;
81+
}
82+
83+
private:
84+
/// The offset of the basic block from the function start.
85+
uint16_t Offset{0};
86+
/// Hash of the basic block instructions, excluding operands.
87+
uint16_t OpcodeHash{0};
88+
/// Hash of the basic block instructions, including opcodes and
89+
/// operands.
90+
uint16_t InstrHash{0};
91+
/// OpcodeHash of the basic block together with OpcodeHashes of its
92+
/// successors and predecessors.
93+
uint16_t NeighborHash{0};
94+
};
95+
96+
class MachineBlockHashInfo : public MachineFunctionPass {
97+
DenseMap<const MachineBasicBlock *, uint64_t> MBBHashInfo;
98+
99+
public:
100+
static char ID;
101+
MachineBlockHashInfo();
102+
103+
StringRef getPassName() const override { return "Basic Block Hash Compute"; }
104+
105+
void getAnalysisUsage(AnalysisUsage &AU) const override;
106+
107+
bool runOnMachineFunction(MachineFunction &F) override;
108+
109+
uint64_t getMBBHash(const MachineBasicBlock &MBB);
110+
};
111+
112+
} // end namespace llvm
113+
114+
#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/include/llvm/MC/MCContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class MCContext {
175175
unsigned GetInstance(unsigned LocalLabelVal);
176176

177177
/// SHT_LLVM_BB_ADDR_MAP version to emit.
178-
uint8_t BBAddrMapVersion = 3;
178+
uint8_t BBAddrMapVersion = 4;
179179

180180
/// The file name of the log file from the environment variable
181181
/// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 15 additions & 6 deletions
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) {
@@ -1434,14 +1439,11 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges,
14341439
"BB entries info is required for BBFreq and BrProb "
14351440
"features");
14361441
}
1437-
return {FuncEntryCountEnabled,
1438-
BBFreqEnabled,
1439-
BrProbEnabled,
1442+
return {FuncEntryCountEnabled, BBFreqEnabled, BrProbEnabled,
14401443
MF.hasBBSections() && NumMBBSectionRanges > 1,
14411444
// Use static_cast to avoid breakage of tests on windows.
1442-
static_cast<bool>(BBAddrMapSkipEmitBBEntries),
1443-
HasCalls,
1444-
false};
1445+
static_cast<bool>(BBAddrMapSkipEmitBBEntries), HasCalls,
1446+
static_cast<bool>(EmitBBHash)};
14451447
}
14461448

14471449
void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
@@ -1500,6 +1502,9 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
15001502
PrevMBBEndSymbol = MBBSymbol;
15011503
}
15021504

1505+
auto MBHI =
1506+
Features.BBHash ? &getAnalysis<MachineBlockHashInfo>() : nullptr;
1507+
15031508
if (!Features.OmitBBEntries) {
15041509
OutStreamer->AddComment("BB id");
15051510
// Emit the BB ID for this basic block.
@@ -1527,6 +1532,10 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
15271532
emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), CurrentLabel);
15281533
// Emit the Metadata.
15291534
OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
1535+
// Emit the Hash.
1536+
if (MBHI) {
1537+
OutStreamer->emitInt64(MBHI->getMBBHash(MBB));
1538+
}
15301539
}
15311540
PrevMBBEndSymbol = MBB.getEndSymbol();
15321541
}

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: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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+
const auto &HashInfo = HashInfos[&MBB];
99+
BlendedBlockHash BlendedHash(fold_64_to_16(HashInfo.Offset),
100+
fold_64_to_16(HashInfo.OpcodeHash),
101+
fold_64_to_16(HashInfo.InstrHash),
102+
fold_64_to_16(HashInfo.NeighborHash));
103+
MBBHashInfo[&MBB] = BlendedHash.combine();
104+
}
105+
106+
return false;
107+
}
108+
109+
uint64_t MachineBlockHashInfo::getMBBHash(const MachineBasicBlock &MBB) {
110+
return MBBHashInfo[&MBB];
111+
}
112+
113+
MachineFunctionPass *llvm::createMachineBlockHashInfoPass() {
114+
return new MachineBlockHashInfo();
115+
}

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()));

llvm/test/CodeGen/X86/basic-block-address-map-empty-function.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ entry:
1919
; CHECK: func:
2020
; CHECK: .Lfunc_begin1:
2121
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text{{$}}
22-
; CHECK-NEXT: .byte 3 # version
22+
; CHECK-NEXT: .byte 4 # version
2323
; BASIC-NEXT: .byte 0 # feature
2424
; PGO-NEXT: .byte 3 # feature
2525
; CHECK-NEXT: .quad .Lfunc_begin1 # function address

0 commit comments

Comments
 (0)