@@ -28,6 +28,46 @@ using namespace swift;
28
28
29
29
STATISTIC (NumEliminatedInsts, " number of removed instructions" );
30
30
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
+
31
71
namespace {
32
72
33
73
struct SemanticARCOptVisitor
@@ -125,36 +165,8 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) {
125
165
// guaranteed value. After that, make sure that our destroys are
126
166
// within the lifetime of our borrowed values.
127
167
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 ;
158
170
159
171
// If we reached this point, then we know that all of our users can
160
172
// accept a guaranteed value and our owned value is destroyed only
0 commit comments