소스 검색

Fixes to ADD/SUB 128 optimisation that didn't check flags properly, and also handling ADC/SBB properly

J. Gareth "Curious Kit" Moreton 3 년 전
부모
커밋
40196f4a43
1개의 변경된 파일38개의 추가작업 그리고 7개의 파일을 삭제
  1. 38 7
      compiler/x86/aoptx86.pas

+ 38 - 7
compiler/x86/aoptx86.pas

@@ -10966,7 +10966,7 @@ unit aoptx86;
     function TX86AsmOptimizer.PostPeepholeOptADDSUB(var p : tai) : boolean;
       var
         hp1, hp2: tai;
-        Opposite: TAsmOp;
+        Opposite, SecondOpposite: TAsmOp;
         NewCond: TAsmCond;
       begin
         Result := False;
@@ -10993,7 +10993,7 @@ unit aoptx86;
               GetNextInstruction(p, hp1) then
               begin
                 TransferUsedRegs(TmpUsedRegs);
-                TmpUsedRegs[R_SPECIALREGISTER].Update(tai(hp1.Next), True);
+                TmpUsedRegs[R_SPECIALREGISTER].Update(tai(p.Next), True);
 
                 hp2 := hp1;
 
@@ -11008,8 +11008,13 @@ unit aoptx86;
                       { Stop searching at an unconditional jump }
                       Break;
 
-                    if (taicpu(hp1).condition = C_None) and RegInInstruction(NR_DEFAULTFLAGS, hp1) then
-                      { Instruction depends on FLAGS; break out }
+                    if not
+                      (
+                        MatchInstruction(hp1, A_ADC, A_SBB, []) and
+                        (taicpu(hp1).oper[0]^.typ = top_const) { We need to be able to invert a constant }
+                      ) and
+                      (taicpu(hp1).condition = C_None) and RegInInstruction(NR_DEFAULTFLAGS, hp1) then
+                      { Instruction depends on FLAGS (and is not ADC or SBB); break out }
                       Exit;
 
                     UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
@@ -11042,7 +11047,33 @@ unit aoptx86;
                           ' to accommodate ' + debug_op2str(taicpu(p).opcode) + ' -> ' + debug_op2str(opposite) + ' above', hp2);
 
                         taicpu(hp2).condition := NewCond;
-                      end;
+                      end
+                    else
+                      if MatchInstruction(hp2, A_ADC, A_SBB, []) then
+                        begin
+                          { Because of the flipping of the carry bit, to ensure
+                            the operation remains equivalent, ADC becomes SBB
+                            and vice versa, and the constant is not-inverted.
+
+                            If multiple ADCs or SBBs appear in a row, each one
+                            changed causes the carry bit to invert, so they all
+                            need to be flipped }
+                          if taicpu(hp2).opcode = A_ADC then
+                            SecondOpposite := A_SBB
+                          else
+                            SecondOpposite := A_ADC;
+
+                          if taicpu(hp2).oper[0]^.typ <> top_const then
+                            { Should have broken out of this optimisation already }
+                            InternalError(2021112901);
+
+                          DebugMsg(SPeepholeOptimization + debug_op2str(taicpu(hp2).opcode) + debug_opsize2str(taicpu(hp2).opsize) + ' $' + debug_tostr(taicpu(hp2).oper[0]^.val) + ',' + debug_operstr(taicpu(hp2).oper[1]^) + ' -> ' +
+                            debug_op2str(SecondOpposite) + debug_opsize2str(taicpu(hp2).opsize) + ' $' + debug_tostr(not taicpu(hp2).oper[0]^.val) + ',' + debug_operstr(taicpu(hp2).oper[1]^) + ' to accommodate inverted carry bit', hp2);
+
+                          { Bit-invert the constant (effectively equivalent to "-1 - val") }
+                          taicpu(hp2).opcode := SecondOpposite;
+                          taicpu(hp2).oper[0]^.val := not taicpu(hp2).oper[0]^.val;
+                        end;
 
                     { Move to the next instruction }
                     GetNextInstruction(hp2, hp2);
@@ -11052,8 +11083,8 @@ unit aoptx86;
                   InternalError(2021111501);
               end;
 
-            DebugMsg(SPeepholeOptimization + debug_op2str(taicpu(p).opcode) + ' 128,' + debug_operstr(taicpu(p).oper[1]^) + ' changed to ' +
-              debug_op2str(opposite) + ' -128,' + debug_operstr(taicpu(p).oper[1]^) + ' to reduce instruction size', p);
+            DebugMsg(SPeepholeOptimization + debug_op2str(taicpu(p).opcode) + debug_opsize2str(taicpu(p).opsize) + ' $128,' + debug_operstr(taicpu(p).oper[1]^) + ' changed to ' +
+              debug_op2str(opposite) + debug_opsize2str(taicpu(p).opsize) + ' $-128,' + debug_operstr(taicpu(p).oper[1]^) + ' to reduce instruction size', p);
 
             taicpu(p).opcode := Opposite;
             taicpu(p).oper[0]^.val := -128;