[Bug c++/100224] incorrect result when doing double vectorized

2021-04-23 Thread zhaoc at apache dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100224

--- Comment #2 from Zhao Chun  ---
(In reply to Richard Biener from comment #1)
> You are accessing 'double' via a pointer to uint64_t * here:
> 
> k = *((uint64_t*)data);
> 
> that violates type based aliasing rules.  You can use -fno-strict-aliasing
> to work around your bug or use
> 
> typedef uint64_t aliasing_uint64_t __attribute__((may_alias));
> k = *((aliasing_uint64_t*)data);

Thanks for your answer, it works for me.

However I don't quite understand why it works after such a change. Could you
please explain it more clearly?

[Bug c++/100224] New: incorrect result when doing double vectorized

2021-04-22 Thread zhaoc at apache dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100224

Bug ID: 100224
   Summary: incorrect result when doing double vectorized
   Product: gcc
   Version: 10.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: zhaoc at apache dot org
  Target Milestone: ---

When I use O3 to compile a code, I got an unexpected result.

test_murmur.cc

#include 
#include 
#include 

static const uint64_t MURMUR_PRIME = 0xc6a4a7935bd1e995ULL;
static const uint32_t MURMUR_SEED = 0xadc83b19ULL;

// Our hash function is MurmurHash2, 64 bit version.
// It was modified in order to provide the same result in
// big and little endian archs (endian neutral).
static uint64_t murmur_hash64A (const void* key, int32_t len, unsigned int
seed) {
const uint64_t m = MURMUR_PRIME;
const int r = 47;
uint64_t h = seed ^ (len * m);
const uint8_t *data = (const uint8_t *)key;
const uint8_t *end = data + (len-(len&7));

while(data != end) {
uint64_t k;
k = *((uint64_t*)data);

k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
data += 8;
}

switch(len & 7) {
case 7: h ^= (uint64_t)data[6] << 48;
case 6: h ^= (uint64_t)data[5] << 40;
case 5: h ^= (uint64_t)data[4] << 32;
case 4: h ^= (uint64_t)data[3] << 24;
case 3: h ^= (uint64_t)data[2] << 16;
case 2: h ^= (uint64_t)data[1] << 8;
case 1: h ^= (uint64_t)data[0];
h *= m;
};

h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}

void update_double(const std::vector& values, std::vector&
hashes) {
auto size = values.size();
for (int i = 0; i < size; ++i) {
auto v = values[i];
uint64_t value = murmur_hash64A(, sizeof(v), MURMUR_SEED);
hashes[i] = value;
}
}

int main() {
std::vector values(3);
std::vector hashes(3);

for (int i = 0; i < 3; ++i) {
values[i] = i + 1;
}
update_double(values, hashes);
for (auto hash : hashes) {
std::cout << hash << std::endl;
}
return 0;
}

gcc-10.3.0/bin/g++  -std=gnu++17  -O3 -msse4.2 -mavx2 test_murmur.cc

output

4138674677912027985
4138674677912027985
4138674677912027985

When I used option O2 to compile this file,

gcc-10.3.0/bin/g++  -std=gnu++17  -O2 -msse4.2 -mavx2 test_murmur.cc

the output is following which is expected:

17614482930881034518
9674455539515676295
16429943614018478328

It seems something wrong when GCC generating optimized code for 'double'.