[fpc-devel] Anyone an idea were/how to look for the missing merge in 3.2.0 [[peephole / fixed]]

Martin Frb lazarus at mfriebe.de
Mon Oct 4 03:44:21 CEST 2021

Update to my original mail: 
I found the needle in the haystack.

It appears fixed in current (2 day old) fixes 3.3.1. / I have not tested 

The code is in: components\lazutils\lazcollections.pas

procedure TLazFifoQueue.Grow(ADelta: integer);
   NewList: array of T;
   c: Integer;
   i: QWord;
   c:=Max(FQueueSize + ADelta, Integer(FTotalItemsPushed - 
   setlength(NewList{%H-}, c);
   while i < FTotalItemsPushed do begin
     NewList[i mod c] := FList[i mod FQueueSize];

   FList := NewList;

Without peephole (the "max" is inlined, below is the compare code)
# Var c located in register ebx

     cmpq    %rax,%rcx
     jl    .Lj37
     jmp    .Lj38
     jmp    .Lj39
     movq    %rcx,%rax
     movl    %eax,%ebx
     movslq    %ebx,%rax

The 2 moves at the end do 2 things
1) extend 32 to 64 bit (afaik)
2) move the result to ebx

Compiled with peephole the code looks like this
     cmpq    %rax,%rcx
     cmovnlq    %rcx,%rax
     movslq    %eax,%rax

The 2 moves have been combined => ebx is no longer loaded.

But ebx is used for c. And hence c has the wrong value.

<little rant>Because for some mystery SetLength does not use the 
register value, but loads from the stackframe, the array is correctly 
sized. Therefore the code above never crashes. But it does not move all 
data to the new array. Other code then accesses random memory. So my 
crashes always happened elsewhere. Really not helpful</little rant>

In 3.3.1 the result is
     cmpq    %rax,%rcx
# Peephole Optimization: JccMov2CMov
     cmovnlq    %rcx,%rax
     movl    %eax,%ebx
# Peephole Optimization: %ebx = %eax; changed to minimise pipeline stall 
     movslq    %eax,%rax

More information about the fpc-devel mailing list