-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Adding Matching and Inference Functionality to Propeller-PR2 #162963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
//===- llvm/CodeGen/MachineBlockHashInfo.h ----------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Compute the hashes of basic blocks. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CODEGEN_MACHINEBLOCKHASHINFO_H | ||
#define LLVM_CODEGEN_MACHINEBLOCKHASHINFO_H | ||
|
||
#include "llvm/CodeGen/MachineFunctionPass.h" | ||
|
||
namespace llvm { | ||
|
||
/// An object wrapping several components of a basic block hash. The combined | ||
/// (blended) hash is represented and stored as one uint64_t, while individual | ||
/// components are of smaller size (e.g., uint16_t or uint8_t). | ||
struct BlendedBlockHash { | ||
public: | ||
explicit BlendedBlockHash(uint16_t Offset, uint16_t OpcodeHash, | ||
uint16_t InstrHash, uint16_t NeighborHash) | ||
: Offset(Offset), OpcodeHash(OpcodeHash), InstrHash(InstrHash), | ||
NeighborHash(NeighborHash) {} | ||
|
||
explicit BlendedBlockHash(uint64_t CombinedHash) { | ||
Offset = CombinedHash & 0xffff; | ||
CombinedHash >>= 16; | ||
OpcodeHash = CombinedHash & 0xffff; | ||
CombinedHash >>= 16; | ||
InstrHash = CombinedHash & 0xffff; | ||
CombinedHash >>= 16; | ||
NeighborHash = CombinedHash & 0xffff; | ||
} | ||
|
||
/// Combine the blended hash into uint64_t. | ||
uint64_t combine() const { | ||
|
||
uint64_t Hash = 0; | ||
|
||
Hash |= uint64_t(NeighborHash); | ||
Hash <<= 16; | ||
|
||
Hash |= uint64_t(InstrHash); | ||
Hash <<= 16; | ||
|
||
Hash |= uint64_t(OpcodeHash); | ||
Hash <<= 16; | ||
|
||
Hash |= uint64_t(Offset); | ||
|
||
return Hash; | ||
} | ||
|
||
/// Compute a distance between two given blended hashes. The smaller the | ||
/// distance, the more similar two blocks are. For identical basic blocks, | ||
/// the distance is zero. | ||
/// Since OpcodeHash is highly stable, we consider a match good only if | ||
/// the OpcodeHashes are identical. Mismatched OpcodeHashes lead to low | ||
/// matching accuracy, and poor matches undermine the quality of final | ||
/// inference. Notably, during inference, we also consider the matching | ||
/// ratio of basic blocks (BBs). For MachineFunctions with a low matching | ||
/// ratio, we directly skip optimization to reduce the impact of | ||
/// mismatches—this ensures even very poor profiles won’t cause negative | ||
/// optimization. | ||
/// In the context of matching, we consider NeighborHash to be more | ||
/// important. This is especially true when accounting for inlining | ||
/// scenarios, where the position of a basic block (BB) in the control | ||
/// flow graph (CFG) is more critical. Therefore, the matching results | ||
/// from NeighborHash carry greater significance. | ||
uint64_t distance(const BlendedBlockHash &BBH) const { | ||
assert(OpcodeHash == BBH.OpcodeHash && | ||
"incorrect blended hash distance computation"); | ||
uint64_t Dist = 0; | ||
// Account for NeighborHash | ||
Dist += NeighborHash == BBH.NeighborHash ? 0 : 1; | ||
Dist <<= 16; | ||
// Account for InstrHash | ||
Dist += InstrHash == BBH.InstrHash ? 0 : 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The shifting in this method means NeighborHash is more important than InstrHash. Could you please explain this in the comments? Also why does opcode hash needs to be exactly the same in order to call this function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please include this in the comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
Dist <<= 16; | ||
// Account for Offset | ||
Dist += (Offset >= BBH.Offset ? Offset - BBH.Offset : BBH.Offset - Offset); | ||
return Dist; | ||
} | ||
|
||
private: | ||
/// The offset of the basic block from the function start. | ||
uint16_t Offset{0}; | ||
/// Hash of the basic block instructions, excluding operands. | ||
uint16_t OpcodeHash{0}; | ||
/// Hash of the basic block instructions, including opcodes and | ||
/// operands. | ||
uint16_t InstrHash{0}; | ||
/// OpcodeHash of the basic block together with OpcodeHashes of its | ||
/// successors and predecessors. | ||
uint16_t NeighborHash{0}; | ||
}; | ||
|
||
class MachineBlockHashInfo : public MachineFunctionPass { | ||
DenseMap<const MachineBasicBlock *, uint64_t> MBBHashInfo; | ||
|
||
public: | ||
static char ID; | ||
MachineBlockHashInfo(); | ||
|
||
StringRef getPassName() const override { return "Basic Block Hash Compute"; } | ||
|
||
void getAnalysisUsage(AnalysisUsage &AU) const override; | ||
|
||
bool runOnMachineFunction(MachineFunction &F) override; | ||
|
||
uint64_t getMBBHash(const MachineBasicBlock &MBB); | ||
}; | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_CODEGEN_MACHINEBLOCKHASHINFO_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
//===- llvm/CodeGen/MachineBlockHashInfo.cpp---------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Compute the hashes of basic blocks. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/CodeGen/MachineBlockHashInfo.h" | ||
#include "llvm/CodeGen/Passes.h" | ||
#include "llvm/InitializePasses.h" | ||
#include "llvm/Target/TargetMachine.h" | ||
|
||
using namespace llvm; | ||
|
||
uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) { | ||
uint64_t Hash = 0; | ||
for (const MachineInstr &MI : MBB) { | ||
if (MI.isMetaInstruction() || MI.isTerminator()) | ||
continue; | ||
Hash = hashing::detail::hash_16_bytes(Hash, MI.getOpcode()); | ||
if (HashOperands) { | ||
for (unsigned i = 0; i < MI.getNumOperands(); i++) { | ||
Hash = | ||
hashing::detail::hash_16_bytes(Hash, hash_value(MI.getOperand(i))); | ||
} | ||
} | ||
} | ||
return Hash; | ||
} | ||
|
||
/// Fold a 64-bit integer to a 16-bit one. | ||
uint16_t fold_64_to_16(const uint64_t Value) { | ||
uint16_t Res = static_cast<uint16_t>(Value); | ||
Res ^= static_cast<uint16_t>(Value >> 16); | ||
Res ^= static_cast<uint16_t>(Value >> 32); | ||
Res ^= static_cast<uint16_t>(Value >> 48); | ||
return Res; | ||
} | ||
|
||
INITIALIZE_PASS(MachineBlockHashInfo, "machine-block-hash", | ||
"Machine Block Hash Analysis", true, true) | ||
|
||
char MachineBlockHashInfo::ID = 0; | ||
|
||
MachineBlockHashInfo::MachineBlockHashInfo() : MachineFunctionPass(ID) { | ||
initializeMachineBlockHashInfoPass(*PassRegistry::getPassRegistry()); | ||
} | ||
|
||
void MachineBlockHashInfo::getAnalysisUsage(AnalysisUsage &AU) const { | ||
AU.setPreservesAll(); | ||
MachineFunctionPass::getAnalysisUsage(AU); | ||
} | ||
|
||
struct CollectHashInfo { | ||
uint64_t Offset; | ||
uint64_t OpcodeHash; | ||
uint64_t InstrHash; | ||
uint64_t NeighborHash; | ||
}; | ||
|
||
bool MachineBlockHashInfo::runOnMachineFunction(MachineFunction &F) { | ||
DenseMap<const MachineBasicBlock *, CollectHashInfo> HashInfos; | ||
uint16_t Offset = 0; | ||
// Initialize hash components | ||
for (const MachineBasicBlock &MBB : F) { | ||
// offset of the machine basic block | ||
HashInfos[&MBB].Offset = Offset; | ||
Offset += MBB.size(); | ||
// Hashing opcodes | ||
HashInfos[&MBB].OpcodeHash = hashBlock(MBB, /*HashOperands=*/false); | ||
// Hash complete instructions | ||
HashInfos[&MBB].InstrHash = hashBlock(MBB, /*HashOperands=*/true); | ||
} | ||
|
||
// Initialize neighbor hash | ||
for (const MachineBasicBlock &MBB : F) { | ||
uint64_t Hash = HashInfos[&MBB].OpcodeHash; | ||
// Append hashes of successors | ||
for (const MachineBasicBlock *SuccMBB : MBB.successors()) { | ||
uint64_t SuccHash = HashInfos[SuccMBB].OpcodeHash; | ||
Hash = hashing::detail::hash_16_bytes(Hash, SuccHash); | ||
} | ||
// Append hashes of predecessors | ||
for (const MachineBasicBlock *PredMBB : MBB.predecessors()) { | ||
uint64_t PredHash = HashInfos[PredMBB].OpcodeHash; | ||
Hash = hashing::detail::hash_16_bytes(Hash, PredHash); | ||
} | ||
HashInfos[&MBB].NeighborHash = Hash; | ||
} | ||
|
||
// Assign hashes | ||
for (const MachineBasicBlock &MBB : F) { | ||
BlendedBlockHash BlendedHash(fold_64_to_16(HashInfos[&MBB].Offset), | ||
fold_64_to_16(HashInfos[&MBB].OpcodeHash), | ||
fold_64_to_16(HashInfos[&MBB].InstrHash), | ||
fold_64_to_16(HashInfos[&MBB].NeighborHash)); | ||
MBBHashInfo[&MBB] = BlendedHash.combine(); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
uint64_t MachineBlockHashInfo::getMBBHash(const MachineBasicBlock &MBB) { | ||
return MBBHashInfo[&MBB]; | ||
} | ||
|
||
MachineFunctionPass *llvm::createMachineBlockHashInfoPass() { | ||
return new MachineBlockHashInfo(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move these to the constructor and combine methods below. I don't think there is any point in defining these here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.