Skip to content

Commit 70dcb2c

Browse files
committed
[CGData] Refactor Global Merge Functions
1 parent 3f335e8 commit 70dcb2c

File tree

1 file changed

+59
-89
lines changed

1 file changed

+59
-89
lines changed

llvm/lib/CodeGen/GlobalMergeFunctions.cpp

Lines changed: 59 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,6 @@ 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");
4234
STATISTIC(NumMergedFunctions,
4335
"Number of functions that are actually merged using function hash");
4436
STATISTIC(NumAnalyzedModues, "Number of modules that are analyzed");
@@ -203,9 +195,9 @@ void GlobalMergeFunc::analyze(Module &M) {
203195
struct FuncMergeInfo {
204196
StableFunctionMap::StableFunctionEntry *SF;
205197
Function *F;
206-
std::unique_ptr<IndexInstrMap> IndexInstruction;
198+
IndexInstrMap *IndexInstruction;
207199
FuncMergeInfo(StableFunctionMap::StableFunctionEntry *SF, Function *F,
208-
std::unique_ptr<IndexInstrMap> IndexInstruction)
200+
IndexInstrMap *IndexInstruction)
209201
: SF(SF), F(F), IndexInstruction(std::move(IndexInstruction)) {}
210202
};
211203

@@ -420,101 +412,79 @@ static ParamLocsVecTy computeParamInfo(
420412
bool GlobalMergeFunc::merge(Module &M, const StableFunctionMap *FunctionMap) {
421413
bool Changed = false;
422414

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.
415+
// Collect stable functions related to the current module.
416+
DenseMap<stable_hash, SmallVector<Function *>> HashToFuncs;
417+
DenseMap<Function *, FunctionHashInfo> FuncToFI;
418+
auto &Maps = FunctionMap->getFunctionMap();
419+
for (auto &F : M) {
420+
if (!isEligibleFunction(&F))
421+
continue;
422+
auto FI = llvm::StructuralHashWithDifferences(F, ignoreOp);
423+
if (Maps.contains(FI.FunctionHash)) {
424+
HashToFuncs[FI.FunctionHash].push_back(&F);
425+
FuncToFI.try_emplace(&F, std::move(FI));
426+
}
427+
}
428+
429+
for (auto &[Hash, Funcs] : HashToFuncs) {
434430
std::optional<ParamLocsVecTy> ParamLocsVec;
435-
Function *MergedFunc = nullptr;
436-
std::string MergedModId;
437431
SmallVector<FuncMergeInfo> FuncMergeInfos;
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))
451-
continue;
452432

453-
auto FI = llvm::StructuralHashWithDifferences(*F, ignoreOp);
454-
uint64_t FuncHash = FI.FunctionHash;
455-
if (Hash != FuncHash) {
456-
++NumMismatchedFunctionHash;
457-
continue;
458-
}
433+
// Iterate functions with the same hash.
434+
for (auto &F : Funcs) {
435+
auto &SFS = Maps.at(Hash);
436+
auto &FI = FuncToFI.at(F);
459437

460-
if (SF->InstCount != FI.IndexInstruction->size()) {
461-
++NumMismatchedInstCount;
438+
// Check if the function is compatible with any stable function
439+
// in terms of the number of instructions and ignored operands.
440+
assert(!SFS.empty());
441+
auto &RFS = SFS[0];
442+
if (RFS->InstCount != FI.IndexInstruction->size())
462443
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;
472-
}
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;
444+
445+
auto hasValidSharedConst =
446+
[&](StableFunctionMap::StableFunctionEntry *SF) {
447+
for (auto &[Index, Hash] : *SF->IndexOperandHashMap) {
448+
auto [InstIndex, OpndIndex] = Index;
449+
assert(InstIndex < FI.IndexInstruction->size());
450+
auto *Inst = FI.IndexInstruction->lookup(InstIndex);
451+
if (!ignoreOp(Inst, OpndIndex))
452+
return false;
453+
}
454+
return true;
455+
};
456+
if (!hasValidSharedConst(RFS.get()))
491457
continue;
492-
}
493458

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;
459+
for (auto &SF : SFS) {
460+
assert(SF->InstCount == FI.IndexInstruction->size());
461+
assert(hasValidSharedConst(SF.get()));
462+
// Check if there is any stable function that is compatiable with the
463+
// current one.
464+
if (!checkConstHashCompatible(*SF->IndexOperandHashMap,
465+
*FI.IndexOperandHashMap))
502466
continue;
467+
if (!ParamLocsVec.has_value()) {
468+
ParamLocsVec = computeParamInfo(SFS);
469+
LLVM_DEBUG(dbgs() << "[GlobalMergeFunc] Merging hash: " << Hash
470+
<< " with Params " << ParamLocsVec->size() << "\n");
503471
}
504-
} else {
505-
MergedFunc = F;
506-
MergedModId = *FunctionMap->getNameForId(SF->ModuleNameId);
507-
}
472+
if (!checkConstLocationCompatible(*SF, *FI.IndexInstruction,
473+
*ParamLocsVec))
474+
continue;
508475

509-
FuncMergeInfos.emplace_back(SF.get(), F, std::move(FI.IndexInstruction));
510-
MergedFunctions.insert(F);
476+
// As long as we found one stable function matching the current one,
477+
// we create a candidate for merging and move on to the next function.
478+
FuncMergeInfos.emplace_back(SF.get(), F, FI.IndexInstruction.get());
479+
break;
480+
}
511481
}
512482
unsigned FuncMergeInfoSize = FuncMergeInfos.size();
513483
if (FuncMergeInfoSize == 0)
514484
continue;
515485

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

519489
for (auto &FMI : FuncMergeInfos) {
520490
Changed = true;

0 commit comments

Comments
 (0)