Procházet zdrojové kódy

* x86: New MOV/AND peephole optimisation and more efficient optimisation searching in "OptPass1MOV"

J. Gareth "Curious Kit" Moreton před 2 měsíci
rodič
revize
833c668e29
1 změnil soubory, kde provedl 70 přidání a 22 odebrání
  1. 70 22
      compiler/x86/aoptx86.pas

+ 70 - 22
compiler/x86/aoptx86.pas

@@ -3145,7 +3145,8 @@ unit aoptx86;
     function TX86AsmOptimizer.OptPass1MOV(var p : tai) : boolean;
     var
       hp1, hp2, hp3, hp4: tai;
-      DoOptimisation, TempBool: Boolean;
+      GetNextInstruction_p, DoOptimisation, TempBool: Boolean;
+      p_SourceReg, p_TargetReg, NewMMReg: TRegister;
 {$ifdef x86_64}
       NewConst: TCGInt;
 {$endif x86_64}
@@ -3161,6 +3162,15 @@ unit aoptx86;
             taicpu(p).oper[0]^.val:=taicpu(p).oper[0]^.val and max_value; { Trim to unsigned }
         end;
 
+      function GetNextHp1(const in_p: tai): Boolean;
+        begin
+          if NotFirstIteration and (cs_opt_level3 in current_settings.optimizerswitches) then
+            GetNextInstruction_p := GetNextInstructionUsingReg(in_p, hp1, p_TargetReg)
+          else
+            GetNextInstruction_p := GetNextInstruction(in_p, hp1);
+          Result := GetNextInstruction_p and (hp1.typ = ait_instruction);
+        end;
+
       function TryConstMerge(var p1, p2: tai): Boolean;
         var
           ThisRef: TReference;
@@ -3246,13 +3256,11 @@ unit aoptx86;
         end;
 
       var
-        GetNextInstruction_p, TempRegUsed, CrossJump: Boolean;
+        TempRegUsed, CrossJump: Boolean;
         PreMessage, RegName1, RegName2, InputVal, MaskNum: string;
         NewSize: topsize; NewOffset: asizeint;
-        p_SourceReg, p_TargetReg, NewMMReg: TRegister;
         SourceRef, TargetRef: TReference;
         MovAligned, MovUnaligned: TAsmOp;
-        ThisRef: TReference;
         JumpTracking: TLinkedList;
       begin
         Result:=false;
@@ -3271,26 +3279,22 @@ unit aoptx86;
         { Prevent compiler warnings }
         p_SourceReg := NR_NO;
         p_TargetReg := NR_NO;
+        hp1 := nil;
 
         if taicpu(p).oper[1]^.typ = top_reg then
           begin
             { Saves on a large number of dereferences }
             p_TargetReg := taicpu(p).oper[1]^.reg;
 
-            if NotFirstIteration and (cs_opt_level3 in current_settings.optimizerswitches) then
-              GetNextInstruction_p := GetNextInstructionUsingReg(p, hp1, p_TargetReg)
-            else
-              GetNextInstruction_p := GetNextInstruction(p, hp1);
-
-            if GetNextInstruction_p and (hp1.typ = ait_instruction) then
+            if GetNextHp1(p) then
               while True do
                 begin
                   if (taicpu(hp1).opcode = A_AND) and
-                    MatchOpType(taicpu(hp1),top_const,top_reg) then
+                    (taicpu(hp1).oper[1]^.typ = top_reg) and
+                    SuperRegistersEqual(p_TargetReg, taicpu(hp1).oper[1]^.reg) then
                     begin
-                      { A change has occurred, just not in p }
-                      Include(OptsToCheck, aoc_ForceNewIteration);
-                      if MatchOperand(taicpu(hp1).oper[1]^, p_TargetReg) then
+                      if (taicpu(hp1).oper[0]^.typ = top_const) and
+                        (taicpu(p).opsize = taicpu(hp1).opsize) then
                         begin
                           case taicpu(p).opsize of
                             S_L:
@@ -3301,9 +3305,15 @@ unit aoptx86;
                                       and ffffffffh, %reg
                                   }
                                   DebugMsg(SPeepholeOptimization + 'MovAnd2Mov 1 done',p);
+                                  hp2 := tai(hp1.Previous);
                                   RemoveInstruction(hp1);
-                                  Result:=true;
-                                  exit;
+
+                                  //Include(OptsToCheck, aoc_ForceNewIteration);
+
+                                  if GetNextHp1(hp2) then
+                                    Continue
+                                  else
+                                    Exit;
                                 end;
                             S_Q: { TODO: Confirm if this is even possible }
                               if (taicpu(hp1).oper[0]^.val = $ffffffffffffffff) then
@@ -3313,9 +3323,16 @@ unit aoptx86;
                                       and ffffffffffffffffh, %reg
                                   }
                                   DebugMsg(SPeepholeOptimization + 'MovAnd2Mov 2 done',p);
+
+                                  hp2 := tai(hp1.Previous);
                                   RemoveInstruction(hp1);
-                                  Result:=true;
-                                  exit;
+
+                                  //Include(OptsToCheck, aoc_ForceNewIteration);
+
+                                  if GetNextHp1(hp2) then
+                                    Continue
+                                  else
+                                    Exit;
                                 end;
                             else
                               ;
@@ -3440,11 +3457,42 @@ unit aoptx86;
                             end;
                         end;
 
+                      if (taicpu(p).opsize = taicpu(hp1).opsize) and
+                        (taicpu(hp1).oper[0]^.typ <> top_ref) and
+                        MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
+                        MatchOperand(taicpu(p).oper[1]^, taicpu(hp1).oper[1]^) and
+                        (
+                          not (cs_opt_level3 in current_settings.optimizerswitches) or
+                          (taicpu(hp1).oper[0]^.typ = top_const) or
+                          not RegModifiedBetween(taicpu(hp1).oper[0]^.reg, p, hp1)
+                        ) then
+                        begin
+                          { With:
+                              mov %reg1,%reg2
+                              ...
+                              and %reg1,%reg2
+                            Or:
+                              mov $x,%reg2
+                              ...
+                              and $x,%reg2
+
+                            Remove the 'and' instruction
+                          }
+                          DebugMsg(SPeepholeOptimization + 'MovAnd2Mov 4 done',hp1);
+
+                          hp2 := tai(hp1.Previous);
+                          RemoveInstruction(hp1);
+
+                          //Include(OptsToCheck, aoc_ForceNewIteration);
+
+                          if GetNextHp1(hp2) then
+                            Continue
+                          else
+                            Exit;
+                        end;
+
                       if IsMOVZXAcceptable and
-                        (taicpu(hp1).oper[1]^.typ = top_reg) and
-                        (taicpu(p).oper[0]^.typ <> top_const) and { MOVZX only supports registers and memory, not immediates (use MOV for that!) }
-                        (getsupreg(p_TargetReg) = getsupreg(taicpu(hp1).oper[1]^.reg))
-                        then
+                        (taicpu(p).oper[0]^.typ <> top_const) then { MOVZX only supports registers and memory, not immediates (use MOV for that!) }
                         begin
                           InputVal := debug_operstr(taicpu(p).oper[0]^);
                           MaskNum := debug_tostr(taicpu(hp1).oper[0]^.val);