Skip to content

Commit cd0d4dc

Browse files
Merge pull request #67217 from nate-chandler/opaque-values/1/20230711
[AddressLowering] Handle move_value.
2 parents b5e3ab5 + d4c83bc commit cd0d4dc

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,9 @@ static Operand *getProjectedDefOperand(SILValue value) {
872872

873873
return nullptr;
874874

875+
case ValueKind::MoveValueInst:
876+
return &cast<MoveValueInst>(value)->getOperandRef();
877+
875878
case ValueKind::MultipleValueInstructionResult: {
876879
SILInstruction *destructure =
877880
cast<MultipleValueInstructionResult>(value)->getParent();
@@ -3050,6 +3053,9 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
30503053
}
30513054
}
30523055

3056+
template <typename Introducer>
3057+
void visitLifetimeIntroducer(Introducer *introducer);
3058+
30533059
void visitBeginBorrowInst(BeginBorrowInst *borrow);
30543060

30553061
void visitEndBorrowInst(EndBorrowInst *end) {}
@@ -3125,6 +3131,8 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
31253131
// types.
31263132
void visitOpenExistentialValueInst(OpenExistentialValueInst *openExistential);
31273133

3134+
void visitMoveValueInst(MoveValueInst *mvi);
3135+
31283136
void visitReturnInst(ReturnInst *returnInst) {
31293137
// Returns are rewritten for any function with indirect results after
31303138
// opaque value rewriting.
@@ -3263,15 +3271,16 @@ void UseRewriter::rewriteDestructure(SILInstruction *destructure) {
32633271
}
32643272
}
32653273

3266-
void UseRewriter::visitBeginBorrowInst(BeginBorrowInst *borrow) {
3267-
assert(use == getProjectedDefOperand(borrow));
3274+
template <typename Introducer>
3275+
void UseRewriter::visitLifetimeIntroducer(Introducer *introducer) {
3276+
assert(use == getProjectedDefOperand(introducer));
32683277

32693278
// Mark the value as rewritten and use the operand's storage.
32703279
auto address = pass.valueStorageMap.getStorage(use->get()).storageAddress;
3271-
markRewritten(borrow, address);
3280+
markRewritten(introducer, address);
32723281

3273-
// Borrows are irrelevant unless they are marked lexical.
3274-
if (borrow->isLexical()) {
3282+
// Lifetime introducers are irrelevant unless they are marked lexical.
3283+
if (introducer->isLexical()) {
32753284
if (auto base = getAccessBase(address)) {
32763285
if (auto *allocStack = dyn_cast<AllocStackInst>(base)) {
32773286
allocStack->setIsLexical();
@@ -3287,6 +3296,14 @@ void UseRewriter::visitBeginBorrowInst(BeginBorrowInst *borrow) {
32873296
}
32883297
}
32893298

3299+
void UseRewriter::visitBeginBorrowInst(BeginBorrowInst *borrow) {
3300+
visitLifetimeIntroducer(borrow);
3301+
}
3302+
3303+
void UseRewriter::visitMoveValueInst(MoveValueInst *mvi) {
3304+
visitLifetimeIntroducer(mvi);
3305+
}
3306+
32903307
// Opening an opaque existential. Rewrite the opened existentials here on
32913308
// the use-side because it may produce either loadable or address-only
32923309
// types.

test/SILOptimizer/address_lowering.sil

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,60 @@ entry(%addr : $*T):
19241924
return %retval : $()
19251925
}
19261926

1927+
// The move_value is lexical so the corresponding alloc_stack must be marked
1928+
// lexical too.
1929+
// CHECK-LABEL: sil [ossa] @testMoveValueLexical : {{.*}} {
1930+
// CHECK: alloc_stack [lexical]
1931+
// CHECK-LABEL: } // end sil function 'testMoveValueLexical'
1932+
sil [ossa] @testMoveValueLexical : $@convention(thin) <T> () -> () {
1933+
%getT = function_ref @getT : $@convention(thin) <T> () -> @out T
1934+
%instance = apply %getT<T>() : $@convention(thin) <T> () -> @out T
1935+
%moved = move_value [lexical] %instance : $T
1936+
destroy_value %moved : $T
1937+
%retval = tuple ()
1938+
return %retval : $()
1939+
}
1940+
1941+
// Verify that the temporary storage is lexical and moved out of
1942+
// (copy_addr [take]).
1943+
// CHECK-LABEL: sil [ossa] @testMoveValueLexicalAndReturn : {{.*}} {
1944+
// CHECK: {{bb[0-9]+}}([[RETVAL:%[^,]+]] :
1945+
// CHECK: [[STACK:%[^,]+]] = alloc_stack [lexical]
1946+
// CHECK: copy_addr [take] [[STACK]] to [init] [[RETVAL]]
1947+
// CHECK-LABEL: } // end sil function 'testMoveValueLexicalAndReturn'
1948+
sil [ossa] @testMoveValueLexicalAndReturn : $@convention(thin) <T> () -> @out T {
1949+
%getT = function_ref @getT : $@convention(thin) <T> () -> @out T
1950+
%instance = apply %getT<T>() : $@convention(thin) <T> () -> @out T
1951+
%moved = move_value [lexical] %instance : $T
1952+
return %moved : $T
1953+
}
1954+
1955+
// Verify that a move_value gets no stack storage if it's from an argument.
1956+
// CHECK-LABEL: sil [ossa] @testMoveValueLexicalArgument : {{.*}} {
1957+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
1958+
// CHECK: destroy_addr [[INSTANCE]]
1959+
// CHECK-LABEL: } // end sil function 'testMoveValueLexicalArgument'
1960+
sil [ossa] @testMoveValueLexicalArgument : $@convention(thin) <T> (@in T) -> () {
1961+
entry(%instance : @owned $T):
1962+
%moved = move_value [lexical] %instance : $T
1963+
destroy_value %moved : $T
1964+
%retval = tuple ()
1965+
return %retval : $()
1966+
}
1967+
1968+
// Only lexical move_values should mark the alloc_stack lexical.
1969+
// CHECK-LABEL: sil [ossa] @testMoveValueNonlexical : {{.*}} {
1970+
// CHECK-NOT: alloc_stack [lexical]
1971+
// CHECK-LABEL: } // end sil function 'testMoveValueNonlexical'
1972+
sil [ossa] @testMoveValueNonlexical : $@convention(thin) <T> () -> () {
1973+
%getT = function_ref @getT : $@convention(thin) <T> () -> @out T
1974+
%instance = apply %getT<T>() : $@convention(thin) <T> () -> @out T
1975+
%moved = move_value %instance : $T
1976+
destroy_value %moved : $T
1977+
%retval = tuple ()
1978+
return %retval : $()
1979+
}
1980+
19271981
// CHECK-LABEL: sil hidden [ossa] @testOpaqueYield :
19281982
// CHECK: bb0(%0 : @guaranteed $TestGeneric<T>):
19291983
// CHECK: [[REF:%.*]] = ref_element_addr %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric

0 commit comments

Comments
 (0)