https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88998

            Bug ID: 88998
           Summary: bad codegen with mmx instructions for unordered_map
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

This program should be valid:

#include <cassert>
#include <unordered_map>
#include <x86intrin.h>

[[gnu::noinline]]
double prepare(int a, int b)
{
    __m128i is = _mm_setr_epi32(a, b, 0, 0);
    __m128d ds =_mm_cvtepi32_pd(is);
    return ds[0] + ds[1];
}

int main(int, char**) {
    double d = prepare(1, 2);

    std::unordered_map<int, int> m;
    m.insert({0, 0});
    m.insert({1, 1});
    assert(m.load_factor() <= m.max_load_factor());

    return d;
}


But if I use MMX instructions, the assertion triggers:

$ g++ -std=c++11 -march=haswell -mtune=haswell -mavx -O3 foo.cxx && ./a.out
a.out: foo.cxx:19: int main(int, char**): Assertion `m.load_factor() <=
m.max_load_factor()' failed.
Aborted (core dumped)

Whereas it does not if I explicitly remove them:

$ g++ -std=c++11 -march=haswell -mtune=haswell -mavx -mno-mmx -O3 foo.cxx &&
./a.out
$ 

Additionally, adding a call to _mm_empty() right before the return statement in
prepare() fixes the issue. 

If you look at the load_factor(), it returns 2 (and then 3 on the next insert,
etc.)

Reply via email to