Skip to content

Commit b68e5f6

Browse files
Merge pull request #67913 from nate-chandler/opaque-values/20230814/partial-apply-loadable
[AddressLowering] Rewrite indirect partial_apply.
2 parents 1a010dd + 16bd80d commit b68e5f6

File tree

3 files changed

+117
-12
lines changed

3 files changed

+117
-12
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -541,9 +541,9 @@ class ApplySite {
541541

542542
void dump() const LLVM_ATTRIBUTE_USED { getInstruction()->dump(); }
543543

544-
/// Attempt to cast this apply site to a full apply site, returning None on
545-
/// failure.
546-
llvm::Optional<FullApplySite> asFullApplySite() const;
544+
/// Form a FullApplySite. Note that it will be null if this apply site is not
545+
/// in fact a FullApplySite.
546+
FullApplySite asFullApplySite() const;
547547
};
548548

549549
//===----------------------------------------------------------------------===//
@@ -818,15 +818,15 @@ template <> struct DenseMapInfo<::swift::FullApplySite> {
818818

819819
namespace swift {
820820

821-
inline llvm::Optional<FullApplySite> ApplySite::asFullApplySite() const {
821+
inline FullApplySite ApplySite::asFullApplySite() const {
822822
return FullApplySite::isa(getInstruction());
823823
}
824824

825825
inline bool ApplySite::isIndirectResultOperand(const Operand &op) const {
826826
auto fas = asFullApplySite();
827827
if (!fas)
828828
return false;
829-
return fas->isIndirectResultOperand(op);
829+
return fas.isIndirectResultOperand(op);
830830
}
831831

832832
} // namespace swift

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ struct AddressLoweringState {
509509
// Applies with indirect results are removed as they are rewritten. Applies
510510
// with only indirect arguments are rewritten in a post-pass, only after all
511511
// parameters are rewritten.
512-
SmallBlotSetVector<FullApplySite, 16> indirectApplies;
512+
SmallBlotSetVector<ApplySite, 16> indirectApplies;
513513

514514
// unconditional_checked_cast instructions of loadable type which need to be
515515
// rewritten.
@@ -732,7 +732,7 @@ class OpaqueValueVisitor {
732732
void mapValueStorage();
733733

734734
protected:
735-
void checkForIndirectApply(FullApplySite applySite);
735+
void checkForIndirectApply(ApplySite applySite);
736736
void visitValue(SILValue value);
737737
void canonicalizeReturnValues();
738738
};
@@ -755,7 +755,7 @@ void OpaqueValueVisitor::mapValueStorage() {
755755
}
756756
}
757757
for (auto &inst : *block) {
758-
if (auto apply = FullApplySite::isa(&inst))
758+
if (auto apply = ApplySite::isa(&inst))
759759
checkForIndirectApply(apply);
760760

761761
if (auto *yieldInst = dyn_cast<YieldInst>(&inst)) {
@@ -774,7 +774,7 @@ void OpaqueValueVisitor::mapValueStorage() {
774774
}
775775

776776
/// Populate `indirectApplies`.
777-
void OpaqueValueVisitor::checkForIndirectApply(FullApplySite applySite) {
777+
void OpaqueValueVisitor::checkForIndirectApply(ApplySite applySite) {
778778
auto calleeConv = applySite.getSubstCalleeConv();
779779
unsigned calleeArgIdx = applySite.getCalleeArgIndexOfFirstAppliedArg();
780780
for (Operand &operand : applySite.getArgumentOperands()) {
@@ -2228,7 +2228,7 @@ void CallArgRewriter::rewriteIndirectArgument(Operand *operand) {
22282228
// Allocate temporary storage for a loadable operand.
22292229
AllocStackInst *allocInst =
22302230
argBuilder.createAllocStack(callLoc, argValue->getType());
2231-
if (apply.getArgumentConvention(*operand).isOwnedConvention()) {
2231+
if (apply.getCaptureConvention(*operand).isOwnedConvention()) {
22322232
argBuilder.createTrivialStoreOr(apply.getLoc(), argValue, allocInst,
22332233
StoreOwnershipQualifier::Init);
22342234
apply.insertAfterApplication([&](SILBuilder &callBuilder) {
@@ -4139,10 +4139,17 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
41394139

41404140
// Rewrite applies with indirect parameters or results of loadable types which
41414141
// were not visited during opaque value rewriting.
4142-
static void rewriteIndirectApply(FullApplySite apply,
4142+
static void rewriteIndirectApply(ApplySite anyApply,
41434143
AddressLoweringState &pass) {
41444144
// If all indirect args were loadable, then they still need to be rewritten.
4145-
CallArgRewriter(apply, pass).rewriteArguments();
4145+
CallArgRewriter(anyApply, pass).rewriteArguments();
4146+
4147+
auto apply = anyApply.asFullApplySite();
4148+
if (!apply) {
4149+
// The "result" of the partial_apply isn't rewritten.
4150+
assert(anyApply.getKind() == ApplySiteKind::PartialApplyInst);
4151+
return;
4152+
}
41464153

41474154
switch (apply.getKind()) {
41484155
case FullApplySiteKind::ApplyInst:

test/SILOptimizer/address_lowering.sil

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ public protocol Comparable {
9393

9494
sil [ossa] @unknown : $@convention(thin) () -> ()
9595
sil [ossa] @getT : $@convention(thin) <T> () -> @out T
96+
sil [ossa] @getKlass : $@convention(thin) () -> (@owned Klass)
97+
sil [ossa] @borrowKlass : $(@in_guaranteed Klass) -> ()
98+
sil [ossa] @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
9699
sil [ossa] @getPair : $@convention(thin) <T> () -> @out Pair<T>
97100
sil [ossa] @getOwned : $@convention(thin) <T : AnyObject> () -> (@owned T)
98101
sil [ossa] @takeGuaranteedObject : $@convention(thin) (@guaranteed AnyObject) -> ()
@@ -2521,6 +2524,101 @@ bb0:
25212524
return %retval : $()
25222525
}
25232526

2527+
// CHECK-LABEL: sil [ossa] @test_partial_apply_1_addronly_heap : {{.*}} {
2528+
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
2529+
// CHECK: [[GET:%[^,]+]] = function_ref @getT
2530+
// CHECK: apply [[GET]]<T>([[STACK]])
2531+
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowT
2532+
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[BORROW]]<T>([[STACK]])
2533+
// CHECK: apply [[CLOSURE]]()
2534+
// CHECK: destroy_value [[CLOSURE]]
2535+
// CHECK: dealloc_stack [[STACK]]
2536+
// CHECK-LABEL: } // end sil function 'test_partial_apply_1_addronly_heap'
2537+
sil [ossa] @test_partial_apply_1_addronly_heap : $<T> () -> () {
2538+
%get = function_ref @getT : $@convention(thin) <T> () -> (@out T)
2539+
%instance = apply %get<T>() : $@convention(thin) <T> () -> (@out T)
2540+
%callee = function_ref @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
2541+
%closure = partial_apply [callee_guaranteed] %callee<T>(%instance) : $@convention(thin) <T> (@in_guaranteed T) -> ()
2542+
apply %closure() : $@callee_guaranteed () -> ()
2543+
destroy_value %closure : $@callee_guaranteed () -> ()
2544+
%retval = tuple ()
2545+
return %retval : $()
2546+
}
2547+
2548+
// CHECK-LABEL: sil [ossa] @test_partial_apply_2_addronly_stack : {{.*}} {
2549+
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
2550+
// CHECK: [[GET:%[^,]+]] = function_ref @getT
2551+
// CHECK: apply [[GET]]<T>([[STACK]])
2552+
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowT
2553+
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[BORROW]]<T>([[STACK]])
2554+
// CHECK: apply [[CLOSURE]]()
2555+
// CHECK: destroy_value [[CLOSURE]]
2556+
// CHECK: destroy_addr [[STACK]]
2557+
// CHECK: dealloc_stack [[STACK]]
2558+
// CHECK-LABEL: } // end sil function 'test_partial_apply_2_addronly_stack'
2559+
sil [ossa] @test_partial_apply_2_addronly_stack : $<T> () -> () {
2560+
%get = function_ref @getT : $@convention(thin) <T> () -> (@out T)
2561+
%instance = apply %get<T>() : $@convention(thin) <T> () -> (@out T)
2562+
%callee = function_ref @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
2563+
%closure = partial_apply [on_stack] [callee_guaranteed] %callee<T>(%instance) : $@convention(thin) <T> (@in_guaranteed T) -> ()
2564+
apply %closure() : $@noescape @callee_guaranteed () -> ()
2565+
destroy_value %closure : $@noescape @callee_guaranteed () -> ()
2566+
destroy_value %instance : $T
2567+
%retval = tuple ()
2568+
return %retval : $()
2569+
}
2570+
2571+
// CHECK-LABEL: sil [ossa] @test_partial_apply_3_loadable_heap : {{.*}} {
2572+
// CHECK: [[GET:%[^,]+]] = function_ref @getKlass
2573+
// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET]]()
2574+
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowKlass
2575+
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Klass
2576+
// CHECK: store [[INSTANCE]] to [init] [[ADDR]]
2577+
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[BORROW]]([[ADDR]])
2578+
// CHECK: dealloc_stack [[ADDR]]
2579+
// CHECK: apply [[CLOSURE]]()
2580+
// CHECK: destroy_value [[CLOSURE]]
2581+
// CHECK-LABEL: } // end sil function 'test_partial_apply_3_loadable_heap'
2582+
sil [ossa] @test_partial_apply_3_loadable_heap : $() -> () {
2583+
%get = function_ref @getKlass : $@convention(thin) () -> (@owned Klass)
2584+
%instance = apply %get() : $@convention(thin) () -> (@owned Klass)
2585+
%callee = function_ref @borrowKlass : $@convention(thin) (@in_guaranteed Klass) -> ()
2586+
%closure = partial_apply [callee_guaranteed] %callee(%instance) : $@convention(thin) (@in_guaranteed Klass) -> ()
2587+
apply %closure() : $@callee_guaranteed () -> ()
2588+
destroy_value %closure : $@callee_guaranteed () -> ()
2589+
// destroy_value %instance : $Klass
2590+
%retval = tuple ()
2591+
return %retval : $()
2592+
}
2593+
2594+
// CHECK-LABEL: sil [ossa] @test_partial_apply_4_loadable_stack : {{.*}} {
2595+
// CHECK: [[GET:%[^,]+]] = function_ref @getKlass
2596+
// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET]]()
2597+
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowKlass
2598+
// CHECK: [[STACK:%[^,]+]] = alloc_stack $Klass
2599+
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
2600+
// CHECK: [[STORAGE_LIFETIME:%[^,]+]] = store_borrow [[LIFETIME]] to [[STACK]]
2601+
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[BORROW]]([[STORAGE_LIFETIME]])
2602+
// FIXME: These end_borrows must be _after_ the apply of the closure!
2603+
// CHECK: end_borrow [[STORAGE_LIFETIME]]
2604+
// CHECK: end_borrow [[LIFETIME]]
2605+
// CHECK: dealloc_stack [[STACK]]
2606+
// CHECK: apply [[CLOSURE]]() : $@noescape @callee_guaranteed () -> ()
2607+
// CHECK: destroy_value [[CLOSURE]] : $@noescape @callee_guaranteed () -> ()
2608+
// CHECK: destroy_value [[INSTANCE]]
2609+
// CHECK-LABEL: } // end sil function 'test_partial_apply_4_loadable_stack'
2610+
sil [ossa] @test_partial_apply_4_loadable_stack : $() -> () {
2611+
%get = function_ref @getKlass : $@convention(thin) () -> (@owned Klass)
2612+
%instance = apply %get() : $@convention(thin) () -> (@owned Klass)
2613+
%callee = function_ref @borrowKlass : $@convention(thin) (@in_guaranteed Klass) -> ()
2614+
%closure = partial_apply [on_stack] [callee_guaranteed] %callee(%instance) : $@convention(thin) (@in_guaranteed Klass) -> ()
2615+
apply %closure() : $@noescape @callee_guaranteed () -> ()
2616+
destroy_value %closure : $@noescape @callee_guaranteed () -> ()
2617+
destroy_value %instance : $Klass
2618+
%retval = tuple ()
2619+
return %retval : $()
2620+
}
2621+
25242622
// CHECK-LABEL: sil hidden [ossa] @test_store_1 : {{.*}} {
25252623
// CHECK: [[MAYBE_ADDR:%[^,]+]] = alloc_stack $Optional<Self>
25262624
// CHECK: [[LOAD_ADDR:%[^,]+]] = alloc_stack $Self

0 commit comments

Comments
 (0)