Skip to content

Commit dbc5063

Browse files
committed
DeadCodeElimination: don't remove empty access scopes
Empty access scopes can be a result of e.g. redundant-load-elimination. It's still important to keep those access scopes to detect access violations. Even if the load is physically not done anymore, in case of a conflicting access a propagated load is still wrong and must be detected. rdar://164571252
1 parent 0ff2cae commit dbc5063

File tree

4 files changed

+74
-15
lines changed

4 files changed

+74
-15
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static bool seemsUseful(SILInstruction *I) {
5454
// Even though begin_access/destroy_value/copy_value/end_lifetime have
5555
// side-effects, they can be DCE'ed if they do not have useful
5656
// dependencies/reverse dependencies
57-
if (isa<BeginAccessInst>(I) || isa<CopyValueInst>(I) ||
57+
if (isa<CopyValueInst>(I) ||
5858
isa<DestroyValueInst>(I) || isa<EndLifetimeInst>(I) ||
5959
isa<EndBorrowInst>(I))
6060
return false;
@@ -361,12 +361,6 @@ void DCE::markLive() {
361361
}
362362
break;
363363
}
364-
case SILInstructionKind::EndAccessInst: {
365-
// An end_access is live only if it's begin_access is also live.
366-
auto *beginAccess = cast<EndAccessInst>(&I)->getBeginAccess();
367-
addReverseDependency(beginAccess, &I);
368-
break;
369-
}
370364
case SILInstructionKind::DestroyValueInst: {
371365
auto phi = PhiValue(I.getOperand(0));
372366
// Disable DCE of phis which are lexical or may have a pointer escape.

test/SILOptimizer/dead_code_elimination.sil

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,10 @@ bb3:
253253
br bb1
254254
}
255255

256-
// Check that DCE eliminates dead access instructions.
256+
// Dead accesses must not be removed
257257
// CHECK-LABEL: sil @dead_access
258-
// CHECK: bb0
259-
// CHECK-NEXT: tuple
260-
// CHECK-NEXT: return
258+
// CHECK: begin_access
259+
// CHECK: begin_access
261260
// CHECK-LABEL: end sil function 'dead_access'
262261
sil @dead_access : $@convention(thin) (@in Container) -> () {
263262
bb0(%0 : $*Container):

test/SILOptimizer/dead_code_elimination_ossa.sil

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,10 @@ bb3:
290290
br bb1
291291
}
292292

293-
// Check that DCE eliminates dead access instructions.
293+
// Dead accesses must not be removed
294294
// CHECK-LABEL: sil [ossa] @dead_access :
295-
// CHECK: bb0
296-
// CHECK-NEXT: tuple
297-
// CHECK-NEXT: return
295+
// CHECK: begin_access
296+
// CHECK: begin_access
298297
// CHECK-LABEL: } // end sil function 'dead_access'
299298
sil [ossa] @dead_access : $@convention(thin) (@in Container) -> () {
300299
bb0(%0 : $*Container):
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: %target-run-simple-swift(-Onone)
2+
// RUN: %target-run-simple-swift(-O)
3+
4+
// REQUIRES: executable_test
5+
6+
import StdlibUnittest
7+
8+
9+
var tests = TestSuite("exclusivity checking")
10+
11+
struct NC: ~Copyable {
12+
var i: Int = 1
13+
14+
mutating func add(_ other: borrowing Self) {
15+
i += other.i
16+
i += other.i
17+
print(self.i, other.i)
18+
}
19+
}
20+
21+
class C1 {
22+
var nc = NC()
23+
24+
func foo() {
25+
nc.add(nc)
26+
}
27+
}
28+
29+
struct S {
30+
var i: Int = 1
31+
32+
mutating func add(_ c: C2) {
33+
let other = c.getS()
34+
i += other.i
35+
i += other.i
36+
print(self.i, other.i)
37+
}
38+
}
39+
40+
final class C2 {
41+
var s = S()
42+
43+
@inline(never)
44+
func getS() -> S { s }
45+
46+
func foo() {
47+
s.add(self)
48+
}
49+
}
50+
51+
tests.test("non-copyable type")
52+
.crashOutputMatches("Simultaneous accesses")
53+
.code {
54+
expectCrashLater()
55+
56+
C1().foo()
57+
}
58+
59+
tests.test("copyable type")
60+
.crashOutputMatches("Simultaneous accesses")
61+
.code {
62+
expectCrashLater()
63+
64+
C2().foo()
65+
}
66+
67+
runAllTests()

0 commit comments

Comments
 (0)