Skip to content

Commit 8618a39

Browse files
committed
TempRValueElimination: support consuming indirect apply operands
1 parent a867ff8 commit 8618a39

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/TempRValueElimination.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ private func hoistDestroy(of allocStack: AllocStackInst, after lastUse: Instruct
177177
case let li as LoadInst where li.loadOwnership == .take:
178178
assert(li.address == allocStack, "load must be not take a projected address")
179179
return
180+
case let apply as ApplyInst where apply.consumes(address: allocStack):
181+
if allocStack.uses.contains(where: { $0.instruction == apply && apply.convention(of: $0)!.isGuaranteed }) {
182+
return
183+
}
180184
default:
181185
break
182186
}
@@ -266,6 +270,14 @@ private extension AllocStackInst {
266270
}
267271
}
268272

273+
private extension ApplySite {
274+
func consumes(address: Value) -> Bool {
275+
argumentOperands.contains { argOp in
276+
argOp.value == address && convention(of: argOp)!.isConsumed
277+
}
278+
}
279+
}
280+
269281
/// Tries to move an `end_access` down to extend the access scope over all uses of the `alloc_stack`.
270282
/// For example:
271283
/// ```
@@ -537,7 +549,12 @@ private struct UseCollector : AddressDefUseWalker {
537549
}
538550

539551
private mutating func visitApply(address: Operand, apply: ApplySite) -> WalkResult {
540-
if !apply.convention(of: address)!.isGuaranteed {
552+
let argConvention = apply.convention(of: address)!
553+
guard argConvention.isGuaranteed ||
554+
// Only accept consuming-in arguments if it consumes the whole `alloc_stack`. A consume from
555+
// a projection would destroy only a part of the `alloc_stack` and we don't handle this.
556+
(argConvention == .indirectIn && (copy.isTakeOfSource && address.value == copy.destinationAddress))
557+
else {
541558
return .abortWalk
542559
}
543560
uses.insert(apply)

test/Interop/Cxx/reference/rvalue-reference.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop -Onone) | %FileCheck -check-prefix=CHECK-DASH-ONONE %s
1+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xllvm -sil-disable-pass=mandatory-temp-rvalue-elimination -Xfrontend -enable-experimental-cxx-interop -Onone) | %FileCheck -check-prefix=CHECK-DASH-ONONE %s
22
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop -O) | %FileCheck -check-prefix=CHECK-DASH-O %s
33
//
44
// REQUIRES: executable_test

test/SILOptimizer/temp_rvalue_opt_ossa.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ sil [ossa] @guaranteed_user_with_result : $@convention(thin) (@guaranteed Klass)
6565
sil [ossa] @inguaranteed_user_without_result_NTS : $@convention(thin) (@in_guaranteed NonTrivialStruct) -> ()
6666
sil [ossa] @inguaranteed_user_without_result_MOS : $@convention(thin) (@in_guaranteed MOS) -> ()
6767

68+
sil [ossa] @consuming_indirect_arg : $@convention(thin) (@in Klass) -> ()
69+
6870
sil [ossa] @inguaranteed_user_without_result : $@convention(thin) (@in_guaranteed Klass) -> () {
6971
bb0(%0 : $*Klass):
7072
%9999 = tuple()
@@ -1643,3 +1645,33 @@ bb0(%0 : @owned $Klass):
16431645
return %4
16441646
}
16451647

1648+
// CHECK-LABEL: sil [ossa] @take_and_consuming_arg :
1649+
// CHECK-NOT: alloc_stack
1650+
// CHECK: apply {{%[0-9]+}}(%0)
1651+
// CHECK-LABEL: } // end sil function 'take_and_consuming_arg'
1652+
sil [ossa] @take_and_consuming_arg : $@convention(thin) (@in Klass) -> () {
1653+
bb0(%0 : $*Klass):
1654+
%1 = alloc_stack $Klass
1655+
copy_addr [take] %0 to [init] %1
1656+
%3 = function_ref @consuming_indirect_arg : $@convention(thin) (@in Klass) -> ()
1657+
%4 = apply %3(%1) : $@convention(thin) (@in Klass) -> ()
1658+
dealloc_stack %1 : $*Klass
1659+
%9 = tuple ()
1660+
return %9 : $()
1661+
}
1662+
1663+
// CHECK-LABEL: sil [ossa] @copy_and_consuming_arg :
1664+
// CHECK: alloc_stack
1665+
// CHECK-NEXT: copy_addr
1666+
// CHECK-LABEL: } // end sil function 'copy_and_consuming_arg'
1667+
sil [ossa] @copy_and_consuming_arg : $@convention(thin) (@inout Klass) -> () {
1668+
bb0(%0 : $*Klass):
1669+
%1 = alloc_stack $Klass
1670+
copy_addr %0 to [init] %1
1671+
%3 = function_ref @consuming_indirect_arg : $@convention(thin) (@in Klass) -> ()
1672+
%4 = apply %3(%1) : $@convention(thin) (@in Klass) -> ()
1673+
dealloc_stack %1 : $*Klass
1674+
%9 = tuple ()
1675+
return %9 : $()
1676+
}
1677+

0 commit comments

Comments
 (0)