Skip to content

Commit 3c7af4e

Browse files
authored
Merge pull request #11253 from gottesmm/rdar33595317
2 parents 3f993ef + 3aadede commit 3c7af4e

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,42 +134,51 @@ class PartialApplyCombiner {
134134

135135
/// Returns true on success.
136136
bool PartialApplyCombiner::allocateTemporaries() {
137-
// Copy the original arguments of the partial_apply into
138-
// newly created temporaries and use these temporaries instead of
139-
// the original arguments afterwards.
140-
// This is done to "extend" the life-time of original partial_apply
141-
// arguments, as they may be destroyed/deallocated before the last
142-
// use by one of the apply instructions.
143-
// TODO:
144-
// Copy arguments of the partial_apply into new temporaries
145-
// only if the lifetime of arguments ends before their uses
146-
// by apply instructions.
137+
// Copy the original arguments of the partial_apply into newly created
138+
// temporaries and use these temporaries instead of the original arguments
139+
// afterwards.
140+
//
141+
// This is done to "extend" the life-time of original partial_apply arguments,
142+
// as they may be destroyed/deallocated before the last use by one of the
143+
// apply instructions.
144+
//
145+
// TODO: Copy arguments of the partial_apply into new temporaries only if the
146+
// lifetime of arguments ends before their uses by apply instructions.
147147
bool needsReleases = false;
148148
CanSILFunctionType PAITy =
149149
PAI->getCallee()->getType().getAs<SILFunctionType>();
150150

151151
// Emit a destroy value for each captured closure argument.
152152
ArrayRef<SILParameterInfo> Params = PAITy->getParameters();
153153
auto Args = PAI->getArguments();
154-
unsigned Delta = Params.size() - Args.size();
154+
Params = Params.drop_front(Params.size() - Args.size());
155155

156156
llvm::SmallVector<std::pair<SILValue, unsigned>, 8> ArgsToHandle;
157-
for (unsigned AI = 0, AE = Args.size(); AI != AE; ++AI) {
158-
SILValue Arg = Args[AI];
159-
SILParameterInfo Param = Params[AI + Delta];
157+
for (unsigned i : indices(Args)) {
158+
SILValue Arg = Args[i];
159+
SILParameterInfo Param = Params[i];
160160
if (Param.isIndirectMutating())
161161
continue;
162+
162163
// Create a temporary and copy the argument into it, if:
163164
// - the argument stems from an alloc_stack
164165
// - the argument is consumed by the callee and is indirect
165166
// (e.g. it is an @in argument)
166167
if (isa<AllocStackInst>(Arg)
167168
|| (Param.isConsumed()
168169
&& PAI->getSubstCalleeConv().isSILIndirect(Param))) {
170+
// If the argument has a dependent type, then we can not create a
171+
// temporary for it at the beginning of the function, so we must bail.
172+
//
173+
// TODO: This is because we are inserting alloc_stack at the beginning/end
174+
// of functions where the dependent type may not exist yet.
175+
if (Arg->getType().hasOpenedExistential())
176+
return false;
177+
169178
// If the temporary is non-trivial, we need to release it later.
170179
if (!Arg->getType().isTrivial(PAI->getModule()))
171180
needsReleases = true;
172-
ArgsToHandle.push_back(std::make_pair(Arg, AI));
181+
ArgsToHandle.push_back(std::make_pair(Arg, i));
173182
}
174183
}
175184

test/SILOptimizer/sil_combine_apply.sil

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ sil @generic_callee : $@convention(thin) <T, U> (@in T, @in U) -> ()
1111

1212
protocol Error {}
1313

14+
protocol SwiftP {
15+
func foo()
16+
}
17+
1418
/////////////////////////////////
1519
// Tests for SILCombinerApply. //
1620
/////////////////////////////////
@@ -235,10 +239,6 @@ bb6(%5 : $Error):
235239
throw %5 : $Error
236240
}
237241

238-
protocol SwiftP {
239-
func foo()
240-
}
241-
242242
// Make sure that we do not optimize this case. If we do optimize this case,
243243
// given the current algorithm which puts alloc_stack at the beginning/end of
244244
// the function, we will have a fatal error.
@@ -285,4 +285,27 @@ bb0(%0 : $*T, %1 : $*T):
285285
%a1 = apply %pa(%0) : $@callee_owned (@in T) -> ()
286286
%r = tuple ()
287287
return %r : $()
288+
}
289+
290+
// Today when we optimize (apply (partial_apply)) -> apply, we can not handle
291+
// dependent types since the algorithm attempts to create an alloc_stack at the
292+
// beginning/end of the function. In such a case, the dependent type may not be
293+
// alive at that point, so the compiler will crash. This test ensures that we do
294+
// not optimize this case.
295+
//
296+
// CHECK-LABEL: sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
297+
// CHECK: [[PAI:%.*]] = partial_apply
298+
// CHECK: apply [[PAI]]
299+
sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
300+
bb0(%0 : $*SwiftP):
301+
%0b = alloc_stack $SwiftP
302+
%1 = open_existential_addr mutable_access %0b : $*SwiftP to $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
303+
%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) -> ()
304+
%0c = alloc_stack $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
305+
%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) -> ()
306+
dealloc_stack %0c : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
307+
dealloc_stack %0b : $*SwiftP
308+
%4 = apply %3() : $@callee_owned () -> ()
309+
%9999 = tuple()
310+
return %9999 : $()
288311
}

0 commit comments

Comments
 (0)