Skip to content

Commit 5a2888d

Browse files
committed
Revert "[CGData] Refactor Global Merge Functions (#115750)"
This reverts commit d3da788.
1 parent 40edb0a commit 5a2888d

File tree

1 file changed

+93
-64
lines changed

1 file changed

+93
-64
lines changed

llvm/lib/CodeGen/GlobalMergeFunctions.cpp

Lines changed: 93 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ static cl::opt<bool> DisableCGDataForMerging(
3131
"merging is still enabled within a module."),
3232
cl::init(false));
3333

34+
STATISTIC(NumMismatchedFunctionHash,
35+
"Number of mismatched function hash for global merge function");
36+
STATISTIC(NumMismatchedInstCount,
37+
"Number of mismatched instruction count for global merge function");
38+
STATISTIC(NumMismatchedConstHash,
39+
"Number of mismatched const hash for global merge function");
40+
STATISTIC(NumMismatchedModuleId,
41+
"Number of mismatched Module Id for global merge function");
3442
STATISTIC(NumMergedFunctions,
3543
"Number of functions that are actually merged using function hash");
3644
STATISTIC(NumAnalyzedModues, "Number of modules that are analyzed");
@@ -102,7 +110,7 @@ bool isEligibleFunction(Function *F) {
102110
return true;
103111
}
104112

105-
static bool isEligibleInstructionForConstantSharing(const Instruction *I) {
113+
static bool isEligibleInstrunctionForConstantSharing(const Instruction *I) {
106114
switch (I->getOpcode()) {
107115
case Instruction::Load:
108116
case Instruction::Store:
@@ -114,15 +122,10 @@ static bool isEligibleInstructionForConstantSharing(const Instruction *I) {
114122
}
115123
}
116124

117-
// This function takes an instruction, \p I, and an operand index, \p OpIdx.
118-
// It returns true if the operand should be ignored in the hash computation.
119-
// If \p OpIdx is out of range based on the other instruction context, it cannot
120-
// be ignored.
121125
static bool ignoreOp(const Instruction *I, unsigned OpIdx) {
122-
if (OpIdx >= I->getNumOperands())
123-
return false;
126+
assert(OpIdx < I->getNumOperands() && "Invalid operand index");
124127

125-
if (!isEligibleInstructionForConstantSharing(I))
128+
if (!isEligibleInstrunctionForConstantSharing(I))
126129
return false;
127130

128131
if (!isa<Constant>(I->getOperand(OpIdx)))
@@ -200,9 +203,9 @@ void GlobalMergeFunc::analyze(Module &M) {
200203
struct FuncMergeInfo {
201204
StableFunctionMap::StableFunctionEntry *SF;
202205
Function *F;
203-
IndexInstrMap *IndexInstruction;
206+
std::unique_ptr<IndexInstrMap> IndexInstruction;
204207
FuncMergeInfo(StableFunctionMap::StableFunctionEntry *SF, Function *F,
205-
IndexInstrMap *IndexInstruction)
208+
std::unique_ptr<IndexInstrMap> IndexInstruction)
206209
: SF(SF), F(F), IndexInstruction(std::move(IndexInstruction)) {}
207210
};
208211

@@ -417,75 +420,101 @@ static ParamLocsVecTy computeParamInfo(
417420
bool GlobalMergeFunc::merge(Module &M, const StableFunctionMap *FunctionMap) {
418421
bool Changed = false;
419422

420-
// Collect stable functions related to the current module.
421-
DenseMap<stable_hash, SmallVector<std::pair<Function *, FunctionHashInfo>>>
422-
HashToFuncs;
423-
auto &Maps = FunctionMap->getFunctionMap();
424-
for (auto &F : M) {
425-
if (!isEligibleFunction(&F))
426-
continue;
427-
auto FI = llvm::StructuralHashWithDifferences(F, ignoreOp);
428-
if (Maps.contains(FI.FunctionHash))
429-
HashToFuncs[FI.FunctionHash].emplace_back(&F, std::move(FI));
430-
}
431-
432-
for (auto &[Hash, Funcs] : HashToFuncs) {
423+
// Build a map from stable function name to function.
424+
StringMap<Function *> StableNameToFuncMap;
425+
for (auto &F : M)
426+
StableNameToFuncMap[get_stable_name(F.getName())] = &F;
427+
// Track merged functions
428+
DenseSet<Function *> MergedFunctions;
429+
430+
auto ModId = M.getModuleIdentifier();
431+
for (auto &[Hash, SFS] : FunctionMap->getFunctionMap()) {
432+
// Parameter locations based on the unique hash sequences
433+
// across the candidates.
433434
std::optional<ParamLocsVecTy> ParamLocsVec;
435+
Function *MergedFunc = nullptr;
436+
std::string MergedModId;
434437
SmallVector<FuncMergeInfo> FuncMergeInfos;
435-
auto &SFS = Maps.at(Hash);
436-
assert(!SFS.empty());
437-
auto &RFS = SFS[0];
438-
439-
// Iterate functions with the same hash.
440-
for (auto &[F, FI] : Funcs) {
441-
// Check if the function is compatible with any stable function
442-
// in terms of the number of instructions and ignored operands.
443-
if (RFS->InstCount != FI.IndexInstruction->size())
438+
for (auto &SF : SFS) {
439+
// Get the function from the stable name.
440+
auto I = StableNameToFuncMap.find(
441+
*FunctionMap->getNameForId(SF->FunctionNameId));
442+
if (I == StableNameToFuncMap.end())
443+
continue;
444+
Function *F = I->second;
445+
assert(F);
446+
// Skip if the function has been merged before.
447+
if (MergedFunctions.count(F))
448+
continue;
449+
// Consider the function if it is eligible for merging.
450+
if (!isEligibleFunction(F))
444451
continue;
445452

446-
auto hasValidSharedConst =
447-
[&](StableFunctionMap::StableFunctionEntry *SF) {
448-
for (auto &[Index, Hash] : *SF->IndexOperandHashMap) {
449-
auto [InstIndex, OpndIndex] = Index;
450-
assert(InstIndex < FI.IndexInstruction->size());
451-
auto *Inst = FI.IndexInstruction->lookup(InstIndex);
452-
if (!ignoreOp(Inst, OpndIndex))
453-
return false;
454-
}
455-
return true;
456-
};
457-
if (!hasValidSharedConst(RFS.get()))
453+
auto FI = llvm::StructuralHashWithDifferences(*F, ignoreOp);
454+
uint64_t FuncHash = FI.FunctionHash;
455+
if (Hash != FuncHash) {
456+
++NumMismatchedFunctionHash;
458457
continue;
458+
}
459459

460-
for (auto &SF : SFS) {
461-
assert(SF->InstCount == FI.IndexInstruction->size());
462-
assert(hasValidSharedConst(SF.get()));
463-
// Check if there is any stable function that is compatiable with the
464-
// current one.
465-
if (!checkConstHashCompatible(*SF->IndexOperandHashMap,
466-
*FI.IndexOperandHashMap))
467-
continue;
468-
if (!ParamLocsVec.has_value()) {
469-
ParamLocsVec = computeParamInfo(SFS);
470-
LLVM_DEBUG(dbgs() << "[GlobalMergeFunc] Merging hash: " << Hash
471-
<< " with Params " << ParamLocsVec->size() << "\n");
460+
if (SF->InstCount != FI.IndexInstruction->size()) {
461+
++NumMismatchedInstCount;
462+
continue;
463+
}
464+
bool HasValidSharedConst = true;
465+
for (auto &[Index, Hash] : *SF->IndexOperandHashMap) {
466+
auto [InstIndex, OpndIndex] = Index;
467+
assert(InstIndex < FI.IndexInstruction->size());
468+
auto *Inst = FI.IndexInstruction->lookup(InstIndex);
469+
if (!ignoreOp(Inst, OpndIndex)) {
470+
HasValidSharedConst = false;
471+
break;
472472
}
473-
if (!checkConstLocationCompatible(*SF, *FI.IndexInstruction,
474-
*ParamLocsVec))
475-
continue;
473+
}
474+
if (!HasValidSharedConst) {
475+
++NumMismatchedConstHash;
476+
continue;
477+
}
478+
if (!checkConstHashCompatible(*SF->IndexOperandHashMap,
479+
*FI.IndexOperandHashMap)) {
480+
++NumMismatchedConstHash;
481+
continue;
482+
}
483+
if (!ParamLocsVec.has_value()) {
484+
ParamLocsVec = computeParamInfo(SFS);
485+
LLVM_DEBUG(dbgs() << "[GlobalMergeFunc] Merging hash: " << Hash
486+
<< " with Params " << ParamLocsVec->size() << "\n");
487+
}
488+
if (!checkConstLocationCompatible(*SF, *FI.IndexInstruction,
489+
*ParamLocsVec)) {
490+
++NumMismatchedConstHash;
491+
continue;
492+
}
476493

477-
// If a stable function matching the current one is found,
478-
// create a candidate for merging and proceed to the next function.
479-
FuncMergeInfos.emplace_back(SF.get(), F, FI.IndexInstruction.get());
480-
break;
494+
if (MergedFunc) {
495+
// Check if the matched functions fall into the same (first) module.
496+
// This module check is not strictly necessary as the functions can move
497+
// around. We just want to avoid merging functions from different
498+
// modules than the first one in the function map, as they may not end
499+
// up with being ICFed by the linker.
500+
if (MergedModId != *FunctionMap->getNameForId(SF->ModuleNameId)) {
501+
++NumMismatchedModuleId;
502+
continue;
503+
}
504+
} else {
505+
MergedFunc = F;
506+
MergedModId = *FunctionMap->getNameForId(SF->ModuleNameId);
481507
}
508+
509+
FuncMergeInfos.emplace_back(SF.get(), F, std::move(FI.IndexInstruction));
510+
MergedFunctions.insert(F);
482511
}
483512
unsigned FuncMergeInfoSize = FuncMergeInfos.size();
484513
if (FuncMergeInfoSize == 0)
485514
continue;
486515

487516
LLVM_DEBUG(dbgs() << "[GlobalMergeFunc] Merging function count "
488-
<< FuncMergeInfoSize << " for hash: " << Hash << "\n");
517+
<< FuncMergeInfoSize << " in " << ModId << "\n");
489518

490519
for (auto &FMI : FuncMergeInfos) {
491520
Changed = true;

0 commit comments

Comments
 (0)