O'Neill'in PCG PRNG'sini uygularken GCC'de bir hata bulduğuma inanıyorum. ( Godbolt'un Derleyici Gezgini'nde başlangıç kodu )
Çarparak sonra oldstate
göre MULTIPLIER
(RDI saklanan sonuç), GCC ile bu sonucu eklemez INCREMENT
movabs'ing, INCREMENT
daha sonra rand32_ret.state dönüş değeri olarak kullanılan alır, bunun yerine, RDX'e
Minimum tekrarlanabilir örnek ( Derleyici Gezgini ):
#include <stdint.h>
struct retstruct {
uint32_t a;
uint64_t b;
};
struct retstruct fn(uint64_t input)
{
struct retstruct ret;
ret.a = 0;
ret.b = input * 11111111111 + 111111111111;
return ret;
}
Oluşturulan montaj (GCC 9.2, x86_64, -O3):
fn:
movabs rdx, 11111111111 # multiplier constant (doesn't fit in imm32)
xor eax, eax # ret.a = 0
imul rdi, rdx
movabs rdx, 111111111111 # add constant; one more 1 than multiplier
# missing add rdx, rdi # ret.b=... that we get with clang or older gcc
ret
# returns RDX:RAX = constant 111111111111 : 0
# independent of input RDI, and not using the imul result it just computed
İlk eleman olarak İlginçtir, yapı değiştirerek uint64_t olması doğru kodu üretir yaptığı gibi, uint64_t olmak hem üyelerini değişen
x86-64 System V, önemsiz bir şekilde kopyalanabildiklerinde RDX: RAX'ta 16 bayttan küçük yapıları döndürür. Bu durumda 2. üye RDX'tedir, çünkü RAX'in yüksek yarısı hizalama veya.b
zaman .a
daha dar bir türüdür. ( sizeof(retstruct)
her iki durumda da 16'dır; kullanmıyoruz, __attribute__((packed))
bu yüzden alignof'a saygı duyuyor (uint64_t) = 8.)
Bu kod, GCC'nin "yanlış" derleme vermesine izin verecek tanımlanmamış bir davranış içeriyor mu?
Değilse, bu https://gcc.gnu.org/bugzilla/ adresinde bildirilmelidir.