Skip to content

Commit 0d9aced

Browse files
committed
Fix SILCombiner for partial_apply [stack]
1 parent 75dcfa4 commit 0d9aced

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,22 @@ static bool foldInverseReabstractionThunks(PartialApplyInst *PAI,
7474
SILInstruction *SILCombiner::visitPartialApplyInst(PartialApplyInst *PAI) {
7575
// partial_apply without any substitutions or arguments is just a
7676
// thin_to_thick_function.
77-
if (!PAI->hasSubstitutions() && (PAI->getNumArguments() == 0))
78-
return Builder.createThinToThickFunction(PAI->getLoc(), PAI->getCallee(),
79-
PAI->getType());
77+
if (!PAI->hasSubstitutions() && (PAI->getNumArguments() == 0)) {
78+
if (!PAI->isOnStack())
79+
return Builder.createThinToThickFunction(PAI->getLoc(), PAI->getCallee(),
80+
PAI->getType());
81+
82+
// Remove dealloc_stack of partial_apply [stack].
83+
for (auto *Use : PAI->getUses())
84+
if (auto *dealloc = dyn_cast<DeallocStackInst>(Use->getUser()))
85+
eraseInstFromFunction(*dealloc);
86+
auto *thinToThick = Builder.createThinToThickFunction(
87+
PAI->getLoc(), PAI->getCallee(), PAI->getType());
88+
replaceInstUsesWith(*PAI, thinToThick);
89+
eraseInstFromFunction(*PAI);
90+
return nullptr;
91+
}
92+
8093

8194
// partial_apply %reabstraction_thunk_typeAtoB(
8295
// partial_apply %reabstraction_thunk_typeBtoA %closure_typeB))
@@ -138,6 +151,12 @@ class PartialApplyCombiner {
138151

139152
/// Returns true on success.
140153
bool PartialApplyCombiner::allocateTemporaries() {
154+
// A partial_apply [stack]'s argument are not owned by the partial_apply and
155+
// therefore their lifetime must outlive any uses.
156+
if (PAI->isOnStack()) {
157+
return true;
158+
}
159+
141160
// Copy the original arguments of the partial_apply into newly created
142161
// temporaries and use these temporaries instead of the original arguments
143162
// afterwards.
@@ -397,6 +416,15 @@ SILInstruction *PartialApplyCombiner::combine() {
397416
Uses.append(CFI->getUses().begin(), CFI->getUses().end());
398417
continue;
399418
}
419+
// Look through mark_dependence users of partial_apply [stack].
420+
if (auto *MD = dyn_cast<MarkDependenceInst>(User)) {
421+
if (MD->getValue() == Use->get() &&
422+
MD->getValue()->getType().is<SILFunctionType>() &&
423+
MD->getValue()->getType().castTo<SILFunctionType>()->isNoEscape()) {
424+
Uses.append(MD->getUses().begin(), MD->getUses().end());
425+
}
426+
continue;
427+
}
400428
// If this use of a partial_apply is not
401429
// an apply which uses it as a callee, bail.
402430
auto AI = FullApplySite::isa(User);

test/SILOptimizer/sil_combine_apply.sil

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,68 @@ bb0:
571571
%999 = tuple ()
572572
return %999 : $()
573573
}
574+
575+
// CHECK-LABEL: sil shared @applied_on_stack : $@convention(thin) () -> () {
576+
// CHECK: bb0:
577+
// CHECK: [[F:%.*]] = function_ref @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
578+
// CHECK: [[STK:%.*]] = alloc_stack $Builtin.Int64
579+
// CHECK: [[STK2:%.*]] = alloc_stack $Builtin.Int64
580+
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int64, 3
581+
// CHECK: store [[I]] to [[STK2]] : $*Builtin.Int64
582+
// CHECK: apply [[F]]([[STK]], [[STK2]]) : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
583+
// CHECK: dealloc_stack [[STK2]] : $*Builtin.Int64
584+
// CHECK: dealloc_stack [[STK]] : $*Builtin.Int64
585+
// CHECK: return %8 : $()
586+
587+
sil shared @applied_on_stack : $@convention(thin) () -> () {
588+
bb0:
589+
%fn = function_ref @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
590+
%pa = partial_apply [callee_guaranteed] [on_stack] %fn() : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
591+
%out = alloc_stack $Builtin.Int64
592+
%in = alloc_stack $Builtin.Int64
593+
%c3 = integer_literal $Builtin.Int64, 3
594+
store %c3 to %in : $*Builtin.Int64
595+
%call = apply %pa(%out, %in) : $@noescape @callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
596+
dealloc_stack %in : $*Builtin.Int64
597+
dealloc_stack %out : $*Builtin.Int64
598+
dealloc_stack %pa : $@noescape @callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
599+
%999 = tuple ()
600+
return %999 : $()
601+
}
602+
603+
sil @guaranteed_closure_throws2 : $@convention(thin) (Builtin.Int32, @guaranteed C) -> @error Error
604+
605+
// CHECK-LABEL: sil @test_guaranteed_closure_try_apply_on_stack
606+
// CHECK: bb0
607+
// CHECK: strong_retain
608+
// CHECK: strong_retain
609+
// CHECK: try_apply
610+
// CHECK: bb1
611+
// CHECK: strong_release
612+
// CHECK: strong_release
613+
// CHECK: br bb3
614+
// CHECK: bb2
615+
// CHECK: strong_release
616+
// CHECK: strong_release
617+
// CHECK: br bb3
618+
sil @test_guaranteed_closure_try_apply_on_stack : $@convention(thin) (@guaranteed C, Builtin.Int32) -> () {
619+
bb0(%0: $C, %1: $Builtin.Int32):
620+
strong_retain %0 : $C
621+
%closure_fun = function_ref @guaranteed_closure_throws2 : $@convention(thin) (Builtin.Int32, @guaranteed C) -> @error Error
622+
%closure = partial_apply [callee_guaranteed] [on_stack] %closure_fun(%0) : $@convention(thin) (Builtin.Int32, @guaranteed C) -> @error Error
623+
try_apply %closure(%1) : $@noescape @callee_guaranteed (Builtin.Int32) -> @error Error, normal bb7, error bb11
624+
625+
bb7(%callret : $()):
626+
dealloc_stack %closure : $@noescape @callee_guaranteed (Builtin.Int32) -> @error Error
627+
strong_release %0: $C
628+
br bb99
629+
630+
bb11(%128 : $Error):
631+
dealloc_stack %closure : $@noescape @callee_guaranteed (Builtin.Int32) -> @error Error
632+
strong_release %0: $C
633+
br bb99
634+
635+
bb99:
636+
%t = tuple()
637+
return %t : $()
638+
}

0 commit comments

Comments
 (0)