Skip to content

Commit 0f53095

Browse files
authored
Merge pull request swiftlang#27902 from gottesmm/pr-6a6eeddd13622a50c612240710f0e66c4e0d528b
2 parents 17d5d10 + 719ee25 commit 0f53095

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,9 +1414,22 @@ static bool constantFoldInstruction(Operand *Op, Optional<bool> &ResultsInError,
14141414
[&](Operand &op) -> SILValue {
14151415
SILValue operandValue = op.get();
14161416
auto ownershipKind = operandValue.getOwnershipKind();
1417-
if (ownershipKind.isCompatibleWith(ValueOwnershipKind::Guaranteed))
1418-
return operandValue;
1419-
return SILValue();
1417+
1418+
// First check if we are not compatible with guaranteed. This means
1419+
// we would be Owned or Unowned. If so, return SILValue().
1420+
if (!ownershipKind.isCompatibleWith(ValueOwnershipKind::Guaranteed))
1421+
return SILValue();
1422+
1423+
// Otherwise check if our operand is non-trivial and None. In cases
1424+
// like that, the non-trivial type could be replacing an owned value
1425+
// where we lost that our underlying value is None due to
1426+
// intermediate aggregate literal operations. In that case, we /do
1427+
// not/ want to eliminate the destructure.
1428+
if (ownershipKind == ValueOwnershipKind::None &&
1429+
!operandValue->getType().isTrivial(*Struct->getFunction()))
1430+
return SILValue();
1431+
1432+
return operandValue;
14201433
});
14211434
return true;
14221435
}
@@ -1435,9 +1448,22 @@ static bool constantFoldInstruction(Operand *Op, Optional<bool> &ResultsInError,
14351448
[&](Operand &op) -> SILValue {
14361449
SILValue operandValue = op.get();
14371450
auto ownershipKind = operandValue.getOwnershipKind();
1438-
if (ownershipKind.isCompatibleWith(ValueOwnershipKind::Guaranteed))
1439-
return operandValue;
1440-
return SILValue();
1451+
1452+
// First check if we are not compatible with guaranteed. This means
1453+
// we would be Owned or Unowned. If so, return SILValue().
1454+
if (!ownershipKind.isCompatibleWith(ValueOwnershipKind::Guaranteed))
1455+
return SILValue();
1456+
1457+
// Otherwise check if our operand is non-trivial and None. In cases
1458+
// like that, the non-trivial type could be replacing an owned value
1459+
// where we lost that our underlying value is None due to
1460+
// intermediate aggregate literal operations. In that case, we /do
1461+
// not/ want to eliminate the destructure.
1462+
if (ownershipKind == ValueOwnershipKind::None &&
1463+
!operandValue->getType().isTrivial(*Tuple->getFunction()))
1464+
return SILValue();
1465+
1466+
return operandValue;
14411467
});
14421468
return true;
14431469
}

test/SILOptimizer/constant_propagation_ownership.sil

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ class Klass {}
2929
sil @klass_allocator : $@convention(method) (@thick Klass.Type) -> @owned Klass
3030
sil @generic_user : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
3131

32+
struct NativeObjectOptNativeObjectPair {
33+
var lhs: Builtin.NativeObject
34+
var rhs: Optional<Builtin.NativeObject>
35+
}
36+
3237
///////////
3338
// Tests //
3439
///////////
@@ -1181,3 +1186,39 @@ bb3:
11811186
%9999 = tuple()
11821187
return %9999 : $()
11831188
}
1189+
1190+
// CHECK-LABEL: sil [ossa] @do_not_RAUW_owned_destructure_with_nontrivial_none_value_tuple : $@convention(thin) (@owned Builtin.NativeObject) -> () {
1191+
// CHECK: ({{%.*}}, [[DESTRUCTURE_RESULT_2:%.*]]) = destructure_tuple
1192+
// CHECK: store [[DESTRUCTURE_RESULT_2]] to [init]
1193+
// CHECK: } // end sil function 'do_not_RAUW_owned_destructure_with_nontrivial_none_value_tuple'
1194+
sil [ossa] @do_not_RAUW_owned_destructure_with_nontrivial_none_value_tuple : $@convention(thin) (@owned Builtin.NativeObject) -> () {
1195+
bb0(%arg : @owned $Builtin.NativeObject):
1196+
%0 = alloc_stack $Optional<Builtin.NativeObject>
1197+
%1 = enum $Optional<Builtin.NativeObject>, #Optional.none!enumelt
1198+
%2 = tuple(%arg : $Builtin.NativeObject, %1 : $Optional<Builtin.NativeObject>)
1199+
(%3, %4) = destructure_tuple %2 : $(Builtin.NativeObject, Optional<Builtin.NativeObject>)
1200+
store %4 to [init] %0 : $*Optional<Builtin.NativeObject>
1201+
destroy_addr %0 : $*Optional<Builtin.NativeObject>
1202+
dealloc_stack %0 : $*Optional<Builtin.NativeObject>
1203+
destroy_value %3 : $Builtin.NativeObject
1204+
%9999 = tuple()
1205+
return %9999 : $()
1206+
}
1207+
1208+
// CHECK-LABEL: sil [ossa] @do_not_RAUW_owned_destructure_with_nontrivial_none_value_struct : $@convention(thin) (@owned Builtin.NativeObject) -> () {
1209+
// CHECK: ({{%.*}}, [[DESTRUCTURE_RESULT_2:%.*]]) = destructure_struct
1210+
// CHECK: store [[DESTRUCTURE_RESULT_2]] to [init]
1211+
// CHECK: } // end sil function 'do_not_RAUW_owned_destructure_with_nontrivial_none_value_struct'
1212+
sil [ossa] @do_not_RAUW_owned_destructure_with_nontrivial_none_value_struct : $@convention(thin) (@owned Builtin.NativeObject) -> () {
1213+
bb0(%arg : @owned $Builtin.NativeObject):
1214+
%0 = alloc_stack $Optional<Builtin.NativeObject>
1215+
%1 = enum $Optional<Builtin.NativeObject>, #Optional.none!enumelt
1216+
%2 = struct $NativeObjectOptNativeObjectPair (%arg : $Builtin.NativeObject, %1 : $Optional<Builtin.NativeObject>)
1217+
(%3, %4) = destructure_struct %2 : $NativeObjectOptNativeObjectPair
1218+
store %4 to [init] %0 : $*Optional<Builtin.NativeObject>
1219+
destroy_addr %0 : $*Optional<Builtin.NativeObject>
1220+
dealloc_stack %0 : $*Optional<Builtin.NativeObject>
1221+
destroy_value %3 : $Builtin.NativeObject
1222+
%9999 = tuple()
1223+
return %9999 : $()
1224+
}

0 commit comments

Comments
 (0)