Skip to content

Commit e3440f6

Browse files
committed
[6.1] SIL: builtin willThrow does not modify memory or release
This enables access enforcement analysis to classify a dynamic begin_access in access patterns (such as the one below) involving a throwing function as not having nested conflicts. ``` struct Stack { var items : [UInt8] mutating func pop() throws -> UInt8 { guard let item = items.popLast() else { throw SomeErr.err } return item } ... } class Container { private var ref : Stack @inline(never) internal func someMethod() throws { try ref.pop() } ... } ``` Scope: Performance improvement Risk: Medium, we are changing the side-effects of willThrow which should not matter all that match. There is a second order effect: other wrongly computed/assigned could now become visible. Original PR: #78091 Reviewed by: Erik Eckstein rdar://141182074 (cherry picked from commit fa01d8d)
1 parent 714ecbd commit e3440f6

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

lib/SIL/IR/SILInstruction.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,8 @@ MemoryBehavior SILInstruction::getMemoryBehavior() const {
997997
return BI->getArguments().size() > 0
998998
? MemoryBehavior::MayWrite
999999
: MemoryBehavior::None;
1000+
} else if (BInfo.ID == BuiltinValueKind::WillThrow) {
1001+
return MemoryBehavior::MayRead;
10001002
}
10011003
if (BInfo.ID != BuiltinValueKind::None)
10021004
return BInfo.isReadNone() ? MemoryBehavior::None
@@ -1188,6 +1190,7 @@ bool SILInstruction::mayRelease() const {
11881190
if (auto Kind = BI->getBuiltinKind()) {
11891191
switch (Kind.value()) {
11901192
case BuiltinValueKind::CopyArray:
1193+
case BuiltinValueKind::WillThrow:
11911194
return false;
11921195
default:
11931196
break;
@@ -1497,6 +1500,14 @@ bool SILInstruction::isTriviallyDuplicatable() const {
14971500
}
14981501

14991502
bool SILInstruction::mayTrap() const {
1503+
if (auto *BI = dyn_cast<BuiltinInst>(this)) {
1504+
if (auto Kind = BI->getBuiltinKind()) {
1505+
if (Kind.value() == BuiltinValueKind::WillThrow) {
1506+
// We don't want willThrow instructions to be removed.
1507+
return true;
1508+
}
1509+
}
1510+
}
15001511
switch(getKind()) {
15011512
case SILInstructionKind::CondFailInst:
15021513
case SILInstructionKind::UnconditionalCheckedCastInst:

test/SILOptimizer/access_enforcement_opts.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,3 +1697,17 @@ bb0(%0 : ${ var Int64 }):
16971697
end_access %access : $*Int64
16981698
return %val : $Int64
16991699
}
1700+
1701+
// CHECK-LABEL: sil @willThrow : $@convention(thin) (RefElemNoConflictClass, @guaranteed any Error) -> () {
1702+
// CHECK: begin_access [modify] [dynamic] [no_nested_conflict]
1703+
// CHECK-LABEL: } // end sil function 'willThrow'
1704+
1705+
sil @willThrow : $@convention(thin) (RefElemNoConflictClass, @guaranteed any Error) -> () {
1706+
bb0(%0 : $RefElemNoConflictClass, %1 : $any Error):
1707+
%x = ref_element_addr %0 : $RefElemNoConflictClass, #RefElemNoConflictClass.x
1708+
%b3 = begin_access [modify] [dynamic] %x : $*Int32
1709+
%w = builtin "willThrow"(%1 : $any Error) : $()
1710+
end_access %b3 : $*Int32
1711+
%10 = tuple ()
1712+
return %10 : $()
1713+
}

test/SILOptimizer/side_effects.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ struct Ptr {
5757
var p: Int32
5858
}
5959

60+
enum SomeErr : Error {
61+
case err
62+
}
6063

6164
sil_global public @global_var : $Int32
6265

@@ -1243,3 +1246,14 @@ sil @test_consuming_in_with_unreachable : $@convention(thin) (@in X) -> () {
12431246
bb0(%0 : $*X):
12441247
unreachable
12451248
}
1249+
1250+
// CHECK-LABEL: sil @test_willThrow_builtin
1251+
// CHECK: [%0: read v**.c*.v**, copy v**.c*.v**]
1252+
// CHECK: [global: read,copy,deinit_barrier]
1253+
1254+
sil @test_willThrow_builtin : $@convention(thin) (@guaranteed any Error) -> () {
1255+
bb0(%0: $any Error):
1256+
%1 = builtin "willThrow"(%0 : $any Error) : $()
1257+
%r = tuple ()
1258+
return %r : $()
1259+
}

0 commit comments

Comments
 (0)