Skip to content

Min/max intrinsics generate wrong code with absolute addressing on x86-64/win64.

Compile this program for x86-64/win64 with -O2+.

{$mode objfpc}
var
	value: SizeUint;

procedure Proc;
var
	x: SizeUint;
begin
	x := random(0);
	if x >= value then value := x; // (!)
end;

begin
	value := 5;
	Proc;
	writeln('Must be 5: ', value);
end.

Line marked with (!) generates the following assembly, where the (!!!) part is obviously wrong because two instructions down the same variable is addressed RIP-relatively:

; if x >= value then value := x; // (!)
mov     rdx, rax ; rdx = rax = x
cmp     [$00014010], rax ; value <= x (!!!)
cmovnbe rdx, [rip+$00012A1F] ; rdx = max(x, value)
mov     [rip+$00012A18], rdx ; value := rdx

For me: the program as is compares x to the arbitrary but readable memory location and gives wrong result (Must be 5: 0), adding uses SysUtils makes it crash instead.

Edited by Rika
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information