Skip to content

Rewrite SILCombiner::propagateConcreteTypeOfInitExistential. #17315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ class SILBuilderContext {
this->silConv = silConv;
}

void setOpenedArchetypesTracker(SILOpenedArchetypesTracker *Tracker) {
OpenedArchetypesTracker = Tracker;
OpenedArchetypes.setOpenedArchetypesTracker(OpenedArchetypesTracker);
}

SILOpenedArchetypesTracker *getOpenedArchetypesTracker() const {
return OpenedArchetypesTracker;
}

protected:
/// Notify the context of each new instruction after it is inserted in the
/// instruction stream.
Expand Down Expand Up @@ -186,12 +195,11 @@ class SILBuilder {
}

void setOpenedArchetypesTracker(SILOpenedArchetypesTracker *Tracker) {
C.OpenedArchetypesTracker = Tracker;
C.OpenedArchetypes.setOpenedArchetypesTracker(C.OpenedArchetypesTracker);
C.setOpenedArchetypesTracker(Tracker);
}

SILOpenedArchetypesTracker *getOpenedArchetypesTracker() const {
return C.OpenedArchetypesTracker;
return C.getOpenedArchetypesTracker();
}

SILOpenedArchetypesState &getOpenedArchetypes() { return C.OpenedArchetypes; }
Expand Down
2 changes: 0 additions & 2 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1930,8 +1930,6 @@ class ApplyInstBase<Impl, Base, true>
assert(hasSelfArgument() && "Must have a self argument");
assert(getNumArguments() && "Should only be called when Callee has "
"at least a self parameter.");
assert(hasSubstitutions() && "Should only be called when Callee has "
"substitutions.");
ArrayRef<Operand> ops = this->getArgumentOperands();
ArrayRef<Operand> opsWithoutSelf = ArrayRef<Operand>(&ops[0],
ops.size()-1);
Expand Down
67 changes: 65 additions & 2 deletions include/swift/SILOptimizer/Utils/Existential.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,76 @@ SILValue getAddressOfStackInit(AllocStackInst *ASI, SILInstruction *ASIUser,
bool &isCopied);

/// Find the init_existential, which could be used to determine a concrete
/// type of the \p Self.
/// type of the value used by \p openedUse.
/// If the value is copied from another stack location, \p isCopied is set to
/// true.
SILInstruction *findInitExistential(FullApplySite AI, SILValue Self,
///
/// FIXME: replace all uses of this with ConcreteExistentialInfo.
SILInstruction *findInitExistential(Operand &openedUse,
ArchetypeType *&OpenedArchetype,
SILValue &OpenedArchetypeDef,
bool &isCopied);

/// Record conformance and concrete type info derived from an init_existential
/// value that is reopened before it's use. This is useful for finding the
/// concrete type of an apply's self argument. For example, an important pattern
/// for a class existential is:
///
/// %e = init_existential_ref %c : $C : $C, $P & Q
/// %o = open_existential_ref %e : $P & Q to $@opened("PQ") P & Q
/// %r = apply %f<@opened("PQ") P & Q>(%o)
/// : $@convention(method) <τ_0_0 where τ_0_0 : P, τ_0_0 : Q>
/// (@guaranteed τ_0_0) -> @owned τ_0_0
struct ConcreteExistentialInfo {
// The opened type passed as self. `$@opened("PQ")` above.
// This is also the replacement type of the method's Self type.
ArchetypeType *OpenedArchetype = nullptr;
// The definition of the OpenedArchetype.
SILValue OpenedArchetypeDef;
// True if the openedValue is copied from another stack location
bool isCopied;
// The init_existential instruction that produces the opened existential.
SILInstruction *InitExistential = nullptr;
// The existential type of the self argument before it is opened,
// produced by an init_existential.
CanType ExistentialType;
// The conformances required by the init_existential. `$C : $P & $Q` above.
ArrayRef<ProtocolConformanceRef> ExistentialConformances;
// The concrete type of self from the init_existential. `$C` above.
CanType ConcreteType;
// When ConcreteType is itself an opened existential, record the type
// definition. May be nullptr for a valid AppliedConcreteType.
SingleValueInstruction *ConcreteTypeDef = nullptr;
// The Substitution map derived from the init_existential.
// This maps a single generic parameter to the replacement ConcreteType
// and includes the full list of existential conformances.
// signature: <P & Q>, replacement: $C : conformances: [$P, $Q]
SubstitutionMap ExistentialSubs;
// The value of concrete type used to initialize the existential. `%c` above.
SILValue ConcreteValue;

// Search for a recognized pattern in which the given value is an opened
// existential that was previously initialized to a concrete type.
// Constructs a valid ConcreteExistentialInfo object if successfull.
ConcreteExistentialInfo(Operand &openedUse);

ConcreteExistentialInfo(ConcreteExistentialInfo &) = delete;

bool isValid() const {
return OpenedArchetype && OpenedArchetypeDef && InitExistential
&& ConcreteType && !ExistentialSubs.empty() && ConcreteValue;
}

// Do a conformance lookup on ConcreteType with the given requirement, P. If P
// is satisfiable based on the existential's conformance, return the new
// conformance on P. Otherwise return None.
Optional<ProtocolConformanceRef>
lookupExistentialConformance(ProtocolDecl *P) const {
CanType selfTy = P->getSelfInterfaceType()->getCanonicalType();
return ExistentialSubs.lookupConformance(selfTy, P);
}
};

} // end namespace swift

#endif
23 changes: 8 additions & 15 deletions lib/SILOptimizer/SILCombiner/SILCombiner.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "swift/SIL/SILValue.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SILOptimizer/Utils/CastOptimizer.h"
#include "swift/SILOptimizer/Utils/Existential.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -279,24 +280,16 @@ class SILCombiner :
StringRef FInverseName, StringRef FName);

private:
SILInstruction * createApplyWithConcreteType(FullApplySite AI,
SILValue NewSelf,
SILValue Self,
CanType ConcreteType,
SILValue ConcreteTypeDef,
ProtocolConformanceRef Conformance,
ArchetypeType *OpenedArchetype);

FullApplySite rewriteApplyCallee(FullApplySite apply, SILValue callee);

SILInstruction *
propagateConcreteTypeOfInitExistential(FullApplySite AI,
ProtocolDecl *Protocol,
llvm::function_ref<void(CanType, ProtocolConformanceRef)> Propagate);
SILInstruction *createApplyWithConcreteType(FullApplySite Apply,
const ConcreteExistentialInfo &CEI,
SILBuilderContext &BuilderCtx);

SILInstruction *propagateConcreteTypeOfInitExistential(FullApplySite AI,
WitnessMethodInst *WMI);
SILInstruction *propagateConcreteTypeOfInitExistential(FullApplySite AI);
SILInstruction *
propagateConcreteTypeOfInitExistential(FullApplySite Apply,
WitnessMethodInst *WMI);
SILInstruction *propagateConcreteTypeOfInitExistential(FullApplySite Apply);

/// Perform one SILCombine iteration.
bool doOneIteration(SILFunction &F, unsigned Iteration);
Expand Down
Loading