Files
swift-mirror/test/SILOptimizer/closure_specialization_multiple_captures.sil
2026-08-05 01:32:48 +03:30

51 lines
2.6 KiB
Plaintext

// RUN: %target-sil-opt -enable-sil-verify-all -closure-specialization %s | %FileCheck %s
// A value captured more than once, with a mark_dependence on it, must still be specialized:
// uniqueCaptureArguments redirects the mark_dependence base onto the capture's identity cast.
import Builtin
class Storage {}
struct Val {}
sil private [readonly] [ossa] @takesClosure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed (Val) -> Val) -> Val {
bb0(%0 : @guaranteed $@noescape @callee_guaranteed (Val) -> Val):
%v = struct $Val ()
%r = apply %0(%v) : $@noescape @callee_guaranteed (Val) -> Val
return %r : $Val
}
// %0 is captured twice; the specialized function takes it as two @guaranteed arguments and
// re-materializes the mark_dependence on the first one.
// CHECK-LABEL: sil {{.*}}@$s12takesClosure{{.*}}Tf1c_n : $@convention(thin) (@guaranteed Storage, @guaranteed Storage) -> Val {
// CHECK: [[PA:%[0-9]+]] = partial_apply [callee_guaranteed] [on_stack] {{%[0-9]+}}(%0, %1)
// CHECK: mark_dependence [[PA]] on %0
// CHECK-LABEL: } // end sil function '$s12takesClosure{{.*}}Tf1c_n'
sil private [ossa] @twiceCapturingClosure : $@convention(thin) (Val, @guaranteed Storage, @guaranteed Storage) -> Val {
bb0(%0 : $Val, %1 : @closureCapture @guaranteed $Storage, %2 : @closureCapture @guaranteed $Storage):
%r = struct $Val ()
return %r : $Val
}
// The apply is rewritten to a direct call passing the capture twice; the dead closure and its
// mark_dependence are deleted.
// CHECK-LABEL: sil [ossa] @testMultiplyCaptured : $@convention(method) (@guaranteed Storage) -> Val {
// CHECK-NOT: partial_apply
// CHECK-NOT: mark_dependence
// CHECK: [[F:%[0-9]+]] = function_ref @$s12takesClosure{{.*}}Tf1c_n
// CHECK: apply [[F]](%0, %0)
// CHECK-NOT: partial_apply
// CHECK-NOT: mark_dependence
// CHECK-LABEL: } // end sil function 'testMultiplyCaptured'
sil [ossa] @testMultiplyCaptured : $@convention(method) (@guaranteed Storage) -> Val {
bb0(%0 : @guaranteed $Storage):
%c = function_ref @twiceCapturingClosure : $@convention(thin) (Val, @guaranteed Storage, @guaranteed Storage) -> Val
%pa = partial_apply [callee_guaranteed] [on_stack] %c(%0, %0) : $@convention(thin) (Val, @guaranteed Storage, @guaranteed Storage) -> Val
%md = mark_dependence %pa : $@noescape @callee_guaranteed (Val) -> Val on %0 : $Storage
%f = function_ref @takesClosure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed (Val) -> Val) -> Val
%r = apply %f(%md) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed (Val) -> Val) -> Val
destroy_value %md
return %r : $Val
}