Skip to content

Commit 6c728da

Browse files
committed
[arc] Put back in the RCIdentity cache.
This shaves of ~0.5 seconds from ARC when compiling the stdlib on my machine. I wired up the cache to the delete notification trigger so we are still memory safe.
1 parent f86bf3a commit 6c728da

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

include/swift/SILOptimizer/Analysis/RCIdentityAnalysis.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class DominanceAnalysis;
3232
/// This class is a simple wrapper around an identity cache.
3333
class RCIdentityFunctionInfo {
3434
llvm::DenseSet<SILArgument *> VisitedArgs;
35+
llvm::DenseMap<SILValue, SILValue> Cache;
3536
DominanceAnalysis *DA;
3637

3738
/// This number is arbitrary and conservative. At some point if compile time
@@ -50,6 +51,16 @@ class RCIdentityFunctionInfo {
5051
/// unchecked_trivial_bit_cast.
5152
void getRCUsers(SILValue V, llvm::SmallVectorImpl<SILInstruction *> &Users);
5253

54+
void handleDeleteNotification(SILInstruction *I) {
55+
// Check the cache. If we don't find it, there is nothing to do.
56+
auto Iter = Cache.find(SILValue(I));
57+
if (Iter == Cache.end())
58+
return;
59+
60+
// Then erase Iter from the cache.
61+
Cache.erase(Iter);
62+
}
63+
5364
private:
5465
SILValue getRCIdentityRootInner(SILValue V, unsigned RecursionDepth);
5566
SILValue stripRCIdentityPreservingOps(SILValue V, unsigned RecursionDepth);
@@ -84,6 +95,23 @@ class RCIdentityAnalysis : public FunctionAnalysisBase<RCIdentityFunctionInfo> {
8495
return true;
8596
}
8697

98+
virtual void handleDeleteNotification(ValueBase *V) override {
99+
auto *I = dyn_cast<SILInstruction>(V);
100+
// We are only interesting in SILInstructions.
101+
if (!I || !I->getParentBB())
102+
return;
103+
104+
// If the parent function of this instruction was just turned into an
105+
// external declaration, bail. This happens during SILFunction destruction,
106+
// when
107+
SILFunction *F = I->getFunction();
108+
if (F->isExternalDeclaration()) {
109+
return;
110+
}
111+
get(F)->handleDeleteNotification(I);
112+
}
113+
114+
virtual bool needsNotifications() override { return true; }
87115
};
88116

89117
} // end swift namespace

lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ static bool isRCIdentityPreservingCast(ValueKind Kind) {
5454
// RC Identity Root Instruction Casting
5555
//===----------------------------------------------------------------------===//
5656

57+
static SILValue stripRCIdentityPreservingCasts(SILValue V) {
58+
while (isRCIdentityPreservingCast(V->getKind()))
59+
V = cast<SILInstruction>(V)->getOperand(0);
60+
return V;
61+
}
62+
5763
static SILValue stripRCIdentityPreservingInsts(SILValue V) {
5864
// First strip off RC identity preserving casts.
5965
if (isRCIdentityPreservingCast(V->getKind()))
@@ -445,14 +451,30 @@ SILValue RCIdentityFunctionInfo::getRCIdentityRootInner(SILValue V,
445451
}
446452

447453
SILValue RCIdentityFunctionInfo::getRCIdentityRoot(SILValue V) {
448-
SILValue Root = getRCIdentityRootInner(V, 0);
454+
// We save some memory here by stripping off casts from any V. This is good to
455+
// do since stripping off casts is the cheap part of
456+
// stripRCIdentityPreservingInsts and reduces the number of possible values we
457+
// can track.
458+
//
459+
// The expensive parts of stripRCIdentityPreservingInsts function are the
460+
// unique non trivial elt calls. It should be investigated if they fit well
461+
// here as well.
462+
SILValue NoCastV = stripRCIdentityPreservingCasts(V);
463+
auto Iter = Cache.find(NoCastV);
464+
if (Iter != Cache.end())
465+
return Iter->second;
466+
467+
SILValue Root = getRCIdentityRootInner(NoCastV, 0);
449468
VisitedArgs.clear();
450469

451-
// If we fail to find a root, return V.
470+
// If we fail to find a root, return NoCastV.
471+
//
472+
// We know that stripping off RC identical preserving casts is always safe, so
473+
// since NoCastV is "better" information, we can return it without issue.
452474
if (!Root)
453-
return V;
475+
return NoCastV;
454476

455-
return Root;
477+
return Cache[NoCastV] = Root;
456478
}
457479

458480
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)