Skip to content

Commit c618f19

Browse files
author
Greg Parker
authored
Merge pull request #8111 from apple/revert-8099-wip-capture-propagation-generics
Revert "[sil-capture-propagation] Switch to the new notifyAddFunction API"
2 parents 3e4eb98 + 44135ae commit c618f19

File tree

4 files changed

+34
-177
lines changed

4 files changed

+34
-177
lines changed

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ class ReabstractionInfo {
5050
/// to direct.
5151
llvm::SmallBitVector Conversions;
5252

53-
/// If set, indirect to direct conversions should be performned by the generic
54-
/// specializer.
55-
bool ConvertIndirectToDirect;
56-
5753
/// The first NumResults bits in Conversions refer to formal indirect
5854
/// out-parameters.
5955
unsigned NumFormalIndirectResults;
@@ -134,8 +130,7 @@ class ReabstractionInfo {
134130
/// If specialization is not possible getSpecializedType() will return an
135131
/// invalid type.
136132
ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
137-
SubstitutionList ParamSubs,
138-
bool ConvertIndirectToDirect = true);
133+
SubstitutionList ParamSubs);
139134

140135
/// Constructs the ReabstractionInfo for generic function \p Orig with
141136
/// additional requirements. Requirements may contain new layout,
@@ -145,15 +140,14 @@ class ReabstractionInfo {
145140
/// Returns true if the \p ParamIdx'th (non-result) formal parameter is
146141
/// converted from indirect to direct.
147142
bool isParamConverted(unsigned ParamIdx) const {
148-
return ConvertIndirectToDirect &&
149-
Conversions.test(ParamIdx + NumFormalIndirectResults);
143+
return Conversions.test(ParamIdx + NumFormalIndirectResults);
150144
}
151145

152146
/// Returns true if the \p ResultIdx'th formal result is converted from
153147
/// indirect to direct.
154148
bool isFormalResultConverted(unsigned ResultIdx) const {
155149
assert(ResultIdx < NumFormalIndirectResults);
156-
return ConvertIndirectToDirect && Conversions.test(ResultIdx);
150+
return Conversions.test(ResultIdx);
157151
}
158152

159153
/// Gets the total number of original function arguments.

lib/SILOptimizer/IPO/CapturePropagation.cpp

Lines changed: 30 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,12 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#define DEBUG_TYPE "capture-prop"
14-
#include "swift/AST/GenericEnvironment.h"
1514
#include "swift/SILOptimizer/PassManager/Passes.h"
16-
#include "swift/SILOptimizer/Utils/Generics.h"
1715
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
1816
#include "swift/Demangling/Demangle.h"
1917
#include "swift/SIL/Mangle.h"
2018
#include "swift/SIL/SILCloner.h"
2119
#include "swift/SIL/SILInstruction.h"
22-
#include "swift/SIL/TypeSubstCloner.h"
2320
#include "swift/SILOptimizer/Analysis/ColdBlockInfo.h"
2421
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
2522
#include "swift/SILOptimizer/PassManager/Transforms.h"
@@ -102,17 +99,16 @@ namespace {
10299
/// caller, so the cloned function will have a mix of locations from different
103100
/// functions.
104101
class CapturePropagationCloner
105-
: public TypeSubstCloner<CapturePropagationCloner> {
106-
using SuperTy = TypeSubstCloner<CapturePropagationCloner>;
102+
: public SILClonerWithScopes<CapturePropagationCloner> {
103+
using SuperTy = SILClonerWithScopes<CapturePropagationCloner>;
107104
friend class SILVisitor<CapturePropagationCloner>;
108105
friend class SILCloner<CapturePropagationCloner>;
109106

110107
SILFunction *OrigF;
111108
bool IsCloningConstant;
112109
public:
113-
CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF,
114-
SubstitutionList Subs)
115-
: SuperTy(*NewF, *OrigF, Subs), OrigF(OrigF), IsCloningConstant(false) {}
110+
CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF)
111+
: SuperTy(*NewF), OrigF(OrigF), IsCloningConstant(false) {}
116112

117113
void cloneBlocks(OperandValueArrayRef Args);
118114

@@ -223,20 +219,6 @@ void CapturePropagationCloner::cloneBlocks(
223219
}
224220
}
225221

226-
CanSILFunctionType getPartialApplyInterfaceResultType(PartialApplyInst *PAI) {
227-
SILFunction *OrigF = PAI->getReferencedFunction();
228-
// The new partial_apply will no longer take any arguments--they are all
229-
// expressed as literals. So its callee signature will be the same as its
230-
// return signature.
231-
auto FTy = PAI->getType().castTo<SILFunctionType>();
232-
CanGenericSignature CanGenericSig;
233-
assert(!PAI->hasSubstitutions() || !hasArchetypes(PAI->getSubstitutions()));
234-
FTy = cast<SILFunctionType>(
235-
OrigF->mapTypeOutOfContext(FTy)->getCanonicalType());
236-
auto NewFTy = FTy;
237-
return NewFTy;
238-
}
239-
240222
/// Given a partial_apply instruction, create a specialized callee by removing
241223
/// all constant arguments and adding constant literals to the specialized
242224
/// function body.
@@ -261,16 +243,12 @@ SILFunction *CapturePropagation::specializeConstClosure(PartialApplyInst *PAI,
261243
// The new partial_apply will no longer take any arguments--they are all
262244
// expressed as literals. So its callee signature will be the same as its
263245
// return signature.
264-
auto NewFTy = getPartialApplyInterfaceResultType(PAI);
265-
NewFTy = Lowering::adjustFunctionType(NewFTy,
266-
SILFunctionType::Representation::Thin);
267-
268-
GenericEnvironment *GenericEnv = nullptr;
269-
if (NewFTy->getGenericSignature())
270-
GenericEnv = OrigF->getGenericEnvironment();
246+
CanSILFunctionType NewFTy =
247+
Lowering::adjustFunctionType(PAI->getType().castTo<SILFunctionType>(),
248+
SILFunctionType::Representation::Thin);
271249
SILFunction *NewF = OrigF->getModule().createFunction(
272250
SILLinkage::Shared, Name, NewFTy,
273-
GenericEnv, OrigF->getLocation(), OrigF->isBare(),
251+
OrigF->getGenericEnvironment(), OrigF->getLocation(), OrigF->isBare(),
274252
OrigF->isTransparent(), Fragile, OrigF->isThunk(),
275253
OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
276254
OrigF->getEffectsKind(),
@@ -281,28 +259,18 @@ SILFunction *CapturePropagation::specializeConstClosure(PartialApplyInst *PAI,
281259
DEBUG(llvm::dbgs() << " Specialize callee as ";
282260
NewF->printName(llvm::dbgs()); llvm::dbgs() << " " << NewFTy << "\n");
283261

284-
DEBUG(if (PAI->hasSubstitutions()) {
285-
llvm::dbgs() << "CapturePropagation of generic partial_apply:\n";
286-
PAI->dumpInContext();
287-
});
288-
CapturePropagationCloner cloner(OrigF, NewF, PAI->getSubstitutions());
262+
CapturePropagationCloner cloner(OrigF, NewF);
289263
cloner.cloneBlocks(PAI->getArguments());
290264
assert(OrigF->getDebugScope()->Parent != NewF->getDebugScope()->Parent);
291265
return NewF;
292266
}
293267

294268
void CapturePropagation::rewritePartialApply(PartialApplyInst *OrigPAI,
295269
SILFunction *SpecialF) {
296-
DEBUG(llvm::dbgs() << "\n Rewriting a partial apply:\n";
297-
OrigPAI->dumpInContext(); llvm::dbgs() << " with special function: "
298-
<< SpecialF->getName() << "\n";
299-
llvm::dbgs() << "\nThe function being rewritten is:\n";
300-
OrigPAI->getFunction()->dump());
301-
302270
SILBuilderWithScope Builder(OrigPAI);
303271
auto FuncRef = Builder.createFunctionRef(OrigPAI->getLoc(), SpecialF);
304-
auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(), FuncRef,
305-
OrigPAI->getType());
272+
auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(),
273+
FuncRef, OrigPAI->getType());
306274
OrigPAI->replaceAllUsesWith(T2TF);
307275
recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
308276
DEBUG(llvm::dbgs() << " Rewrote caller:\n" << *T2TF);
@@ -343,16 +311,12 @@ static bool onlyContainsReturnOrThrowOfArg(SILBasicBlock *BB) {
343311

344312
/// Checks if \p Orig is a thunk which calls another function but without
345313
/// passing the trailing \p numDeadParams dead parameters.
346-
/// If a generic specialization was performed for a generic capture,
347-
/// GenericSpecialized contains a tuple:
348-
/// (new specialized function, old function)
349-
static SILFunction *getSpecializedWithDeadParams(
350-
PartialApplyInst *PAI, SILFunction *Orig, int numDeadParams,
351-
std::pair<SILFunction *, SILFunction *> &GenericSpecialized) {
314+
static SILFunction *getSpecializedWithDeadParams(SILFunction *Orig,
315+
int numDeadParams) {
352316
SILBasicBlock &EntryBB = *Orig->begin();
353317
unsigned NumArgs = EntryBB.getNumArguments();
354318
SILModule &M = Orig->getModule();
355-
319+
356320
// Check if all dead parameters have trivial types. We don't support non-
357321
// trivial types because it's very hard to find places where we can release
358322
// those parameters (as a replacement for the removed partial_apply).
@@ -364,20 +328,20 @@ static SILFunction *getSpecializedWithDeadParams(
364328
}
365329
SILFunction *Specialized = nullptr;
366330
SILValue RetValue;
367-
331+
368332
// Check all instruction of the entry block.
369333
for (SILInstruction &I : EntryBB) {
370334
if (auto FAS = FullApplySite::isa(&I)) {
335+
371336
// Check if this is the call of the specialized function.
372-
// If the original partial_apply didn't have substitutions,
373-
// also the specialized function must be not generic.
374-
if (!PAI->hasSubstitutions() && FAS.hasSubstitutions())
337+
// As the original function is not generic, also the specialized function
338+
// must be not generic.
339+
if (FAS.hasSubstitutions())
375340
return nullptr;
376-
377341
// Is it the only call?
378342
if (Specialized)
379343
return nullptr;
380-
344+
381345
Specialized = FAS.getReferencedFunction();
382346
if (!Specialized)
383347
return nullptr;
@@ -412,54 +376,29 @@ static SILFunction *getSpecializedWithDeadParams(
412376
if (I.mayHaveSideEffects() || isa<TermInst>(&I))
413377
return nullptr;
414378
}
415-
416-
GenericSpecialized = std::make_pair(nullptr, nullptr);
417-
418-
if (PAI->hasSubstitutions()) {
419-
if (Specialized->isExternalDeclaration())
420-
return nullptr;
421-
// Perform a generic specialization of the Specialized function.
422-
ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
423-
/* ConvertIndirectToDirect */ false);
424-
GenericFuncSpecializer FuncSpecializer(Specialized,
425-
ReInfo.getClonerParamSubstitutions(),
426-
Specialized->isFragile(), ReInfo);
427-
428-
SILFunction *GenericSpecializedFunc = FuncSpecializer.trySpecialization();
429-
if (!GenericSpecializedFunc)
430-
return nullptr;
431-
GenericSpecialized = std::make_pair(GenericSpecializedFunc, Specialized);
432-
return GenericSpecializedFunc;
433-
}
434379
return Specialized;
435380
}
436381

437382
bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
383+
// Check if the partial_apply has generic substitutions.
384+
// FIXME: We could handle generic thunks if it's worthwhile.
385+
if (PAI->hasSubstitutions())
386+
return false;
387+
438388
SILFunction *SubstF = PAI->getReferencedFunction();
439389
if (!SubstF)
440390
return false;
441391
if (SubstF->isExternalDeclaration())
442392
return false;
443393

444-
if (PAI->hasSubstitutions() && hasArchetypes(PAI->getSubstitutions())) {
445-
DEBUG(llvm::dbgs()
446-
<< "CapturePropagation: cannot handle partial specialization "
447-
"of partial_apply:\n";
448-
PAI->dumpInContext());
449-
return false;
450-
}
451-
394+
assert(!SubstF->getLoweredFunctionType()->isPolymorphic() &&
395+
"cannot specialize generic partial apply");
452396

453397
// First possibility: Is it a partial_apply where all partially applied
454398
// arguments are dead?
455-
std::pair<SILFunction *, SILFunction *> GenericSpecialized;
456-
if (auto *NewFunc = getSpecializedWithDeadParams(
457-
PAI, SubstF, PAI->getNumArguments(), GenericSpecialized)) {
399+
if (SILFunction *NewFunc = getSpecializedWithDeadParams(SubstF,
400+
PAI->getNumArguments())) {
458401
rewritePartialApply(PAI, NewFunc);
459-
if (GenericSpecialized.first) {
460-
// Notify the pass manager about the new function.
461-
notifyAddFunction(GenericSpecialized.first, GenericSpecialized.second);
462-
}
463402
return true;
464403
}
465404

@@ -472,8 +411,7 @@ bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
472411
return false;
473412

474413
DEBUG(llvm::dbgs() << "Specializing closure for constant arguments:\n"
475-
<< " " << SubstF->getName() << "\n"
476-
<< *PAI);
414+
<< " " << SubstF->getName() << "\n" << *PAI);
477415
++NumCapturesPropagated;
478416
SILFunction *NewF = specializeConstClosure(PAI, SubstF);
479417
rewritePartialApply(PAI, NewF);

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,10 @@ bool ReabstractionInfo::canBeSpecialized(ApplySite Apply, SILFunction *Callee,
290290
}
291291

292292
ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
293-
ArrayRef<Substitution> ParamSubs,
294-
bool ConvertIndirectToDirect) {
293+
ArrayRef<Substitution> ParamSubs) {
295294
if (!prepareAndCheck(Apply, Callee, ParamSubs))
296295
return;
297296

298-
this->ConvertIndirectToDirect = ConvertIndirectToDirect;
299-
300297
if (SpecializeGenericSubstitutions) {
301298
specializeConcreteAndGenericSubstitutions(Apply, Callee, ParamSubs);
302299
} else {

test/SILOptimizer/capture_propagation.sil

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -378,75 +378,3 @@ bb0:
378378
return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
379379
}
380380

381-
// Test generic capture propagation
382-
383-
sil @_TFtest_generic_capture_propagation2_closure : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> () {
384-
bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*T):
385-
%9999 = tuple()
386-
return %9999 : $()
387-
}
388-
389-
// CHECK-LABEL: sil @test_generic_capture_propagation2_caller
390-
// CHECK: %[[CALLEE:[0-9]+]] = function_ref @test_generic_capture_propagation2_callee
391-
// CHECK: %[[FR:[0-9]+]] = function_ref @{{.*}}test_generic_capture_propagation2_thunk : $@convention(thin) () -> ()
392-
// CHECK: %[[CONVERTED:[0-9]+]] = thin_to_thick_function %[[FR]] : $@convention(thin) () -> () to $@callee_owned () -> ()
393-
// CHECK-NOT: partial_apply
394-
// CHECK: apply %[[CALLEE]](%[[CONVERTED]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
395-
// CHECL-NOT: partial_apply
396-
// CHECK: return
397-
sil @test_generic_capture_propagation2_caller : $@convention(thin) () -> () {
398-
%0 = integer_literal $Builtin.Int32, 0
399-
%1 = float_literal $Builtin.FPIEEE32, 0
400-
%2 = string_literal utf8 "123"
401-
%3 = global_addr @globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8 : $*Builtin.Word
402-
%4 = function_ref @_TFtest_generic_capture_propagation2_closure : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
403-
%5 = thin_to_thick_function %4 : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> () to $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
404-
%6 = function_ref @test_generic_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
405-
%7 = function_ref @test_generic_capture_propagation2_thunk : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T, @owned @callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()) -> ()
406-
%8 = partial_apply %7<Builtin.Word>(%0, %1, %2, %3, %5) : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T, @owned @callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()) -> ()
407-
apply %6(%8) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
408-
%9999 = tuple()
409-
return %9999 : $()
410-
}
411-
412-
sil shared @test_generic_capture_propagation2_thunk : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T, @owned @callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()) -> () {
413-
bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*T, %4 : $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()):
414-
apply %4<T>(%0, %1, %2, %3) : $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
415-
%9999 = tuple()
416-
return %9999 : $()
417-
}
418-
419-
sil shared @test_generic_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> () {
420-
bb0(%0 : $@callee_owned () -> ()):
421-
apply %0() : $@callee_owned () -> ()
422-
%9999 = tuple()
423-
return %9999 : $()
424-
}
425-
426-
// Test dead partial applied arguments when using generics
427-
428-
sil @specialized_generic_nonthrowing_closure : $@convention(thin) <T> (@in T, @in T) -> Bool {
429-
bb0(%0 : $*T, %1 : $*T):
430-
%10 = integer_literal $Builtin.Int1, -1
431-
%9999 = struct $Bool (%10 : $Builtin.Int1)
432-
return %9999 : $Bool
433-
}
434-
435-
sil @nonthrowing_generic_closure : $@convention(method) <T> (@in T, @in T, @thin T.Type) -> Bool {
436-
bb0(%0 : $*T, %1 : $*T, %2 : $@thin T.Type):
437-
%3 = function_ref @specialized_generic_nonthrowing_closure : $@convention(thin) <T> (@in T, @in T) -> Bool
438-
%4 = apply %3<T>(%0, %1) : $@convention(thin) <T> (@in T, @in T) -> Bool
439-
return %4 : $Bool
440-
}
441-
442-
// CHECK-LABEL: sil @return_generic_nonthrowing_closure
443-
// CHECK: [[F:%[0-9]+]] = function_ref @_TTSg5Vs5Int32__specialized_generic_nonthrowing_closure
444-
// CHECK: [[R:%[0-9]+]] = thin_to_thick_function [[F]]
445-
// CHECK: return [[R]]
446-
sil @return_generic_nonthrowing_closure : $@convention(thin) () -> @owned @callee_owned (@in Int32, @in Int32) -> Bool {
447-
bb0:
448-
%0 = metatype $@thin Int32.Type
449-
%1 = function_ref @nonthrowing_generic_closure : $@convention(method) <T> (@in T, @in T, @thin T.Type) -> Bool
450-
%2 = partial_apply %1<Int32>(%0) : $@convention(method) <T>(@in T, @in T, @thin T.Type) -> Bool
451-
return %2 : $@callee_owned (@in Int32, @in Int32) -> Bool
452-
}

0 commit comments

Comments
 (0)