فهرست منبع

+ i386 compiler tracks now flag usage if needed, so the mov $0,reg -> xor reg,reg transformation can be enabled

git-svn-id: trunk@33545 -
florian 9 سال پیش
والد
کامیت
77b4709e7a
4فایلهای تغییر یافته به همراه29 افزوده شده و 8 حذف شده
  1. 11 8
      compiler/i386/aoptcpu.pas
  2. 14 0
      compiler/i386/cgcpu.pas
  3. 2 0
      compiler/i386/n386add.pas
  4. 2 0
      compiler/x86/nx86mat.pas

+ 11 - 8
compiler/i386/aoptcpu.pas

@@ -326,7 +326,6 @@ unit aoptcpu;
     end;
 
 
-
   function TCpuAsmOptimizer.RegReadByInstruction(reg: TRegister; hp: tai): boolean;
     var
       p: taicpu;
@@ -389,6 +388,12 @@ unit aoptcpu;
                       RegReadByInstruction := true;
                       exit
                     end;
+                Ch_RFlags,Ch_RWFlags:
+                  if reg=NR_DEFAULTFLAGS then
+                    begin
+                      RegReadByInstruction := true;
+                      exit
+                  end;
               end;
           end;
       end;
@@ -2534,8 +2539,10 @@ var
   IsTestConstX: boolean;
 begin
   p := BlockStart;
+  ClearUsedRegs;
   while (p <> BlockEnd) Do
     begin
+      UpdateUsedRegs(UsedRegs, tai(p.next));
       case p.Typ Of
         Ait_Instruction:
           begin
@@ -2599,19 +2606,15 @@ begin
                       continue;
                     end;
                 end;
-(*
-Optimization is not safe; xor clears the carry flag.
-See test/tgadint64 in the test suite.
               A_MOV:
-                if (taicpu(p).oper[0]^.typ = Top_Const) and
-                   (taicpu(p).oper[0]^.val = 0) and
-                   (taicpu(p).oper[1]^.typ = Top_Reg) then
+                if MatchOperand(taicpu(p).oper[0]^,0) and
+                   (taicpu(p).oper[1]^.typ = Top_Reg) and
+                   not(RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs)) then
                   { change "mov $0, %reg" into "xor %reg, %reg" }
                   begin
                     taicpu(p).opcode := A_XOR;
                     taicpu(p).loadReg(0,taicpu(p).oper[1]^.reg);
                   end;
-*)
               A_MOVZX:
                 { if register vars are on, it's possible there is code like }
                 {   "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx"           }

+ 14 - 0
compiler/i386/cgcpu.pas

@@ -640,9 +640,13 @@ unit cgcpu;
             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_ref_reg(op1,S_L,tempref,reg.reglo));
             inc(tempref.offset,4);
             list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
+            if op in [OP_ADD,OP_SUB] then
+              cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
           end
         else
           begin
@@ -662,8 +666,10 @@ unit cgcpu;
               if (regsrc.reglo<>regdst.reglo) then
                 a_load64_reg_reg(list,regsrc,regdst);
               list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
+              cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
               list.concat(taicpu.op_reg(A_NEG,S_L,regdst.reglo));
               list.concat(taicpu.op_const_reg(A_SBB,S_L,-1,regdst.reghi));
+              cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
               exit;
             end;
           OP_NOT :
@@ -676,8 +682,12 @@ unit cgcpu;
             end;
         end;
         get_64bit_ops(op,op1,op2);
+        if op in [OP_ADD,OP_SUB] then
+          cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
         list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
         list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
+        if op in [OP_ADD,OP_SUB] then
+          cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
       end;
 
 
@@ -695,8 +705,10 @@ unit cgcpu;
             begin
               // can't use a_op_const_ref because this may use dec/inc
               get_64bit_ops(op,op1,op2);
+              cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
               list.concat(taicpu.op_const_reg(op1,S_L,aint(lo(value)),reg.reglo));
               list.concat(taicpu.op_const_reg(op2,S_L,aint(hi(value)),reg.reghi));
+              cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
             end;
           else
             internalerror(200204021);
@@ -722,9 +734,11 @@ unit cgcpu;
             begin
               get_64bit_ops(op,op1,op2);
               // can't use a_op_const_ref because this may use dec/inc
+              cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
               list.concat(taicpu.op_const_ref(op1,S_L,aint(lo(value)),tempref));
               inc(tempref.offset,4);
               list.concat(taicpu.op_const_ref(op2,S_L,aint(hi(value)),tempref));
+              cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
             end;
           else
             internalerror(200204022);

+ 2 - 0
compiler/i386/n386add.pas

@@ -190,11 +190,13 @@ interface
             begin
               r:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
               cg64.a_load64low_loc_reg(current_asmdata.CurrAsmList,right.location,r);
+              cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
               emit_reg_reg(op1,opsize,left.location.register64.reglo,r);
               emit_reg_reg(A_MOV,opsize,r,left.location.register64.reglo);
               cg64.a_load64high_loc_reg(current_asmdata.CurrAsmList,right.location,r);
               { the carry flag is still ok }
               emit_reg_reg(op2,opsize,left.location.register64.reghi,r);
+              cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
               emit_reg_reg(A_MOV,opsize,r,left.location.register64.reghi);
             end
            else

+ 2 - 0
compiler/x86/nx86mat.pas

@@ -471,6 +471,7 @@ interface
                     d:=tordconstnode(right).value.svalue;
                     if d>=aword(1) shl (left.resultdef.size*8-1) then
                       begin
+                        cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         if (cgsize in [OS_64,OS_S64]) then
                           begin
                             hreg2:=cg.getintregister(current_asmdata.CurrAsmList,cgsize);
@@ -482,6 +483,7 @@ interface
                         location.register:=cg.getintregister(current_asmdata.CurrAsmList,cgsize);
                         emit_const_reg(A_MOV,opsize,0,location.register);
                         emit_const_reg(A_SBB,opsize,-1,location.register);
+                        cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                       end
                     else
                       begin