12
12
13
13
#define DEBUG_TYPE " sil-inliner"
14
14
#include " swift/AST/Module.h"
15
+ #include " swift/SIL/MemAccessUtils.h"
15
16
#include " swift/SIL/OptimizationRemark.h"
16
17
#include " swift/SILOptimizer/Analysis/SideEffectAnalysis.h"
17
18
#include " swift/SILOptimizer/PassManager/Passes.h"
@@ -100,6 +101,11 @@ class SILPerformanceInliner {
100
101
// / specialization for a call.
101
102
GenericSpecializationBenefit = RemovedCallBenefit + 300 ,
102
103
104
+ // / The benefit of inlining an exclusivity-containing callee.
105
+ // / The exclusivity needs to be: dynamic,
106
+ // / has no nested conflict and addresses known storage
107
+ ExclusivityBenefit = RemovedCallBenefit + 300 ,
108
+
103
109
// / The benefit of inlining class methods with -Osize.
104
110
// / We only inline very small class methods with -Osize.
105
111
OSizeClassMethodBenefit = 5 ,
@@ -108,8 +114,8 @@ class SILPerformanceInliner {
108
114
// / increasing the code size.
109
115
TrivialFunctionThreshold = 18 ,
110
116
111
- // / Configuration for the "soft" caller block limit. When changing, make sure
112
- // / you update BlockLimitMaxIntNumerator.
117
+ // / Configuration for the "soft" caller block limit. When changing, make
118
+ // / sure you update BlockLimitMaxIntNumerator.
113
119
BlockLimitDenominator = 3000 ,
114
120
115
121
// / Computations with BlockLimitDenominator will overflow with numerators
@@ -298,9 +304,18 @@ bool SILPerformanceInliner::isProfitableToInline(
298
304
SILBasicBlock *CalleeEntry = &Callee->front ();
299
305
DominanceOrder domOrder (CalleeEntry, DT, Callee->size ());
300
306
307
+ // We don't want to blow up code-size
308
+ // We will only inline if *ALL* dynamic accesses are
309
+ // known and have no nested conflict
310
+ bool AllAccessesBeneficialToInline = true ;
311
+
301
312
// Calculate the inlining cost of the callee.
302
313
int CalleeCost = 0 ;
303
314
int Benefit = 0 ;
315
+ // We don’t know if we want to update the benefit with
316
+ // the exclusivity heuristic or not. We can *only* do that
317
+ // if AllAccessesBeneficialToInline is true
318
+ int ExclusivityBenefitWeight = 0 ;
304
319
305
320
SubstitutionMap CalleeSubstMap = AI.getSubstitutionMap ();
306
321
@@ -392,6 +407,21 @@ bool SILPerformanceInliner::isProfitableToInline(
392
407
} else if (auto *BI = dyn_cast<BuiltinInst>(&I)) {
393
408
if (BI->getBuiltinInfo ().ID == BuiltinValueKind::OnFastPath)
394
409
BlockW.updateBenefit (Benefit, FastPathBuiltinBenefit);
410
+ } else if (auto *BAI = dyn_cast<BeginAccessInst>(&I)) {
411
+ if (BAI->getEnforcement () == SILAccessEnforcement::Dynamic) {
412
+ // The access is dynamic and has no nested conflict
413
+ // See if the storage location is considered by
414
+ // access enforcement optimizations
415
+ AccessedStorage storage =
416
+ findAccessedStorageNonNested (BAI->getSource ());
417
+ if (BAI->hasNoNestedConflict () &&
418
+ (storage.isUniquelyIdentified () ||
419
+ storage.getKind () == AccessedStorage::Class)) {
420
+ BlockW.updateBenefit (ExclusivityBenefitWeight, ExclusivityBenefit);
421
+ } else {
422
+ AllAccessesBeneficialToInline = false ;
423
+ }
424
+ }
395
425
}
396
426
}
397
427
// Don't count costs in blocks which are dead after inlining.
@@ -407,6 +437,10 @@ bool SILPerformanceInliner::isProfitableToInline(
407
437
}
408
438
}
409
439
440
+ if (AllAccessesBeneficialToInline) {
441
+ Benefit = std::max (Benefit, ExclusivityBenefitWeight);
442
+ }
443
+
410
444
if (AI.getFunction ()->isThunk ()) {
411
445
// Only inline trivial functions into thunks (which will not increase the
412
446
// code size).
0 commit comments