Skip to content

Commit 64ce7b9

Browse files
authored
Merge pull request #24835 from eeckstein/fix-silcombine
2 parents a579af3 + 71b8c56 commit 64ce7b9

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,16 @@ SILCombiner::visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
9191
if (SingleStore && SingleRelease) {
9292
assert(SingleProjection && "store without a projection");
9393
// Release the value that was stored into the existential box. The box
94-
// is going away so we need to release the stored value now.
95-
Builder.setInsertionPoint(SingleStore);
94+
// is going away so we need to release the stored value.
95+
// NOTE: It's important that the release is inserted at the single
96+
// release of the box and not at the store, because a balancing retain could
97+
// be _after_ the store, e.g:
98+
// %box = alloc_existential_box
99+
// %addr = project_existential_box %box
100+
// store %value to %addr
101+
// retain_value %value // must insert the release after this retain
102+
// strong_release %box
103+
Builder.setInsertionPoint(SingleRelease);
96104
Builder.createReleaseValue(AEBI->getLoc(), SingleStore->getSrc(),
97105
SingleRelease->getAtomicity());
98106

test/SILOptimizer/sil_combine.sil

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,6 +2806,32 @@ bb3(%19 : $Double): // Preds: bb1 bb2
28062806
return %19 : $Double // id: %20
28072807
}
28082808

2809+
enum ErrorEnum: Error {
2810+
case errorCase(label: [Error])
2811+
case other
2812+
}
2813+
2814+
// CHECK-LABEL: sil @insert_compensating_release_at_release_of_box
2815+
// CHECK: [[L:%[0-9]+]] = load
2816+
// CHECK-NEXT: [[T:%[0-9]+]] = tuple
2817+
// CHECK-NEXT: retain_value [[L]]
2818+
// CHECK-NEXT: release_value [[T]]
2819+
// CHECK-NEXT: tuple
2820+
// CHECK-NEXT: return
2821+
sil @insert_compensating_release_at_release_of_box : $@convention(method) (@in_guaranteed Array<Error>) -> () {
2822+
bb0(%0 : $*Array<Error>):
2823+
%20 = load %0 : $*Array<Error>
2824+
%22 = tuple $(label: Array<Error>) (%20)
2825+
%23 = enum $ErrorEnum, #ErrorEnum.errorCase!enumelt.1, %22 : $(label: Array<Error>)
2826+
%36 = alloc_existential_box $Error, $ErrorEnum
2827+
%37 = project_existential_box $ErrorEnum in %36 : $Error
2828+
store %23 to %37 : $*ErrorEnum
2829+
retain_value %20 : $Array<Error>
2830+
strong_release %36 : $Error
2831+
%52 = tuple ()
2832+
return %52 : $()
2833+
}
2834+
28092835
sil [reabstraction_thunk] @_TTRXFo_oSS_dSb_XFo_iSS_iSb_ : $@convention(thin) (@in String, @owned @callee_owned (@owned String) -> Bool) -> @out Bool
28102836
sil [reabstraction_thunk] @_TTRXFo_iSS_iSb_XFo_oSS_dSb_ : $@convention(thin) (@owned String, @owned @callee_owned (@in String) -> @out Bool) -> Bool
28112837

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -O -module-name=a %s -o %t/a.out
3+
// RUN: %target-run %t/a.out | %FileCheck %s
4+
5+
// REQUIRES: executable_test
6+
7+
// This is an end-to-end test for rdar://problem/50759056.
8+
9+
enum ErrorEnum: Error {
10+
case errorCase([Error])
11+
case other
12+
}
13+
14+
final class Myclass {
15+
var e = [Error]()
16+
var b = true
17+
18+
@inline(never)
19+
func foo() {
20+
e.append(ErrorEnum.other)
21+
if b {
22+
bar(ErrorEnum.errorCase(e))
23+
}
24+
}
25+
26+
@inline(never)
27+
func bar(_: Error?) {
28+
b = false
29+
foo()
30+
}
31+
}
32+
33+
let c = Myclass()
34+
c.foo()
35+
36+
// CHECK: [a.ErrorEnum.other, a.ErrorEnum.other]
37+
print(c.e)

0 commit comments

Comments
 (0)