Skip to content

Commit b14c34a

Browse files
Merge pull request #67660 from nate-chandler/opaque-values/20230801/2/rewrite_consuming_uses_last
[AddressLowering] Rewrite lifetime-ends last.
2 parents 5f624d1 + 6aa44d8 commit b14c34a

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

lib/SIL/IR/SILInstruction.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/SIL/SILDebugScope.h"
2727
#include "swift/SIL/SILModule.h"
2828
#include "swift/SIL/SILVisitor.h"
29+
#include "swift/SIL/Test.h"
2930
#include "llvm/ADT/APInt.h"
3031
#include "llvm/ADT/SmallString.h"
3132
#include "llvm/Support/ErrorHandling.h"
@@ -120,6 +121,15 @@ void SILInstruction::moveBefore(SILInstruction *Later) {
120121
SILBasicBlock::moveInstruction(this, Later);
121122
}
122123

124+
namespace swift::test {
125+
FunctionTest MoveBeforeTest("instruction-move-before",
126+
[](auto &function, auto &arguments, auto &test) {
127+
auto *inst = arguments.takeInstruction();
128+
auto *other = arguments.takeInstruction();
129+
inst->moveBefore(other);
130+
});
131+
} // end namespace swift::test
132+
123133
/// Unlink this instruction from its current basic block and insert it into
124134
/// the basic block that Earlier lives in, right after Earlier.
125135
void SILInstruction::moveAfter(SILInstruction *Earlier) {

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4169,19 +4169,19 @@ static void rewriteFunction(AddressLoweringState &pass) {
41694169

41704170
// Collect end_borrows and rewrite them last so that when rewriting other
41714171
// users the lifetime ends of a borrow introducer can be used.
4172-
StackList<EndBorrowInst *> endBorrows(pass.function);
4172+
StackList<Operand *> lifetimeEndingUses(pass.function);
41734173
SmallPtrSet<Operand *, 8> originalUses;
41744174
SmallVector<Operand *, 8> uses(valueDef->getUses());
41754175
for (auto *oper : uses) {
41764176
originalUses.insert(oper);
4177-
if (auto *ebi = dyn_cast<EndBorrowInst>(oper->getUser())) {
4178-
endBorrows.push_back(ebi);
4177+
if (oper->isLifetimeEnding()) {
4178+
lifetimeEndingUses.push_back(oper);
41794179
continue;
41804180
}
41814181
UseRewriter::rewriteUse(oper, pass);
41824182
}
4183-
for (auto *ebi : endBorrows) {
4184-
UseRewriter::rewriteUse(&ebi->getOperandRef(), pass);
4183+
for (auto *oper : lifetimeEndingUses) {
4184+
UseRewriter::rewriteUse(oper, pass);
41854185
}
41864186
// Rewrite every new use that was added.
41874187
uses.clear();
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-sil-opt -test-runner -address-lowering -enable-sil-opaque-values -emit-sorted-sil -sil-verify-none %s > %t/out.sil
3+
// RUN: %target-sil-opt -emit-sorted-sil -sil-verify-all %t/out.sil | %FileCheck %s
4+
5+
import Builtin
6+
import Swift
7+
import SwiftShims
8+
9+
struct Box<T> {
10+
var _value : T
11+
}
12+
13+
// Verify that the isCopyValue assertion in
14+
// AddressMaterialization::materializeDefProjection is not triggered. This is
15+
// possible because the destroy_value is rewritten last. Rewriting it last
16+
// enables the lifetime analysis done in isStoreCopy to remain valid until the
17+
// lifetime-ending uses are rewritten.
18+
// CHECK-LABEL: sil [ossa] @destroy_before_copy_in_use_list : {{.*}} {
19+
// CHECK: bb0([[T:%[^,]+]] : $*T, [[BOX:%[^,]+]] :
20+
// CHECK: [[FIELD_ADDR:%[^,]+]] = struct_element_addr [[BOX]] : {{.*}}, #Box._value
21+
// CHECK: copy_addr [[T]] to [[FIELD_ADDR]]
22+
// CHECK: [[RETVAL:%[^,]+]] = tuple ()
23+
// CHECK: destroy_addr [[T]]
24+
// CHECK: return [[RETVAL]]
25+
// CHECK-LABEL: } // end sil function 'destroy_before_copy_in_use_list'
26+
sil [ossa] @destroy_before_copy_in_use_list : $@convention(thin) <T> (@in T, @inout Box<T>) -> () {
27+
bb0(%t : @owned $T, %box : $*Box<T>):
28+
// The destroy_value appears first in the textual SIL in order to be first in
29+
// the use list. Before running AddressLowering, it's sunk to after the
30+
// end_access.
31+
test_specification "instruction-move-before @instruction @instruction[+5]"
32+
destroy_value %t : $T
33+
%copy = copy_value %t : $T
34+
%field_addr = struct_element_addr %box : $*Box<T>, #Box._value
35+
store %copy to [assign] %field_addr : $*T
36+
%retval = tuple ()
37+
return %retval : $()
38+
}

0 commit comments

Comments
 (0)