@@ -830,10 +830,20 @@ rewriteReborrows(SILValue newBorrowedValue,
830
830
namespace {
831
831
832
832
struct OwnershipRAUWUtility {
833
- SingleValueInstruction * oldValue;
833
+ SILValue oldValue;
834
834
SILValue newValue;
835
835
OwnershipFixupContext &ctx;
836
836
837
+ // For terminator results, the consuming point is the predecessor's
838
+ // terminator. This avoids destroys on unused paths. It is also the
839
+ // instruction which will be deleted, thus needs operand cleanup.
840
+ SILInstruction *getConsumingPoint () const {
841
+ if (auto *blockArg = dyn_cast<SILPhiArgument>(oldValue))
842
+ return blockArg->getTerminatorForResult ();
843
+
844
+ return cast<SingleValueInstruction>(oldValue);
845
+ }
846
+
837
847
SILBasicBlock::iterator handleUnowned ();
838
848
839
849
SILBasicBlock::iterator handleGuaranteed ();
@@ -989,9 +999,9 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
989
999
// NOTE: This handles RAUWing with undef.
990
1000
if (newValue.getOwnershipKind () == OwnershipKind::None)
991
1001
return replaceAllUsesAndErase (oldValue, newValue, ctx.callbacks );
992
- assert (SILValue ( oldValue) .getOwnershipKind () != OwnershipKind::None);
1002
+ assert (oldValue.getOwnershipKind () != OwnershipKind::None);
993
1003
994
- switch (SILValue ( oldValue) .getOwnershipKind ()) {
1004
+ switch (oldValue.getOwnershipKind ()) {
995
1005
case OwnershipKind::None:
996
1006
// If our old value was none and our new value is not, we need to do
997
1007
// something more complex that we do not support yet, so bail. We should
@@ -1005,13 +1015,15 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
1005
1015
case OwnershipKind::Owned: {
1006
1016
// If we have an owned value that we want to replace with a value with any
1007
1017
// other non-None ownership, we need to copy the other value for a
1008
- // lifetimeEnding RAUW, then RAUW the value, and insert a destroy_value on
1018
+ // lifetimeEnding RAUW, RAUW the value, and insert a destroy_value of
1009
1019
// the original value.
1010
1020
auto extender = getLifetimeExtender ();
1011
- SILValue copy = extender.createPlusOneCopy (newValue, oldValue);
1012
- cleanupOperandsBeforeDeletion (oldValue, ctx.callbacks );
1013
- auto result = replaceAllUsesAndErase (oldValue, copy, ctx.callbacks );
1014
- return result;
1021
+ auto *consumingPoint = getConsumingPoint ();
1022
+ SILValue copy = extender.createPlusOneCopy (newValue, consumingPoint);
1023
+
1024
+ cleanupOperandsBeforeDeletion (consumingPoint, ctx.callbacks );
1025
+
1026
+ return replaceAllUsesAndErase (oldValue, copy, ctx.callbacks );
1015
1027
}
1016
1028
case OwnershipKind::Unowned: {
1017
1029
return handleUnowned ();
@@ -1027,8 +1039,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
1027
1039
SILBasicBlock::iterator
1028
1040
OwnershipRAUWHelper::replaceAddressUses (SingleValueInstruction *oldValue,
1029
1041
SILValue newValue) {
1030
- assert (oldValue->getType ().isAddress () &&
1031
- oldValue->getType () == newValue->getType ());
1042
+ assert (oldValue->getType ().isAddress () && newValue->getType ().isAddress ());
1032
1043
1033
1044
// If we are replacing addresses, see if we need to handle interior pointer
1034
1045
// fixups. If we don't have any extra info, then we know that we can just RAUW
@@ -1080,7 +1091,7 @@ OwnershipRAUWHelper::replaceAddressUses(SingleValueInstruction *oldValue,
1080
1091
// ===----------------------------------------------------------------------===//
1081
1092
1082
1093
OwnershipRAUWHelper::OwnershipRAUWHelper (OwnershipFixupContext &inputCtx,
1083
- SingleValueInstruction * inputOldValue,
1094
+ SILValue inputOldValue,
1084
1095
SILValue inputNewValue)
1085
1096
: ctx(&inputCtx), oldValue(inputOldValue), newValue(inputNewValue) {
1086
1097
// If we are already not valid, just bail.
@@ -1092,6 +1103,14 @@ OwnershipRAUWHelper::OwnershipRAUWHelper(OwnershipFixupContext &inputCtx,
1092
1103
if (!oldValue->getFunction ()->hasOwnership ())
1093
1104
return ;
1094
1105
1106
+ // This utility currently only handles erasing SingleValueInstructions and
1107
+ // terminator results.
1108
+ assert (isa<SingleValueInstruction>(inputOldValue)
1109
+ || cast<SILPhiArgument>(inputOldValue)->isTerminatorResult ());
1110
+
1111
+ // Clear the context before populating it anew.
1112
+ ctx->clear ();
1113
+
1095
1114
// Otherwise, lets check if we can perform this RAUW operation. If we can't,
1096
1115
// set ctx to nullptr to invalidate the helper and return.
1097
1116
if (!canFixUpOwnershipForRAUW (oldValue, newValue, inputCtx)) {
@@ -1204,9 +1223,12 @@ OwnershipRAUWHelper::perform(SingleValueInstruction *maybeTransformedNewValue) {
1204
1223
// Make sure to always clear our context after we transform.
1205
1224
SWIFT_DEFER { ctx->clear (); };
1206
1225
1207
- if (oldValue->getType ().isAddress ())
1208
- return replaceAddressUses (oldValue, actualNewValue);
1209
-
1226
+ if (oldValue->getType ().isAddress ()) {
1227
+ assert (isa<SingleValueInstruction>(oldValue)
1228
+ && " block argument cannot be an address" );
1229
+ return replaceAddressUses (cast<SingleValueInstruction>(oldValue),
1230
+ actualNewValue);
1231
+ }
1210
1232
OwnershipRAUWUtility utility{oldValue, actualNewValue, *ctx};
1211
1233
return utility.perform ();
1212
1234
}
0 commit comments