Skip to content

Commit 4cdcc14

Browse files
committed
Prepare OwnershipRAUWHelper support for terminator results.
The 'oldValue' can now be a terminator result instead of a SingleValueInstruction.
1 parent 55e0523 commit 4cdcc14

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed

include/swift/SILOptimizer/Utils/OwnershipOptUtils.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,24 +117,26 @@ class OwnershipRAUWHelper {
117117

118118
private:
119119
OwnershipFixupContext *ctx;
120-
SingleValueInstruction *oldValue;
120+
SILValue oldValue;
121121
SILValue newValue;
122122

123123
public:
124-
OwnershipRAUWHelper() : ctx(nullptr), oldValue(nullptr), newValue(nullptr) {}
124+
OwnershipRAUWHelper() : ctx(nullptr) {}
125125

126126
/// Return an instance of this class if we can perform the specific RAUW
127127
/// operation ignoring if the types line up. Returns None otherwise.
128128
///
129+
/// \p oldValue may be either a SingleValueInstruction or a terminator result.
130+
///
129131
/// DISCUSSION: We do not check that the types line up here so that we can
130132
/// allow for our users to transform our new value in ways that preserve
131133
/// ownership at \p oldValue before we perform the actual RAUW. If \p newValue
132134
/// is an object, any instructions in the chain of transforming instructions
133135
/// from \p newValue at \p oldValue's must be forwarding. If \p newValue is an
134136
/// address, then these transforms can only transform the address into a
135137
/// derived address.
136-
OwnershipRAUWHelper(OwnershipFixupContext &ctx,
137-
SingleValueInstruction *oldValue, SILValue newValue);
138+
OwnershipRAUWHelper(OwnershipFixupContext &ctx, SILValue oldValue,
139+
SILValue newValue);
138140

139141
/// Returns true if this helper was initialized into a valid state.
140142
operator bool() const { return isValid(); }

lib/SILOptimizer/Utils/OwnershipOptUtils.cpp

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -830,10 +830,20 @@ rewriteReborrows(SILValue newBorrowedValue,
830830
namespace {
831831

832832
struct OwnershipRAUWUtility {
833-
SingleValueInstruction *oldValue;
833+
SILValue oldValue;
834834
SILValue newValue;
835835
OwnershipFixupContext &ctx;
836836

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+
837847
SILBasicBlock::iterator handleUnowned();
838848

839849
SILBasicBlock::iterator handleGuaranteed();
@@ -989,9 +999,9 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
989999
// NOTE: This handles RAUWing with undef.
9901000
if (newValue.getOwnershipKind() == OwnershipKind::None)
9911001
return replaceAllUsesAndErase(oldValue, newValue, ctx.callbacks);
992-
assert(SILValue(oldValue).getOwnershipKind() != OwnershipKind::None);
1002+
assert(oldValue.getOwnershipKind() != OwnershipKind::None);
9931003

994-
switch (SILValue(oldValue).getOwnershipKind()) {
1004+
switch (oldValue.getOwnershipKind()) {
9951005
case OwnershipKind::None:
9961006
// If our old value was none and our new value is not, we need to do
9971007
// something more complex that we do not support yet, so bail. We should
@@ -1005,13 +1015,15 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
10051015
case OwnershipKind::Owned: {
10061016
// If we have an owned value that we want to replace with a value with any
10071017
// 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
10091019
// the original value.
10101020
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);
10151027
}
10161028
case OwnershipKind::Unowned: {
10171029
return handleUnowned();
@@ -1027,8 +1039,7 @@ SILBasicBlock::iterator OwnershipRAUWUtility::perform() {
10271039
SILBasicBlock::iterator
10281040
OwnershipRAUWHelper::replaceAddressUses(SingleValueInstruction *oldValue,
10291041
SILValue newValue) {
1030-
assert(oldValue->getType().isAddress() &&
1031-
oldValue->getType() == newValue->getType());
1042+
assert(oldValue->getType().isAddress() && newValue->getType().isAddress());
10321043

10331044
// If we are replacing addresses, see if we need to handle interior pointer
10341045
// 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,
10801091
//===----------------------------------------------------------------------===//
10811092

10821093
OwnershipRAUWHelper::OwnershipRAUWHelper(OwnershipFixupContext &inputCtx,
1083-
SingleValueInstruction *inputOldValue,
1094+
SILValue inputOldValue,
10841095
SILValue inputNewValue)
10851096
: ctx(&inputCtx), oldValue(inputOldValue), newValue(inputNewValue) {
10861097
// If we are already not valid, just bail.
@@ -1092,6 +1103,14 @@ OwnershipRAUWHelper::OwnershipRAUWHelper(OwnershipFixupContext &inputCtx,
10921103
if (!oldValue->getFunction()->hasOwnership())
10931104
return;
10941105

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+
10951114
// Otherwise, lets check if we can perform this RAUW operation. If we can't,
10961115
// set ctx to nullptr to invalidate the helper and return.
10971116
if (!canFixUpOwnershipForRAUW(oldValue, newValue, inputCtx)) {
@@ -1204,9 +1223,12 @@ OwnershipRAUWHelper::perform(SingleValueInstruction *maybeTransformedNewValue) {
12041223
// Make sure to always clear our context after we transform.
12051224
SWIFT_DEFER { ctx->clear(); };
12061225

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+
}
12101232
OwnershipRAUWUtility utility{oldValue, actualNewValue, *ctx};
12111233
return utility.perform();
12121234
}

0 commit comments

Comments
 (0)