https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82776
Bug ID: 82776 Summary: Unable to optimize the loop when iteration count is unavailable. Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: hiraditya at msn dot com Target Milestone: --- Compiling with g++ -O2 --std=c++14 -msse4 -DENABLE_FORLOOP vs. g++ -O2 --std=c++14 -msse4 gives dramatically different results in the sense that the loop is completely optimized when for-loop is present instead of `while(true)` loop. Reproduces with g++-7.2 and g++-trunk. $ cat test.cpp #include <type_traits> #include <cstdint> #include <emmintrin.h> #include <vector> #include <cstdlib> #include <array> #include <memory> struct Chunk { std::array<uint8_t,14> tags_; uint8_t control_; bool eof() const { return (control_ & 1) != 0; } static constexpr unsigned kFullMask = (1 << 14) - 1; __m128i const* tagVector() const { return static_cast<__m128i const*>(static_cast<void const*>(&tags_[0])); } unsigned emptyMask() const { auto tagV = _mm_load_si128(tagVector()); auto emptyTagV = _mm_cmpeq_epi8(tagV, _mm_setzero_si128()); return _mm_movemask_epi8(emptyTagV) & kFullMask; } unsigned occupiedMask() const { return emptyMask() ^ kFullMask; } }; #define LIKELY(x) __builtin_expect((x), true) #define UNLIKELY(x) __builtin_expect((x), false) struct Iter { Chunk* chunk_; std::size_t index_; void advance() { // common case is packed entries while (index_ > 0) { --index_; if (LIKELY(chunk_->tags_[index_] != 0)) { return; } } // bar only skips the work of advance() if this loop can // be guaranteed to terminate #ifdef ENABLE_FORLOOP for (std::size_t i = 1; i != 0; ++i) { #else while (true) { #endif // exhausted the current chunk if (chunk_->eof()) { chunk_ = nullptr; break; } ++chunk_; auto m = chunk_->occupiedMask(); if (m != 0) { index_ = 31 - __builtin_clz(m); break; } } } }; static Iter foo(Iter iter) { puts("hello"); iter.advance(); return iter; } void bar(Iter iter) { foo(iter); }