Skip to content

Commit 8e7dae5

Browse files
committed
[OSSACanOwned] Bail on escaping inner pointers.
If there is a pointer escape, we cannot safely rewrite its lifetime.
1 parent f1bc3b5 commit 8e7dae5

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,13 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
239239
break;
240240
case OperandOwnership::InteriorPointer:
241241
case OperandOwnership::AnyInteriorPointer:
242+
if (liveness->checkAndUpdateInteriorPointer(use) !=
243+
AddressUseKind::NonEscaping) {
244+
LLVM_DEBUG(llvm::dbgs()
245+
<< " Inner address use is escaping! Giving up\n");
246+
return false;
247+
}
248+
break;
242249
case OperandOwnership::GuaranteedForwarding:
243250
case OperandOwnership::EndBorrow:
244251
// Guaranteed values are exposed by inner adjacent reborrows. If user is

test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
// RUN: %target-sil-opt -sil-print-types -test-runner %s -o /dev/null 2>&1 | %FileCheck %s
22

3+
import Builtin
34
import Swift
45

56
class C {}
67

78
enum Never {}
9+
10+
struct Pointer {
11+
var rawValue: Builtin.RawPointer
12+
}
13+
14+
struct Int32 {
15+
var int: Builtin.Int32
16+
}
817
sil @run : $@convention(thin) () -> Never
918
sil @getOwned : $@convention(thin) () -> @owned C
1019
sil @barrier : $@convention(thin) () -> ()
1120
sil [ossa] @getC : $@convention(thin) () -> @owned C
1221
sil [ossa] @borrowC : $@convention(thin) (@guaranteed C) -> ()
1322
sil [ossa] @takeC : $@convention(thin) (@owned C) -> ()
23+
sil @getPointer : $@convention(thin) () -> (@owned Pointer)
24+
1425
struct S {}
1526

1627
struct MoS: ~Copyable {}
@@ -963,3 +974,28 @@ entry(%c : @owned $C):
963974
%run = function_ref @run : $@convention(thin) () -> Never
964975
unreachable
965976
}
977+
978+
/// If there's a pointer escape (here, mark_dependence) of the value, we can't
979+
/// canonicalize its lifetime.
980+
// CHECK-LABEL: begin running test {{.*}} on dont_canonicalize_on_pointer_escape
981+
// CHECK-LABEL: sil [ossa] @dont_canonicalize_on_pointer_escape : {{.*}} {
982+
// CHECK: load
983+
// CHECK-NEXT: destroy_value
984+
// CHECK-LABEL: } // end sil function 'dont_canonicalize_on_pointer_escape'
985+
// CHECK-LABEL: end running test {{.*}} on dont_canonicalize_on_pointer_escape
986+
sil [ossa] @dont_canonicalize_on_pointer_escape : $@convention(thin) () -> () {
987+
entry:
988+
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
989+
%getPointer = function_ref @getPointer : $@convention(thin) () -> (@owned Pointer)
990+
%c = apply %getC() : $@convention(thin) () -> (@owned C)
991+
%pointer = apply %getPointer() : $@convention(thin) () -> (@owned Pointer)
992+
specify_test "canonicalize_ossa_lifetime true false true %c"
993+
%rawPointer = struct_extract %pointer, #Pointer.rawValue
994+
%o = pointer_to_address %rawPointer to [strict] $*Int32
995+
%dependent = mark_dependence [nonescaping] %o on %c
996+
%int_addr = struct_element_addr %dependent, #Int32.int
997+
%int = load [trivial] %int_addr
998+
destroy_value %c
999+
%retval = tuple ()
1000+
return %retval : $()
1001+
}

0 commit comments

Comments
 (0)