Skip to content

Bit shift error, depending on optimization level

Consider the following program:

var
  A, B, C: QWord;

begin
  A := 140737488355327;
  WriteLn('A                : ',BinStr(A, 64));
  B := (A shr 47) shl 48;
  WriteLn('(A shr 47) shl 48: ',BinStr(B, 64));
  C := A shr 47;
  writeln('C := A shr 47    : ',BinStr(C, 64));
  C := C shl 48;
  WriteLn('C := C shl 48    : ',BinStr(C, 64));
end.

The 2 calculations should give the same result. If you build for Win64 and use -O1 or higher the output will be wrong:

C:\Users\Bart\LazarusProjecten\bugs\Console\bitshift>fpc test.lpr -Px86_64 -O1
Free Pascal Compiler version 3.3.1 [2024/12/18] for x86_64
Copyright (c) 1993-2024 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling test.lpr
Linking test.exe
17 lines compiled, 0.1 sec, 33872 bytes code, 1732 bytes data

C:\Users\Bart\LazarusProjecten\bugs\Console\bitshift>test
A                : 0000000000000000011111111111111111111111111111111111111111111111
(A shr 47) shl 48: 0000000000000000111111111111111111111111111111110000000000000000
C := A shr 47    : 0000000000000000000000000000000000000000000000000000000000000000
C := C shl 48    : 0000000000000000000000000000000000000000000000000000000000000000

You get the correct output with -O-, or compiling for 32-bit (with any value for -O):

C:\Users\Bart\LazarusProjecten\bugs\Console\bitshift>fpc test.lpr -Px86_64
Free Pascal Compiler version 3.3.1 [2024/12/18] for x86_64
Copyright (c) 1993-2024 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling test.lpr
Linking test.exe
17 lines compiled, 0.1 sec, 33920 bytes code, 1732 bytes data

C:\Users\Bart\LazarusProjecten\bugs\Console\bitshift>test
A                : 0000000000000000011111111111111111111111111111111111111111111111
(A shr 47) shl 48: 0000000000000000000000000000000000000000000000000000000000000000
C := A shr 47    : 0000000000000000000000000000000000000000000000000000000000000000
C := C shl 48    : 0000000000000000000000000000000000000000000000000000000000000000

The error does not seem to depend on the state of range-checking or overflow-checking.

Issue originally raised in the forum.

Tested with fpc main (3.3.1-5463-gb28681e91d). (The issue is also present in fpc 3.2.2 and 3.2.0, but not on 3.0.4)

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