Skip to content

[4.0] [sil-combine] Make sure that (apply (partial_apply)) -> (apply') bail… #11261

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
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
19 changes: 14 additions & 5 deletions lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,34 @@ bool PartialApplyCombiner::allocateTemporaries() {
// Emit a destroy value for each captured closure argument.
ArrayRef<SILParameterInfo> Params = PAITy->getParameters();
auto Args = PAI->getArguments();
unsigned Delta = Params.size() - Args.size();
Params = Params.drop_front(Params.size() - Args.size());

llvm::SmallVector<std::pair<SILValue, unsigned>, 8> ArgsToHandle;
for (unsigned AI = 0, AE = Args.size(); AI != AE; ++AI) {
SILValue Arg = Args[AI];
SILParameterInfo Param = Params[AI + Delta];
for (unsigned i : indices(Args)) {
SILValue Arg = Args[i];
SILParameterInfo Param = Params[i];
if (Param.isIndirectMutating())
continue;

// Create a temporary and copy the argument into it, if:
// - the argument stems from an alloc_stack
// - the argument is consumed by the callee and is indirect
// (e.g. it is an @in argument)
if (isa<AllocStackInst>(Arg)
|| (Param.isConsumed()
&& PAI->getSubstCalleeConv().isSILIndirect(Param))) {
// If the argument has a dependent type, then we can not create a
// temporary for it at the beginning of the function, so we must bail.
//
// TODO: This is because we are inserting alloc_stack at the beginning/end
// of functions where the dependent type may not exist yet.
if (Arg->getType().hasOpenedExistential())
return false;

// If the temporary is non-trivial, we need to release it later.
if (!Arg->getType().isTrivial(PAI->getModule()))
needsReleases = true;
ArgsToHandle.push_back(std::make_pair(Arg, AI));
ArgsToHandle.push_back(std::make_pair(Arg, i));
}
}

Expand Down
31 changes: 27 additions & 4 deletions test/SILOptimizer/sil_combine_apply.sil
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ sil @generic_callee : $@convention(thin) <T, U> (@in T, @in U) -> ()

protocol Error {}

protocol SwiftP {
func foo()
}

/////////////////////////////////
// Tests for SILCombinerApply. //
/////////////////////////////////
Expand Down Expand Up @@ -235,10 +239,6 @@ bb6(%5 : $Error):
throw %5 : $Error
}

protocol SwiftP {
func foo()
}

// Make sure that we do not optimize this case. If we do optimize this case,
// given the current algorithm which puts alloc_stack at the beginning/end of
// the function, we will have a fatal error.
Expand Down Expand Up @@ -285,4 +285,27 @@ bb0(%0 : $*T, %1 : $*T):
%a1 = apply %pa(%0) : $@callee_owned (@in T) -> ()
%r = tuple ()
return %r : $()
}

// Today when we optimize (apply (partial_apply)) -> apply, we can not handle
// dependent types since the algorithm attempts to create an alloc_stack at the
// beginning/end of the function. In such a case, the dependent type may not be
// alive at that point, so the compiler will crash. This test ensures that we do
// not optimize this case.
//
// CHECK-LABEL: sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
// CHECK: [[PAI:%.*]] = partial_apply
// CHECK: apply [[PAI]]
sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
bb0(%0 : $*SwiftP):
%0b = alloc_stack $SwiftP
%1 = open_existential_addr mutable_access %0b : $*SwiftP to $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
%2 = witness_method $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP, #SwiftP.foo!1, %1 : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP : $@convention(witness_method) <τ_0_0 where τ_0_0 : SwiftP> (@in_guaranteed τ_0_0) -> ()
%0c = alloc_stack $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
%3 = partial_apply %2<@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP>(%0c) : $@convention(witness_method) <τ_0_0 where τ_0_0 : SwiftP> (@in_guaranteed τ_0_0) -> ()
dealloc_stack %0c : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
dealloc_stack %0b : $*SwiftP
%4 = apply %3() : $@callee_owned () -> ()
%9999 = tuple()
return %9999 : $()
}