Skip to content

Commit 4212142

Browse files
committed
[semantic-arc-opts] Abstract out the check if a value is consumed into a utility called isConsumed().
I am doing this for two reasons: 1. I want to use this in a different optimization where we optimize load [copy] => load_borrow. 2. This will ensure that if/when the ownership APIs change to use isConsume/etc instead of the current operand ownership map, the optimization will be easy to update.
1 parent 71c11b7 commit 4212142

File tree

1 file changed

+42
-30
lines changed

1 file changed

+42
-30
lines changed

lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,46 @@ using namespace swift;
2828

2929
STATISTIC(NumEliminatedInsts, "number of removed instructions");
3030

31+
//===----------------------------------------------------------------------===//
32+
// Utility
33+
//===----------------------------------------------------------------------===//
34+
35+
static bool isConsumed(SILValue v,
36+
SmallVectorImpl<DestroyValueInst *> &destroys) {
37+
assert(v.getOwnershipKind() == ValueOwnershipKind::Owned);
38+
return !all_of(v->getUses(), [&destroys](Operand *op) {
39+
// We know that a copy_value produces an @owned value. Look
40+
// through all of our uses and classify them as either
41+
// invalidating or not invalidating. Make sure that all of the
42+
// invalidating ones are destroy_value since otherwise the
43+
// live_range is not complete.
44+
auto map = op->getOwnershipKindMap();
45+
auto constraint = map.getLifetimeConstraint(ValueOwnershipKind::Owned);
46+
switch (constraint) {
47+
case UseLifetimeConstraint::MustBeInvalidated: {
48+
// See if we have a destroy value. If we don't we have an
49+
// unknown consumer. Return false, we need this live range.
50+
auto *dvi = dyn_cast<DestroyValueInst>(op->getUser());
51+
if (!dvi)
52+
return false;
53+
54+
// Otherwise, return true and stash this destroy value.
55+
destroys.push_back(dvi);
56+
return true;
57+
}
58+
case UseLifetimeConstraint::MustBeLive:
59+
// Ok, this constraint can take something owned as live. Lets
60+
// see if it can also take something that is guaranteed. If it
61+
// can not, then we bail.
62+
return map.canAcceptKind(ValueOwnershipKind::Guaranteed);
63+
}
64+
});
65+
}
66+
67+
//===----------------------------------------------------------------------===//
68+
// Implementation
69+
//===----------------------------------------------------------------------===//
70+
3171
namespace {
3272

3373
struct SemanticARCOptVisitor
@@ -125,36 +165,8 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) {
125165
// guaranteed value. After that, make sure that our destroys are
126166
// within the lifetime of our borrowed values.
127167
SmallVector<DestroyValueInst *, 16> destroys;
128-
for (auto *op : cvi->getUses()) {
129-
// We know that a copy_value produces an @owned value. Look
130-
// through all of our uses and classify them as either
131-
// invalidating or not invalidating. Make sure that all of the
132-
// invalidating ones are destroy_value since otherwise the
133-
// live_range is not complete.
134-
auto map = op->getOwnershipKindMap();
135-
auto constraint = map.getLifetimeConstraint(ValueOwnershipKind::Owned);
136-
switch (constraint) {
137-
case UseLifetimeConstraint::MustBeInvalidated:
138-
// And we have a destroy_value, track it and continue.
139-
if (auto *dvi = dyn_cast<DestroyValueInst>(op->getUser())) {
140-
destroys.push_back(dvi);
141-
continue;
142-
}
143-
// Otherwise, we found a non-destroy value invalidating owned
144-
// user... This is not an unnecessary live range.
145-
return false;
146-
case UseLifetimeConstraint::MustBeLive:
147-
// Ok, this constraint can take something owned as live. Lets
148-
// see if it can also take something that is guaranteed. If it
149-
// can not, then we bail.
150-
if (!map.canAcceptKind(ValueOwnershipKind::Guaranteed)) {
151-
return false;
152-
}
153-
154-
// Otherwise, continue.
155-
continue;
156-
}
157-
}
168+
if (isConsumed(cvi, destroys))
169+
return false;
158170

159171
// If we reached this point, then we know that all of our users can
160172
// accept a guaranteed value and our owned value is destroyed only

0 commit comments

Comments
 (0)