Skip to content

Commit d55ebae

Browse files
committed
[arc] Make all *RefCountStates and RCStateTransition trivially destructable and constructable.
Tested via static assert. There is no reason for these data structures to not have these properties. Adding these properties will improve the compile time efficiency of ARC by allowing for cheaper copying and 0 cost destruction.
1 parent 069a9d5 commit d55ebae

File tree

5 files changed

+49
-44
lines changed

5 files changed

+49
-44
lines changed

lib/SILOptimizer/ARC/RCStateTransition.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,6 @@ raw_ostream &llvm::operator<<(raw_ostream &os, RCStateTransitionKind Kind) {
121121
}
122122
#include "RCStateTransition.def"
123123

124-
RCStateTransition::RCStateTransition(const RCStateTransition &R) {
125-
Kind = R.Kind;
126-
if (R.isEndPoint()) {
127-
EndPoint = R.EndPoint;
128-
return;
129-
}
130-
131-
if (!R.isMutator())
132-
return;
133-
Mutators = R.Mutators;
134-
}
135-
136124
bool RCStateTransition::matchingInst(SILInstruction *Inst) const {
137125
// We only pair mutators for now.
138126
if (!isMutator())

lib/SILOptimizer/ARC/RCStateTransition.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
/// Misc |
4444
///-------
4545
///
46+
/// An invalid transition kind. This must always be first so that it is zero.
47+
KIND(Invalid)
4648
/// An unknown kind.
4749
KIND(Unknown)
4850
/// An autorelease pool call.

lib/SILOptimizer/ARC/RCStateTransition.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_RCSTATETRANSITION_H
1414
#define SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_RCSTATETRANSITION_H
1515

16+
#include "swift/Basic/type_traits.h"
1617
#include "swift/Basic/ImmutablePointerSet.h"
1718
#include "swift/SIL/SILArgument.h"
1819
#include "swift/SIL/SILInstruction.h"
@@ -60,10 +61,14 @@ RCStateTransitionKind getRCStateTransitionKind(ValueBase *V);
6061
//===----------------------------------------------------------------------===//
6162

6263
class RefCountState;
64+
class BottomUpRefCountState;
65+
class TopDownRefCountState;
6366

6467
/// Represents a transition in the RC history of a ref count.
6568
class RCStateTransition {
6669
friend class RefCountState;
70+
friend class BottomUpRefCountState;
71+
friend class TopDownRefCountState;
6772

6873
/// An RCStateTransition can represent either an RC end point (i.e. an initial
6974
/// or terminal RC transition) or a ptr set of Mutators.
@@ -73,11 +78,11 @@ class RCStateTransition {
7378
RCStateTransitionKind Kind;
7479

7580
// Should only be constructed be default RefCountState.
76-
RCStateTransition() {}
81+
RCStateTransition() = default;
7782

7883
public:
79-
~RCStateTransition() {}
80-
RCStateTransition(const RCStateTransition &R);
84+
~RCStateTransition() = default;
85+
RCStateTransition(const RCStateTransition &R) = default;
8186

8287
RCStateTransition(ImmutablePointerSet<SILInstruction> *I) {
8388
assert(I->size() == 1);
@@ -132,8 +137,15 @@ class RCStateTransition {
132137
/// Attempt to merge \p Other into \p this. Returns true if we succeeded,
133138
/// false otherwise.
134139
bool merge(const RCStateTransition &Other);
140+
141+
/// Return true if the kind of this RCStateTransition is not 'Invalid'.
142+
bool isValid() const { return getKind() != RCStateTransitionKind::Invalid; }
135143
};
136144

145+
// These static assert checks are here for performance reasons.
146+
static_assert(IsTriviallyCopyable<RCStateTransition>::value,
147+
"RCStateTransitions must be trivially copyable");
148+
137149
} // end swift namespace
138150

139151
namespace llvm {

lib/SILOptimizer/ARC/RefCountState.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void BottomUpRefCountState::clear() {
124124
// be removed, be conservative and clear the transition state, so we do not
125125
// propagate KnownSafety forward.
126126
if (mightRemoveMutators())
127-
Transition = None;
127+
Transition = RCStateTransition();
128128
LatState = LatticeState::None;
129129
SuperTy::clear();
130130
}
@@ -261,13 +261,13 @@ bool BottomUpRefCountState::handleGuaranteedUser(
261261
bool BottomUpRefCountState::isRefCountInstMatchedToTrackedInstruction(
262262
SILInstruction *RefCountInst) {
263263
// If we are not tracking any state transitions bail.
264-
if (!Transition.hasValue())
264+
if (!Transition.isValid())
265265
return false;
266266

267267
// Otherwise, ask the transition state if this instruction causes a
268268
// transition that can be matched with the transition in order to eliminate
269269
// the transition.
270-
if (!Transition->matchingInst(RefCountInst))
270+
if (!Transition.matchingInst(RefCountInst))
271271
return false;
272272

273273
return handleRefCountInstMatch(RefCountInst);
@@ -328,8 +328,8 @@ bool BottomUpRefCountState::merge(const BottomUpRefCountState &Other) {
328328
return false;
329329
}
330330

331-
if (!Transition.hasValue() || !Other.Transition.hasValue() ||
332-
!Transition->merge(Other.Transition.getValue())) {
331+
if (!Transition.isValid() || !Other.Transition.isValid() ||
332+
!Transition.merge(Other.Transition)) {
333333
DEBUG(llvm::dbgs() << " Failed merge!\n");
334334
clear();
335335
return false;
@@ -568,7 +568,7 @@ bool TopDownRefCountState::initWithMutatorInst(
568568
void TopDownRefCountState::initWithArg(SILArgument *Arg) {
569569
LatState = LatticeState::Incremented;
570570
Transition = RCStateTransition(Arg);
571-
assert((*Transition).getKind() == RCStateTransitionKind::StrongEntrance &&
571+
assert(Transition.getKind() == RCStateTransitionKind::StrongEntrance &&
572572
"Expected a strong entrance here");
573573
RCRoot = Arg;
574574
KnownSafe = false;
@@ -581,7 +581,7 @@ void TopDownRefCountState::initWithEntranceInst(
581581
ImmutablePointerSet<SILInstruction> *I, SILValue RCIdentity) {
582582
LatState = LatticeState::Incremented;
583583
Transition = RCStateTransition(I);
584-
assert((*Transition).getKind() == RCStateTransitionKind::StrongEntrance &&
584+
assert(Transition.getKind() == RCStateTransitionKind::StrongEntrance &&
585585
"Expected a strong entrance here");
586586
RCRoot = RCIdentity;
587587
KnownSafe = false;
@@ -590,7 +590,7 @@ void TopDownRefCountState::initWithEntranceInst(
590590

591591
/// Uninitialize the current state.
592592
void TopDownRefCountState::clear() {
593-
Transition = None;
593+
Transition = RCStateTransition();
594594
LatState = LatticeState::None;
595595
SuperTy::clear();
596596
}
@@ -719,13 +719,13 @@ bool TopDownRefCountState::handleGuaranteedUser(
719719
bool TopDownRefCountState::isRefCountInstMatchedToTrackedInstruction(
720720
SILInstruction *RefCountInst) {
721721
// If we are not tracking any state transitions bail.
722-
if (!Transition.hasValue())
722+
if (!Transition.isValid())
723723
return false;
724724

725725
// Otherwise, ask the transition state if this instruction causes a
726726
// transition that can be matched with the transition in order to eliminate
727727
// the transition.
728-
if (!Transition->matchingInst(RefCountInst))
728+
if (!Transition.matchingInst(RefCountInst))
729729
return false;
730730

731731
return handleRefCountInstMatch(RefCountInst);
@@ -783,8 +783,8 @@ bool TopDownRefCountState::merge(const TopDownRefCountState &Other) {
783783
return false;
784784
}
785785

786-
if (!Transition.hasValue() || !Other.Transition.hasValue() ||
787-
!Transition->merge(Other.Transition.getValue())) {
786+
if (!Transition.isValid() || !Other.Transition.isValid() ||
787+
!Transition.merge(Other.Transition)) {
788788
DEBUG(llvm::dbgs() << " Failed merge!\n");
789789
clear();
790790
return false;

lib/SILOptimizer/ARC/RefCountState.h

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_REFCOUNTSTATE_H
1515

1616
#include "RCStateTransition.h"
17+
#include "swift/Basic/type_traits.h"
1718
#include "swift/Basic/Fallthrough.h"
1819
#include "swift/Basic/ImmutablePointerSet.h"
1920
#include "swift/SIL/SILInstruction.h"
@@ -22,7 +23,6 @@
2223
#include "swift/SIL/InstructionUtils.h"
2324
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
2425
#include <algorithm>
25-
#include <type_traits>
2626

2727
namespace swift {
2828
class AliasAnalysis;
@@ -37,17 +37,14 @@ namespace swift {
3737
/// A struct that abstracts over reference counts manipulated by strong_retain,
3838
/// retain_value, strong_release,
3939
class RefCountState {
40-
public:
41-
using InstructionSet = llvm::SmallPtrSet<SILInstruction *, 1>;
42-
4340
protected:
4441
/// Return the SILValue that represents the RCRoot that we are
4542
/// tracking.
4643
SILValue RCRoot;
4744

4845
/// The last state transition that this RefCountState went through. None if we
4946
/// have not see any transition on this ref count yet.
50-
llvm::Optional<RCStateTransition> Transition;
47+
RCStateTransition Transition;
5148

5249
/// Was the pointer we are tracking known incremented when we visited the
5350
/// current increment we are tracking? In that case we know that it is safe
@@ -67,8 +64,8 @@ class RefCountState {
6764
bool Partial = false;
6865

6966
public:
70-
RefCountState() {}
71-
~RefCountState() {}
67+
RefCountState() = default;
68+
~RefCountState() = default;
7269
RefCountState(const RefCountState &) = default;
7370
RefCountState &operator=(const RefCountState &) = default;
7471
RefCountState(RefCountState &&) = default;
@@ -83,7 +80,7 @@ class RefCountState {
8380
bool Nested = isTrackingRefCount();
8481

8582
Transition = RCStateTransition(I);
86-
assert((*Transition).isMutator() && "Expected I to be a mutator!\n");
83+
assert(Transition.isMutator() && "Expected I to be a mutator!\n");
8784

8885
// Initialize KnownSafe to a conservative false value.
8986
KnownSafe = false;
@@ -105,31 +102,29 @@ class RefCountState {
105102
}
106103

107104
/// Is this ref count initialized and tracking a ref count ptr.
108-
bool isTrackingRefCount() const {
109-
return Transition.hasValue();
110-
}
105+
bool isTrackingRefCount() const { return Transition.isValid(); }
111106

112107
/// Are we tracking an instruction currently? This returns false when given an
113108
/// uninitialized ReferenceCountState.
114109
bool isTrackingRefCountInst() const {
115-
return Transition.hasValue() && Transition->isMutator();
110+
return Transition.isValid() && Transition.isMutator();
116111
}
117112

118113
/// Are we tracking a source of ref counts? This currently means that we are
119114
/// tracking an argument that is @owned. In the future this will include
120115
/// return values of functions that are @owned.
121116
bool isTrackingRefCountSource() const {
122-
return Transition.hasValue() && Transition->isEndPoint();
117+
return Transition.isValid() && Transition.isEndPoint();
123118
}
124119

125120
/// Return the increment we are tracking.
126121
RCStateTransition::mutator_range getInstructions() const {
127-
return Transition->getMutators();
122+
return Transition.getMutators();
128123
}
129124

130125
/// Returns true if I is in the instructions we are tracking.
131126
bool containsInstruction(SILInstruction *I) const {
132-
return Transition.hasValue() && Transition->containsMutator(I);
127+
return Transition.isValid() && Transition.containsMutator(I);
133128
}
134129

135130
/// Return the value with reference semantics that is the operand of our
@@ -200,7 +195,8 @@ class BottomUpRefCountState : public RefCountState {
200195
bool FoundNonARCUser = false;
201196

202197
public:
203-
BottomUpRefCountState() {}
198+
BottomUpRefCountState() = default;
199+
~BottomUpRefCountState() = default;
204200
BottomUpRefCountState(const BottomUpRefCountState &) = default;
205201
BottomUpRefCountState &operator=(const BottomUpRefCountState &) = default;
206202
BottomUpRefCountState(BottomUpRefCountState &&) = default;
@@ -344,7 +340,8 @@ class TopDownRefCountState : public RefCountState {
344340
LatticeState LatState = LatticeState::None;
345341

346342
public:
347-
TopDownRefCountState() {}
343+
TopDownRefCountState() = default;
344+
~TopDownRefCountState() = default;
348345
TopDownRefCountState(const TopDownRefCountState &) = default;
349346
TopDownRefCountState &operator=(const TopDownRefCountState &) = default;
350347
TopDownRefCountState(TopDownRefCountState &&) = default;
@@ -454,6 +451,12 @@ class TopDownRefCountState : public RefCountState {
454451
bool handleRefCountInstMatch(SILInstruction *RefCountInst);
455452
};
456453

454+
// These static asserts are here for performance reasons.
455+
static_assert(IsTriviallyCopyable<BottomUpRefCountState>::value,
456+
"All ref count states must be trivially copyable");
457+
static_assert(IsTriviallyCopyable<TopDownRefCountState>::value,
458+
"All ref count states must be trivially copyable");
459+
457460
} // end swift namespace
458461

459462
namespace llvm {

0 commit comments

Comments
 (0)