Skip to content

Commit f6791a2

Browse files
authored
Merge pull request #76153 from eeckstein/fix-compute-side-effects
ComputeSideEffects: fix a corner case with consuming indirect arguments in dead-end functions
2 parents ec8f091 + e683d7b commit f6791a2

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ComputeSideEffects.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ let computeSideEffects = FunctionPass(name: "compute-side-effects") {
5757
// instruction the argument might have escaped.
5858
for argument in function.arguments {
5959
collectedEffects.addEffectsForEscapingArgument(argument: argument)
60+
collectedEffects.addEffectsForConsumingArgument(argument: argument)
6061
}
6162

6263
// Don't modify the effects if they didn't change. This avoids sending a change notification
@@ -236,7 +237,17 @@ private struct CollectedEffects {
236237
addEffects(.destroy, to: argument)
237238
}
238239
}
239-
240+
241+
mutating func addEffectsForConsumingArgument(argument: FunctionArgument) {
242+
if argument.convention == .indirectIn {
243+
// Usually there _must_ be a read from a consuming in-argument, because the function has to consume the argument.
244+
// But in the special case if all control paths end up in an `unreachable`, the consuming read might have been
245+
// dead-code eliminated. Therefore make sure to add the read-effect in any case. Otherwise it can result
246+
// in memory lifetime failures at a call site.
247+
addEffects(.read, to: argument)
248+
}
249+
}
250+
240251
private mutating func handleApply(_ apply: ApplySite) {
241252
let callees = calleeAnalysis.getCallees(callee: apply.callee)
242253
let args = apply.argumentOperands.lazy.map {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=function-signature-opts -emit-sil -primary-file %s | %FileCheck %s
2+
3+
public struct S {
4+
@inline(never)
5+
init<T>(_ t: T) {
6+
fatalError()
7+
}
8+
}
9+
10+
// check that this doesn't cause a memory lifetime failure
11+
12+
// CHECK-LABEL: sil @$s22generic_specialization6testityAA1SVSSF :
13+
// CHECK: [[F:%.*]] = function_ref @$s22generic_specialization1SVyACxclufCSS_Tt0g5 :
14+
// CHECK: = apply [[F]](%0) : $@convention(thin) (@owned String) -> S
15+
// CHECK: } // end sil function '$s22generic_specialization6testityAA1SVSSF'
16+
public func testit(_ s: String) -> S {
17+
return S(s)
18+
}
19+

test/SILOptimizer/side_effects.sil

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,3 +1234,12 @@ bb0(%0 : $SP):
12341234
%r = tuple ()
12351235
return %r : $()
12361236
}
1237+
1238+
// CHECK-LABEL: sil @test_consuming_in_with_unreachable
1239+
// CHECK-NEXT: [%0: read v**]
1240+
// CHECK-NEXT: [global: ]
1241+
// CHECK-NEXT: {{^[^[]}}
1242+
sil @test_consuming_in_with_unreachable : $@convention(thin) (@in X) -> () {
1243+
bb0(%0 : $*X):
1244+
unreachable
1245+
}

0 commit comments

Comments
 (0)