Skip to content

Commit 3897e9a

Browse files
authored
Merge pull request swiftlang#66161 from atrick/fix-silcombine
Fix SILCombine to preserve a release of a move-only type
2 parents 8f0382c + dc974e8 commit 3897e9a

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

lib/SIL/IR/TypeLowering.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2323,6 +2323,8 @@ namespace {
23232323
return handleReference(classType, properties);
23242324
}
23252325

2326+
// WARNING: when the specification of trivial types changes, also update
2327+
// the isValueTrivial() API used by SILCombine.
23262328
TypeLowering *visitAnyStructType(CanType structType,
23272329
AbstractionPattern origType,
23282330
StructDecl *D,
@@ -2391,7 +2393,9 @@ namespace {
23912393
return handleAggregateByProperties<LoadableStructTypeLowering>(structType,
23922394
properties);
23932395
}
2394-
2396+
2397+
// WARNING: when the specification of trivial types changes, also update
2398+
// the isValueTrivial() API used by SILCombine.
23952399
TypeLowering *visitAnyEnumType(CanType enumType,
23962400
AbstractionPattern origType,
23972401
EnumDecl *D,

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,12 @@ SILInstruction *SILCombiner::visitIndexAddrInst(IndexAddrInst *IA) {
815815
/// operation for \p value is required. This differs from a simple `isTrivial`
816816
/// check, because it treats a value_to_bridge_object instruction as "trivial".
817817
/// It can also handle non-trivial enums with trivial cases.
818-
static bool isTrivial(SILValue value, SILFunction *function) {
818+
///
819+
/// TODO: Define this as a top-level SILValue API. It needs to be updated
820+
/// whenever we refine the specification of isTrivial. For example, in the
821+
/// future we will check for the existence of a user-defined deinitializer and
822+
/// handle C++ types specially.
823+
static bool isValueTrivial(SILValue value, SILFunction *function) {
819824
SmallVector<ValueBase *, 32> workList;
820825
SmallPtrSet<ValueBase *, 16> visited;
821826
workList.push_back(value);
@@ -825,6 +830,11 @@ static bool isTrivial(SILValue value, SILFunction *function) {
825830
continue;
826831
if (isa<ValueToBridgeObjectInst>(v))
827832
continue;
833+
834+
// MoveOnly types may have a user-defined deinit.
835+
if (v->getType().isPureMoveOnly())
836+
return false;
837+
828838
if (isa<StructInst>(v) || isa<TupleInst>(v)) {
829839
for (SILValue op : cast<SingleValueInstruction>(v)->getOperandValues()) {
830840
if (visited.insert(op).second)
@@ -876,7 +886,7 @@ SILInstruction *SILCombiner::visitReleaseValueInst(ReleaseValueInst *RVI) {
876886
RVI->getAtomicity());
877887

878888
// ReleaseValueInst of a trivial type is a no-op.
879-
if (isTrivial(Operand, RVI->getFunction()))
889+
if (isValueTrivial(Operand, RVI->getFunction()))
880890
return eraseInstFromFunction(*RVI);
881891

882892
// Do nothing for non-trivial non-reference types.
@@ -2297,4 +2307,4 @@ SILCombiner::visitCopyAddrInst(CopyAddrInst *CAI) {
22972307
return Builder.createCopyAddr(
22982308
CAI->getLoc(), Src->getOperand(), Dst->getOperand(),
22992309
CAI->isTakeOfSrc(), CAI->isInitializationOfDest());
2300-
}
2310+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all -sil-combine %s | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
7+
struct S : ~Copyable {
8+
deinit {}
9+
}
10+
11+
// Test that a release_value is not removed for a struct-with-deinit.
12+
// Doing so would forget the deinit.
13+
//
14+
// public func testStructDeinit() {
15+
// var s = S()
16+
// }
17+
//
18+
// CHECK-LABEL: sil @testStructDeinit : $@convention(thin) () -> () {
19+
// CHECK: release_value %{{.*}} : $S
20+
// CHECK-LABEL: } // end sil function 'testStructDeinit'
21+
sil @testStructDeinit : $@convention(thin) () -> () {
22+
bb0:
23+
%0 = struct $S ()
24+
release_value %0 : $S
25+
%5 = tuple ()
26+
return %5 : $()
27+
}
28+

0 commit comments

Comments
 (0)