-CpCOREAVX2 is scared of reinterpret-casting ‘result’ on x86-32
Original Reporter info from Mantis: runewalsh
-
Reporter name:
Original Reporter info from Mantis: runewalsh
- Reporter name:
Description:
Code in ‘Steps to reproduce’ gives wrong result on i386-win32 with -CpCOREAVX2 and -O2 or higher.
Expected: 45 23 1
Actual: 45 123 0
The code itself does the following.
Imagine a W×H grid. We can number its cells in row-major order as PackPoint2D(x, y) = y×W + x and define an inverse operation, UnpackPoint2D(pid) = {x = pid % W, y = pid / W}.
Three-dimensional counterpart is W×H×D grid.
UnpackPoint3D(pid) unpacks Z = pid / (W×H) and, for the simplicity, delegates the rest of work (unpacking X and Y) to UnpackPoint2D(pid % (W×H)).
Although it's not nice to reinterpret_cast 3D vector as 2D that way, this ought to work neverthless, right? At least this is not an excuse for “uint64 mod 100” to give 123.
With size=100×100×100, point (XX, YY, ZZ) gets packed into decimal value ZZYYXX and vice versa. Thus, Unpack(12345) should give (45, 23, 1).
Steps to reproduce:
type
FlatIndex = uint64;
UintVec2 = array[0 .. 1] of uint32; PUintVec2 = ^UintVec2;
UintVec3 = array[0 .. 2] of uint32; PUintVec3 = ^UintVec3;
function UnpackPoint(index: FlatIndex; const size: UintVec2): UintVec2;
var
q: FlatIndex;
begin
q := index div size[0];
result[1] := q;
result[0] := index - q * size[0];
end;
function UnpackPoint(index: FlatIndex; const size: UintVec3): UintVec3;
var
d, q: FlatIndex;
begin
d := FlatIndex(size[1]) * size[0];
q := index div d;
result[2] := q;
PUintVec2(@result)^ := UnpackPoint(index - q * d, PUintVec2(@size)^);
end;
var
v, sz: UintVec3;
begin
sz[0] := 100;
sz[1] := 100;
sz[2] := 100;
v := UnpackPoint(12345, sz);
writeln('Expected: 45 23 1');
writeln('Actual: ', v[0], ' ', v[1], ' ', v[2]);
end.
Mantis conversion info:
- Mantis ID: 38533
- Build: r48765 [2021/02/22]
- Platform: i386-win32
- Version: 3.3.1
- Fixed in version: 3.3.1
- Fixed in revision: 48791 (#cefa05c8)