Skip to content

Commit d4f8339

Browse files
Merge pull request #74335 from nate-chandler/cherrypick/release/6.0/rdar129593468
6.0: [NoncopyableWrapperElim] Process undef values.
2 parents cf475c2 + 0aa17db commit d4f8339

File tree

8 files changed

+103
-55
lines changed

8 files changed

+103
-55
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "swift/SIL/SILDeclRef.h"
2929
#include "swift/SIL/SILLinkage.h"
3030
#include "swift/SIL/SILPrintContext.h"
31+
#include "swift/SIL/SILUndef.h"
32+
#include "llvm/ADT/MapVector.h"
3133

3234
namespace swift {
3335

@@ -337,12 +339,8 @@ class SILFunction
337339

338340
PerformanceConstraints perfConstraints = PerformanceConstraints::None;
339341

340-
/// This is the set of undef values we've created, for uniquing purposes.
341-
///
342-
/// We use a SmallDenseMap since in most functions, we will have only one type
343-
/// of undef if we have any at all. In that case, by staying small we avoid
344-
/// needing a heap allocation.
345-
llvm::SmallDenseMap<SILType, SILUndef *, 1> undefValues;
342+
/// The undefs of each type in the function.
343+
llvm::SmallMapVector<SILType, SILUndef *, 1> undefValues;
346344

347345
/// This is the number of uses of this SILFunction inside the SIL.
348346
/// It does not include references from debug scopes.
@@ -1605,6 +1603,10 @@ class SILFunction
16051603
decl->getLifetimeAnnotation());
16061604
}
16071605

1606+
ArrayRef<std::pair<SILType, SILUndef *>> getUndefValues() {
1607+
return {undefValues.begin(), undefValues.end()};
1608+
}
1609+
16081610
/// verify - Run the SIL verifier to make sure that the SILFunction follows
16091611
/// invariants.
16101612
void verify(CalleeCache *calleeCache = nullptr,

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9110,7 +9110,7 @@ class MoveOnlyWrapperToCopyableBoxInst
91109110
ValueOwnershipKind forwardingOwnershipKind)
91119111
: UnaryInstructionBase(
91129112
DebugLoc, operand,
9113-
operand->getType().removingMoveOnlyWrapperToBoxedType(
9113+
operand->getType().removingMoveOnlyWrapperFromBoxedType(
91149114
operand->getFunction()),
91159115
forwardingOwnershipKind) {
91169116
assert(

include/swift/SIL/SILType.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,15 @@ class SILType {
855855
///
856856
/// DISCUSSION: This is separate from removingMoveOnlyWrapper since this API
857857
/// requires a SILFunction * and is specialized.
858-
SILType removingMoveOnlyWrapperToBoxedType(const SILFunction *fn);
858+
SILType removingMoveOnlyWrapperFromBoxedType(const SILFunction *fn);
859+
860+
/// Whether there's a direct wrapper or a wrapper inside a box.
861+
bool hasAnyMoveOnlyWrapping(const SILFunction *fn) {
862+
return isMoveOnlyWrapped() || isBoxedMoveOnlyWrappedType(fn);
863+
}
864+
865+
/// Removes a direct wrapper from a type or a wrapper from a type in a box.
866+
SILType removingAnyMoveOnlyWrapping(const SILFunction *fn);
859867

860868
/// Returns a SILType with any archetypes mapped out of context.
861869
SILType mapTypeOutOfContext() const;

include/swift/SIL/SILValue.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -597,14 +597,9 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
597597
/// NOTE: Please do not use this directly! It is only meant to be used by the
598598
/// optimizer pass: SILMoveOnlyWrappedTypeEliminator.
599599
bool unsafelyEliminateMoveOnlyWrapper(const SILFunction *fn) {
600-
if (!Type.isMoveOnlyWrapped() && !Type.isBoxedMoveOnlyWrappedType(fn))
600+
if (!Type.hasAnyMoveOnlyWrapping(fn))
601601
return false;
602-
if (Type.isMoveOnlyWrapped()) {
603-
Type = Type.removingMoveOnlyWrapper();
604-
} else {
605-
assert(Type.isBoxedMoveOnlyWrappedType(fn));
606-
Type = Type.removingMoveOnlyWrapperToBoxedType(fn);
607-
}
602+
Type = Type.removingAnyMoveOnlyWrapping(fn);
608603
return true;
609604
}
610605

lib/SIL/IR/SILType.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,7 @@ SILType SILType::addingMoveOnlyWrapperToBoxedType(const SILFunction *fn) {
12661266
return SILType::getPrimitiveObjectType(newBoxType);
12671267
}
12681268

1269-
SILType SILType::removingMoveOnlyWrapperToBoxedType(const SILFunction *fn) {
1269+
SILType SILType::removingMoveOnlyWrapperFromBoxedType(const SILFunction *fn) {
12701270
auto boxTy = castTo<SILBoxType>();
12711271
auto *oldLayout = boxTy->getLayout();
12721272
auto oldField = oldLayout->getFields()[0];
@@ -1284,6 +1284,17 @@ SILType SILType::removingMoveOnlyWrapperToBoxedType(const SILFunction *fn) {
12841284
return SILType::getPrimitiveObjectType(newBoxType);
12851285
}
12861286

1287+
SILType SILType::removingAnyMoveOnlyWrapping(const SILFunction *fn) {
1288+
if (!isMoveOnlyWrapped() && !isBoxedMoveOnlyWrappedType(fn))
1289+
return *this;
1290+
1291+
if (isMoveOnlyWrapped())
1292+
return removingMoveOnlyWrapper();
1293+
1294+
assert(isBoxedMoveOnlyWrappedType(fn));
1295+
return removingMoveOnlyWrapperFromBoxedType(fn);
1296+
}
1297+
12871298
bool SILType::isSendable(SILFunction *fn) const {
12881299
return getASTType()->isSendableType();
12891300
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6463,9 +6463,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
64636463
"Operand value should be an object");
64646464
require(cvt->getOperand()->getType().isBoxedMoveOnlyWrappedType(cvt->getFunction()),
64656465
"Operand should be move only wrapped");
6466-
require(cvt->getType() ==
6467-
cvt->getOperand()->getType().removingMoveOnlyWrapperToBoxedType(cvt->getFunction()),
6468-
"Result and operand must have the same type, today.");
6466+
require(
6467+
cvt->getType() ==
6468+
cvt->getOperand()->getType().removingMoveOnlyWrapperFromBoxedType(
6469+
cvt->getFunction()),
6470+
"Result and operand must have the same type, today.");
64696471
}
64706472

64716473
void checkCopyableToMoveOnlyWrapperValueInst(

lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,6 @@ namespace {
5151

5252
struct SILMoveOnlyWrappedTypeEliminatorVisitor
5353
: SILInstructionVisitor<SILMoveOnlyWrappedTypeEliminatorVisitor, bool> {
54-
const llvm::SmallSetVector<SILArgument *, 8> &touchedArgs;
55-
56-
SILMoveOnlyWrappedTypeEliminatorVisitor(
57-
const llvm::SmallSetVector<SILArgument *, 8> &touchedArgs)
58-
: touchedArgs(touchedArgs) {}
59-
6054
bool visitSILInstruction(SILInstruction *inst) {
6155
llvm::errs() << "Unhandled SIL Instruction: " << *inst;
6256
llvm_unreachable("error");
@@ -294,56 +288,76 @@ static bool isMoveOnlyWrappedTrivial(SILValue value) {
294288
}
295289

296290
bool SILMoveOnlyWrappedTypeEliminator::process() {
297-
bool madeChange = true;
291+
bool madeChange = false;
298292

299-
llvm::SmallSetVector<SILArgument *, 8> touchedArgs;
300293
llvm::SmallSetVector<SILInstruction *, 8> touchedInsts;
301294

295+
// For each value whose type is move-only wrapped:
296+
// - rewrite the value's type
297+
// - record its users for later visitation
298+
auto visitValue = [&touchedInsts, fn = fn,
299+
trivialOnly = trivialOnly](SILValue value) -> bool {
300+
if (!value->getType().hasAnyMoveOnlyWrapping(fn))
301+
return false;
302+
303+
// If we are looking at trivial only, skip non-trivial function args.
304+
if (trivialOnly && !isMoveOnlyWrappedTrivial(value))
305+
return false;
306+
307+
for (auto *use : value->getNonTypeDependentUses())
308+
touchedInsts.insert(use->getUser());
309+
310+
if (isa<SILUndef>(value))
311+
value->replaceAllUsesWith(
312+
SILUndef::get(fn, value->getType().removingAnyMoveOnlyWrapping(fn)));
313+
else
314+
value->unsafelyEliminateMoveOnlyWrapper(fn);
315+
316+
return true;
317+
};
318+
302319
for (auto &bb : *fn) {
303320
for (auto *arg : bb.getArguments()) {
304-
if (!arg->getType().isMoveOnlyWrapped() &&
305-
!arg->getType().isBoxedMoveOnlyWrappedType(fn))
321+
bool relevant = visitValue(arg);
322+
if (!relevant)
306323
continue;
307324

308-
// If we are looking at trivial only, skip non-trivial function args.
309-
if (trivialOnly &&
310-
!arg->getType().removingMoveOnlyWrapper().isTrivial(*fn))
311-
continue;
312-
313-
arg->unsafelyEliminateMoveOnlyWrapper(fn);
314-
315325
// If our new type is trivial, convert the arguments ownership to
316326
// None. Otherwise, preserve the ownership kind of the argument.
317327
if (arg->getType().isTrivial(*fn))
318328
arg->setOwnershipKind(OwnershipKind::None);
319-
touchedArgs.insert(arg);
320-
for (auto *use : arg->getNonTypeDependentUses())
321-
touchedInsts.insert(use->getUser());
329+
330+
madeChange = true;
322331
}
323332

324333
for (auto &ii : bb) {
325-
for (SILValue v : ii.getResults()) {
326-
if (!v->getType().isMoveOnlyWrapped() &&
327-
!v->getType().isBoxedMoveOnlyWrappedType(fn))
328-
continue;
329-
330-
if (trivialOnly &&
331-
!isMoveOnlyWrappedTrivial(v))
334+
bool touched = false;
335+
for (SILValue value : ii.getResults()) {
336+
bool relevant = visitValue(value);
337+
if (!relevant)
332338
continue;
333339

334-
v->unsafelyEliminateMoveOnlyWrapper(fn);
335-
touchedInsts.insert(&ii);
336-
337-
// Add all users as well. This ensures we visit things like
338-
// destroy_value and end_borrow.
339-
for (auto *use : v->getNonTypeDependentUses())
340-
touchedInsts.insert(use->getUser());
341-
madeChange = true;
340+
touched = true;
342341
}
342+
if (!touched)
343+
continue;
344+
touchedInsts.insert(&ii);
345+
346+
madeChange = true;
343347
}
344348
}
349+
// SILFunction::undefValues may grow during the loop.
350+
SmallVector<std::pair<SILType, SILUndef *>, 4> originalUndefs(
351+
fn->getUndefValues());
352+
for (auto pair : originalUndefs) {
353+
bool relevant = visitValue(pair.second);
354+
if (!relevant)
355+
continue;
356+
357+
madeChange = true;
358+
}
345359

346-
SILMoveOnlyWrappedTypeEliminatorVisitor visitor(touchedArgs);
360+
SILMoveOnlyWrappedTypeEliminatorVisitor visitor;
347361
while (!touchedInsts.empty()) {
348362
visitor.visit(touchedInsts.pop_back_val());
349363
}

test/SILOptimizer/moveonly_type_eliminator.sil

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,3 +562,19 @@ bb3(%result : @owned $@moveOnly FakeOptional<Klass>):
562562
%result2 = moveonlywrapper_to_copyable [owned] %result : $@moveOnly FakeOptional<Klass>
563563
return %result2 : $FakeOptional<Klass>
564564
}
565+
566+
// CHECK-LABEL: sil [ossa] @debug_value_undef : {{.*}} {
567+
// CHECK: debug_value [moveable_value_debuginfo] undef : $*Klass, var, name "s"
568+
// CHECK-LABEL: } // end sil function 'debug_value_undef'
569+
sil [ossa] @debug_value_undef : $@convention(thin) (@owned Klass) -> () {
570+
bb0(%x : @owned $Klass):
571+
%addr = alloc_stack $@moveOnly Klass
572+
%unwrapped_addr = moveonlywrapper_to_copyable_addr %addr : $*@moveOnly Klass
573+
store %x to [init] %unwrapped_addr : $*Klass
574+
debug_value %addr : $*@moveOnly Klass, var, name "s", argno 1, expr op_deref
575+
destroy_addr %addr : $*@moveOnly Klass
576+
debug_value undef : $*@moveOnly Klass, var, name "s", argno 1, expr op_deref
577+
dealloc_stack %addr : $*@moveOnly Klass
578+
%retval = tuple ()
579+
return %retval : $()
580+
}

0 commit comments

Comments
 (0)