Browse Source

* x86: Fixed update of used registers in the CMOV optimizations.
This fixes a bug reported by Martin Frb in fpc-devel which is triggered
by the recently provided test code in FPC 3.2.2 x86_64, but is hidden
in trunk by other pipeline peephole optimizations.

(cherry picked from commit e9d318e7e2f772bf455a92461cd5c229e69858d8)

Yuriy Sydorov 3 years ago
parent
commit
eb69bbf4f1
2 changed files with 59 additions and 11 deletions
  1. 11 11
      compiler/x86/aoptx86.pas
  2. 48 0
      tests/tbs/tb0686.pp

+ 11 - 11
compiler/x86/aoptx86.pas

@@ -2768,6 +2768,7 @@ unit aoptx86;
                       if (l<=4) and (l>0) then
                         begin
                           condition:=inverse_cond(taicpu(p).condition);
+                          UpdateUsedRegs(tai(p.next));
                           GetNextInstruction(p,hp1);
                           repeat
                             if not Assigned(hp1) then
@@ -2775,7 +2776,7 @@ unit aoptx86;
 
                             taicpu(hp1).opcode:=A_CMOVcc;
                             taicpu(hp1).condition:=condition;
-                            UpdateUsedRegs(hp1);
+                            UpdateUsedRegs(tai(hp1.next));
                             GetNextInstruction(hp1,hp1);
                           until not(CanBeCMOV(hp1));
 
@@ -2822,6 +2823,7 @@ unit aoptx86;
                           asml.Remove(p);
                           p.Free;
 
+                          UpdateUsedRegs(tai(hp2.next));
                           GetNextInstruction(hp2, p); { Instruction after the label }
 
                           { Remove the label if this is its final reference }
@@ -2832,10 +2834,7 @@ unit aoptx86;
                             end;
 
                           if Assigned(p) then
-                            begin
-                              UpdateUsedRegs(p);
-                              result:=true;
-                            end;
+                            result:=true;
                           exit;
                         end;
                     end
@@ -2885,29 +2884,33 @@ unit aoptx86;
                              FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
                              begin
                                 condition:=inverse_cond(taicpu(p).condition);
+                                UpdateUsedRegs(tai(p.next));
                                 GetNextInstruction(p,hp1);
                                 repeat
                                   taicpu(hp1).opcode:=A_CMOVcc;
                                   taicpu(hp1).condition:=condition;
-                                  UpdateUsedRegs(hp1);
+                                  UpdateUsedRegs(tai(hp1.next));
                                   GetNextInstruction(hp1,hp1);
                                 until not(assigned(hp1)) or
                                   not(CanBeCMOV(hp1));
 
                                 condition:=inverse_cond(condition);
+                                if GetLastInstruction(hpmov2,hp1) then
+                                  UpdateUsedRegs(tai(hp1.next));
                                 hp1 := hpmov2;
                                 { hp1 is now at <several movs 2> }
                                 while Assigned(hp1) and CanBeCMOV(hp1) do
                                   begin
                                     taicpu(hp1).opcode:=A_CMOVcc;
                                     taicpu(hp1).condition:=condition;
-                                    UpdateUsedRegs(hp1);
+                                    UpdateUsedRegs(tai(hp1.next));
                                     GetNextInstruction(hp1,hp1);
                                   end;
 
                                 hp1 := p;
 
                                 { Get first instruction after label }
+                                UpdateUsedRegs(tai(hp3.next));
                                 GetNextInstruction(hp3, p);
 
                                 if assigned(p) and (hp3.typ = ait_align) then
@@ -2962,10 +2965,7 @@ unit aoptx86;
                                   end;
 
                                 if Assigned(p) then
-                                  begin
-                                    UpdateUsedRegs(p);
-                                    result:=true;
-                                  end;
+                                  result:=true;
                                 exit;
                              end;
                          end;

+ 48 - 0
tests/tbs/tb0686.pp

@@ -0,0 +1,48 @@
+{$mode objfpc}
+
+uses math;
+
+type
+  generic TLazFifoQueue<T> = class
+  private
+    FList: array of T;
+    FQueueSize: integer;
+  protected
+    FTotalItemsPopped: QWord;
+    FTotalItemsPushed: QWord;
+  public
+    procedure Grow(ADelta: integer);
+  end;
+
+procedure TLazFifoQueue.Grow(ADelta: integer);
+var
+  NewList: array of integer;
+  c: Integer;
+  i: QWord;
+begin
+  c:=Max(FQueueSize + ADelta, Integer(FTotalItemsPushed - FTotalItemsPopped));
+  setlength(NewList{%H-}, c);
+  i:=FTotalItemsPopped;
+  while i < FTotalItemsPushed do begin
+    NewList[i mod c] := FList[i mod FQueueSize];
+    inc(i);
+  end;
+
+  FList := NewList;
+  FQueueSize:=c;
+end;
+
+type
+  TIntQ = specialize TLazFifoQueue<integer>;
+
+begin
+  with TIntQ.Create do begin
+    Grow(123);
+    if FQueueSize <> 123 then begin
+      writeln('FAILED');
+      halt(1);
+    end;
+    Free;
+  end;
+  writeln('OK');
+end.