This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug tree-optimization/82776] New: Unable to optimize the loop when iteration count is unavailable.


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);
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]