Files
swift-mirror/test/SILOptimizer/definite-init-convert-to-escape.swift
Meghana Gupta 6c2d3eb27d Bailout of CopyValueOpts when there is a pointer escape
Copy propagation does these optimizations more generally. It should be
able to replace this optimization. Fixing it and not just deleting CopyValueOpts
because it happens to be called in the mandatory pipeline.
2025-03-07 10:40:37 -08:00

127 lines
6.4 KiB
Swift

// RUN: %target-swift-frontend -module-name A -verify -Xllvm -sil-print-types -emit-sil -import-objc-header %S/Inputs/Closure.h -enable-copy-propagation=false -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
// RUN: %target-swift-frontend -module-name A -verify -Xllvm -sil-print-types -emit-sil -import-objc-header %S/Inputs/Closure.h -enable-copy-propagation=false -disable-objc-attr-requires-foundation-module -Xllvm -sil-disable-convert-escape-to-noescape-switch-peephole %s | %FileCheck %s --check-prefix=NOPEEPHOLE
//
// Using -enable-copy-propagation=false to pattern match against older SIL
// output. At least until -enable-copy-propagation has been around
// long enough in the same form to be worth rewriting CHECK lines.
// REQUIRES: objc_interop
import Foundation
// Make sure that we keep the escaping closures alive across the ultimate call.
// CHECK-LABEL: sil @$s1A19bridgeNoescapeBlock5optFn0D3Fn2yySSSgcSg_AFtF
// CHECK: bb0
// CHECK: retain_value %0
// CHECK: retain_value %0
// CHECK: bb1
// CHECK: convert_escape_to_noescape %
// CHECK: strong_release
// CHECK: bb5
// CHECK: retain_value %1
// CHECK: retain_value %1
// CHECK: bb6
// CHECK: convert_escape_to_noescape %
// CHECK: strong_release
// CHECK: bb10
// CHECK: [[F:%.*]] = function_ref @noescapeBlock3
// CHECK: apply [[F]]
// CHECK: release_value {{.*}} : $Optional<NSString>
// CHECK: release_value %1 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
// CHECK: release_value {{.*}} : $Optional<@convention(block) @noescape (Optional<NSString>) -> ()>
// CHECK: release_value %0 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
// CHECK: release_value {{.*}} : $Optional<@convention(block) @noescape (Optional<NSString>)
public func bridgeNoescapeBlock( optFn: ((String?) -> ())?, optFn2: ((String?) -> ())?) {
noescapeBlock3(optFn, optFn2, "Foobar")
}
@_silgen_name("_returnOptionalEscape")
public func returnOptionalEscape() -> (() ->())?
// Make sure that we keep the escaping closure alive across the ultimate call.
// CHECK-LABEL: sil @$s1A19bridgeNoescapeBlockyyF : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK: [[NONE:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// CHECK: [[V0:%.*]] = function_ref @_returnOptionalEscape
// CHECK: [[V1:%.*]] = apply [[V0]]
// CHECK: retain_value [[V1]]
// CHECK: switch_enum [[V1]] : $Optional<{{.*}}>, case #Optional.some!enumelt: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]([[V2:%.*]] : $@callee_guaranteed () -> ()):
// CHECK: [[V1_UNWRAPPED:%.*]] = unchecked_enum_data [[V1]]
// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[V1_UNWRAPPED]]
// CHECK: [[SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt, [[CVT]]
// CHECK: strong_release [[V2]]
// CHECK: br [[NEXT_BB:bb[0-9]+]]([[SOME]] :
//
// CHECK: [[NEXT_BB]]([[SOME_PHI:%.*]] :
// CHECK: switch_enum [[SOME_PHI]] : $Optional<{{.*}}>, case #Optional.some!enumelt: [[SOME_BB_2:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB_2:bb[0-9]+]]
//
// CHECK: [[SOME_BB_2]]([[SOME_PHI_PAYLOAD:%.*]] :
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[SOME_PHI_PAYLOAD]])
// CHECK: [[MDI:%.*]] = mark_dependence [[PAI]]
// CHECK: strong_retain [[MDI]]
// CHECK: [[BLOCK_SLOT:%.*]] = alloc_stack
// CHECK: [[BLOCK_PROJ:%.*]] = project_block_storage [[BLOCK_SLOT]]
// CHECK: store [[MDI]] to [[BLOCK_PROJ]]
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_SLOT]]
// CHECK: [[SOME_2:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt, [[MDI]]
// CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
// CHECK: [[BLOCK_SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt, [[BLOCK_COPY]]
// CHECK: br bb5([[BLOCK_SOME]] : ${{.*}}, [[SOME_2]] :
//
// CHECK: bb4:
// CHECK: [[NONE_BLOCK:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// CHECK: br bb5([[NONE_BLOCK]] : {{.*}}, [[NONE]] :
//
// CHECK: bb5([[BLOCK_PHI:%.*]] : $Optional<{{.*}}>, [[SWIFT_CLOSURE_PHI:%.*]] :
// CHECK: [[F:%.*]] = function_ref @noescapeBlock
// CHECK: apply [[F]]([[BLOCK_PHI]])
// CHECK: release_value [[BLOCK_PHI]]
// CHECK: release_value [[SWIFT_CLOSURE_PHI]]
// CHECK-NEXT: return
// NOPEEPHOLE-LABEL: sil @$s1A19bridgeNoescapeBlockyyF : $@convention(thin) () -> () {
// NOPEEPHOLE: bb0:
// NOPEEPHOLE: [[NONE_1:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// NOPEEPHOLE: [[NONE_2:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// NOPEEPHOLE: [[V0:%.*]] = function_ref @_returnOptionalEscape
// NOPEEPHOLE: [[V1:%.*]] = apply [[V0]]
// NOPEEPHOLE: switch_enum [[V1]] : $Optional<{{.*}}>, case #Optional.some!enumelt: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
//
// NOPEEPHOLE: [[SOME_BB]]([[V2:%.*]]: $@callee_guaranteed () -> ()):
// NOPEEPHOLE-NEXT: strong_retain [[V2]]
// NOPEEPHOLE-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[V2]]
// NOPEEPHOLE-NEXT: [[SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt, [[V2]]
// NOPEEPHOLE-NEXT: [[MDI:%.*]] = mark_dependence [[CVT]] : $@noescape @callee_guaranteed () -> () on [[SOME]] : $Optional<@callee_guaranteed () -> ()>
// NOPEEPHOLE-NEXT: [[NOESCAPE_SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt, [[MDI]]
// NOPEEPHOLE-NEXT: strong_release [[V2]]
// NOPEEPHOLE-NEXT: br bb2([[NOESCAPE_SOME]] : $Optional<{{.*}}>, [[SOME]] : $Optional<{{.*}}>, [[SOME]] : $Optional<{{.*}}>)
//
// NOPEEPHOLE: bb2([[NOESCAPE_SOME:%.*]] : $Optional<{{.*}}>, [[SOME1:%.*]] : $Optional<{{.*}}>, [[SOME:%.*]] : $Optional<{{.*}}>):
// NOPEEPHOLE: switch_enum [[NOESCAPE_SOME]] : $Optional<{{.*}}>, case #Optional.some!enumelt: [[SOME_BB_2:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB_2:bb[0-9]+]]
//
// NOPEEPHOLE: [[SOME_BB_2]](
// NOPEEPHOLE: br bb5
//
// NOPEEPHOLE: [[NONE_BB_2]]:
// NOPEEPHOLE: br bb5
//
// NOPEEPHOLE: bb5([[BLOCK_PHI:%.*]] : $Optional<{{.*}}>, [[SWIFT_CLOSURE_PHI:%.*]] :
// NOPEEPHOLE-NEXT: function_ref noescapeBlock
// NOPEEPHOLE-NEXT: [[F:%.*]] = function_ref @noescapeBlock :
// NOPEEPHOLE-NEXT: apply [[F]]([[BLOCK_PHI]])
// NOPEEPHOLE-NEXT: release_value [[BLOCK_PHI]]
// NOPEEPHOLE-NEXT: tuple
// NOPEEPHOLE-NEXT: release_value [[SOME]]
// NOPEEPHOLE-NEXT: release_value [[SWIFT_CLOSURE_PHI]]
// NOPEEPHOLE-NEXT: return
// NOPEEPHOLE: } // end sil function '$s1A19bridgeNoescapeBlockyyF'
public func bridgeNoescapeBlock() {
noescapeBlock(returnOptionalEscape())
}