Merge pull request #8111 from apple/revert-8099-wip-capture-propagation-generics
Revert "[sil-capture-propagation] Switch to the new notifyAddFunction API"
diff --git a/include/swift/SILOptimizer/Utils/Generics.h b/include/swift/SILOptimizer/Utils/Generics.h
index da4efce..58406b6 100644
--- a/include/swift/SILOptimizer/Utils/Generics.h
+++ b/include/swift/SILOptimizer/Utils/Generics.h
@@ -50,10 +50,6 @@
/// to direct.
llvm::SmallBitVector Conversions;
- /// If set, indirect to direct conversions should be performned by the generic
- /// specializer.
- bool ConvertIndirectToDirect;
-
/// The first NumResults bits in Conversions refer to formal indirect
/// out-parameters.
unsigned NumFormalIndirectResults;
@@ -134,8 +130,7 @@
/// If specialization is not possible getSpecializedType() will return an
/// invalid type.
ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
- SubstitutionList ParamSubs,
- bool ConvertIndirectToDirect = true);
+ SubstitutionList ParamSubs);
/// Constructs the ReabstractionInfo for generic function \p Orig with
/// additional requirements. Requirements may contain new layout,
@@ -145,15 +140,14 @@
/// Returns true if the \p ParamIdx'th (non-result) formal parameter is
/// converted from indirect to direct.
bool isParamConverted(unsigned ParamIdx) const {
- return ConvertIndirectToDirect &&
- Conversions.test(ParamIdx + NumFormalIndirectResults);
+ return Conversions.test(ParamIdx + NumFormalIndirectResults);
}
/// Returns true if the \p ResultIdx'th formal result is converted from
/// indirect to direct.
bool isFormalResultConverted(unsigned ResultIdx) const {
assert(ResultIdx < NumFormalIndirectResults);
- return ConvertIndirectToDirect && Conversions.test(ResultIdx);
+ return Conversions.test(ResultIdx);
}
/// Gets the total number of original function arguments.
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index 3665886..acfa77a 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -11,15 +11,12 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "capture-prop"
-#include "swift/AST/GenericEnvironment.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
-#include "swift/SILOptimizer/Utils/Generics.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "swift/Demangling/Demangle.h"
#include "swift/SIL/Mangle.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILInstruction.h"
-#include "swift/SIL/TypeSubstCloner.h"
#include "swift/SILOptimizer/Analysis/ColdBlockInfo.h"
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
@@ -102,17 +99,16 @@
/// caller, so the cloned function will have a mix of locations from different
/// functions.
class CapturePropagationCloner
- : public TypeSubstCloner<CapturePropagationCloner> {
- using SuperTy = TypeSubstCloner<CapturePropagationCloner>;
+ : public SILClonerWithScopes<CapturePropagationCloner> {
+ using SuperTy = SILClonerWithScopes<CapturePropagationCloner>;
friend class SILVisitor<CapturePropagationCloner>;
friend class SILCloner<CapturePropagationCloner>;
SILFunction *OrigF;
bool IsCloningConstant;
public:
- CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF,
- SubstitutionList Subs)
- : SuperTy(*NewF, *OrigF, Subs), OrigF(OrigF), IsCloningConstant(false) {}
+ CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF)
+ : SuperTy(*NewF), OrigF(OrigF), IsCloningConstant(false) {}
void cloneBlocks(OperandValueArrayRef Args);
@@ -223,20 +219,6 @@
}
}
-CanSILFunctionType getPartialApplyInterfaceResultType(PartialApplyInst *PAI) {
- SILFunction *OrigF = PAI->getReferencedFunction();
- // The new partial_apply will no longer take any arguments--they are all
- // expressed as literals. So its callee signature will be the same as its
- // return signature.
- auto FTy = PAI->getType().castTo<SILFunctionType>();
- CanGenericSignature CanGenericSig;
- assert(!PAI->hasSubstitutions() || !hasArchetypes(PAI->getSubstitutions()));
- FTy = cast<SILFunctionType>(
- OrigF->mapTypeOutOfContext(FTy)->getCanonicalType());
- auto NewFTy = FTy;
- return NewFTy;
-}
-
/// Given a partial_apply instruction, create a specialized callee by removing
/// all constant arguments and adding constant literals to the specialized
/// function body.
@@ -261,16 +243,12 @@
// The new partial_apply will no longer take any arguments--they are all
// expressed as literals. So its callee signature will be the same as its
// return signature.
- auto NewFTy = getPartialApplyInterfaceResultType(PAI);
- NewFTy = Lowering::adjustFunctionType(NewFTy,
- SILFunctionType::Representation::Thin);
-
- GenericEnvironment *GenericEnv = nullptr;
- if (NewFTy->getGenericSignature())
- GenericEnv = OrigF->getGenericEnvironment();
+ CanSILFunctionType NewFTy =
+ Lowering::adjustFunctionType(PAI->getType().castTo<SILFunctionType>(),
+ SILFunctionType::Representation::Thin);
SILFunction *NewF = OrigF->getModule().createFunction(
SILLinkage::Shared, Name, NewFTy,
- GenericEnv, OrigF->getLocation(), OrigF->isBare(),
+ OrigF->getGenericEnvironment(), OrigF->getLocation(), OrigF->isBare(),
OrigF->isTransparent(), Fragile, OrigF->isThunk(),
OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
OrigF->getEffectsKind(),
@@ -281,11 +259,7 @@
DEBUG(llvm::dbgs() << " Specialize callee as ";
NewF->printName(llvm::dbgs()); llvm::dbgs() << " " << NewFTy << "\n");
- DEBUG(if (PAI->hasSubstitutions()) {
- llvm::dbgs() << "CapturePropagation of generic partial_apply:\n";
- PAI->dumpInContext();
- });
- CapturePropagationCloner cloner(OrigF, NewF, PAI->getSubstitutions());
+ CapturePropagationCloner cloner(OrigF, NewF);
cloner.cloneBlocks(PAI->getArguments());
assert(OrigF->getDebugScope()->Parent != NewF->getDebugScope()->Parent);
return NewF;
@@ -293,16 +267,10 @@
void CapturePropagation::rewritePartialApply(PartialApplyInst *OrigPAI,
SILFunction *SpecialF) {
- DEBUG(llvm::dbgs() << "\n Rewriting a partial apply:\n";
- OrigPAI->dumpInContext(); llvm::dbgs() << " with special function: "
- << SpecialF->getName() << "\n";
- llvm::dbgs() << "\nThe function being rewritten is:\n";
- OrigPAI->getFunction()->dump());
-
SILBuilderWithScope Builder(OrigPAI);
auto FuncRef = Builder.createFunctionRef(OrigPAI->getLoc(), SpecialF);
- auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(), FuncRef,
- OrigPAI->getType());
+ auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(),
+ FuncRef, OrigPAI->getType());
OrigPAI->replaceAllUsesWith(T2TF);
recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
DEBUG(llvm::dbgs() << " Rewrote caller:\n" << *T2TF);
@@ -343,16 +311,12 @@
/// Checks if \p Orig is a thunk which calls another function but without
/// passing the trailing \p numDeadParams dead parameters.
-/// If a generic specialization was performed for a generic capture,
-/// GenericSpecialized contains a tuple:
-/// (new specialized function, old function)
-static SILFunction *getSpecializedWithDeadParams(
- PartialApplyInst *PAI, SILFunction *Orig, int numDeadParams,
- std::pair<SILFunction *, SILFunction *> &GenericSpecialized) {
+static SILFunction *getSpecializedWithDeadParams(SILFunction *Orig,
+ int numDeadParams) {
SILBasicBlock &EntryBB = *Orig->begin();
unsigned NumArgs = EntryBB.getNumArguments();
SILModule &M = Orig->getModule();
-
+
// Check if all dead parameters have trivial types. We don't support non-
// trivial types because it's very hard to find places where we can release
// those parameters (as a replacement for the removed partial_apply).
@@ -364,20 +328,20 @@
}
SILFunction *Specialized = nullptr;
SILValue RetValue;
-
+
// Check all instruction of the entry block.
for (SILInstruction &I : EntryBB) {
if (auto FAS = FullApplySite::isa(&I)) {
+
// Check if this is the call of the specialized function.
- // If the original partial_apply didn't have substitutions,
- // also the specialized function must be not generic.
- if (!PAI->hasSubstitutions() && FAS.hasSubstitutions())
+ // As the original function is not generic, also the specialized function
+ // must be not generic.
+ if (FAS.hasSubstitutions())
return nullptr;
-
// Is it the only call?
if (Specialized)
return nullptr;
-
+
Specialized = FAS.getReferencedFunction();
if (!Specialized)
return nullptr;
@@ -412,54 +376,29 @@
if (I.mayHaveSideEffects() || isa<TermInst>(&I))
return nullptr;
}
-
- GenericSpecialized = std::make_pair(nullptr, nullptr);
-
- if (PAI->hasSubstitutions()) {
- if (Specialized->isExternalDeclaration())
- return nullptr;
- // Perform a generic specialization of the Specialized function.
- ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
- /* ConvertIndirectToDirect */ false);
- GenericFuncSpecializer FuncSpecializer(Specialized,
- ReInfo.getClonerParamSubstitutions(),
- Specialized->isFragile(), ReInfo);
-
- SILFunction *GenericSpecializedFunc = FuncSpecializer.trySpecialization();
- if (!GenericSpecializedFunc)
- return nullptr;
- GenericSpecialized = std::make_pair(GenericSpecializedFunc, Specialized);
- return GenericSpecializedFunc;
- }
return Specialized;
}
bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
+ // Check if the partial_apply has generic substitutions.
+ // FIXME: We could handle generic thunks if it's worthwhile.
+ if (PAI->hasSubstitutions())
+ return false;
+
SILFunction *SubstF = PAI->getReferencedFunction();
if (!SubstF)
return false;
if (SubstF->isExternalDeclaration())
return false;
- if (PAI->hasSubstitutions() && hasArchetypes(PAI->getSubstitutions())) {
- DEBUG(llvm::dbgs()
- << "CapturePropagation: cannot handle partial specialization "
- "of partial_apply:\n";
- PAI->dumpInContext());
- return false;
- }
-
+ assert(!SubstF->getLoweredFunctionType()->isPolymorphic() &&
+ "cannot specialize generic partial apply");
// First possibility: Is it a partial_apply where all partially applied
// arguments are dead?
- std::pair<SILFunction *, SILFunction *> GenericSpecialized;
- if (auto *NewFunc = getSpecializedWithDeadParams(
- PAI, SubstF, PAI->getNumArguments(), GenericSpecialized)) {
+ if (SILFunction *NewFunc = getSpecializedWithDeadParams(SubstF,
+ PAI->getNumArguments())) {
rewritePartialApply(PAI, NewFunc);
- if (GenericSpecialized.first) {
- // Notify the pass manager about the new function.
- notifyAddFunction(GenericSpecialized.first, GenericSpecialized.second);
- }
return true;
}
@@ -472,8 +411,7 @@
return false;
DEBUG(llvm::dbgs() << "Specializing closure for constant arguments:\n"
- << " " << SubstF->getName() << "\n"
- << *PAI);
+ << " " << SubstF->getName() << "\n" << *PAI);
++NumCapturesPropagated;
SILFunction *NewF = specializeConstClosure(PAI, SubstF);
rewritePartialApply(PAI, NewF);
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index f886a9c..b02d39f 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -290,13 +290,10 @@
}
ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
- ArrayRef<Substitution> ParamSubs,
- bool ConvertIndirectToDirect) {
+ ArrayRef<Substitution> ParamSubs) {
if (!prepareAndCheck(Apply, Callee, ParamSubs))
return;
- this->ConvertIndirectToDirect = ConvertIndirectToDirect;
-
if (SpecializeGenericSubstitutions) {
specializeConcreteAndGenericSubstitutions(Apply, Callee, ParamSubs);
} else {
diff --git a/test/SILOptimizer/capture_propagation.sil b/test/SILOptimizer/capture_propagation.sil
index d8dce48..b0317c9 100644
--- a/test/SILOptimizer/capture_propagation.sil
+++ b/test/SILOptimizer/capture_propagation.sil
@@ -378,75 +378,3 @@
return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
}
-// Test generic capture propagation
-
-sil @_TFtest_generic_capture_propagation2_closure : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> () {
-bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*T):
- %9999 = tuple()
- return %9999 : $()
-}
-
-// CHECK-LABEL: sil @test_generic_capture_propagation2_caller
-// CHECK: %[[CALLEE:[0-9]+]] = function_ref @test_generic_capture_propagation2_callee
-// CHECK: %[[FR:[0-9]+]] = function_ref @{{.*}}test_generic_capture_propagation2_thunk : $@convention(thin) () -> ()
-// CHECK: %[[CONVERTED:[0-9]+]] = thin_to_thick_function %[[FR]] : $@convention(thin) () -> () to $@callee_owned () -> ()
-// CHECK-NOT: partial_apply
-// CHECK: apply %[[CALLEE]](%[[CONVERTED]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
-// CHECL-NOT: partial_apply
-// CHECK: return
-sil @test_generic_capture_propagation2_caller : $@convention(thin) () -> () {
- %0 = integer_literal $Builtin.Int32, 0
- %1 = float_literal $Builtin.FPIEEE32, 0
- %2 = string_literal utf8 "123"
- %3 = global_addr @globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8 : $*Builtin.Word
- %4 = function_ref @_TFtest_generic_capture_propagation2_closure : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
- %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) -> ()
- %6 = function_ref @test_generic_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
- %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) -> ()) -> ()
- %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) -> ()) -> ()
- apply %6(%8) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
- %9999 = tuple()
- return %9999 : $()
-}
-
-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) -> ()) -> () {
-bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*T, %4 : $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()):
- apply %4<T>(%0, %1, %2, %3) : $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
- %9999 = tuple()
- return %9999 : $()
-}
-
-sil shared @test_generic_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> () {
-bb0(%0 : $@callee_owned () -> ()):
- apply %0() : $@callee_owned () -> ()
- %9999 = tuple()
- return %9999 : $()
-}
-
-// Test dead partial applied arguments when using generics
-
-sil @specialized_generic_nonthrowing_closure : $@convention(thin) <T> (@in T, @in T) -> Bool {
-bb0(%0 : $*T, %1 : $*T):
- %10 = integer_literal $Builtin.Int1, -1
- %9999 = struct $Bool (%10 : $Builtin.Int1)
- return %9999 : $Bool
-}
-
-sil @nonthrowing_generic_closure : $@convention(method) <T> (@in T, @in T, @thin T.Type) -> Bool {
-bb0(%0 : $*T, %1 : $*T, %2 : $@thin T.Type):
- %3 = function_ref @specialized_generic_nonthrowing_closure : $@convention(thin) <T> (@in T, @in T) -> Bool
- %4 = apply %3<T>(%0, %1) : $@convention(thin) <T> (@in T, @in T) -> Bool
- return %4 : $Bool
-}
-
-// CHECK-LABEL: sil @return_generic_nonthrowing_closure
-// CHECK: [[F:%[0-9]+]] = function_ref @_TTSg5Vs5Int32__specialized_generic_nonthrowing_closure
-// CHECK: [[R:%[0-9]+]] = thin_to_thick_function [[F]]
-// CHECK: return [[R]]
-sil @return_generic_nonthrowing_closure : $@convention(thin) () -> @owned @callee_owned (@in Int32, @in Int32) -> Bool {
-bb0:
- %0 = metatype $@thin Int32.Type
- %1 = function_ref @nonthrowing_generic_closure : $@convention(method) <T> (@in T, @in T, @thin T.Type) -> Bool
- %2 = partial_apply %1<Int32>(%0) : $@convention(method) <T>(@in T, @in T, @thin T.Type) -> Bool
- return %2 : $@callee_owned (@in Int32, @in Int32) -> Bool
-}
\ No newline at end of file