Skip to content

Commit 9fda3f5

Browse files
committed
Verify OSSA address phis.
Verify that address phis are prohibited in all OSSA passes. Eventually they should be prohibited in all passes. This at least allows preserving access markers in OSSA passes.
1 parent 8af488e commit 9fda3f5

File tree

3 files changed

+43
-51
lines changed

3 files changed

+43
-51
lines changed

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -909,25 +909,22 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
909909
return InstNumbers[a] < InstNumbers[b];
910910
}
911911

912-
// FIXME: For sanity, address-type block args should be prohibited at all SIL
912+
// FIXME: For sanity, address-type phis should be prohibited at all SIL
913913
// stages. However, the optimizer currently breaks the invariant in three
914914
// places:
915915
// 1. Normal Simplify CFG during conditional branch simplification
916916
// (sneaky jump threading).
917917
// 2. Simplify CFG via Jump Threading.
918918
// 3. Loop Rotation.
919919
//
920+
// BasicBlockCloner::canCloneInstruction and sinkAddressProjections is
921+
// designed to avoid this issue, we just need to make sure all passes use it
922+
// correctly.
920923
//
921-
bool prohibitAddressBlockArgs() {
922-
// If this function was deserialized from canonical SIL, this invariant may
923-
// already have been violated regardless of this module's SIL stage or
924-
// exclusivity enforcement level. Presumably, access markers were already
925-
// removed prior to serialization.
926-
if (F.wasDeserializedCanonical())
927-
return false;
928-
929-
SILModule &M = F.getModule();
930-
return M.getStage() == SILStage::Raw;
924+
// Minimally, we must prevent address-type phis as long as access markers are
925+
// preserved. A goal is to preserve access markers in OSSA.
926+
bool prohibitAddressPhis() {
927+
return F.hasOwnership();
931928
}
932929

933930
void visitSILPhiArgument(SILPhiArgument *arg) {
@@ -943,9 +940,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
943940
}
944941
} else {
945942
}
946-
if (arg->isPhiArgument() && prohibitAddressBlockArgs()) {
947-
// As a property of well-formed SIL, we disallow address-type block
948-
// arguments. Supporting them would prevent reliably reasoning about the
943+
if (arg->isPhiArgument() && prohibitAddressPhis()) {
944+
// As a property of well-formed SIL, we disallow address-type
945+
// phis. Supporting them would prevent reliably reasoning about the
949946
// underlying storage of memory access. This reasoning is important for
950947
// diagnosing violations of memory access rules and supporting future
951948
// optimizations such as bitfield packing. Address-type block arguments
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: not --crash %target-sil-opt -enable-sil-verify-all %s 2> %t/err.txt
3+
// RUN: %FileCheck %s < %t/err.txt
4+
5+
class Klass {}
6+
7+
struct MyStruct {
8+
@_hasStorage var k: Klass
9+
}
10+
11+
// The SIL verifier must crash on address phis.
12+
//
13+
// CHECK: SIL verification failed: Block arguments cannot be addresses: !arg->getType().isAddress()
14+
sil [ossa] @handle_phi_address_nodes : $@convention(thin) (@owned Klass) -> () {
15+
bb0(%0 : @owned $Klass):
16+
%1 = alloc_stack $MyStruct
17+
%2 = struct_element_addr %1 : $*MyStruct, #MyStruct.k
18+
store %0 to [init] %2 : $*Klass
19+
cond_br undef, bb1, bb2
20+
21+
bb1:
22+
br bb3(%1 : $*MyStruct)
23+
24+
bb2:
25+
br bb3(%1 : $*MyStruct)
26+
27+
bb3(%7 : $*MyStruct):
28+
destroy_addr %7 : $*MyStruct
29+
dealloc_stack %1 : $*MyStruct
30+
%9999 = tuple()
31+
return %9999 : $()
32+
}

test/SILOptimizer/semantic-arc-opts-canonical.sil

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -394,43 +394,6 @@ bb0(%0 : @guaranteed $(Klass, MyInt)):
394394
return %4 : $Builtin.Int32
395395
}
396396

397-
// Make sure that we do not optimize this case.
398-
//
399-
// CHECK-LABEL: sil [ossa] @handle_phi_address_nodes : $@convention(thin) (@guaranteed Klass) -> () {
400-
// CHECK: load [copy]
401-
// CHECK: } // end sil function 'handle_phi_address_nodes'
402-
sil [ossa] @handle_phi_address_nodes : $@convention(thin) (@guaranteed Klass) -> () {
403-
bb0(%0 : @guaranteed $Klass):
404-
%1 = enum $FakeOptional<Klass>, #FakeOptional.some!enumelt, %0 : $Klass
405-
%2 = copy_value %1 : $FakeOptional<Klass>
406-
%3 = copy_value %1 : $FakeOptional<Klass>
407-
408-
%4 = alloc_stack $FakeOptional<Klass>
409-
store %2 to [init] %4 : $*FakeOptional<Klass>
410-
%5 = alloc_stack $FakeOptional<Klass>
411-
store %3 to [init] %5 : $*FakeOptional<Klass>
412-
413-
cond_br undef, bb1, bb2
414-
415-
bb1:
416-
br bb3(%4 : $*FakeOptional<Klass>)
417-
418-
bb2:
419-
br bb3(%5 : $*FakeOptional<Klass>)
420-
421-
bb3(%6 : $*FakeOptional<Klass>):
422-
%7 = load [copy] %6 : $*FakeOptional<Klass>
423-
%8 = function_ref @fakeoptional_guaranteed_user : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
424-
apply %8(%7) : $@convention(thin) (@guaranteed FakeOptional<Klass>) -> ()
425-
destroy_value %7 : $FakeOptional<Klass>
426-
destroy_addr %5 : $*FakeOptional<Klass>
427-
dealloc_stack %5 : $*FakeOptional<Klass>
428-
destroy_addr %4 : $*FakeOptional<Klass>
429-
dealloc_stack %4 : $*FakeOptional<Klass>
430-
%9999 = tuple()
431-
return %9999 : $()
432-
}
433-
434397
// CHECK-LABEL: sil [ossa] @switch_enum_test_loadcopy_no_default : $@convention(thin) (@owned FakeOptional<Builtin.NativeObject>) -> () {
435398
// CHECK-NOT: load [copy]
436399
// CHECK: load_borrow

0 commit comments

Comments
 (0)