Skip to content

Commit faf7994

Browse files
authored
Merge pull request swiftlang#33331 from eeckstein/merge-functions
LLVMMergeFunctions: allow more parameters if the function is bigger
2 parents 20e25e4 + 145b8ae commit faf7994

File tree

1 file changed

+35
-26
lines changed

1 file changed

+35
-26
lines changed

lib/LLVMPasses/LLVMMergeFunctions.cpp

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,6 @@ class SwiftMergeFunctions : public ModulePass {
222222
bool runOnModule(Module &M) override;
223223

224224
private:
225-
enum {
226-
/// The maximum number of parameters added to a merged functions. This
227-
/// roughly corresponds to the number of differing constants.
228-
maxAddedParams = 4
229-
};
230-
231225
struct FunctionEntry;
232226

233227
/// Describes the set of functions which are considered as "equivalent" (i.e.
@@ -359,7 +353,7 @@ class SwiftMergeFunctions : public ModulePass {
359353
}
360354
};
361355

362-
using ParamInfos = SmallVector<ParamInfo, maxAddedParams>;
356+
using ParamInfos = SmallVector<ParamInfo, 16>;
363357

364358
GlobalNumberState GlobalNumbers;
365359

@@ -398,14 +392,15 @@ class SwiftMergeFunctions : public ModulePass {
398392

399393
FunctionInfo removeFuncWithMostParams(FunctionInfos &FInfos);
400394

401-
bool deriveParams(ParamInfos &Params, FunctionInfos &FInfos);
395+
bool deriveParams(ParamInfos &Params, FunctionInfos &FInfos,
396+
unsigned maxParams);
402397

403398
bool numOperandsDiffer(FunctionInfos &FInfos);
404399

405400
bool constsDiffer(const FunctionInfos &FInfos, unsigned OpIdx);
406401

407402
bool tryMapToParameter(FunctionInfos &FInfos, unsigned OpIdx,
408-
ParamInfos &Params);
403+
ParamInfos &Params, unsigned maxParams);
409404

410405
void mergeWithParams(const FunctionInfos &FInfos, ParamInfos &Params);
411406

@@ -524,17 +519,9 @@ static bool mayMergeCallsToFunction(Function &F) {
524519
return true;
525520
}
526521

527-
/// Returns true if function \p F is eligible for merging.
528-
static bool isEligibleFunction(Function *F) {
529-
if (F->isDeclaration())
530-
return false;
531-
532-
if (F->hasAvailableExternallyLinkage())
533-
return false;
534-
535-
if (F->getFunctionType()->isVarArg())
536-
return false;
537-
522+
/// Returns the benefit, which is approximately the size of the function.
523+
/// Return 0, if the function should not be merged.
524+
static unsigned getBenefit(Function *F) {
538525
unsigned Benefit = 0;
539526

540527
// We don't want to merge very small functions, because the overhead of
@@ -545,7 +532,7 @@ static bool isEligibleFunction(Function *F) {
545532
if (CallBase *CB = dyn_cast<CallBase>(&I)) {
546533
Function *Callee = CB->getCalledFunction();
547534
if (Callee && !mayMergeCallsToFunction(*Callee))
548-
return false;
535+
return 0;
549536
if (!Callee || !Callee->isIntrinsic()) {
550537
Benefit += 5;
551538
continue;
@@ -554,6 +541,21 @@ static bool isEligibleFunction(Function *F) {
554541
Benefit += 1;
555542
}
556543
}
544+
return Benefit;
545+
}
546+
547+
/// Returns true if function \p F is eligible for merging.
548+
static bool isEligibleFunction(Function *F) {
549+
if (F->isDeclaration())
550+
return false;
551+
552+
if (F->hasAvailableExternallyLinkage())
553+
return false;
554+
555+
if (F->getFunctionType()->isVarArg())
556+
return false;
557+
558+
unsigned Benefit = getBenefit(F);
557559
if (Benefit < FunctionMergeThreshold)
558560
return false;
559561

@@ -723,12 +725,17 @@ bool SwiftMergeFunctions::tryMergeEquivalenceClass(FunctionEntry *FirstInClass)
723725
bool Changed = false;
724726
int Try = 0;
725727

728+
unsigned Benefit = getBenefit(FirstInClass->F);
729+
730+
// The bigger the function, the more parameters are allowed.
731+
unsigned maxParams = std::max(4u, Benefit / 100);
732+
726733
// We need multiple tries if there are some functions in FInfos which differ
727734
// too much from the first function in FInfos. But we limit the number of
728735
// tries to a small number, because this is quadratic.
729736
while (FInfos.size() >= 2 && Try++ < 4) {
730737
ParamInfos Params;
731-
bool Merged = deriveParams(Params, FInfos);
738+
bool Merged = deriveParams(Params, FInfos, maxParams);
732739
if (Merged) {
733740
mergeWithParams(FInfos, Params);
734741
Changed = true;
@@ -767,7 +774,8 @@ removeFuncWithMostParams(FunctionInfos &FInfos) {
767774
/// Returns true on success, i.e. the functions in \p FInfos can be merged with
768775
/// the parameters returned in \p Params.
769776
bool SwiftMergeFunctions::deriveParams(ParamInfos &Params,
770-
FunctionInfos &FInfos) {
777+
FunctionInfos &FInfos,
778+
unsigned maxParams) {
771779
for (FunctionInfo &FI : FInfos)
772780
FI.init();
773781

@@ -796,7 +804,7 @@ bool SwiftMergeFunctions::deriveParams(ParamInfos &Params,
796804
if (constsDiffer(FInfos, OpIdx)) {
797805
// This instruction has operands which differ in at least some
798806
// functions. So we need to parameterize it.
799-
if (!tryMapToParameter(FInfos, OpIdx, Params)) {
807+
if (!tryMapToParameter(FInfos, OpIdx, Params, maxParams)) {
800808
// We ran out of parameters.
801809
return false;
802810
}
@@ -845,7 +853,8 @@ bool SwiftMergeFunctions::constsDiffer(const FunctionInfos &FInfos,
845853
/// Returns true if a parameter could be created or found without exceeding the
846854
/// maximum number of parameters.
847855
bool SwiftMergeFunctions::tryMapToParameter(FunctionInfos &FInfos,
848-
unsigned OpIdx, ParamInfos &Params) {
856+
unsigned OpIdx, ParamInfos &Params,
857+
unsigned maxParams) {
849858
ParamInfo *Matching = nullptr;
850859
// Try to find an existing parameter which exactly matches the differing
851860
// operands of the current instruction.
@@ -858,7 +867,7 @@ bool SwiftMergeFunctions::tryMapToParameter(FunctionInfos &FInfos,
858867
if (!Matching) {
859868
// We need a new parameter.
860869
// Check if we are within the limit.
861-
if (Params.size() >= maxAddedParams)
870+
if (Params.size() >= maxParams)
862871
return false;
863872

864873
Params.resize(Params.size() + 1);

0 commit comments

Comments
 (0)