Skip to content

Commit 1ebe33e

Browse files
committed
GenericSpecializer: Allow simple function specialization cycles.
So far we immediately bailed once we detect a cycle in specializations. But it turned out that this prevented efficient code generation for some stdlib functions like compactMap. With this change we allow specialization of cycles up to a depth of 1 (= still very limited to prevent code size explosion in some corner cases). The effect of this optimization is tested with the existing benchmark FatCompactMap. SR-7952, rdar://problem/41005326
1 parent 0cde468 commit 1ebe33e

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ static bool createsInfiniteSpecializationLoop(ApplySite Apply) {
288288
auto *Callee = Apply.getCalleeFunction();
289289
SILFunction *Caller = nullptr;
290290
Caller = Apply.getFunction();
291+
int numAcceptedCycles = 1;
291292

292293
// Name of the function to be specialized.
293294
auto GenericFunc = Callee;
@@ -327,7 +328,13 @@ static bool createsInfiniteSpecializationLoop(ApplySite Apply) {
327328
if (growingSubstitutions(CurSpecializationInfo->getSubstitutions(),
328329
Apply.getSubstitutionMap())) {
329330
DEBUG(llvm::dbgs() << "Found a generic specialization loop!\n");
330-
return true;
331+
332+
// Accept a cycles up to a limit. This is necessary to generate
333+
// efficient code for some library functions, like compactMap, which
334+
// contain small specialization cycles.
335+
if (numAcceptedCycles == 0)
336+
return true;
337+
numAcceptedCycles--;
331338
}
332339
}
333340

test/SILOptimizer/generic_specialization_loops_detection_with_loops.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@
2121

2222
// Check that the compiler has produced a specialization information for a call-site that
2323
// was inlined from a specialized generic function.
24-
// CHECK-LABEL: // Generic specialization information for call-site $S044generic_specialization_loops_detection_with_C04foo4yyx_q_tr0_lF <Array<Int>, Array<Double>>
24+
// CHECK-LABEL: // Generic specialization information for call-site $S044generic_specialization_loops_detection_with_C04foo4yyx_q_tr0_lFSaySays5UInt8VGG_SaySaySiGGTg5:
2525
// CHECK-NEXT: // Caller: $S044generic_specialization_loops_detection_with_C04foo4yyx_q_tr0_lFSi_SdTg5
2626
// CHECK-NEXT: // Parent: $S044generic_specialization_loops_detection_with_C04bar4yyx_q_tr0_lF
27-
// CHECK-NEXT: // Substitutions: <Int, Double>
27+
// CHECK-NEXT: // Substitutions: <Array<UInt8>, Array<Int>>
2828
// CHECK-NEXT: //
2929
// CHECK-NEXT: // Caller: $S044generic_specialization_loops_detection_with_C011testFooBar4yyF
3030
// CHECK-NEXT: // Parent: $S044generic_specialization_loops_detection_with_C04foo4yyx_q_tr0_lF
3131
// CHECK-NEXT: // Substitutions: <Int, Double>
3232
// CHECK-NEXT: //
33-
// CHECK-NEXT: apply %{{[0-9]+}}<Array<Int>, Array<Double>>
33+
// CHECK-NEXT: apply %{{.*}}Array<Array<UInt8>>
3434

3535
// Check specializations of mutually recursive functions which
3636
// may result in an infinite specialization loop.

0 commit comments

Comments
 (0)