@@ -953,11 +953,14 @@ OwnershipLifetimeExtender::borrowOverSingleUse(SILValue newValue,
953
953
// / invariants. We leave fixing up the lifetime of old value to our caller.
954
954
namespace {
955
955
956
- struct OwnershipRAUWUtility {
956
+ struct OwnershipRAUWPrepare {
957
957
SILValue oldValue;
958
- SILValue newValue;
959
958
OwnershipFixupContext &ctx;
960
959
960
+ OwnershipLifetimeExtender getLifetimeExtender () { return {ctx}; }
961
+
962
+ const InstModCallbacks &getCallbacks () const { return ctx.callbacks ; }
963
+
961
964
// For terminator results, the consuming point is the predecessor's
962
965
// terminator. This avoids destroys on unused paths. It is also the
963
966
// instruction which will be deleted, thus needs operand cleanup.
@@ -968,18 +971,15 @@ struct OwnershipRAUWUtility {
968
971
return cast<SingleValueInstruction>(oldValue);
969
972
}
970
973
971
- SILBasicBlock::iterator handleUnowned ();
972
-
973
- SILBasicBlock::iterator perform ();
974
-
975
- OwnershipLifetimeExtender getLifetimeExtender () { return {ctx}; }
974
+ SILValue prepareReplacement (SILValue newValue);
976
975
977
- const InstModCallbacks &getCallbacks () const { return ctx.callbacks ; }
976
+ private:
977
+ SILValue prepareUnowned (SILValue newValue);
978
978
};
979
979
980
980
} // anonymous namespace
981
981
982
- SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned ( ) {
982
+ SILValue OwnershipRAUWPrepare::prepareUnowned (SILValue newValue ) {
983
983
auto &callbacks = ctx.callbacks ;
984
984
switch (newValue.getOwnershipKind ()) {
985
985
case OwnershipKind::None:
@@ -988,15 +988,15 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
988
988
llvm_unreachable (" Invalid for values" );
989
989
case OwnershipKind::Unowned:
990
990
// An unowned value can always be RAUWed with another unowned value.
991
- return replaceAllUsesAndErase (oldValue, newValue, callbacks) ;
991
+ return newValue;
992
992
case OwnershipKind::Guaranteed: {
993
993
// If we have an unowned value that we want to replace with a guaranteed
994
994
// value, we need to ensure that the guaranteed value is live at all use
995
995
// points of the unowned value. If so, just replace and continue.
996
996
//
997
997
// TODO: Implement this for more interesting cases.
998
998
if (isa<SILFunctionArgument>(newValue))
999
- return replaceAllUsesAndErase (oldValue, newValue, callbacks) ;
999
+ return newValue;
1000
1000
1001
1001
// Otherwise, we need to lifetime extend the borrow over all of the use
1002
1002
// points. To do so, we copy the value, borrow it, and insert an unchecked
@@ -1024,7 +1024,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
1024
1024
auto borrowPt = getBorrowPoint (newValue, oldValue);
1025
1025
SILValue borrow = extender.borrowCopyOverGuaranteedUses (
1026
1026
newValue, borrowPt, oldValue->getUses ());
1027
- return replaceAllUsesAndErase (oldValue, borrow, callbacks) ;
1027
+ return borrow;
1028
1028
}
1029
1029
case OwnershipKind::Owned: {
1030
1030
// If we have an unowned value that we want to replace with an owned value,
@@ -1053,23 +1053,23 @@ SILBasicBlock::iterator OwnershipRAUWUtility::handleUnowned() {
1053
1053
}
1054
1054
auto extender = getLifetimeExtender ();
1055
1055
SILValue copy = extender.createPlusZeroCopy (newValue, oldValue->getUses ());
1056
- auto result = replaceAllUsesAndErase (oldValue, copy, callbacks);
1057
- return result;
1056
+ return copy;
1058
1057
}
1059
1058
}
1060
1059
llvm_unreachable (" covered switch isn't covered?!" );
1061
1060
}
1062
1061
1063
- SILBasicBlock::iterator OwnershipRAUWUtility::perform ( ) {
1062
+ SILValue OwnershipRAUWPrepare::prepareReplacement (SILValue newValue ) {
1064
1063
assert (oldValue->getFunction ()->hasOwnership ());
1065
1064
assert (OwnershipRAUWHelper::hasValidRAUWOwnership (oldValue, newValue) &&
1066
1065
" Should have checked if can perform this operation before calling it?!" );
1067
- // If our new value is just none, we can pass anything to do it so just RAUW
1066
+ // If our new value is just none, we can pass anything to it so just RAUW
1068
1067
// and return.
1069
1068
//
1070
1069
// NOTE: This handles RAUWing with undef.
1071
1070
if (newValue.getOwnershipKind () == OwnershipKind::None)
1072
- return replaceAllUsesAndErase (oldValue, newValue, ctx.callbacks );
1071
+ return newValue;
1072
+
1073
1073
assert (oldValue.getOwnershipKind () != OwnershipKind::None);
1074
1074
1075
1075
switch (oldValue.getOwnershipKind ()) {
@@ -1081,9 +1081,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
1081
1081
case OwnershipKind::Any:
1082
1082
llvm_unreachable (" Invalid for values" );
1083
1083
case OwnershipKind::Guaranteed: {
1084
- auto extender = getLifetimeExtender ();
1085
- SILValue newGuaranteedValue = extender.borrowOverValue (newValue, oldValue);
1086
- return replaceAllUsesAndErase (oldValue, newGuaranteedValue, ctx.callbacks );
1084
+ return getLifetimeExtender ().borrowOverValue (newValue, oldValue);
1087
1085
}
1088
1086
case OwnershipKind::Owned: {
1089
1087
// If we have an owned value that we want to replace with a value with any
@@ -1095,11 +1093,10 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
1095
1093
SILValue copy = extender.createPlusOneCopy (newValue, consumingPoint);
1096
1094
1097
1095
cleanupOperandsBeforeDeletion (consumingPoint, ctx.callbacks );
1098
-
1099
- return replaceAllUsesAndErase (oldValue, copy, ctx.callbacks );
1096
+ return copy;
1100
1097
}
1101
1098
case OwnershipKind::Unowned: {
1102
- return handleUnowned ( );
1099
+ return prepareUnowned (newValue );
1103
1100
}
1104
1101
}
1105
1102
llvm_unreachable (" Covered switch isn't covered?!" );
@@ -1109,20 +1106,21 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
1109
1106
// Interior Pointer Operand Rebasing
1110
1107
// ===----------------------------------------------------------------------===//
1111
1108
1112
- SILBasicBlock::iterator
1113
- OwnershipRAUWHelper::replaceAddressUses (SingleValueInstruction *oldValue,
1114
- SILValue newValue) {
1109
+ // / Return an address equivalent to \p newValue that can be used to replace all
1110
+ // / uses of \p oldValue.
1111
+ // /
1112
+ // / Precondition: RAUW of two addresses
1113
+ SILValue
1114
+ OwnershipRAUWHelper::getReplacementAddress () {
1115
1115
assert (oldValue->getType ().isAddress () && newValue->getType ().isAddress ());
1116
1116
1117
1117
// If newValue was not generated by an interior pointer, then it cannot
1118
1118
// be within a borrow scope, so direct replacement works.
1119
1119
if (!requiresCopyBorrowAndClone ())
1120
- return replaceAllUsesAndErase (oldValue, newValue, ctx-> callbacks ) ;
1120
+ return newValue;
1121
1121
1122
- // We are RAUWing two addresses and we found that:
1123
- //
1124
- // 1. newValue is an address associated with an interior pointer instruction.
1125
- // 2. oldValue has uses that are outside of newValue's borrow scope.
1122
+ // newValue may be within a borrow scope, and oldValue may have uses that are
1123
+ // outside of newValue's borrow scope.
1126
1124
//
1127
1125
// So, we need to copy/borrow the base value of the interior pointer to
1128
1126
// lifetime extend the base value over the new uses. Then we clone the
@@ -1151,12 +1149,9 @@ OwnershipRAUWHelper::replaceAddressUses(SingleValueInstruction *oldValue,
1151
1149
auto checkBase = [&](SILValue srcAddr) {
1152
1150
return (srcAddr == refProjection) ? SILValue (newBase) : SILValue ();
1153
1151
};
1154
- SILValue clonedAddr =
1155
- cloneUseDefChain (newValue, /* insetPt*/ oldValue, checkBase);
1152
+ SILValue clonedAddr = cloneUseDefChain (newValue, bbiNext, checkBase);
1156
1153
assert (clonedAddr != newValue && " expect at least the base to be replaced" );
1157
-
1158
- // Now that we have an addr that is setup appropriately, RAUW!
1159
- return replaceAllUsesAndErase (oldValue, clonedAddr, ctx->callbacks );
1154
+ return clonedAddr;
1160
1155
}
1161
1156
1162
1157
// ===----------------------------------------------------------------------===//
@@ -1286,14 +1281,10 @@ OwnershipRAUWHelper::OwnershipRAUWHelper(OwnershipFixupContext &inputCtx,
1286
1281
}
1287
1282
}
1288
1283
1289
- SILBasicBlock::iterator
1290
- OwnershipRAUWHelper::perform (SingleValueInstruction *maybeTransformedNewValue) {
1284
+ SILValue OwnershipRAUWHelper::prepareReplacement (SILValue rewrittenNewValue) {
1291
1285
assert (isValid () && " OwnershipRAUWHelper invalid?!" );
1292
1286
1293
- SILValue actualNewValue = newValue;
1294
- if (maybeTransformedNewValue) {
1295
- // Temporary variable for rebasing
1296
- SILValue rewrittenNewValue = maybeTransformedNewValue;
1287
+ if (rewrittenNewValue) {
1297
1288
// Everything about \n newValue that the constructor checks should also be
1298
1289
// true for rewrittenNewValue.
1299
1290
// FIXME: enable these...
@@ -1304,27 +1295,33 @@ OwnershipRAUWHelper::perform(SingleValueInstruction *maybeTransformedNewValue) {
1304
1295
assert (!newValue->getType ().isAddress () ||
1305
1296
AddressOwnership (rewrittenNewValue) == AddressOwnership (newValue));
1306
1297
1307
- actualNewValue = maybeTransformedNewValue;
1308
-
1309
- // TODO: newValue = rewrittenNewValue; (remove actualNewValue)
1298
+ newValue = rewrittenNewValue;
1310
1299
}
1311
1300
assert (newValue && " prepareReplacement can only be called once" );
1312
1301
SWIFT_DEFER { newValue = SILValue (); };
1313
1302
1314
1303
if (!oldValue->getFunction ()->hasOwnership ())
1315
- return replaceAllUsesAndErase (oldValue, actualNewValue, ctx->callbacks );
1304
+ return newValue;
1305
+
1306
+ if (oldValue->getType ().isAddress ()) {
1307
+ return getReplacementAddress ();
1308
+ }
1309
+ OwnershipRAUWPrepare rauwPrepare{oldValue, *ctx};
1310
+ return rauwPrepare.prepareReplacement (newValue);
1311
+ }
1312
+
1313
+ SILBasicBlock::iterator
1314
+ OwnershipRAUWHelper::perform (SILValue replacementValue) {
1315
+ if (!replacementValue)
1316
+ replacementValue = prepareReplacement ();
1317
+
1318
+ assert (!newValue && " prepareReplacement() must be called" );
1316
1319
1317
1320
// Make sure to always clear our context after we transform.
1318
1321
SWIFT_DEFER { ctx->clear (); };
1319
1322
1320
- if (oldValue->getType ().isAddress ()) {
1321
- assert (isa<SingleValueInstruction>(oldValue)
1322
- && " block argument cannot be an address" );
1323
- return replaceAddressUses (cast<SingleValueInstruction>(oldValue),
1324
- actualNewValue);
1325
- }
1326
- OwnershipRAUWUtility utility{oldValue, actualNewValue, *ctx};
1327
- return utility.perform ();
1323
+ auto *svi = dyn_cast<SingleValueInstruction>(oldValue);
1324
+ return replaceAllUsesAndErase (svi, replacementValue, ctx->callbacks );
1328
1325
}
1329
1326
1330
1327
// ===----------------------------------------------------------------------===//
0 commit comments