This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug tree-optimization/82776] New: Unable to optimize the loop when iteration count is unavailable.
- From: "hiraditya at msn dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 31 Oct 2017 00:55:29 +0000
- Subject: [Bug tree-optimization/82776] New: Unable to optimize the loop when iteration count is unavailable.
- Auto-submitted: auto-generated
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);
}