Skip to content

Commit 898db79

Browse files
committed
improve performance of span_iterator w/ clang
Issue: microsoft#1165 Before this PR, the range-for loop was ~3300x slower. After this PR, it is ~1.005x slower The clang optimizer is very good at optimizing `current != end`, so we changed to this idiom. This moves the Expects assertion into the constructor instead of on the hot-path which is called whenever either operator++ or operator* is called. Note: The codegen for the assertion is still a missed optimization, but less worrisome as it only happens once per iterator. Note: benchmarks on M1 Macbook Pro w/ Apple Clang 16.0.0
1 parent 87f9d76 commit 898db79

File tree

1 file changed

+8
-11
lines changed

1 file changed

+8
-11
lines changed

include/gsl/span

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ namespace details
140140

141141
constexpr span_iterator(pointer begin, pointer end, pointer current)
142142
: begin_(begin), end_(end), current_(current)
143-
{}
143+
{
144+
Expects(begin && current && end);
145+
Expects(begin <= current && current <= end);
146+
}
144147

145148
constexpr operator span_iterator<const Type>() const noexcept
146149
{
@@ -149,21 +152,18 @@ namespace details
149152

150153
constexpr reference operator*() const noexcept
151154
{
152-
Expects(begin_ && end_);
153-
Expects(begin_ <= current_ && current_ < end_);
155+
Expects(current_ != end_);
154156
return *current_;
155157
}
156158

157159
constexpr pointer operator->() const noexcept
158160
{
159-
Expects(begin_ && end_);
160-
Expects(begin_ <= current_ && current_ < end_);
161+
Expects(current_ != end_);
161162
return current_;
162163
}
163164
constexpr span_iterator& operator++() noexcept
164165
{
165-
Expects(begin_ && current_ && end_);
166-
Expects(current_ < end_);
166+
Expects(current_ != end_);
167167
// clang-format off
168168
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
169169
// clang-format on
@@ -180,8 +180,7 @@ namespace details
180180

181181
constexpr span_iterator& operator--() noexcept
182182
{
183-
Expects(begin_ && end_);
184-
Expects(begin_ < current_);
183+
Expects(begin != current_);
185184
--current_;
186185
return *this;
187186
}
@@ -195,7 +194,6 @@ namespace details
195194

196195
constexpr span_iterator& operator+=(const difference_type n) noexcept
197196
{
198-
if (n != 0) Expects(begin_ && current_ && end_);
199197
if (n > 0) Expects(end_ - current_ >= n);
200198
if (n < 0) Expects(current_ - begin_ >= -n);
201199
// clang-format off
@@ -220,7 +218,6 @@ namespace details
220218

221219
constexpr span_iterator& operator-=(const difference_type n) noexcept
222220
{
223-
if (n != 0) Expects(begin_ && current_ && end_);
224221
if (n > 0) Expects(current_ - begin_ >= n);
225222
if (n < 0) Expects(end_ - current_ >= -n);
226223
GSL_SUPPRESS(bounds .1)

0 commit comments

Comments
 (0)