Browse Source

* remove some obsolete i386 specific code
* use a_optimize_const to remove useless opcodes

git-svn-id: trunk@2910 -

peter 19 years ago
parent
commit
588cccb3ca

+ 2 - 1
compiler/cgbase.pas

@@ -81,6 +81,7 @@ interface
        topcg =
        topcg =
        (
        (
           OP_NONE,
           OP_NONE,
+          OP_MOVE,      { replaced operation with direct load }
           OP_ADD,       { simple addition          }
           OP_ADD,       { simple addition          }
           OP_AND,       { simple logical and       }
           OP_AND,       { simple logical and       }
           OP_DIV,       { simple unsigned division }
           OP_DIV,       { simple unsigned division }
@@ -593,7 +594,7 @@ implementation
     function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
     function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
       const
       const
         list: array[topcg] of boolean =
         list: array[topcg] of boolean =
-          (true,true,true,false,false,true,true,false,false,
+          (true,false,true,true,false,false,true,true,false,false,
            true,false,false,false,false,true);
            true,false,false,false,false,true);
       begin
       begin
         commutativeop := list[op];
         commutativeop := list[op];

+ 42 - 30
compiler/cgobj.pas

@@ -285,18 +285,16 @@ unit cgobj;
           procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
           procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
 
 
           {
           {
-             This routine tries to optimize the const_reg opcode, and should be
-             called at the start of a_op_const_reg. It returns the actual opcode
-             to emit, and the constant value to emit. If this routine returns
-             TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
+             This routine tries to optimize the op_const_reg/ref opcode, and should be
+             called at the start of a_op_const_reg/ref. It returns the actual opcode
+             to emit, and the constant value to emit. This function can opcode OP_NONE to
+             remove the opcode and OP_MOVE to replace it with a simple load
 
 
              @param(op The opcode to emit, returns the opcode which must be emitted)
              @param(op The opcode to emit, returns the opcode which must be emitted)
              @param(a  The constant which should be emitted, returns the constant which must
              @param(a  The constant which should be emitted, returns the constant which must
                     be emitted)
                     be emitted)
-             @param(reg The register to emit the opcode with, returns the register with
-                   which the opcode will be emitted)
           }
           }
-          function optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aint; var reg: tregister): boolean;virtual;
+          procedure optimize_op_const(var op: topcg; var a : aint);virtual;
 
 
          {#
          {#
              This routine is used in exception management nodes. It should
              This routine is used in exception management nodes. It should
@@ -936,55 +934,69 @@ implementation
       end;
       end;
 
 
 
 
-    function tcg.optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aint; var reg:tregister): boolean;
+    procedure tcg.optimize_op_const(var op: topcg; var a : aint);
       var
       var
         powerval : longint;
         powerval : longint;
       begin
       begin
-        optimize_op_const_reg := false;
         case op of
         case op of
-          { or with zero returns same result }
-          OP_OR : if a = 0 then optimize_op_const_reg := true;
-          { and with max returns same result }
-          OP_AND : if (a = high(a)) then optimize_op_const_reg := true;
-          { division by 1 returns result }
+          OP_OR :
+            begin
+              { or with zero returns same result }
+              if a = 0 then
+                op:=OP_NONE
+              else
+              { or with max returns max }
+                if a = -1 then
+                  op:=OP_MOVE;
+            end;
+          OP_AND :
+            begin
+              { and with max returns same result }
+              if (a = -1) then
+                op:=OP_NONE
+              else
+              { and with 0 returns 0 }
+                if a=0 then
+                  op:=OP_MOVE;
+            end;
           OP_DIV :
           OP_DIV :
             begin
             begin
+              { division by 1 returns result }
               if a = 1 then
               if a = 1 then
-                optimize_op_const_reg := true
+                op:=OP_NONE
               else if ispowerof2(int64(a), powerval) then
               else if ispowerof2(int64(a), powerval) then
                 begin
                 begin
                   a := powerval;
                   a := powerval;
                   op:= OP_SHR;
                   op:= OP_SHR;
                 end;
                 end;
-              exit;
             end;
             end;
           OP_IDIV:
           OP_IDIV:
             begin
             begin
               if a = 1 then
               if a = 1 then
-                optimize_op_const_reg := true
-              else if ispowerof2(int64(a), powerval) then
-                begin
-                  a := powerval;
-                  op:= OP_SAR;
-                end;
-               exit;
+                op:=OP_NONE;
             end;
             end;
-        OP_MUL,OP_IMUL:
+         OP_MUL,OP_IMUL:
             begin
             begin
                if a = 1 then
                if a = 1 then
-                  optimize_op_const_reg := true
+                 op:=OP_NONE
+               else
+                 if a=0 then
+                   op:=OP_MOVE
                else if ispowerof2(int64(a), powerval) then
                else if ispowerof2(int64(a), powerval) then
                  begin
                  begin
                    a := powerval;
                    a := powerval;
                    op:= OP_SHL;
                    op:= OP_SHL;
                  end;
                  end;
-               exit;
+            end;
+        OP_ADD,OP_SUB:
+            begin
+               if a = 0 then
+                 op:=OP_NONE;
             end;
             end;
         OP_SAR,OP_SHL,OP_SHR:
         OP_SAR,OP_SHL,OP_SHR:
            begin
            begin
               if a = 0 then
               if a = 0 then
-                 optimize_op_const_reg := true;
-              exit;
+                op:=OP_NONE;
            end;
            end;
         end;
         end;
       end;
       end;
@@ -1729,7 +1741,7 @@ implementation
 {$endif}
 {$endif}
                 if to_signed then
                 if to_signed then
                   begin
                   begin
-                    { calculation of the low/high ranges must not overflow 64 bit 
+                    { calculation of the low/high ranges must not overflow 64 bit
                      otherwise we end up comparing with zero for 64 bit data types on
                      otherwise we end up comparing with zero for 64 bit data types on
                      64 bit processors }
                      64 bit processors }
                     if (lto = (int64(-1) << (tosize * 8 - 1))) and
                     if (lto = (int64(-1) << (tosize * 8 - 1))) and
@@ -1738,7 +1750,7 @@ implementation
                   end
                   end
                 else
                 else
                   begin
                   begin
-                    { calculation of the low/high ranges must not overflow 64 bit 
+                    { calculation of the low/high ranges must not overflow 64 bit
                      otherwise we end up having all zeros for 64 bit data types on
                      otherwise we end up having all zeros for 64 bit data types on
                      64 bit processors }
                      64 bit processors }
                     if (lto = 0) and
                     if (lto = 0) and

+ 2 - 0
compiler/i386/n386add.pas

@@ -349,6 +349,8 @@ interface
         hl4 : tasmlabel;
         hl4 : tasmlabel;
 
 
     begin
     begin
+      pass_left_right;
+
       {The location.register will be filled in later (JM)}
       {The location.register will be filled in later (JM)}
       location_reset(location,LOC_REGISTER,OS_INT);
       location_reset(location,LOC_REGISTER,OS_INT);
       {Get a temp register and load the left value into it
       {Get a temp register and load the left value into it

+ 103 - 140
compiler/i386/n386mat.pas

@@ -33,9 +33,8 @@ interface
          procedure pass_2;override;
          procedure pass_2;override;
       end;
       end;
 
 
-      ti386shlshrnode = class(tshlshrnode)
-         procedure pass_2;override;
-         { everything will be handled in pass_2 }
+      ti386shlshrnode = class(tcgshlshrnode)
+         procedure second_64bit;override;
          function first_shlshr64bitint: tnode; override;
          function first_shlshr64bitint: tnode; override;
       end;
       end;
 
 
@@ -165,7 +164,7 @@ implementation
                         m_high:=m_high shr 1;
                         m_high:=m_high shr 1;
                         dec(l);
                         dec(l);
                       end;
                       end;
-                    m:=m_high;
+                    m:=dword(m_high);
                     s:=l;
                     s:=l;
                     if (m_high shr 31)<>0 then
                     if (m_high shr 31)<>0 then
                       a:=1
                       a:=1
@@ -223,7 +222,7 @@ implementation
                     d:=tordconstnode(right).value;
                     d:=tordconstnode(right).value;
                     if d>=$80000000 then
                     if d>=$80000000 then
                       begin
                       begin
-                        emit_const_reg(A_CMP,S_L,d,hreg1);
+                        emit_const_reg(A_CMP,S_L,aint(d),hreg1);
                         location.register:=cg.getintregister(exprasmlist,OS_INT);
                         location.register:=cg.getintregister(exprasmlist,OS_INT);
                         emit_const_reg(A_MOV,S_L,0,location.register);
                         emit_const_reg(A_MOV,S_L,0,location.register);
                         emit_const_reg(A_SBB,S_L,-1,location.register);
                         emit_const_reg(A_SBB,S_L,-1,location.register);
@@ -359,147 +358,111 @@ implementation
 
 
 
 
     function ti386shlshrnode.first_shlshr64bitint: tnode;
     function ti386shlshrnode.first_shlshr64bitint: tnode;
+      begin
+        result := nil;
+      end;
 
 
-    begin
-      result := nil;
-    end;
-
-    procedure ti386shlshrnode.pass_2;
-
-    var hreg64hi,hreg64lo:Tregister;
-        op:Tasmop;
+    procedure ti386shlshrnode.second_64bit;
+      var
+        hreg64hi,hreg64lo:Tregister;
         v : TConstExprInt;
         v : TConstExprInt;
         l1,l2,l3:Tasmlabel;
         l1,l2,l3:Tasmlabel;
+      begin
+        location_reset(location,LOC_REGISTER,OS_64);
+
+        { load left operator in a register }
+        location_force_reg(exprasmlist,left.location,OS_64,false);
+        hreg64hi:=left.location.register64.reghi;
+        hreg64lo:=left.location.register64.reglo;
 
 
-    begin
-      secondpass(left);
-      secondpass(right);
-
-      { determine operator }
-      if nodetype=shln then
-        op:=A_SHL
-      else
-        op:=A_SHR;
-
-      if is_64bitint(left.resulttype.def) then
-        begin
-          location_reset(location,LOC_REGISTER,OS_64);
-
-          { load left operator in a register }
-          location_force_reg(exprasmlist,left.location,OS_64,false);
-          hreg64hi:=left.location.register64.reghi;
-          hreg64lo:=left.location.register64.reglo;
-
-          { shifting by a constant directly coded: }
-          if (right.nodetype=ordconstn) then
-            begin
-              v:=Tordconstnode(right).value and 63;
-              if v>31 then
-                begin
-                  if nodetype=shln then
-                    begin
-                      emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
-                      if ((v and 31) <> 0) then
-                        emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
-                    end
-                  else
-                    begin
-                      emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
-                      if ((v and 31) <> 0) then
-                        emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
-                    end;
-                  location.register64.reghi:=hreg64lo;
-                  location.register64.reglo:=hreg64hi;
-                end
-              else
-                begin
-                  if nodetype=shln then
-                    begin
-                      emit_const_reg_reg(A_SHLD,S_L,v and 31,hreg64lo,hreg64hi);
+        { shifting by a constant directly coded: }
+        if (right.nodetype=ordconstn) then
+          begin
+            v:=Tordconstnode(right).value and 63;
+            if v>31 then
+              begin
+                if nodetype=shln then
+                  begin
+                    emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+                    if ((v and 31) <> 0) then
                       emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
                       emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
-                    end
-                  else
-                    begin
-                      emit_const_reg_reg(A_SHRD,S_L,v and 31,hreg64hi,hreg64lo);
+                  end
+                else
+                  begin
+                    emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+                    if ((v and 31) <> 0) then
                       emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
                       emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
-                    end;
-                  location.register64.reglo:=hreg64lo;
-                  location.register64.reghi:=hreg64hi;
-                end;
-            end
-          else
-            begin
-              { load right operators in a register }
-              cg.getcpuregister(exprasmlist,NR_ECX);
-              cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
-
-              { left operator is already in a register }
-              { hence are both in a register }
-              { is it in the case ECX ? }
-
-              { the damned shift instructions work only til a count of 32 }
-              { so we've to do some tricks here                           }
-              objectlibrary.getjumplabel(l1);
-              objectlibrary.getjumplabel(l2);
-              objectlibrary.getjumplabel(l3);
-              emit_const_reg(A_CMP,S_L,64,NR_ECX);
-              cg.a_jmp_flags(exprasmlist,F_L,l1);
-              emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
-              emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
-              cg.a_jmp_always(exprasmlist,l3);
-              cg.a_label(exprasmlist,l1);
-              emit_const_reg(A_CMP,S_L,32,NR_ECX);
-              cg.a_jmp_flags(exprasmlist,F_L,l2);
-              emit_const_reg(A_SUB,S_L,32,NR_ECX);
-              if nodetype=shln then
-                begin
-                  emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
-                  emit_reg_reg(A_MOV,S_L,hreg64lo,hreg64hi);
-                  emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
-                  cg.a_jmp_always(exprasmlist,l3);
-                  cg.a_label(exprasmlist,l2);
-                  emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hreg64lo,hreg64hi);
-                  emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
-                end
-              else
-                begin
-                  emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
-                  emit_reg_reg(A_MOV,S_L,hreg64hi,hreg64lo);
-                  emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
-                  cg.a_jmp_always(exprasmlist,l3);
-                  cg.a_label(exprasmlist,l2);
-                  emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hreg64hi,hreg64lo);
-                  emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
-                end;
-              cg.a_label(exprasmlist,l3);
-
-              cg.ungetcpuregister(exprasmlist,NR_ECX);
-              location.register64.reglo:=hreg64lo;
-              location.register64.reghi:=hreg64hi;
-            end;
-        end
-      else
-        begin
-          { load left operators in a register }
-          location_copy(location,left.location);
-          location_force_reg(exprasmlist,location,OS_INT,false);
-
-          { shifting by a constant directly coded: }
-          if (right.nodetype=ordconstn) then
-            { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
-            emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
-          else
-            begin
-              { load right operators in a ECX }
-              cg.getcpuregister(exprasmlist,NR_ECX);
-              cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
-
-              { right operand is in ECX }
-              cg.ungetcpuregister(exprasmlist,NR_ECX);
-              emit_reg_reg(op,S_L,NR_CL,location.register);
-            end;
-        end;
-    end;
+                  end;
+                location.register64.reghi:=hreg64lo;
+                location.register64.reglo:=hreg64hi;
+              end
+            else
+              begin
+                if nodetype=shln then
+                  begin
+                    emit_const_reg_reg(A_SHLD,S_L,v and 31,hreg64lo,hreg64hi);
+                    emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
+                  end
+                else
+                  begin
+                    emit_const_reg_reg(A_SHRD,S_L,v and 31,hreg64hi,hreg64lo);
+                    emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
+                  end;
+                location.register64.reglo:=hreg64lo;
+                location.register64.reghi:=hreg64hi;
+              end;
+          end
+        else
+          begin
+            { load right operators in a register }
+            cg.getcpuregister(exprasmlist,NR_ECX);
+            cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
+
+            { left operator is already in a register }
+            { hence are both in a register }
+            { is it in the case ECX ? }
+
+            { the damned shift instructions work only til a count of 32 }
+            { so we've to do some tricks here                           }
+            objectlibrary.getjumplabel(l1);
+            objectlibrary.getjumplabel(l2);
+            objectlibrary.getjumplabel(l3);
+            emit_const_reg(A_CMP,S_L,64,NR_ECX);
+            cg.a_jmp_flags(exprasmlist,F_L,l1);
+            emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+            emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+            cg.a_jmp_always(exprasmlist,l3);
+            cg.a_label(exprasmlist,l1);
+            emit_const_reg(A_CMP,S_L,32,NR_ECX);
+            cg.a_jmp_flags(exprasmlist,F_L,l2);
+            emit_const_reg(A_SUB,S_L,32,NR_ECX);
+            if nodetype=shln then
+              begin
+                emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
+                emit_reg_reg(A_MOV,S_L,hreg64lo,hreg64hi);
+                emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+                cg.a_jmp_always(exprasmlist,l3);
+                cg.a_label(exprasmlist,l2);
+                emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hreg64lo,hreg64hi);
+                emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
+              end
+            else
+              begin
+                emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
+                emit_reg_reg(A_MOV,S_L,hreg64hi,hreg64lo);
+                emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+                cg.a_jmp_always(exprasmlist,l3);
+                cg.a_label(exprasmlist,l2);
+                emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hreg64hi,hreg64lo);
+                emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
+              end;
+            cg.a_label(exprasmlist,l3);
+
+            cg.ungetcpuregister(exprasmlist,NR_ECX);
+            location.register64.reglo:=hreg64lo;
+            location.register64.reghi:=hreg64hi;
+          end;
+      end;
 
 
 
 
 begin
 begin

+ 5 - 3
compiler/m68k/cgcpu.pas

@@ -404,11 +404,13 @@ unit cgcpu;
        opcode : tasmop;
        opcode : tasmop;
        r,r2 : Tregister;
        r,r2 : Tregister;
       begin
       begin
-        { need to emit opcode? }
-        if optimize_op_const_reg(list, op, a, reg) then
-           exit;
+        optimize_op_const_reg(list, op, a, reg);
         opcode := topcg2tasmop[op];
         opcode := topcg2tasmop[op];
         case op of
         case op of
+          OP_NONE :
+              begin
+                { Opcode is optimized away }
+              end;
           OP_ADD :
           OP_ADD :
               begin
               begin
                 if (a >= 1) and (a <= 8) then
                 if (a >= 1) and (a <= 8) then

+ 4 - 6
compiler/ncgadd.pas

@@ -459,8 +459,7 @@ interface
         ovloc.loc:=LOC_VOID;
         ovloc.loc:=LOC_VOID;
 
 
         pass_left_right;
         pass_left_right;
-        force_reg_left_right(false,(cs_check_overflow in aktlocalswitches) and
-                                   (nodetype in [addn,subn]));
+        force_reg_left_right(false,true);
         set_result_location_reg;
         set_result_location_reg;
 
 
         { assume no overflow checking is required }
         { assume no overflow checking is required }
@@ -634,8 +633,7 @@ interface
         ovloc.loc:=LOC_VOID;
         ovloc.loc:=LOC_VOID;
 
 
         pass_left_right;
         pass_left_right;
-        force_reg_left_right(false,(cs_check_overflow in aktlocalswitches) and
-                                   (nodetype in [addn,subn,muln]));
+        force_reg_left_right(false,true);
         set_result_location_reg;
         set_result_location_reg;
 
 
         { determine if the comparison will be unsigned }
         { determine if the comparison will be unsigned }
@@ -680,7 +678,7 @@ interface
 
 
        if nodetype<>subn then
        if nodetype<>subn then
         begin
         begin
-          if (right.location.loc >LOC_CONSTANT) then
+          if (right.location.loc<>LOC_CONSTANT) then
             cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,cgop,location.size,
             cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,cgop,location.size,
                left.location.register,right.location.register,
                left.location.register,right.location.register,
                location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
                location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
@@ -708,7 +706,7 @@ interface
             begin
             begin
               tmpreg:=cg.getintregister(exprasmlist,location.size);
               tmpreg:=cg.getintregister(exprasmlist,location.size);
               cg.a_load_const_reg(exprasmlist,location.size,
               cg.a_load_const_reg(exprasmlist,location.size,
-                aword(left.location.value),tmpreg);
+                left.location.value,tmpreg);
               cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
               cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
                 right.location.register,tmpreg,location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
                 right.location.register,tmpreg,location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
             end;
             end;

+ 36 - 110
compiler/x86/cgx86.pas

@@ -63,11 +63,6 @@ unit cgx86;
         procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
         procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
         procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
         procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
 
 
-        procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
-          size: tcgsize; a: aint; src, dst: tregister); override;
-        procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
-          size: tcgsize; src1, src2, dst: tregister); override;
-
         { move instructions }
         { move instructions }
         procedure a_load_const_reg(list : taasmoutput; tosize: tcgsize; a : aint;reg : tregister);override;
         procedure a_load_const_reg(list : taasmoutput; tosize: tcgsize; a : aint;reg : tregister);override;
         procedure a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aint;const ref : treference);override;
         procedure a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aint;const ref : treference);override;
@@ -160,8 +155,8 @@ unit cgx86;
        fmodule;
        fmodule;
 
 
     const
     const
-      TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
-                            A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
+      TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_DIV,
+                            A_IDIV,A_IMUL,A_MUL,A_NEG,A_NOT,A_OR,
                             A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
                             A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
 
 
       TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
       TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
@@ -572,7 +567,7 @@ unit cgx86;
         sym : tasmsymbol;
         sym : tasmsymbol;
         r : treference;
         r : treference;
       begin
       begin
- 
+
         if (target_info.system <> system_i386_darwin) then
         if (target_info.system <> system_i386_darwin) then
           begin
           begin
             sym:=objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION);
             sym:=objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION);
@@ -984,10 +979,10 @@ unit cgx86;
         opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
         opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
           ( { scalar }
           ( { scalar }
             ( { OS_F32 }
             ( { OS_F32 }
-              A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP
+              A_NOP,A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP
             ),
             ),
             ( { OS_F64 }
             ( { OS_F64 }
-              A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP
+              A_NOP,A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP
             )
             )
           ),
           ),
           ( { vectorized/packed }
           ( { vectorized/packed }
@@ -995,10 +990,10 @@ unit cgx86;
               these
               these
             }
             }
             ( { OS_F32 }
             ( { OS_F32 }
-              A_NOP,A_ADDPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
+              A_NOP,A_NOP,A_ADDPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
             ),
             ),
             ( { OS_F64 }
             ( { OS_F64 }
-              A_NOP,A_ADDPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPD
+              A_NOP,A_NOP,A_ADDPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPD
             )
             )
           )
           )
         );
         );
@@ -1062,9 +1057,11 @@ unit cgx86;
         tmpreg : tregister;
         tmpreg : tregister;
 {$endif x86_64}
 {$endif x86_64}
       begin
       begin
+        optimize_op_const(op, a);
 {$ifdef x86_64}
 {$ifdef x86_64}
         { x86_64 only supports signed 32 bits constants directly }
         { x86_64 only supports signed 32 bits constants directly }
-        if (size in [OS_S64,OS_64]) and
+        if not(op in [OP_NONE,OP_MOVE) and
+           (size in [OS_S64,OS_64]) and
             ((a<low(longint)) or (a>high(longint))) then
             ((a<low(longint)) or (a>high(longint))) then
           begin
           begin
             tmpreg:=getintregister(list,size);
             tmpreg:=getintregister(list,size);
@@ -1075,6 +1072,15 @@ unit cgx86;
 {$endif x86_64}
 {$endif x86_64}
         check_register_size(size,reg);
         check_register_size(size,reg);
         case op of
         case op of
+          OP_NONE :
+            begin
+              { Opcode is optimized away }
+            end;
+          OP_MOVE :
+            begin
+              { Optimized, replaced with a simple load }
+              a_load_const_reg(list,size,a,reg);
+            end;
           OP_DIV, OP_IDIV:
           OP_DIV, OP_IDIV:
             begin
             begin
               if ispowerof2(int64(a),power) then
               if ispowerof2(int64(a),power) then
@@ -1155,11 +1161,13 @@ unit cgx86;
 {$endif x86_64}
 {$endif x86_64}
         tmpref  : treference;
         tmpref  : treference;
       begin
       begin
+        optimize_op_const(op, a);
         tmpref:=ref;
         tmpref:=ref;
         make_simple_ref(list,tmpref);
         make_simple_ref(list,tmpref);
 {$ifdef x86_64}
 {$ifdef x86_64}
         { x86_64 only supports signed 32 bits constants directly }
         { x86_64 only supports signed 32 bits constants directly }
-        if (size in [OS_S64,OS_64]) and
+        if not(op in [OP_NONE,OP_MOVE) and
+           (size in [OS_S64,OS_64]) and
             ((a<low(longint)) or (a>high(longint))) then
             ((a<low(longint)) or (a>high(longint))) then
           begin
           begin
             tmpreg:=getintregister(list,size);
             tmpreg:=getintregister(list,size);
@@ -1169,6 +1177,15 @@ unit cgx86;
           end;
           end;
 {$endif x86_64}
 {$endif x86_64}
         Case Op of
         Case Op of
+          OP_NONE :
+            begin
+              { Opcode is optimized away }
+            end;
+          OP_MOVE :
+            begin
+              { Optimized, replaced with a simple load }
+              a_load_const_ref(list,size,a,ref);
+            end;
           OP_DIV, OP_IDIV:
           OP_DIV, OP_IDIV:
             Begin
             Begin
               if ispowerof2(int64(a),power) then
               if ispowerof2(int64(a),power) then
@@ -1266,10 +1283,11 @@ unit cgx86;
             internalerror(200109233);
             internalerror(200109233);
           OP_SHR,OP_SHL,OP_SAR:
           OP_SHR,OP_SHL,OP_SAR:
             begin
             begin
-              getcpuregister(list,NR_CL);
-              a_load_reg_reg(list,OS_8,OS_8,makeregsize(list,src,OS_8),NR_CL);
-              list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,src));
-              ungetcpuregister(list,NR_CL);
+              { Use ecx to load the value, that allows beter coalescing }
+              getcpuregister(list,NR_ECX);
+              a_load_reg_reg(list,size,OS_32,src,NR_ECX);
+              list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,dst));
+              ungetcpuregister(list,NR_ECX);
             end;
             end;
           else
           else
             begin
             begin
@@ -1338,98 +1356,6 @@ unit cgx86;
       end;
       end;
 
 
 
 
-    procedure tcgx86.a_op_const_reg_reg(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister);
-      var
-        tmpref: treference;
-        power: longint;
-{$ifdef x86_64}
-        tmpreg : tregister;
-{$endif x86_64}
-      begin
-{$ifdef x86_64}
-        { x86_64 only supports signed 32 bits constants directly }
-        if (size in [OS_S64,OS_64]) and
-            ((a<low(longint)) or (a>high(longint))) then
-          begin
-            tmpreg:=getintregister(list,size);
-            a_load_const_reg(list,size,a,tmpreg);
-            a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
-            exit;
-          end;
-{$endif x86_64}
-        check_register_size(size,src);
-        check_register_size(size,dst);
-        if tcgsize2size[size]<>tcgsize2size[OS_INT] then
-          begin
-            inherited a_op_const_reg_reg(list,op,size,a,src,dst);
-            exit;
-          end;
-        { if we get here, we have to do a 32 bit calculation, guaranteed }
-        case op of
-          OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
-          OP_SAR:
-            { can't do anything special for these }
-            inherited a_op_const_reg_reg(list,op,size,a,src,dst);
-          OP_IMUL:
-            begin
-              if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(int64(a),power) then
-                { can be done with a shift }
-                begin
-                  inherited a_op_const_reg_reg(list,op,size,a,src,dst);
-                  exit;
-                end;
-              list.concat(taicpu.op_const_reg_reg(A_IMUL,tcgsize2opsize[size],a,src,dst));
-            end;
-          OP_ADD, OP_SUB:
-            if (a = 0) then
-              a_load_reg_reg(list,size,size,src,dst)
-            else
-              begin
-                reference_reset(tmpref);
-                tmpref.base := src;
-                tmpref.offset := longint(a);
-                if op = OP_SUB then
-                  tmpref.offset := -tmpref.offset;
-                list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[size],tmpref,dst));
-              end
-          else internalerror(200112302);
-        end;
-      end;
-
-
-    procedure tcgx86.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;size: tcgsize; src1, src2, dst: tregister);
-      var
-        tmpref: treference;
-      begin
-        check_register_size(size,src1);
-        check_register_size(size,src2);
-        check_register_size(size,dst);
-        if tcgsize2size[size]<>tcgsize2size[OS_INT] then
-          begin
-            inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
-            exit;
-          end;
-        { if we get here, we have to do a 32 bit calculation, guaranteed }
-        Case Op of
-          OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
-          OP_SAR,OP_SUB,OP_NOT,OP_NEG:
-            { can't do anything special for these }
-            inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
-          OP_IMUL:
-            list.concat(taicpu.op_reg_reg_reg(A_IMUL,tcgsize2opsize[size],src1,src2,dst));
-          OP_ADD:
-            begin
-              reference_reset(tmpref);
-              tmpref.base := src1;
-              tmpref.index := src2;
-              tmpref.scalefactor := 1;
-              list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[size],tmpref,dst));
-            end
-          else internalerror(200112303);
-        end;
-      end;
-
 {*************** compare instructructions ****************}
 {*************** compare instructructions ****************}
 
 
     procedure tcgx86.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
     procedure tcgx86.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;

+ 5 - 53
compiler/x86/nx86add.pas

@@ -978,65 +978,17 @@ unit nx86add;
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure tx86addnode.second_addordinal;
     procedure tx86addnode.second_addordinal;
-      var
-         mboverflow : boolean;
-         op : tasmop;
-         opsize : tcgsize;
-         { true, if unsigned types are compared }
-         unsigned : boolean;
-         { true, if for sets subtractions the extra not should generated }
-         extra_not : boolean;
       begin
       begin
-         { defaults }
-         extra_not:=false;
-         mboverflow:=false;
-         unsigned:=not(is_signed(left.resulttype.def)) or
-                   not(is_signed(right.resulttype.def));
-         opsize:=def_cgsize(left.resulttype.def);
-
-         pass_left_right;
-
-         case nodetype of
-           addn :
-             begin
-               op:=A_ADD;
-               mboverflow:=true;
-             end;
-           muln :
-             begin
-               if unsigned then
-                 op:=A_MUL
-               else
-                 op:=A_IMUL;
-               mboverflow:=true;
-             end;
-           subn :
-             begin
-               op:=A_SUB;
-               mboverflow:=true;
-             end;
-           xorn :
-             op:=A_XOR;
-           orn :
-             op:=A_OR;
-           andn :
-             op:=A_AND;
-           else
-             internalerror(200304229);
-         end;
-
-         { filter MUL, which requires special handling }
-         if op=A_MUL then
+         { filter unsigned MUL opcode, which requires special handling }
+         if (nodetype=muln) and
+            (not(is_signed(left.resulttype.def)) or
+             not(is_signed(right.resulttype.def))) then
            begin
            begin
              second_mul;
              second_mul;
              exit;
              exit;
            end;
            end;
 
 
-         left_must_be_reg(opsize,false);
-         emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
-         location_freetemp(exprasmlist,right.location);
-
-         set_result_location_reg;
+         inherited second_addordinal;
       end;
       end;