Skip to content

Commit 70bc9cd

Browse files
authored
Merge pull request #80486 from eeckstein/fix-struct-extract
SIL: fix the ownership computation of `struct_extract` and `tuple_extract`
2 parents eb1c925 + f1fc864 commit 70bc9cd

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,27 @@ CONSTANT_OWNERSHIP_INST(None, TypeValue)
183183

184184
#undef CONSTANT_OWNERSHIP_INST
185185

186+
ValueOwnershipKind ValueOwnershipKindClassifier::visitStructExtractInst(StructExtractInst *sei) {
187+
if (sei->getType().isTrivial(*sei->getFunction()) ||
188+
// A struct value can have "none" ownership even if its type is not trivial.
189+
// This happens when the struct/tuple contains a non-trivial enum, but it's initialized with
190+
// a trivial enum case (e.g. with `Optional.none`).
191+
sei->getOperand()->getOwnershipKind() == OwnershipKind::None) {
192+
return OwnershipKind::None;
193+
}
194+
return OwnershipKind::Guaranteed;
195+
}
196+
197+
ValueOwnershipKind ValueOwnershipKindClassifier::visitTupleExtractInst(TupleExtractInst *tei) {
198+
if (tei->getType().isTrivial(*tei->getFunction()) ||
199+
// A tuple value can have "none" ownership even if its type is not trivial.
200+
// This happens when the struct/tuple contains a non-trivial enum, but it's initialized with
201+
// a trivial enum case (e.g. with `Optional.none`).
202+
tei->getOperand()->getOwnershipKind() == OwnershipKind::None)
203+
return OwnershipKind::None;
204+
return OwnershipKind::Guaranteed;
205+
}
206+
186207
#define CONSTANT_OR_NONE_OWNERSHIP_INST(OWNERSHIP, INST) \
187208
ValueOwnershipKind ValueOwnershipKindClassifier::visit##INST##Inst( \
188209
INST##Inst *I) { \
@@ -192,8 +213,6 @@ CONSTANT_OWNERSHIP_INST(None, TypeValue)
192213
} \
193214
return OwnershipKind::OWNERSHIP; \
194215
}
195-
CONSTANT_OR_NONE_OWNERSHIP_INST(Guaranteed, StructExtract)
196-
CONSTANT_OR_NONE_OWNERSHIP_INST(Guaranteed, TupleExtract)
197216
CONSTANT_OR_NONE_OWNERSHIP_INST(Guaranteed, TuplePackExtract)
198217
CONSTANT_OR_NONE_OWNERSHIP_INST(Guaranteed, DifferentiableFunctionExtract)
199218
CONSTANT_OR_NONE_OWNERSHIP_INST(Guaranteed, LinearFunctionExtract)

test/SILOptimizer/redundant_load_elim_ossa.sil

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ struct ExistentialIntPair {
137137
var x: Int
138138
}
139139

140+
public struct S {
141+
var e: Optional<String>
142+
}
143+
144+
140145
sil_global @total : $Int32
141146

142147
sil @use : $@convention(thin) (Builtin.Int32) -> ()
@@ -1703,3 +1708,38 @@ bb0(%0 : $*ExistentialIntPair, %1 : $*ExistentialIntPair):
17031708
return %4
17041709
}
17051710

1711+
// CHECK-LABEL: sil [ossa] @struct_of_optional_none :
1712+
// CHECK: [[E:%.*]] = enum
1713+
// CHECK: [[S:%.*]] = struct $S ([[E]] : $Optional<String>)
1714+
// CHECK: [[F:%.*]] = struct_extract [[S]] : $S, #S.e
1715+
// CHECK: return [[F]]
1716+
// CHECK-LABEL: } // end sil function 'struct_of_optional_none'
1717+
sil [ossa] @struct_of_optional_none : $@convention(thin) () -> @owned Optional<String> {
1718+
bb0:
1719+
%0 = enum $Optional<String>, #Optional.none!enumelt
1720+
%1 = struct $S (%0)
1721+
%2 = alloc_stack $S
1722+
store %1 to [init] %2
1723+
%4 = struct_element_addr %2, #S.e
1724+
%5 = load [take] %4
1725+
dealloc_stack %2
1726+
return %5
1727+
}
1728+
1729+
// CHECK-LABEL: sil [ossa] @tuple_of_optional_none :
1730+
// CHECK: [[E:%.*]] = enum
1731+
// CHECK: [[T:%.*]] = tuple ([[E]] : $Optional<String>, %0 : $Int)
1732+
// CHECK: [[F:%.*]] = tuple_extract [[T]] : $(Optional<String>, Int), 0
1733+
// CHECK: return [[F]]
1734+
// CHECK-LABEL: } // end sil function 'tuple_of_optional_none'
1735+
sil [ossa] @tuple_of_optional_none : $@convention(thin) (Int) -> @owned Optional<String> {
1736+
bb0(%0 : $Int):
1737+
%1 = enum $Optional<String>, #Optional.none!enumelt
1738+
%2 = tuple (%1, %0)
1739+
%3 = alloc_stack $(Optional<String>, Int)
1740+
store %2 to [init] %3
1741+
%5 = tuple_element_addr %3, 0
1742+
%6 = load [take] %5
1743+
dealloc_stack %3
1744+
return %6
1745+
}

0 commit comments

Comments
 (0)