Răsfoiți Sursa

+ Add optimization to optimize [0..31]-x set expression to use one less
register. This construction is used in our Shootout meteor contest
implementation.

git-svn-id: trunk@7176 -

daniel 18 ani în urmă
părinte
comite
ea79e69176
1 a modificat fișierele cu 30 adăugiri și 6 ștergeri
  1. 30 6
      compiler/x86/nx86add.pas

+ 30 - 6
compiler/x86/nx86add.pas

@@ -334,11 +334,14 @@ unit nx86add;
         op     : TAsmOp;
         extra_not,
         noswap : boolean;
+        all_member_optimization:boolean;
+
       begin
         pass_left_right;
 
         noswap:=false;
         extra_not:=false;
+        all_member_optimization:=false;
         opsize:=int_cgsize(resultdef.size);
         case nodetype of
           addn :
@@ -371,6 +374,10 @@ unit nx86add;
           subn :
             begin
               op:=A_AND;
+              if (not(nf_swapped in flags) and (left.location.loc=LOC_CONSTANT) and (left.location.value=-1)) or
+                  ((nf_swapped in flags) and (right.location.loc=LOC_CONSTANT) and (right.location.value=-1)) then
+                all_member_optimization:=true;
+
               if (not(nf_swapped in flags)) and
                  (right.location.loc=LOC_CONSTANT) then
                 right.location.value := not(right.location.value)
@@ -389,13 +396,30 @@ unit nx86add;
           else
             internalerror(2003042215);
         end;
-        { left must be a register }
-        left_must_be_reg(opsize,noswap);
-        emit_generic_code(op,opsize,true,extra_not,false);
-        location_freetemp(current_asmdata.CurrAsmList,right.location);
+        if all_member_optimization then
+          begin
+            { right.location is a LOC_REGISTER }
+            { when swapped another result register }
+            if nf_swapped in flags then
+              begin
+                { newly swapped also set swapped flag }
+                location_swap(left.location,right.location);
+                toggleflag(nf_swapped);
+              end;
+            location_force_reg(current_asmdata.currAsmList,right.location,opsize,false);
+            emit_reg(A_NOT,TCGSize2Opsize[opsize],right.location.register);
+            location:=right.location;
+          end
+        else
+          begin
+            { left must be a register }
+            left_must_be_reg(opsize,noswap);
+            emit_generic_code(op,opsize,true,extra_not,false);
+            location_freetemp(current_asmdata.CurrAsmList,right.location);
 
-        { left is always a register and contains the result }
-        location:=left.location;
+            { left is always a register and contains the result }
+            location:=left.location;
+          end;
 
         { fix the changed opsize we did above because of the missing btsb }
         if opsize<>int_cgsize(resultdef.size) then