There is a bug in Delphi 2006 if activating both overflow checking and optimization. The bug seems to appear only in the particular situation where a 32 bit integer is added to itself, and then a byte is added to this previous sum, in this particular order, as seen on below program.
program OptimizationBug;
{$OPTIMIZATION ON}
{$APPTYPE CONSOLE}
{$OVERFLOWCHECKS ON}
function f: integer;
var i: integer;
b: byte;
begin
i:=0;
b:=1;
Result:=i+i+b;
end;
{$OVERFLOWCHECKS OFF}
function g: integer;
var i: integer;
b: byte;
begin
i:=0;
b:=1;
Result:=i+i+b;
end;
begin
writeLn(f); //wrong, prints "2" in D2006
writeLn(g); //good, prints "1"
readLn;
end.
Note: Overflow check must be encoded in the source file, not via project options. This leads us to another bug: Overflow detection via project options has no effect.
As seen on the CPU window, the optimizer gets distracted by a move with zero extension movzx (extending an 8 bit value to a 32 bit value) and by the overflow check, forgetting to load byte b on a separate register, overwriting the previous contents, with the net effect of adding b to itself instead to 2i. The upper half of below assembly code belongs to the bugged function while the bottom half to the sane construct.
OptimizationBug.dpr.20: i:=0;
00403EAC 33C0 xor eax,eax
OptimizationBug.dpr.21: b:=1;
00403EAE B201 mov dl,$01
OptimizationBug.dpr.22: Result:=i+i+b;
00403EB0 03C0 add eax,eax
00403EB2 7105 jno $00403eb9
00403EB4 E82BF5FFFF call @IntOver
00403EB9 0FB6C2 movzx eax,dl //BUG: should have x-moved DL to EDX register!
00403EBC 03C0 add eax,eax // (and added EDX to EAX)
00403EBE 7105 jno $00403ec5
00403EC0 E81FF5FFFF call @IntOver
OptimizationBug.dpr.23: end;
00403EC5 C3 ret
00403EC6 8BC0 mov eax,eax
OptimizationBug.dpr.30: i:=0;
00403EC8 33C0 xor eax,eax
OptimizationBug.dpr.31: b:=1;
00403ECA B201 mov dl,$01
OptimizationBug.dpr.32: Result:=i+i+b;
00403ECC 03C0 add eax,eax
00403ECE 0FB6D2 movzx edx,dl //OK!
00403ED1 03C2 add eax,edx //ok
OptimizationBug.dpr.33: end;
00403ED3 C3 ret
By the way, this code is not a pathological example, I found it while adapting D.Knuth' magnificent TeX program to modern Pascal. When checking the effect of enabling optimization and of turning off all compiler checks on the final *.exe size, it was not able to interpret the disk saved hash tables back correctly (which were generated with optimization turned off), which I traced back to above bug, which is the part which generates the tables.
The question is simple, can someone check the program on a newer version of Delphi?
The bug has not been fixed even in the latest version of Delphi, XE6. The bug does not affect the 64 bit Windows compiler. The bug is present as far back as Delphi 6, the oldest version that I can run.
I strongly recommend that you submit a QC report.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With