@@ -217,10 +217,10 @@ class SILPerformanceInliner {
217
217
int &NumCallerBlocks,
218
218
const llvm::DenseMap<SILBasicBlock *, uint64_t > &BBToWeightMap);
219
219
220
- bool decideInColdBlock (FullApplySite AI, SILFunction *Callee);
220
+ bool decideInColdBlock (FullApplySite AI, SILFunction *Callee, int numCallerBlocks );
221
221
222
222
void visitColdBlocks (SmallVectorImpl<FullApplySite> &AppliesToInline,
223
- SILBasicBlock *root, DominanceInfo *DT);
223
+ SILBasicBlock *root, DominanceInfo *DT, int numCallerBlocks );
224
224
225
225
void collectAppliesToInline (SILFunction *Caller,
226
226
SmallVectorImpl<FullApplySite> &Applies);
@@ -619,12 +619,29 @@ static bool returnsClosure(SILFunction *F) {
619
619
return false ;
620
620
}
621
621
622
- static bool isInlineAlwaysCallSite (SILFunction *Callee) {
622
+ static bool hasMaxNumberOfBasicBlocks (SILFunction *f, int limit) {
623
+ for (SILBasicBlock &block : *f) {
624
+ (void )block;
625
+ if (limit == 0 )
626
+ return false ;
627
+ limit--;
628
+ }
629
+ return true ;
630
+ }
631
+
632
+ static bool isInlineAlwaysCallSite (SILFunction *Callee, int numCallerBlocks) {
623
633
if (Callee->isTransparent ())
624
634
return true ;
625
- if (Callee->getInlineStrategy () == AlwaysInline)
626
- if (!Callee->getModule ().getOptions ().IgnoreAlwaysInline )
627
- return true ;
635
+ if (Callee->getInlineStrategy () == AlwaysInline &&
636
+ !Callee->getModule ().getOptions ().IgnoreAlwaysInline &&
637
+
638
+ // Protect against misuse of @inline(__always).
639
+ // Inline-always should only be used on relatively small functions.
640
+ // It must not be used on recursive functions. This check prevents that
641
+ // the compiler blows up if @inline(__always) is put on a recursive function.
642
+ (numCallerBlocks < 64 || hasMaxNumberOfBasicBlocks (Callee, 64 ))) {
643
+ return true ;
644
+ }
628
645
return false ;
629
646
}
630
647
@@ -634,7 +651,7 @@ static bool isInlineAlwaysCallSite(SILFunction *Callee) {
634
651
// / It returns false if a function should not be inlined.
635
652
// / It returns None if the decision cannot be made without a more complex
636
653
// / analysis.
637
- static Optional<bool > shouldInlineGeneric (FullApplySite AI) {
654
+ static Optional<bool > shouldInlineGeneric (FullApplySite AI, int numCallerBlocks ) {
638
655
assert (AI.hasSubstitutions () &&
639
656
" Expected a generic apply" );
640
657
@@ -654,7 +671,7 @@ static Optional<bool> shouldInlineGeneric(FullApplySite AI) {
654
671
655
672
// Always inline generic functions which are marked as
656
673
// AlwaysInline or transparent.
657
- if (isInlineAlwaysCallSite (Callee))
674
+ if (isInlineAlwaysCallSite (Callee, numCallerBlocks ))
658
675
return true ;
659
676
660
677
// If all substitutions are concrete, then there is no need to perform the
@@ -694,14 +711,14 @@ bool SILPerformanceInliner::decideInWarmBlock(
694
711
const llvm::DenseMap<SILBasicBlock *, uint64_t > &BBToWeightMap) {
695
712
if (AI.hasSubstitutions ()) {
696
713
// Only inline generics if definitively clear that it should be done.
697
- auto ShouldInlineGeneric = shouldInlineGeneric (AI);
714
+ auto ShouldInlineGeneric = shouldInlineGeneric (AI, NumCallerBlocks );
698
715
if (ShouldInlineGeneric.has_value ())
699
716
return ShouldInlineGeneric.value ();
700
717
}
701
718
702
719
SILFunction *Callee = AI.getReferencedFunctionOrNull ();
703
720
704
- if (isInlineAlwaysCallSite (Callee)) {
721
+ if (isInlineAlwaysCallSite (Callee, NumCallerBlocks )) {
705
722
LLVM_DEBUG (dumpCaller (AI.getFunction ());
706
723
llvm::dbgs () << " always-inline decision "
707
724
<< Callee->getName () << ' \n ' );
@@ -714,17 +731,17 @@ bool SILPerformanceInliner::decideInWarmBlock(
714
731
715
732
// / Return true if inlining this call site into a cold block is profitable.
716
733
bool SILPerformanceInliner::decideInColdBlock (FullApplySite AI,
717
- SILFunction *Callee) {
734
+ SILFunction *Callee, int numCallerBlocks ) {
718
735
if (AI.hasSubstitutions ()) {
719
736
// Only inline generics if definitively clear that it should be done.
720
- auto ShouldInlineGeneric = shouldInlineGeneric (AI);
737
+ auto ShouldInlineGeneric = shouldInlineGeneric (AI, numCallerBlocks );
721
738
if (ShouldInlineGeneric.has_value ())
722
739
return ShouldInlineGeneric.value ();
723
740
724
741
return false ;
725
742
}
726
743
727
- if (isInlineAlwaysCallSite (Callee)) {
744
+ if (isInlineAlwaysCallSite (Callee, numCallerBlocks )) {
728
745
LLVM_DEBUG (dumpCaller (AI.getFunction ());
729
746
llvm::dbgs () << " always-inline decision "
730
747
<< Callee->getName () << ' \n ' );
@@ -923,7 +940,7 @@ void SILPerformanceInliner::collectAppliesToInline(
923
940
if (Callee) {
924
941
// Check if we have an always_inline or transparent function. If we do,
925
942
// just add it to our final Applies list and continue.
926
- if (isInlineAlwaysCallSite (Callee)) {
943
+ if (isInlineAlwaysCallSite (Callee, NumCallerBlocks )) {
927
944
NumCallerBlocks += Callee->size ();
928
945
Applies.push_back (AI);
929
946
continue ;
@@ -953,7 +970,7 @@ void SILPerformanceInliner::collectAppliesToInline(
953
970
domOrder.pushChildrenIf (block, [&] (SILBasicBlock *child) {
954
971
if (CBI.isSlowPath (block, child)) {
955
972
// Handle cold blocks separately.
956
- visitColdBlocks (InitialCandidates, child, DT);
973
+ visitColdBlocks (InitialCandidates, child, DT, NumCallerBlocks );
957
974
return false ;
958
975
}
959
976
return true ;
@@ -1089,7 +1106,7 @@ bool SILPerformanceInliner::inlineCallsIntoFunction(SILFunction *Caller) {
1089
1106
// All other functions are not inlined in cold blocks.
1090
1107
void SILPerformanceInliner::visitColdBlocks (
1091
1108
SmallVectorImpl<FullApplySite> &AppliesToInline, SILBasicBlock *Root,
1092
- DominanceInfo *DT) {
1109
+ DominanceInfo *DT, int numCallerBlocks ) {
1093
1110
DominanceOrder domOrder (Root, DT);
1094
1111
while (SILBasicBlock *block = domOrder.getNext ()) {
1095
1112
for (SILInstruction &I : *block) {
@@ -1098,7 +1115,7 @@ void SILPerformanceInliner::visitColdBlocks(
1098
1115
continue ;
1099
1116
1100
1117
auto *Callee = getEligibleFunction (AI, WhatToInline);
1101
- if (Callee && decideInColdBlock (AI, Callee)) {
1118
+ if (Callee && decideInColdBlock (AI, Callee, numCallerBlocks )) {
1102
1119
AppliesToInline.push_back (AI);
1103
1120
}
1104
1121
}
0 commit comments