Optimize btree_iterator increment/decrement to avoid aliasing issues by using local variables instead of repeatedly writing to `this`. Also update the benchmark to use DoNotOptimize to make sure the iterators are actually materialized. PiperOrigin-RevId: 736229349 Change-Id: I7422544398210a48a7a40d81d341fd4beaf71861
diff --git a/absl/container/btree_benchmark.cc b/absl/container/btree_benchmark.cc index d0dac37..b1525bd 100644 --- a/absl/container/btree_benchmark.cc +++ b/absl/container/btree_benchmark.cc
@@ -406,22 +406,18 @@ template <typename T> void BM_FwdIter(benchmark::State& state) { using V = typename remove_pair_const<typename T::value_type>::type; - using R = typename T::value_type const*; std::vector<V> values = GenerateValues<V>(kBenchmarkValues); T container(values.begin(), values.end()); auto iter = container.end(); - R r = nullptr; - while (state.KeepRunning()) { if (iter == container.end()) iter = container.begin(); - r = &(*iter); - ++iter; + auto *v = &(*iter); + benchmark::DoNotOptimize(v); + benchmark::DoNotOptimize(++iter); } - - benchmark::DoNotOptimize(r); } // Benchmark random range-construction of a container.
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index a742829..bed6be1 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h
@@ -2151,50 +2151,54 @@ template <typename N, typename R, typename P> void btree_iterator<N, R, P>::increment_slow() { - if (node_->is_leaf()) { - assert(position_ >= node_->finish()); - btree_iterator save(*this); - while (position_ == node_->finish() && !node_->is_root()) { - assert(node_->parent()->child(node_->position()) == node_); - position_ = node_->position(); - node_ = node_->parent(); + N* node = node_; + int position = position_; + if (node->is_leaf()) { + assert(position >= node->finish()); + while (position == node->finish() && !node->is_root()) { + assert(node->parent()->child(node->position()) == node); + position = node->position(); + node = node->parent(); } // TODO(ezb): assert we aren't incrementing end() instead of handling. - if (position_ == node_->finish()) { - *this = save; + if (position == node->finish()) { + return; } } else { - assert(position_ < node_->finish()); - node_ = node_->child(static_cast<field_type>(position_ + 1)); - while (node_->is_internal()) { - node_ = node_->start_child(); + assert(position < node->finish()); + node = node->child(static_cast<field_type>(position + 1)); + while (node->is_internal()) { + node = node->start_child(); } - position_ = node_->start(); + position = node->start(); } + *this = {node, position}; } template <typename N, typename R, typename P> void btree_iterator<N, R, P>::decrement_slow() { - if (node_->is_leaf()) { - assert(position_ <= -1); - btree_iterator save(*this); - while (position_ < node_->start() && !node_->is_root()) { - assert(node_->parent()->child(node_->position()) == node_); - position_ = node_->position() - 1; - node_ = node_->parent(); + N* node = node_; + int position = position_; + if (node->is_leaf()) { + assert(position <= -1); + while (position < node->start() && !node->is_root()) { + assert(node->parent()->child(node->position()) == node); + position = node->position() - 1; + node = node->parent(); } // TODO(ezb): assert we aren't decrementing begin() instead of handling. - if (position_ < node_->start()) { - *this = save; + if (position < node->start()) { + return; } } else { - assert(position_ >= node_->start()); - node_ = node_->child(static_cast<field_type>(position_)); - while (node_->is_internal()) { - node_ = node_->child(node_->finish()); + assert(position >= node->start()); + node = node->child(static_cast<field_type>(position)); + while (node->is_internal()) { + node = node->child(node->finish()); } - position_ = node_->finish() - 1; + position = node->finish() - 1; } + *this = {node, position}; } template <typename N, typename R, typename P>