Kaynağa Gözat

* 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.

Yuriy Sydorov 3 yıl önce
ebeveyn
işleme
e9d318e7e2
2 değiştirilmiş dosya ile 59 ekleme ve 11 silme
  1. 11 11
      compiler/x86/aoptx86.pas
  2. 48 0
      tests/tbs/tb0686.pp

+ 11 - 11
compiler/x86/aoptx86.pas

@@ -8446,6 +8446,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
@@ -8453,7 +8454,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));
 
@@ -8495,6 +8496,7 @@ unit aoptx86;
                               { Remove the original jump }
                               RemoveInstruction(p); { Note, the choice to not use RemoveCurrentp is deliberate }
 
+                              UpdateUsedRegs(tai(hp2.next));
                               GetNextInstruction(hp2, p); { Instruction after the label }
 
                               { Remove the label if this is its final reference }
@@ -8502,10 +8504,7 @@ unit aoptx86;
                                 StripLabelFast(hp1);
 
                               if Assigned(p) then
-                                begin
-                                  UpdateUsedRegs(p);
-                                  result:=true;
-                                end;
+                                result:=true;
                               exit;
                             end;
                         end
@@ -8555,29 +8554,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
@@ -8612,10 +8615,7 @@ unit aoptx86;
                                       StripLabelFast(hp3);
 
                                     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.