Skip to content

Commit 6b46213

Browse files
authored
Merge pull request #19248 from apple/revert-17370-raj-cp-allargs
2 parents 237c6bb + bd82664 commit 6b46213

File tree

3 files changed

+87
-856
lines changed

3 files changed

+87
-856
lines changed

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,9 @@ class SILCombiner :
295295
private:
296296
FullApplySite rewriteApplyCallee(FullApplySite apply, SILValue callee);
297297

298-
bool canReplaceArg(FullApplySite Apply, const ConcreteExistentialInfo &CEI,
299-
unsigned ArgIdx);
300-
SILInstruction *createApplyWithConcreteType(
301-
FullApplySite Apply,
302-
const llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *>
303-
&CEIs,
304-
SILBuilderContext &BuilderCtx);
298+
SILInstruction *createApplyWithConcreteType(FullApplySite Apply,
299+
const ConcreteExistentialInfo &CEI,
300+
SILBuilderContext &BuilderCtx);
305301

306302
// Common utility function to replace the WitnessMethodInst using a
307303
// BuilderCtx.

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 84 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -693,26 +693,22 @@ SILCombiner::propagateSoleConformingType(FullApplySite Apply,
693693
SILBuilderContext BuilderCtx(M, Builder.getTrackingList());
694694
replaceWitnessMethodInst(WMI, BuilderCtx, ConcreteType,
695695
*(CEI.ExistentialSubs.getConformances().begin()));
696-
// Construct the map for Self to be used for createApplyWithConcreteType.
697-
llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *> CEIs;
698-
CEIs.insert(std::pair<unsigned, const ConcreteExistentialInfo *>(
699-
Apply.getCalleeArgIndex(Apply.getSelfArgumentOperand()), &CEI));
700696
/// Create the new apply instruction using the concrete type.
701-
auto *NewAI = createApplyWithConcreteType(Apply, CEIs, BuilderCtx);
697+
auto *NewAI = createApplyWithConcreteType(Apply, CEI, BuilderCtx);
702698
return NewAI;
703699
}
704700

705701
/// Given an Apply and an argument value produced by InitExistentialAddrInst,
706702
/// return true if the argument can be replaced by a copy of its value.
707703
///
708704
/// FIXME: remove this helper when we can assume SIL opaque values.
709-
static bool canReplaceCopiedArg(FullApplySite Apply,
705+
static bool canReplaceCopiedSelf(FullApplySite Apply,
710706
SILInstruction *InitExistential,
711-
DominanceAnalysis *DA, unsigned ArgIdx) {
712-
// If the witness method mutates Arg, we cannot replace Arg with
707+
DominanceAnalysis *DA) {
708+
// If the witness method mutates self, we cannot replace self with
713709
// the source of a copy. Otherwise the call would modify another value than
714-
// the original argument.
715-
if (Apply.getOrigCalleeType()->getParameters()[ArgIdx].isIndirectMutating())
710+
// the original self.
711+
if (Apply.getOrigCalleeType()->getSelfParameter().isIndirectMutating())
716712
return false;
717713

718714
auto *DT = DA->get(Apply.getFunction());
@@ -755,54 +751,6 @@ static bool canReplaceCopiedArg(FullApplySite Apply,
755751
return true;
756752
}
757753

758-
// Check the legal conditions under which a Arg parameter (specified as ArgIdx)
759-
// can be replaced with a concrete type. Concrete type info is passed as CEI
760-
// argument.
761-
bool SILCombiner::canReplaceArg(FullApplySite Apply,
762-
const ConcreteExistentialInfo &CEI,
763-
unsigned ArgIdx) {
764-
765-
// Don't specialize apply instructions that return the callee's Arg type,
766-
// because this optimization does not know how to substitute types in the
767-
// users of this apply. In the function type substitution below, all
768-
// references to OpenedArchetype will be substituted. So walk to type to
769-
// find all possible references, such as returning Optional<Arg>.
770-
if (Apply.getType().getASTType().findIf(
771-
[&CEI](Type t) -> bool { return t->isEqual(CEI.OpenedArchetype); })) {
772-
return false;
773-
}
774-
// Bail out if any other arguments or indirect result that refer to the
775-
// OpenedArchetype. The following optimization substitutes all occurrences
776-
// of OpenedArchetype in the function signature, but will only rewrite the
777-
// Arg operand.
778-
//
779-
// Note that the language does not allow Self to occur in contravariant
780-
// position. However, SIL does allow this and it can happen as a result of
781-
// upstream transformations. Since this is bail-out logic, it must handle
782-
// all verifiable SIL.
783-
784-
// This bailout check is also needed for non-Self arguments [including Self].
785-
unsigned NumApplyArgs = Apply.getNumArguments();
786-
for (unsigned Idx = 0; Idx < NumApplyArgs; Idx++) {
787-
if (Idx == ArgIdx)
788-
continue;
789-
if (Apply.getArgument(Idx)->getType().getASTType().findIf(
790-
[&CEI](Type t) -> bool {
791-
return t->isEqual(CEI.OpenedArchetype);
792-
})) {
793-
return false;
794-
}
795-
}
796-
// The apply can only be rewritten in terms of the concrete value if it is
797-
// legal to pass that value as the Arg argument.
798-
if (CEI.isCopied && (!CEI.InitExistential ||
799-
!canReplaceCopiedArg(Apply, CEI.InitExistential, DA, ArgIdx))) {
800-
return false;
801-
}
802-
// It is safe to replace Arg.
803-
return true;
804-
}
805-
806754
/// Rewrite the given method apply instruction in terms of the provided conrete
807755
/// type information.
808756
///
@@ -826,61 +774,74 @@ bool SILCombiner::canReplaceArg(FullApplySite Apply,
826774
/// FIXME: Protocol methods (witness or default) that return Self will be given
827775
/// a new return type. This implementation fails to update the type signature of
828776
/// SSA uses in those cases. Currently we bail out on methods that return Self.
829-
SILInstruction *SILCombiner::createApplyWithConcreteType(
830-
FullApplySite Apply,
831-
const llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *> &CEIs,
832-
SILBuilderContext &BuilderCtx) {
833-
834-
// Ensure that the callee is polymorphic.
777+
SILInstruction *
778+
SILCombiner::createApplyWithConcreteType(FullApplySite Apply,
779+
const ConcreteExistentialInfo &CEI,
780+
SILBuilderContext &BuilderCtx) {
835781
assert(Apply.getOrigCalleeType()->isPolymorphic());
836782

837-
// Create the new set of arguments to apply including their substitutions.
838-
SubstitutionMap NewCallSubs = Apply.getSubstitutionMap();
839-
SmallVector<SILValue, 8> NewArgs;
840-
unsigned NumApplyArgs = Apply.getNumArguments();
841-
bool UpdatedArgs = false;
842-
for (unsigned ArgIdx = 0; ArgIdx < NumApplyArgs; ArgIdx++) {
843-
auto ArgIt = CEIs.find(ArgIdx);
844-
if (ArgIt == CEIs.end()) {
845-
// Use the old argument if it does not have a valid concrete existential.
846-
NewArgs.push_back(Apply.getArgument(ArgIdx));
847-
continue;
848-
}
849-
auto *CEI = ArgIt->second;
850-
// Check for Arg's concrete type propagation legality.
851-
if (!canReplaceArg(Apply, *CEI, ArgIdx)) {
852-
NewArgs.push_back(Apply.getArgument(ArgIdx));
853-
continue;
783+
// Don't specialize apply instructions that return the callee's Self type,
784+
// because this optimization does not know how to substitute types in the
785+
// users of this apply. In the function type substitution below, all
786+
// references to OpenedArchetype will be substituted. So walk to type to find
787+
// all possible references, such as returning Optional<Self>.
788+
if (Apply.getType().getASTType().findIf(
789+
[&CEI](Type t) -> bool { return t->isEqual(CEI.OpenedArchetype); })) {
790+
return nullptr;
791+
}
792+
// Bail out if any non-self arguments or indirect result that refer to the
793+
// OpenedArchetype. The following optimization substitutes all occurrences of
794+
// OpenedArchetype in the function signature, but will only rewrite the self
795+
// operand.
796+
//
797+
// Note that the language does not allow Self to occur in contravariant
798+
// position. However, SIL does allow this and it can happen as a result of
799+
// upstream transformations. Since this is bail-out logic, it must handle all
800+
// verifiable SIL.
801+
for (auto Arg : Apply.getArgumentsWithoutSelf()) {
802+
if (Arg->getType().getASTType().findIf([&CEI](Type t) -> bool {
803+
return t->isEqual(CEI.OpenedArchetype);
804+
})) {
805+
return nullptr;
854806
}
855-
UpdatedArgs = true;
856-
// Ensure that we have a concrete value to propagate.
857-
assert(CEI->ConcreteValue);
858-
NewArgs.push_back(CEI->ConcreteValue);
859-
// Form a new set of substitutions where the argument is
860-
// replaced with a concrete type.
861-
NewCallSubs = NewCallSubs.subst(
862-
[&](SubstitutableType *type) -> Type {
863-
if (type == CEI->OpenedArchetype)
864-
return CEI->ConcreteType;
865-
return type;
866-
},
867-
[&](CanType origTy, Type substTy,
868-
ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
869-
if (origTy->isEqual(CEI->OpenedArchetype)) {
870-
assert(substTy->isEqual(CEI->ConcreteType));
871-
// Do a conformance lookup on this witness requirement using the
872-
// existential's conformances. The witness requirement may be a
873-
// base type of the existential's requirements.
874-
return CEI->lookupExistentialConformance(proto);
875-
}
876-
return ProtocolConformanceRef(proto);
877-
});
878807
}
879-
880-
if (!UpdatedArgs)
808+
// The apply can only be rewritten in terms of the concrete value if it is
809+
// legal to pass that value as the self argument.
810+
if (CEI.isCopied && (!CEI.InitExistential ||
811+
!canReplaceCopiedSelf(Apply, CEI.InitExistential, DA))) {
881812
return nullptr;
813+
}
814+
815+
// Create a set of arguments.
816+
SmallVector<SILValue, 8> NewArgs;
817+
for (auto Arg : Apply.getArgumentsWithoutSelf()) {
818+
NewArgs.push_back(Arg);
819+
}
820+
NewArgs.push_back(CEI.ConcreteValue);
821+
822+
assert(Apply.getOrigCalleeType()->isPolymorphic());
823+
824+
// Form a new set of substitutions where Self is
825+
// replaced by a concrete type.
826+
SubstitutionMap OrigCallSubs = Apply.getSubstitutionMap();
827+
SubstitutionMap NewCallSubs = OrigCallSubs.subst(
828+
[&](SubstitutableType *type) -> Type {
829+
if (type == CEI.OpenedArchetype)
830+
return CEI.ConcreteType;
831+
return type;
832+
},
833+
[&](CanType origTy, Type substTy,
834+
ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
835+
if (origTy->isEqual(CEI.OpenedArchetype)) {
836+
assert(substTy->isEqual(CEI.ConcreteType));
837+
// Do a conformance lookup on this witness requirement using the
838+
// existential's conformances. The witness requirement may be a base
839+
// type of the existential's requirements.
840+
return CEI.lookupExistentialConformance(proto).getValue();
841+
}
842+
return ProtocolConformanceRef(proto);
843+
});
882844

883-
// Now create the new apply instruction.
884845
SILBuilderWithScope ApplyBuilder(Apply.getInstruction(), BuilderCtx);
885846
FullApplySite NewApply;
886847
if (auto *TAI = dyn_cast<TryApplyInst>(Apply))
@@ -959,12 +920,8 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite Apply,
959920
replaceWitnessMethodInst(WMI, BuilderCtx, CEI.ConcreteType,
960921
SelfConformance);
961922
}
962-
// Construct the map for Self to be used for createApplyWithConcreteType.
963-
llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *> CEIs;
964-
CEIs.insert(std::pair<unsigned, const ConcreteExistentialInfo *>(
965-
Apply.getCalleeArgIndex(Apply.getSelfArgumentOperand()), &CEI));
966923
// Try to rewrite the apply.
967-
return createApplyWithConcreteType(Apply, CEIs, BuilderCtx);
924+
return createApplyWithConcreteType(Apply, CEI, BuilderCtx);
968925
}
969926

970927
/// Rewrite a protocol extension lookup type from an archetype to a concrete
@@ -979,36 +936,27 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite Apply,
979936
/// ==> apply %f<C : P>(%ref)
980937
SILInstruction *
981938
SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite Apply) {
982-
// This optimization requires a generic argument.
983-
if (!Apply.hasSubstitutions())
939+
// This optimization requires a generic self argument.
940+
if (!Apply.hasSelfArgument() || !Apply.hasSubstitutions())
941+
return nullptr;
942+
943+
// Try to derive the concrete type of self and a related conformance from
944+
// the found init_existential.
945+
const ConcreteExistentialInfo CEI(Apply.getSelfArgumentOperand());
946+
if (!CEI.isValid())
984947
return nullptr;
985948

986949
SILBuilderContext BuilderCtx(Builder.getModule(), Builder.getTrackingList());
987950
SILOpenedArchetypesTracker OpenedArchetypesTracker(&Builder.getFunction());
988951
BuilderCtx.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
989-
llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *> CEIs;
990-
for (unsigned ArgIdx = 0; ArgIdx < Apply.getNumArguments(); ArgIdx++) {
991-
auto ArgASTType = Apply.getArgument(ArgIdx)->getType().getASTType();
992-
if (!ArgASTType->hasArchetype())
993-
continue;
994-
const ConcreteExistentialInfo CEI(Apply.getArgumentOperands()[ArgIdx]);
995-
if (!CEI.isValid())
996-
continue;
997-
998-
CEIs.insert(
999-
std::pair<unsigned, const ConcreteExistentialInfo *>(ArgIdx, &CEI));
1000-
1001-
if (CEI.ConcreteType->isOpenedExistential()) {
1002-
// Temporarily record this opened existential def in this local
1003-
// BuilderContext before rewriting the witness method.
1004-
OpenedArchetypesTracker.addOpenedArchetypeDef(
1005-
cast<ArchetypeType>(CEI.ConcreteType), CEI.ConcreteTypeDef);
1006-
}
952+
if (CEI.ConcreteType->isOpenedExistential()) {
953+
// Temporarily record this opened existential def in this local
954+
// BuilderContext before rewriting the witness method.
955+
OpenedArchetypesTracker.addOpenedArchetypeDef(
956+
cast<ArchetypeType>(CEI.ConcreteType), CEI.ConcreteTypeDef);
1007957
}
1008-
// Bail, if no argument has a concrete existential to propagate.
1009-
if (CEIs.empty())
1010-
return nullptr;
1011-
return createApplyWithConcreteType(Apply, CEIs, BuilderCtx);
958+
// Perform the transformation by rewriting the apply.
959+
return createApplyWithConcreteType(Apply, CEI, BuilderCtx);
1012960
}
1013961

1014962
/// \brief Check that all users of the apply are retain/release ignoring one

0 commit comments

Comments
 (0)