Skip to content

Commit 678a707

Browse files
authored
Merge pull request #28656 from gottesmm/pr-1b805643ed16875a451d67e7554f321977df32bf
[semantic-arc-opts] Convert isDeadLiveRange into a method on a general LiveRange class.
2 parents 6742368 + f236e0f commit 678a707

File tree

1 file changed

+64
-28
lines changed

1 file changed

+64
-28
lines changed

lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,50 @@ STATISTIC(NumLoadCopyConvertedToLoadBorrow,
4141
// Utility
4242
//===----------------------------------------------------------------------===//
4343

44-
/// Return true if v only has invalidating uses that are destroy_value. Such an
45-
/// owned value is said to represent a dead "live range".
46-
///
47-
/// Semantically this implies that a value is never passed off as +1 to memory
48-
/// or another function implying it can be used everywhere at +0.
49-
static bool
50-
isDeadLiveRange(SILValue v, SmallVectorImpl<SILInstruction *> &destroys,
51-
SmallVectorImpl<SILInstruction *> &forwardingInsts) {
52-
assert(v.getOwnershipKind() == ValueOwnershipKind::Owned);
53-
SmallVector<Operand *, 32> worklist(v->use_begin(), v->use_end());
44+
//===----------------------------------------------------------------------===//
45+
// Live Range Modeling
46+
//===----------------------------------------------------------------------===//
47+
48+
namespace {
49+
50+
class LiveRange {
51+
/// A list of destroy_values of the live range.
52+
SmallVector<SILInstruction *, 16> destroys;
53+
54+
/// A list of forwarding instructions that forward our destroys ownership, but
55+
/// that are also able to forward guaranteed ownership.
56+
SmallVector<SILInstruction *, 16> generalForwardingInsts;
57+
58+
/// Consuming users that we were not able to understand as a forwarding
59+
/// instruction or a destroy_value. These must be passed a strongly control
60+
/// equivalent +1 value.
61+
SmallVector<SILInstruction *, 16> unknownConsumingUsers;
62+
63+
public:
64+
LiveRange(SILValue value);
65+
66+
LiveRange(const LiveRange &) = delete;
67+
LiveRange &operator=(const LiveRange &) = delete;
68+
69+
/// Return true if v only has invalidating uses that are destroy_value. Such
70+
/// an owned value is said to represent a dead "live range".
71+
///
72+
/// Semantically this implies that a value is never passed off as +1 to memory
73+
/// or another function implying it can be used everywhere at +0.
74+
bool hasConsumingUse() const { return unknownConsumingUsers.size(); }
75+
76+
ArrayRef<SILInstruction *> getDestroys() const { return destroys; }
77+
ArrayRef<SILInstruction *> getNonConsumingForwardingInsts() const {
78+
return generalForwardingInsts;
79+
}
80+
};
81+
82+
} // end anonymous namespace
83+
84+
LiveRange::LiveRange(SILValue value)
85+
: destroys(), generalForwardingInsts(), unknownConsumingUsers() {
86+
SmallVector<Operand *, 32> worklist(value->getUses());
87+
5488
while (!worklist.empty()) {
5589
auto *op = worklist.pop_back_val();
5690

@@ -93,13 +127,14 @@ isDeadLiveRange(SILValue v, SmallVectorImpl<SILInstruction *> &destroys,
93127
return v.getOwnershipKind() ==
94128
ValueOwnershipKind::Owned;
95129
})) {
96-
return false;
130+
unknownConsumingUsers.push_back(user);
131+
continue;
97132
}
98133

99134
// Ok, this is a forwarding instruction whose ownership we can flip from
100135
// owned -> guaranteed. Visit its users recursively to see if the the
101136
// users force the live range to be alive.
102-
forwardingInsts.push_back(user);
137+
generalForwardingInsts.push_back(user);
103138
for (SILValue v : user->getResults()) {
104139
if (v.getOwnershipKind() != ValueOwnershipKind::Owned)
105140
continue;
@@ -118,10 +153,6 @@ isDeadLiveRange(SILValue v, SmallVectorImpl<SILInstruction *> &destroys,
118153
continue;
119154
}
120155
}
121-
122-
// We visited all of our users and were able to prove that all of them were
123-
// benign. Return true.
124-
return true;
125156
}
126157

127158
//===----------------------------------------------------------------------===//
@@ -372,12 +403,13 @@ bool SemanticARCOptVisitor::visitBeginBorrowInst(BeginBorrowInst *bbi) {
372403
}
373404

374405
static void convertForwardingInstsFromOwnedToGuaranteed(
375-
SmallVectorImpl<SILInstruction *> &guaranteedForwardingInsts) {
406+
ArrayRef<SILInstruction *> guaranteedForwardingInsts) {
376407
// Then change all of our guaranteed forwarding insts to have guaranteed
377408
// ownership kind instead of what ever they previously had (ignoring trivial
378409
// results);
379410
while (!guaranteedForwardingInsts.empty()) {
380-
auto *i = guaranteedForwardingInsts.pop_back_val();
411+
auto *i = guaranteedForwardingInsts.back();
412+
guaranteedForwardingInsts = guaranteedForwardingInsts.drop_back();
381413
assert(i->hasResults());
382414

383415
for (SILValue result : i->getResults()) {
@@ -461,9 +493,8 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
461493
// must be some consuming use that we either do not understand is /actually/
462494
// forwarding or a user that truly represents a necessary consume of the
463495
// value (e.x. storing into memory).
464-
SmallVector<SILInstruction *, 16> destroys;
465-
SmallVector<SILInstruction *, 16> guaranteedForwardingInsts;
466-
if (!isDeadLiveRange(cvi, destroys, guaranteedForwardingInsts))
496+
LiveRange lr(cvi);
497+
if (lr.hasConsumingUse())
467498
return false;
468499

469500
// Next check if we do not have any destroys of our copy_value and are
@@ -526,6 +557,7 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
526557
return borrowScope.isLocalScope();
527558
});
528559

560+
auto destroys = lr.getDestroys();
529561
if (destroys.empty() && haveAnyLocalScopes) {
530562
return false;
531563
}
@@ -568,13 +600,15 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
568600
// Otherwise, we know that our copy_value/destroy_values are all completely
569601
// within the guaranteed value scope. First delete the destroys/copies.
570602
while (!destroys.empty()) {
571-
auto *dvi = destroys.pop_back_val();
603+
auto *dvi = destroys.back();
604+
destroys = destroys.drop_back();
572605
eraseInstruction(dvi);
573606
++NumEliminatedInsts;
574607
}
575608

576609
eraseAndRAUWSingleValueInstruction(cvi, cvi->getOperand());
577-
convertForwardingInstsFromOwnedToGuaranteed(guaranteedForwardingInsts);
610+
convertForwardingInstsFromOwnedToGuaranteed(
611+
lr.getNonConsumingForwardingInsts());
578612

579613
++NumEliminatedInsts;
580614
return true;
@@ -842,14 +876,14 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
842876
// FIXME: We should consider if it is worth promoting a load [copy]
843877
// -> load_borrow if we can put a copy_value on a cold path and thus
844878
// eliminate RR traffic on a hot path.
845-
SmallVector<SILInstruction *, 32> destroyValues;
846-
SmallVector<SILInstruction *, 16> guaranteedForwardingInsts;
847-
if (!isDeadLiveRange(li, destroyValues, guaranteedForwardingInsts))
879+
LiveRange lr(li);
880+
if (lr.hasConsumingUse())
848881
return false;
849882

850883
// Then check if our address is ever written to. If it is, then we cannot use
851884
// the load_borrow because the stored value may be released during the loaded
852885
// value's live range.
886+
auto destroyValues = lr.getDestroys();
853887
if (isWrittenTo(li, destroyValues))
854888
return false;
855889

@@ -878,7 +912,8 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
878912

879913
// Then delete all of our destroy_value.
880914
while (!destroyValues.empty()) {
881-
auto *dvi = destroyValues.pop_back_val();
915+
auto *dvi = destroyValues.back();
916+
destroyValues = destroyValues.drop_back();
882917
eraseInstruction(dvi);
883918
++NumEliminatedInsts;
884919
}
@@ -888,7 +923,8 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
888923

889924
// And then change the ownership all of our owned forwarding users to be
890925
// guaranteed.
891-
convertForwardingInstsFromOwnedToGuaranteed(guaranteedForwardingInsts);
926+
convertForwardingInstsFromOwnedToGuaranteed(
927+
lr.getNonConsumingForwardingInsts());
892928

893929
++NumEliminatedInsts;
894930
++NumLoadCopyConvertedToLoadBorrow;

0 commit comments

Comments
 (0)