Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 5e8da17

Browse files
committed
Mark internal classes as POD-like to get better behavior out of
SmallVector and DenseMap. This speeds up SROA by 25% on PR15412. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177259 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 2ee4e42 commit 5e8da17

File tree

1 file changed

+109
-102
lines changed

1 file changed

+109
-102
lines changed

lib/Transforms/Scalar/SROA.cpp

Lines changed: 109 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -69,123 +69,130 @@ static cl::opt<bool>
6969
ForceSSAUpdater("force-ssa-updater", cl::init(false), cl::Hidden);
7070

7171
namespace {
72-
/// \brief Alloca partitioning representation.
73-
///
74-
/// This class represents a partitioning of an alloca into slices, and
75-
/// information about the nature of uses of each slice of the alloca. The goal
76-
/// is that this information is sufficient to decide if and how to split the
77-
/// alloca apart and replace slices with scalars. It is also intended that this
78-
/// structure can capture the relevant information needed both to decide about
79-
/// and to enact these transformations.
80-
class AllocaPartitioning {
81-
public:
82-
/// \brief A common base class for representing a half-open byte range.
83-
struct ByteRange {
84-
/// \brief The beginning offset of the range.
85-
uint64_t BeginOffset;
72+
/// \brief A common base class for representing a half-open byte range.
73+
struct ByteRange {
74+
/// \brief The beginning offset of the range.
75+
uint64_t BeginOffset;
8676

87-
/// \brief The ending offset, not included in the range.
88-
uint64_t EndOffset;
77+
/// \brief The ending offset, not included in the range.
78+
uint64_t EndOffset;
8979

90-
ByteRange() : BeginOffset(), EndOffset() {}
91-
ByteRange(uint64_t BeginOffset, uint64_t EndOffset)
92-
: BeginOffset(BeginOffset), EndOffset(EndOffset) {}
80+
ByteRange() : BeginOffset(), EndOffset() {}
81+
ByteRange(uint64_t BeginOffset, uint64_t EndOffset)
82+
: BeginOffset(BeginOffset), EndOffset(EndOffset) {}
9383

94-
/// \brief Support for ordering ranges.
95-
///
96-
/// This provides an ordering over ranges such that start offsets are
97-
/// always increasing, and within equal start offsets, the end offsets are
98-
/// decreasing. Thus the spanning range comes first in a cluster with the
99-
/// same start position.
100-
bool operator<(const ByteRange &RHS) const {
101-
if (BeginOffset < RHS.BeginOffset) return true;
102-
if (BeginOffset > RHS.BeginOffset) return false;
103-
if (EndOffset > RHS.EndOffset) return true;
104-
return false;
105-
}
84+
/// \brief Support for ordering ranges.
85+
///
86+
/// This provides an ordering over ranges such that start offsets are
87+
/// always increasing, and within equal start offsets, the end offsets are
88+
/// decreasing. Thus the spanning range comes first in a cluster with the
89+
/// same start position.
90+
bool operator<(const ByteRange &RHS) const {
91+
if (BeginOffset < RHS.BeginOffset) return true;
92+
if (BeginOffset > RHS.BeginOffset) return false;
93+
if (EndOffset > RHS.EndOffset) return true;
94+
return false;
95+
}
10696

107-
/// \brief Support comparison with a single offset to allow binary searches.
108-
friend bool operator<(const ByteRange &LHS, uint64_t RHSOffset) {
109-
return LHS.BeginOffset < RHSOffset;
110-
}
97+
/// \brief Support comparison with a single offset to allow binary searches.
98+
friend bool operator<(const ByteRange &LHS, uint64_t RHSOffset) {
99+
return LHS.BeginOffset < RHSOffset;
100+
}
111101

112-
friend LLVM_ATTRIBUTE_UNUSED bool operator<(uint64_t LHSOffset,
113-
const ByteRange &RHS) {
114-
return LHSOffset < RHS.BeginOffset;
115-
}
102+
friend LLVM_ATTRIBUTE_UNUSED bool operator<(uint64_t LHSOffset,
103+
const ByteRange &RHS) {
104+
return LHSOffset < RHS.BeginOffset;
105+
}
116106

117-
bool operator==(const ByteRange &RHS) const {
118-
return BeginOffset == RHS.BeginOffset && EndOffset == RHS.EndOffset;
119-
}
120-
bool operator!=(const ByteRange &RHS) const { return !operator==(RHS); }
121-
};
107+
bool operator==(const ByteRange &RHS) const {
108+
return BeginOffset == RHS.BeginOffset && EndOffset == RHS.EndOffset;
109+
}
110+
bool operator!=(const ByteRange &RHS) const { return !operator==(RHS); }
111+
};
122112

123-
/// \brief A partition of an alloca.
113+
/// \brief A partition of an alloca.
114+
///
115+
/// This structure represents a contiguous partition of the alloca. These are
116+
/// formed by examining the uses of the alloca. During formation, they may
117+
/// overlap but once an AllocaPartitioning is built, the Partitions within it
118+
/// are all disjoint.
119+
struct Partition : public ByteRange {
120+
/// \brief Whether this partition is splittable into smaller partitions.
124121
///
125-
/// This structure represents a contiguous partition of the alloca. These are
126-
/// formed by examining the uses of the alloca. During formation, they may
127-
/// overlap but once an AllocaPartitioning is built, the Partitions within it
128-
/// are all disjoint.
129-
struct Partition : public ByteRange {
130-
/// \brief Whether this partition is splittable into smaller partitions.
131-
///
132-
/// We flag partitions as splittable when they are formed entirely due to
133-
/// accesses by trivially splittable operations such as memset and memcpy.
134-
bool IsSplittable;
135-
136-
/// \brief Test whether a partition has been marked as dead.
137-
bool isDead() const {
138-
if (BeginOffset == UINT64_MAX) {
139-
assert(EndOffset == UINT64_MAX);
140-
return true;
141-
}
142-
return false;
122+
/// We flag partitions as splittable when they are formed entirely due to
123+
/// accesses by trivially splittable operations such as memset and memcpy.
124+
bool IsSplittable;
125+
126+
/// \brief Test whether a partition has been marked as dead.
127+
bool isDead() const {
128+
if (BeginOffset == UINT64_MAX) {
129+
assert(EndOffset == UINT64_MAX);
130+
return true;
143131
}
132+
return false;
133+
}
144134

145-
/// \brief Kill a partition.
146-
/// This is accomplished by setting both its beginning and end offset to
147-
/// the maximum possible value.
148-
void kill() {
149-
assert(!isDead() && "He's Dead, Jim!");
150-
BeginOffset = EndOffset = UINT64_MAX;
151-
}
135+
/// \brief Kill a partition.
136+
/// This is accomplished by setting both its beginning and end offset to
137+
/// the maximum possible value.
138+
void kill() {
139+
assert(!isDead() && "He's Dead, Jim!");
140+
BeginOffset = EndOffset = UINT64_MAX;
141+
}
152142

153-
Partition() : ByteRange(), IsSplittable() {}
154-
Partition(uint64_t BeginOffset, uint64_t EndOffset, bool IsSplittable)
155-
: ByteRange(BeginOffset, EndOffset), IsSplittable(IsSplittable) {}
156-
};
143+
Partition() : ByteRange(), IsSplittable() {}
144+
Partition(uint64_t BeginOffset, uint64_t EndOffset, bool IsSplittable)
145+
: ByteRange(BeginOffset, EndOffset), IsSplittable(IsSplittable) {}
146+
};
157147

158-
/// \brief A particular use of a partition of the alloca.
159-
///
160-
/// This structure is used to associate uses of a partition with it. They
161-
/// mark the range of bytes which are referenced by a particular instruction,
162-
/// and includes a handle to the user itself and the pointer value in use.
163-
/// The bounds of these uses are determined by intersecting the bounds of the
164-
/// memory use itself with a particular partition. As a consequence there is
165-
/// intentionally overlap between various uses of the same partition.
166-
class PartitionUse : public ByteRange {
167-
/// \brief Combined storage for both the Use* and split state.
168-
PointerIntPair<Use*, 1, bool> UsePtrAndIsSplit;
148+
/// \brief A particular use of a partition of the alloca.
149+
///
150+
/// This structure is used to associate uses of a partition with it. They
151+
/// mark the range of bytes which are referenced by a particular instruction,
152+
/// and includes a handle to the user itself and the pointer value in use.
153+
/// The bounds of these uses are determined by intersecting the bounds of the
154+
/// memory use itself with a particular partition. As a consequence there is
155+
/// intentionally overlap between various uses of the same partition.
156+
class PartitionUse : public ByteRange {
157+
/// \brief Combined storage for both the Use* and split state.
158+
PointerIntPair<Use*, 1, bool> UsePtrAndIsSplit;
169159

170-
public:
171-
PartitionUse() : ByteRange(), UsePtrAndIsSplit() {}
172-
PartitionUse(uint64_t BeginOffset, uint64_t EndOffset, Use *U,
173-
bool IsSplit)
174-
: ByteRange(BeginOffset, EndOffset), UsePtrAndIsSplit(U, IsSplit) {}
160+
public:
161+
PartitionUse() : ByteRange(), UsePtrAndIsSplit() {}
162+
PartitionUse(uint64_t BeginOffset, uint64_t EndOffset, Use *U,
163+
bool IsSplit)
164+
: ByteRange(BeginOffset, EndOffset), UsePtrAndIsSplit(U, IsSplit) {}
175165

176-
/// \brief The use in question. Provides access to both user and used value.
177-
///
178-
/// Note that this may be null if the partition use is *dead*, that is, it
179-
/// should be ignored.
180-
Use *getUse() const { return UsePtrAndIsSplit.getPointer(); }
166+
/// \brief The use in question. Provides access to both user and used value.
167+
///
168+
/// Note that this may be null if the partition use is *dead*, that is, it
169+
/// should be ignored.
170+
Use *getUse() const { return UsePtrAndIsSplit.getPointer(); }
181171

182-
/// \brief Set the use for this partition use range.
183-
void setUse(Use *U) { UsePtrAndIsSplit.setPointer(U); }
172+
/// \brief Set the use for this partition use range.
173+
void setUse(Use *U) { UsePtrAndIsSplit.setPointer(U); }
184174

185-
/// \brief Whether this use is split across multiple partitions.
186-
bool isSplit() const { return UsePtrAndIsSplit.getInt(); }
187-
};
175+
/// \brief Whether this use is split across multiple partitions.
176+
bool isSplit() const { return UsePtrAndIsSplit.getInt(); }
177+
};
178+
}
179+
180+
namespace llvm {
181+
template <> struct isPodLike<Partition> : llvm::true_type {};
182+
template <> struct isPodLike<PartitionUse> : llvm::true_type {};
183+
}
188184

185+
namespace {
186+
/// \brief Alloca partitioning representation.
187+
///
188+
/// This class represents a partitioning of an alloca into slices, and
189+
/// information about the nature of uses of each slice of the alloca. The goal
190+
/// is that this information is sufficient to decide if and how to split the
191+
/// alloca apart and replace slices with scalars. It is also intended that this
192+
/// structure can capture the relevant information needed both to decide about
193+
/// and to enact these transformations.
194+
class AllocaPartitioning {
195+
public:
189196
/// \brief Construct a partitioning of a particular alloca.
190197
///
191198
/// Construction does most of the work for partitioning the alloca. This
@@ -1389,7 +1396,7 @@ class PHIOrSelectSpeculator : public InstVisitor<PHIOrSelectSpeculator> {
13891396
// may be grown during speculation. However, we never need to re-visit the
13901397
// new uses, and so we can use the initial size bound.
13911398
for (unsigned Idx = 0, Size = P.use_size(PI); Idx != Size; ++Idx) {
1392-
const AllocaPartitioning::PartitionUse &PU = P.getUse(PI, Idx);
1399+
const PartitionUse &PU = P.getUse(PI, Idx);
13931400
if (!PU.getUse())
13941401
continue; // Skip dead use.
13951402

@@ -1594,7 +1601,7 @@ class PHIOrSelectSpeculator : public InstVisitor<PHIOrSelectSpeculator> {
15941601
IRBuilder<> IRB(&SI);
15951602
Use *Ops[2] = { &SI.getOperandUse(1), &SI.getOperandUse(2) };
15961603
AllocaPartitioning::iterator PIs[2];
1597-
AllocaPartitioning::PartitionUse PUs[2];
1604+
PartitionUse PUs[2];
15981605
for (unsigned i = 0, e = 2; i != e; ++i) {
15991606
PIs[i] = P.findPartitionForPHIOrSelectOperand(Ops[i]);
16001607
if (PIs[i] != P.end()) {

0 commit comments

Comments
 (0)