Skip to content

Extend SILCombiner code to handle existential self concrete type propagation using ProtocolConformanceAnalysis #18109

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
Aug 13, 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
6 changes: 4 additions & 2 deletions include/swift/SILOptimizer/Utils/Existential.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@ struct ConcreteExistentialInfo {

ConcreteExistentialInfo(ConcreteExistentialInfo &) = delete;

/// We do not not need to check for InitExistential not being not null
/// since if that were the case, we would have everything else null too.
bool isValid() const {
return OpenedArchetype && OpenedArchetypeDef && InitExistential
&& ConcreteType && !ExistentialSubs.empty() && ConcreteValue;
return OpenedArchetype && OpenedArchetypeDef && ConcreteType &&
!ExistentialSubs.empty() && ConcreteValue;
}

// Do a conformance lookup on ConcreteType with the given requirement, P. If P
Expand Down
7 changes: 7 additions & 0 deletions lib/SILOptimizer/SILCombiner/SILCombiner.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,13 @@ class SILCombiner :
WitnessMethodInst *WMI);
SILInstruction *propagateConcreteTypeOfInitExistential(FullApplySite Apply);

// Common utility function to replace the WitnessMethodInst using a
// BuilderCtx.
void replaceWitnessMethodInst(FullApplySite Apply, WitnessMethodInst *WMI,
SILBuilderContext &BuilderCtx,
const CanType &ConcreteType,
const ProtocolConformanceRef ConformanceRef);

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

Expand Down
43 changes: 24 additions & 19 deletions lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,23 @@ SILCombiner::optimizeConcatenationOfStringLiterals(ApplyInst *AI) {
return tryToConcatenateStrings(AI, Builder);
}

/// This routine replaces the old witness method inst with a new one.
void SILCombiner::replaceWitnessMethodInst(
FullApplySite Apply, WitnessMethodInst *WMI, SILBuilderContext &BuilderCtx,
const CanType &ConcreteType, const ProtocolConformanceRef ConformanceRef) {
SILBuilderWithScope WMIBuilder(WMI, BuilderCtx);
auto *NewWMI = WMIBuilder.createWitnessMethod(
WMI->getLoc(), ConcreteType, ConformanceRef, WMI->getMember(),
WMI->getType());
MutableArrayRef<Operand> Operands = Apply.getInstruction()->getAllOperands();
for (auto &Op : Operands) {
if (Op.get() == WMI)
Op.set(NewWMI);
}
if (WMI->use_empty())
eraseInstFromFunction(*WMI);
}

/// Given an Apply and an argument value produced by InitExistentialAddrInst,
/// return true if the argument can be replaced by a copy of its value.
///
Expand Down Expand Up @@ -712,8 +729,10 @@ SILCombiner::createApplyWithConcreteType(FullApplySite Apply,
}
// The apply can only be rewritten in terms of the concrete value if it is
// legal to pass that value as the self argument.
if (CEI.isCopied && !canReplaceCopiedSelf(Apply, CEI.InitExistential, DA))
if (CEI.isCopied && (!CEI.InitExistential ||
!canReplaceCopiedSelf(Apply, CEI.InitExistential, DA))) {
return nullptr;
}

// Create a set of arguments.
SmallVector<SILValue, 8> NewArgs;
Expand Down Expand Up @@ -819,24 +838,10 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite Apply,
// are stuck:
// We will re-create the same instruction and re-populate the worklist
// with it.
if (CEI.ConcreteType != WMI->getLookupType()
|| SelfConformance != WMI->getConformance()) {
SILBuilderWithScope WMIBuilder(WMI, BuilderCtx);
// Keep around the dependence on the open instruction unless we've
// actually eliminated the use.
auto *NewWMI = WMIBuilder.createWitnessMethod(
WMI->getLoc(), CEI.ConcreteType, SelfConformance, WMI->getMember(),
WMI->getType());
// Replace only uses of the witness_method in the apply that was analyzed by
// ConcreteExistentialInfo.
MutableArrayRef<Operand> Operands =
Apply.getInstruction()->getAllOperands();
for (auto &Op : Operands) {
if (Op.get() == WMI)
Op.set(NewWMI);
}
if (WMI->use_empty())
eraseInstFromFunction(*WMI);
if (CEI.ConcreteType != WMI->getLookupType() ||
SelfConformance != WMI->getConformance()) {
replaceWitnessMethodInst(Apply, WMI, BuilderCtx, CEI.ConcreteType,
SelfConformance);
}
// Try to rewrite the apply.
return createApplyWithConcreteType(Apply, CEI, BuilderCtx);
Expand Down