Skip to content

Commit 91f5b9d

Browse files
committed
[sil-performance-inliner] Re-introduce inlining of generics as a staging feature behind a flag
Use the following options to enable this flag: -Xllvm -sil-inline-generics Generic inlining is now handled by a dedicated logic in isProfitableToInlineGeneric. This makes it easier to find this logic. And it will make it easier to extend and improve it in the future. The initial policy for generic inlining is: - unconditionally inline generic functions if the -sil-inline-generics flag is used. - If the flag is not used, only perform generic inlining of always_inline and transparent functions. There are slight standard library's code-size regressions with this policy. They will be addressed by the future work on the generic inlining.
1 parent c5b1e09 commit 91f5b9d

File tree

1 file changed

+48
-6
lines changed

1 file changed

+48
-6
lines changed

lib/SILOptimizer/Transforms/PerformanceInliner.cpp

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/SILOptimizer/PassManager/Passes.h"
1515
#include "swift/SILOptimizer/PassManager/Transforms.h"
1616
#include "swift/SILOptimizer/Utils/PerformanceInlinerUtils.h"
17+
#include "swift/Strings.h"
1718
#include "llvm/ADT/Statistic.h"
1819
#include "llvm/Support/Debug.h"
1920
#include "llvm/Support/CommandLine.h"
@@ -26,6 +27,10 @@ llvm::cl::opt<bool> PrintShortestPathInfo(
2627
"print-shortest-path-info", llvm::cl::init(false),
2728
llvm::cl::desc("Print shortest-path information for inlining"));
2829

30+
llvm::cl::opt<bool> EnableSILInliningOfGenerics(
31+
"sil-inline-generics", llvm::cl::init(false),
32+
llvm::cl::desc("Enable inlining of generics"));
33+
2934
//===----------------------------------------------------------------------===//
3035
// Performance Inliner
3136
//===----------------------------------------------------------------------===//
@@ -122,6 +127,11 @@ class SILPerformanceInliner {
122127
ConstantTracker &constTracker,
123128
int &NumCallerBlocks);
124129

130+
bool isProfitableToInlineGeneric(FullApplySite AI,
131+
Weight CallerWeight,
132+
ConstantTracker &constTracker,
133+
int &NumCallerBlocks);
134+
125135
bool isProfitableInColdBlock(FullApplySite AI, SILFunction *Callee);
126136

127137
void visitColdBlocks(SmallVectorImpl<FullApplySite> &AppliesToInline,
@@ -191,10 +201,6 @@ SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
191201
return nullptr;
192202
}
193203

194-
// We don't support this yet.
195-
if (AI.hasSubstitutions())
196-
return nullptr;
197-
198204
SILFunction *Caller = AI.getFunction();
199205

200206
// We don't support inlining a function that binds dynamic self because we
@@ -369,6 +375,37 @@ bool SILPerformanceInliner::isProfitableToInlineNonGeneric(FullApplySite AI,
369375
return true;
370376
}
371377

378+
/// Return true if inlining this call site is profitable.
379+
bool SILPerformanceInliner::isProfitableToInlineGeneric(FullApplySite AI,
380+
Weight CallerWeight,
381+
ConstantTracker &callerTracker,
382+
int &NumCallerBlocks) {
383+
assert(!AI.getSubstitutions().empty() &&
384+
"Expected a generic apply");
385+
386+
SILFunction *Callee = AI.getReferencedFunction();
387+
388+
// Do not inline @_semantics functions when compiling the stdlib,
389+
// because they need to be preserved, so that the optimizer
390+
// can properly optimize a user code later.
391+
auto ModuleName = Callee->getModule().getSwiftModule()->getName().str();
392+
if (Callee->hasSemanticsAttrThatStartsWith("array.") &&
393+
(ModuleName == STDLIB_NAME || ModuleName == SWIFT_ONONE_SUPPORT))
394+
return false;
395+
396+
// Always inline generic functions which are marked as
397+
// AlwaysInline or transparent.
398+
bool ShouldInline = Callee->getInlineStrategy() == AlwaysInline ||
399+
Callee->isTransparent();
400+
401+
// Only inline if we decided to inline or we are asked to inline all
402+
// generic functions.
403+
if (ShouldInline || EnableSILInliningOfGenerics)
404+
return true;
405+
406+
return false;
407+
}
408+
372409
/// Return true if inlining this call site into a cold block is profitable.
373410
bool SILPerformanceInliner::isProfitableInColdBlock(FullApplySite AI,
374411
SILFunction *Callee) {
@@ -482,8 +519,13 @@ void SILPerformanceInliner::collectAppliesToInline(
482519
// The actual weight including a possible weight correction.
483520
Weight W(BlockWeight, WeightCorrections.lookup(AI));
484521

485-
bool IsProfitableToInline = isProfitableToInlineNonGeneric(
486-
AI, W, constTracker, NumCallerBlocks);
522+
bool IsGenericApply = !AI.getSubstitutions().empty();
523+
bool IsProfitableToInline =
524+
IsGenericApply ? isProfitableToInlineGeneric(AI, W, constTracker,
525+
NumCallerBlocks)
526+
: isProfitableToInlineNonGeneric(AI, W, constTracker,
527+
NumCallerBlocks);
528+
487529
if (IsProfitableToInline)
488530
InitialCandidates.push_back(AI);
489531
}

0 commit comments

Comments
 (0)