Skip to content

Commit 0ee53f9

Browse files
authored
Merge pull request #32992 from atrick/prohibit-phi-args
Verify OSSA address phis.
2 parents da427ff + 9fda3f5 commit 0ee53f9

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)