瀏覽代碼

+ implemented the in_neg_assign_x and in_not_assign_x inline nodes, which will
be used (TBD in a future commit) for optimizing x:=-x and x:=not x on CPUs
that support performing these operations directly in memory (such as x86)

git-svn-id: trunk@35749 -

nickysn 8 年之前
父節點
當前提交
256dc546ac

+ 2 - 0
.gitattributes

@@ -11572,6 +11572,7 @@ tests/test/cg/tmoddiv1.pp svneol=native#text/plain
 tests/test/cg/tmoddiv2.pp svneol=native#text/plain
 tests/test/cg/tmul3264.pp svneol=native#text/plain
 tests/test/cg/tneg.pp svneol=native#text/plain
+tests/test/cg/tnegnotassign1.pp svneol=native#text/plain
 tests/test/cg/tnot.pp svneol=native#text/plain
 tests/test/cg/tobjsiz2.pp svneol=native#text/plain
 tests/test/cg/tobjsize.pp svneol=native#text/plain
@@ -11602,6 +11603,7 @@ tests/test/cg/ttryfin5.pp svneol=native#text/plain
 tests/test/cg/tumin.pp svneol=native#text/plain
 tests/test/cg/tvec.pp svneol=native#text/plain
 tests/test/cg/uandorxorassign.pp svneol=native#text/plain
+tests/test/cg/unegnotassign.pp svneol=native#text/plain
 tests/test/cg/uprintf3.pp svneol=native#text/plain
 tests/test/cg/variants/ivarol10.pp svneol=native#text/plain
 tests/test/cg/variants/ivarol100.pp svneol=native#text/plain

+ 4 - 1
compiler/cg64f32.pas

@@ -739,7 +739,10 @@ unit cg64f32;
         tempreg.reghi:=cg.getintregister(list,OS_32);
         tempreg.reglo:=cg.getintregister(list,OS_32);
         a_load64_ref_reg(list,ref,tempreg);
-        a_op64_reg_reg(list,op,size,reg,tempreg);
+        if op in [OP_NEG,OP_NOT] then
+          a_op64_reg_reg(list,op,size,tempreg,tempreg)
+        else
+          a_op64_reg_reg(list,op,size,reg,tempreg);
         a_load64_reg_ref(list,tempreg,ref);
       end;
 

+ 1 - 2
compiler/compinnr.inc

@@ -101,10 +101,9 @@ const
    in_shl_assign_x_y    = 90;
    in_shr_assign_x_y    = 91;
    in_rol_assign_x_y    = 92;
-   in_ror_assign_x_y    = 93;
+   in_ror_assign_x_y    = 93;}
    in_neg_assign_x      = 94;
    in_not_assign_x      = 95;
-}
 
 { Internal constant functions }
    in_const_sqr        = 100;

+ 34 - 13
compiler/i386/cgcpu.pas

@@ -662,21 +662,42 @@ unit cgcpu;
         op1,op2 : TAsmOp;
         tempref : treference;
       begin
-        if not(op in [OP_NEG,OP_NOT]) then
-          begin
-            get_64bit_ops(op,op1,op2);
-            tempref:=ref;
-            tcgx86(cg).make_simple_ref(list,tempref);
-            if op in [OP_ADD,OP_SUB] then
+        case op of
+          OP_NOT:
+            begin
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
+            end;
+          OP_NEG:
+            begin
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
               cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
-            list.concat(taicpu.op_reg_ref(op1,S_L,reg.reglo,tempref));
-            inc(tempref.offset,4);
-            list.concat(taicpu.op_reg_ref(op2,S_L,reg.reghi,tempref));
-            if op in [OP_ADD,OP_SUB] then
+              dec(tempref.offset,4);
+              list.concat(taicpu.op_ref(A_NEG,S_L,tempref));
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_const_ref(A_SBB,S_L,-1,tempref));
               cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
-          end
-        else
-          inherited;
+            end;
+          else
+            begin
+              get_64bit_ops(op,op1,op2);
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              if op in [OP_ADD,OP_SUB] then
+                cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
+              list.concat(taicpu.op_reg_ref(op1,S_L,reg.reglo,tempref));
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_reg_ref(op2,S_L,reg.reghi,tempref));
+              if op in [OP_ADD,OP_SUB] then
+                cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
+            end;
+        end;
       end;
 
 

+ 48 - 16
compiler/i8086/cgcpu.pas

@@ -1011,7 +1011,8 @@ unit cgcpu;
       begin
         tmpref:=ref;
         make_simple_ref(list,tmpref);
-        check_register_size(size,reg);
+        if not (op in [OP_NEG,OP_NOT]) then
+          check_register_size(size,reg);
 
         if size in [OS_64, OS_S64] then
           internalerror(2013050803);
@@ -2593,21 +2594,52 @@ unit cgcpu;
         op1,op2 : TAsmOp;
         tempref : treference;
       begin
-        if not(op in [OP_NEG,OP_NOT]) then
-          begin
-            get_64bit_ops(op,op1,op2);
-            tempref:=ref;
-            tcgx86(cg).make_simple_ref(list,tempref);
-            list.concat(taicpu.op_reg_ref(op1,S_W,reg.reglo,tempref));
-            inc(tempref.offset,2);
-            list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reglo),tempref));
-            inc(tempref.offset,2);
-            list.concat(taicpu.op_reg_ref(op2,S_W,reg.reghi,tempref));
-            inc(tempref.offset,2);
-            list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reghi),tempref));
-          end
-        else
-          inherited;
+        case op of
+          OP_NOT:
+            begin
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+            end;
+          OP_NEG:
+            begin
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              inc(tempref.offset,6);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+              dec(tempref.offset,2);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+              dec(tempref.offset,2);
+              list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
+              dec(tempref.offset,2);
+              list.concat(taicpu.op_ref(A_NEG,S_W,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
+            end;
+          else
+            begin
+              get_64bit_ops(op,op1,op2);
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              list.concat(taicpu.op_reg_ref(op1,S_W,reg.reglo,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reglo),tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_reg_ref(op2,S_W,reg.reghi,tempref));
+              inc(tempref.offset,2);
+              list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reghi),tempref));
+            end;
+        end;
       end;
 
 

+ 27 - 0
compiler/ncginl.pas

@@ -36,6 +36,7 @@ interface
           procedure second_predsucc;virtual;
           procedure second_incdec;virtual;
           procedure second_AndOrXor_assign;virtual;
+          procedure second_NegNot_assign;virtual;
           procedure second_typeinfo;virtual;
           procedure second_includeexclude;virtual;
           procedure second_pi; virtual;
@@ -204,6 +205,9 @@ implementation
             in_or_assign_x_y,
             in_xor_assign_x_y:
                second_AndOrXor_assign;
+            in_neg_assign_x,
+            in_not_assign_x:
+               second_NegNot_assign;
             else internalerror(9);
          end;
       end;
@@ -493,6 +497,29 @@ implementation
         end;
 
 
+{*****************************************************************************
+                       NEG/NOT ASSIGN GENERIC HANDLING
+*****************************************************************************}
+      procedure tcginlinenode.second_NegNot_assign;
+        const
+          negnotop:array[in_neg_assign_x..in_not_assign_x] of TOpCG=(OP_NEG,OP_NOT);
+{$ifndef cpu64bitalu}
+        var
+          NR_NO64: tregister64=(reglo:NR_NO;reghi:NR_NO);
+{$endif not cpu64bitalu}
+        begin
+          { load parameter, must be a reference }
+          secondpass(left);
+
+{$ifndef cpu64bitalu}
+          if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
+            cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],def_cgsize(left.resultdef),NR_NO64,left.location)
+          else
+{$endif not cpu64bitalu}
+            hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],left.resultdef,NR_NO,left.location);
+        end;
+
+
 {*****************************************************************************
                          TYPEINFO GENERIC HANDLING
 *****************************************************************************}

+ 42 - 0
compiler/ninl.pas

@@ -91,6 +91,7 @@ interface
           function first_sar: tnode; virtual;
           function first_fma : tnode; virtual;
           function first_AndOrXor_assign: tnode; virtual;
+          function first_NegNot_assign: tnode; virtual;
         private
           function handle_str: tnode;
           function handle_reset_rewrite_typed: tnode;
@@ -3067,6 +3068,34 @@ implementation
                     end;
                 end;
 
+              in_neg_assign_x,
+              in_not_assign_x:
+                begin
+                  resultdef:=voidtype;
+                  if not(df_generic in current_procinfo.procdef.defoptions) then
+                    begin
+                      valid_for_var(left,true);
+                      set_varstate(left,vs_readwritten,[vsf_must_be_valid]);
+
+                      if is_integer(left.resultdef) then
+                        begin
+                          { value of left gets changed -> must be unique }
+                          set_unique(left);
+                          { these nodes shouldn't be created, when range checking is on }
+                          if [cs_check_range,cs_check_overflow]*current_settings.localswitches<>[] then
+                            internalerror(2017040703);
+                        end
+                      { generic type parameter? }
+                      else if is_typeparam(left.resultdef) then
+                        begin
+                          result:=cnothingnode.create;
+                          exit;
+                        end
+                      else
+                        CGMessagePos(left.fileinfo,type_e_ordinal_expr_expected);
+                    end;
+                end;
+
               in_read_x,
               in_readln_x,
               in_readstr_x,
@@ -3597,6 +3626,12 @@ implementation
               result:=first_AndOrXor_assign;
             end;
 
+          in_neg_assign_x,
+          in_not_assign_x:
+            begin
+              result:=first_NegNot_assign;
+            end;
+
          in_include_x_y,
          in_exclude_x_y:
            begin
@@ -4618,5 +4653,12 @@ implementation
          expectloc:=tcallparanode(tcallparanode(left).right).left.expectloc;
        end;
 
+
+     function tinlinenode.first_NegNot_assign: tnode;
+       begin
+         result:=nil;
+         expectloc:=left.expectloc;
+       end;
+
 end.
 

+ 2 - 1
compiler/x86/cgx86.pas

@@ -2059,7 +2059,8 @@ unit cgx86;
       begin
         tmpref:=ref;
         make_simple_ref(list,tmpref);
-        check_register_size(size,reg);
+        if not (op in [OP_NEG,OP_NOT]) then
+          check_register_size(size,reg);
         if (op=OP_MUL) and not (cs_check_overflow in current_settings.localswitches) then
           op:=OP_IMUL;
         case op of

+ 5 - 3
rtl/inc/innr.inc

@@ -94,9 +94,11 @@ const
    fpc_in_delete_x_y_z      = 83;
    fpc_in_reset_typedfile_name   = 84;
    fpc_in_rewrite_typedfile_name = 85;
-   fpc_in_and_assign_x_y   = 86;
-   fpc_in_or_assign_x_y    = 87;
-   fpc_in_xor_assign_x_y   = 88;
+   fpc_in_and_assign_x_y    = 86;
+   fpc_in_or_assign_x_y     = 87;
+   fpc_in_xor_assign_x_y    = 88;
+   fpc_in_neg_assign_x      = 94;
+   fpc_in_not_assign_x      = 95;
 
 { Internal constant functions }
    fpc_in_const_sqr        = 100;

+ 104 - 0
tests/test/cg/tnegnotassign1.pp

@@ -0,0 +1,104 @@
+program tnegnotassign1;
+
+uses unegnotassign;
+
+{$R-,Q-}
+
+procedure Check(Value, ExpectedValue: QWord);
+begin
+  if Value <> ExpectedValue then
+  begin
+    Writeln('Error!');
+    Halt(1);
+  end;
+end;
+
+var
+  gr: record
+    b: Byte;
+    w: Word;
+    d: DWord;
+    q: QWord;
+  end;
+
+procedure Test_RegVar;
+var
+  b: Byte;
+  w: Word;
+  d: DWord;
+  q: QWord;
+begin
+  b := $5A;
+  NotAssignByte(b);
+  Check(b,$A5);
+
+  w := $5A7E;
+  NotAssignWord(w);
+  Check(w, $A581);
+
+  d := $5A7EFF44;
+  NotAssignDWord(d);
+  Check(d, $A58100BB);
+
+  q := $5A7EFF4455AAFF00;
+  NotAssignQWord(q);
+  Check(q, $A58100BBAA5500FF);
+
+  b := $5A;
+  NegAssignByte(b);
+  Check(b,$A6);
+
+  w := $5A7E;
+  NegAssignWord(w);
+  Check(w, $A582);
+
+  d := $5A7EFF44;
+  NegAssignDWord(d);
+  Check(d, $A58100BC);
+
+  q := $5A7EFF4455AAFF00;
+  NegAssignQWord(q);
+  Check(q, $A58100BBAA550100);
+end;
+
+procedure Test_Ref;
+begin
+  gr.b := $5A;
+  NotAssignByte(gr.b);
+  Check(gr.b,$A5);
+
+  gr.w := $5A7E;
+  NotAssignWord(gr.w);
+  Check(gr.w, $A581);
+
+  gr.d := $5A7EFF44;
+  NotAssignDWord(gr.d);
+  Check(gr.d, $A58100BB);
+
+  gr.q := $5A7EFF4455AAFF00;
+  NotAssignQWord(gr.q);
+  Check(gr.q, $A58100BBAA5500FF);
+
+  gr.b := $5A;
+  NegAssignByte(gr.b);
+  Check(gr.b,$A6);
+
+  gr.w := $5A7E;
+  NegAssignWord(gr.w);
+  Check(gr.w, $A582);
+
+  gr.d := $5A7EFF44;
+  NegAssignDWord(gr.d);
+  Check(gr.d, $A58100BC);
+
+  gr.q := $5A7EFF4455AAFF00;
+  NegAssignQWord(gr.q);
+  Check(gr.q, $A58100BBAA550100);
+end;
+
+begin
+  Test_RegVar;
+  Test_Ref;
+
+  Writeln('Ok!');
+end.

+ 21 - 0
tests/test/cg/unegnotassign.pp

@@ -0,0 +1,21 @@
+unit unegnotassign;
+
+interface
+
+const
+   fpc_in_neg_assign_x      = 94;
+   fpc_in_not_assign_x      = 95;
+
+procedure NegAssignByte(var X: Byte);[internproc:fpc_in_neg_assign_x];
+procedure NegAssignWord(var X: Word);[internproc:fpc_in_neg_assign_x];
+procedure NegAssignDWord(var X: DWord);[internproc:fpc_in_neg_assign_x];
+procedure NegAssignQWord(var X: QWord);[internproc:fpc_in_neg_assign_x];
+
+procedure NotAssignByte(var X: Byte);[internproc:fpc_in_not_assign_x];
+procedure NotAssignWord(var X: Word);[internproc:fpc_in_not_assign_x];
+procedure NotAssignDWord(var X: DWord);[internproc:fpc_in_not_assign_x];
+procedure NotAssignQWord(var X: QWord);[internproc:fpc_in_not_assign_x];
+
+implementation
+
+end.