Skip to content

4.2 SILCombiner::propagateConcreteTypeOfInitExistential fixes. #17554

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 4 commits 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
299 changes: 185 additions & 114 deletions include/swift/SIL/SILBuilder.h

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1955,8 +1955,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
107 changes: 107 additions & 0 deletions include/swift/SILOptimizer/Utils/Existential.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//===--- Existential.h - Existential related Analyses. -------*- C++ //-*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SILOPTIMIZER_UTILS_EXISTENTIAL_H
#define SWIFT_SILOPTIMIZER_UTILS_EXISTENTIAL_H

#include "swift/AST/SubstitutionMap.h"
#include "swift/SIL/SILInstruction.h"

namespace swift {

/// Find InitExistential from global_addr and copy_addr.
SILValue findInitExistentialFromGlobalAddr(GlobalAddrInst *GAI,
CopyAddrInst *CAI);

/// Returns the address of an object with which the stack location \p ASI is
/// initialized. This is either a init_existential_addr or the destination of a
/// copy_addr. Returns a null value if the address does not dominate the
/// alloc_stack user \p ASIUser.
/// If the value is copied from another stack location, \p isCopied is set to
/// true.
SILValue getAddressOfStackInit(AllocStackInst *ASI, SILInstruction *ASIUser,
bool &isCopied);

/// Find the init_existential, which could be used to determine a concrete
/// type of the value used by \p openedUse.
/// If the value is copied from another stack location, \p isCopied is set to
/// true.
///
/// 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: 13 additions & 10 deletions lib/SIL/SILBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ using namespace swift;

SILBuilder::SILBuilder(SILGlobalVariable *GlobVar,
SmallVectorImpl<SILInstruction *> *InsertedInstrs)
: F(nullptr), Mod(GlobVar->getModule()), InsertedInstrs(InsertedInstrs) {
: TempContext(GlobVar->getModule(), InsertedInstrs), C(TempContext),
F(nullptr) {
setInsertionPoint(&GlobVar->StaticInitializerBlock);
}

Expand Down Expand Up @@ -100,7 +101,8 @@ SILBuilder::tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
return nullptr;

return insert(UncheckedRefCastInst::create(getSILDebugLocation(Loc), Op,
ResultTy, getFunction(), OpenedArchetypes));
ResultTy, getFunction(),
C.OpenedArchetypes));
}

ClassifyBridgeObjectInst *
Expand All @@ -120,15 +122,15 @@ SILBuilder::createUncheckedBitCast(SILLocation Loc, SILValue Op, SILType Ty) {
assert(Ty.isLoadableOrOpaque(getModule()));
if (Ty.isTrivial(getModule()))
return insert(UncheckedTrivialBitCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), OpenedArchetypes));
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));

if (auto refCast = tryCreateUncheckedRefCast(Loc, Op, Ty))
return refCast;

// The destination type is nontrivial, and may be smaller than the source
// type, so RC identity cannot be assumed.
return insert(UncheckedBitwiseCastInst::create(getSILDebugLocation(Loc), Op,
Ty, getFunction(), OpenedArchetypes));
return insert(UncheckedBitwiseCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}

BranchInst *SILBuilder::createBranch(SILLocation Loc,
Expand Down Expand Up @@ -420,7 +422,7 @@ SILValue SILBuilder::emitObjCToThickMetatype(SILLocation Loc, SILValue Op,
void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) {
// The list of archetypes from the previous instruction needs
// to be replaced, because it may reference a removed instruction.
OpenedArchetypes.addOpenedArchetypeOperands(I->getTypeDependentOperands());
C.OpenedArchetypes.addOpenedArchetypeOperands(I->getTypeDependentOperands());
if (I && I->getNumTypeDependentOperands() > 0)
return;

Expand All @@ -447,18 +449,19 @@ void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) {
I = SVI;
continue;
}
auto Def = OpenedArchetypes.getOpenedArchetypeDef(Archetype);
auto Def = C.OpenedArchetypes.getOpenedArchetypeDef(Archetype);
// Return if it is a known open archetype.
if (Def)
return;
// Otherwise register it and return.
if (OpenedArchetypesTracker)
OpenedArchetypesTracker->addOpenedArchetypeDef(Archetype, SVI);
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->addOpenedArchetypeDef(Archetype, SVI);
return;
}

if (I && I->getNumTypeDependentOperands() > 0) {
OpenedArchetypes.addOpenedArchetypeOperands(I->getTypeDependentOperands());
C.OpenedArchetypes.addOpenedArchetypeOperands(
I->getTypeDependentOperands());
}
}

Expand Down
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