Bläddra i källkod

* modified patch of Paul W to replace leave by mov/pop, resolves #26455

git-svn-id: trunk@29633 -
florian 10 år sedan
förälder
incheckning
35a04ad095
5 ändrade filer med 73 tillägg och 19 borttagningar
  1. 1 1
      compiler/i386/cgcpu.pas
  2. 32 8
      compiler/i386/popt386.pas
  3. 1 9
      compiler/i8086/cgcpu.pas
  4. 38 0
      compiler/x86/cgx86.pas
  5. 1 1
      compiler/x86_64/cgcpu.pas

+ 1 - 1
compiler/i386/cgcpu.pas

@@ -343,7 +343,7 @@ unit cgcpu;
               begin
                 if (not paramanager.use_fixed_stack) then
                   internal_restore_regs(list,not (pi_has_stack_allocs in current_procinfo.flags));
-                list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+                generate_leave(list);
               end;
             list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
           end;

+ 32 - 8
compiler/i386/popt386.pas

@@ -79,6 +79,35 @@ begin
 end;
 
 
+function IsExitCode(p : tai) : boolean;
+  var
+    hp2,hp3 : tai;
+  begin
+    result:=(p.typ=ait_instruction) and
+    ((taicpu(p).opcode = A_RET) or
+     ((taicpu(p).opcode=A_LEAVE) and
+      GetNextInstruction(p,hp2) and
+      (hp2.typ=ait_instruction) and
+      (taicpu(hp2).opcode=A_RET)
+     ) or
+     ((taicpu(p).opcode=A_MOV) and
+      (taicpu(p).oper[0]^.typ=top_reg) and
+      (taicpu(p).oper[0]^.reg=NR_EBP) and
+      (taicpu(p).oper[1]^.typ=top_reg) and
+      (taicpu(p).oper[1]^.reg=NR_ESP) and
+      GetNextInstruction(p,hp2) and
+      (hp2.typ=ait_instruction) and
+      (taicpu(hp2).opcode=A_POP) and
+      (taicpu(hp2).oper[0]^.typ=top_reg) and
+      (taicpu(hp2).oper[0]^.reg=NR_EBP) and
+      GetNextInstruction(hp2,hp3) and
+      (hp3.typ=ait_instruction) and
+      (taicpu(hp3).opcode=A_RET)
+     )
+    );
+  end;
+
+
 function doFpuLoadStoreOpt(asmL: TAsmList; var p: tai): boolean;
 { returns true if a "continue" should be done after this optimization }
 var hp1, hp2: tai;
@@ -99,8 +128,7 @@ begin
       if (taicpu(p).opsize=S_FX) and
          getNextInstruction(hp1, hp2) and
          (hp2.typ = ait_instruction) and
-         ((taicpu(hp2).opcode = A_LEAVE) or
-          (taicpu(hp2).opcode = A_RET)) and
+         IsExitCode(hp2) and
          (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
          not(assigned(current_procinfo.procdef.funcretsym) and
              (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
@@ -517,7 +545,6 @@ function MatchReference(const ref : treference;base,index : TRegister) : Boolean
       (ref.index=index));
   end;
 
-
 { First pass of peephole optimizations }
 procedure PeepHoleOptPass1(Asml: TAsmList; BlockStart, BlockEnd: tai);
 
@@ -1214,8 +1241,7 @@ begin
                     result)}
                           if GetNextInstruction(p, hp1) and
                              (tai(hp1).typ = ait_instruction) then
-                            if ((taicpu(hp1).opcode = A_LEAVE) or
-                                (taicpu(hp1).opcode = A_RET)) and
+                            if IsExitCode(hp1) and
                                (taicpu(p).oper[1]^.typ = top_ref) and
                                (taicpu(p).oper[1]^.ref^.base = current_procinfo.FramePointer) and
                                not(assigned(current_procinfo.procdef.funcretsym) and
@@ -1873,9 +1899,7 @@ begin
                       if (taicpu(p).oper[0]^.typ = top_ref) and
                          GetNextInstruction(p, hp1) and
                          GetNextInstruction(hp1, hp2) and
-                         (hp2.typ = ait_instruction) and
-                         ((taicpu(hp2).opcode = A_LEAVE) or
-                          (taicpu(hp2).opcode = A_RET)) and
+                         IsExitCode(hp2) and
                          (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
                          (taicpu(p).oper[0]^.ref^.index = NR_NO) and
                          not(assigned(current_procinfo.procdef.funcretsym) and

+ 1 - 9
compiler/i8086/cgcpu.pas

@@ -1781,15 +1781,7 @@ unit cgcpu;
                   cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
               end
             else
-              begin
-                if current_settings.cputype < cpu_186 then
-                  begin
-                    list.concat(Taicpu.op_reg_reg(A_MOV, S_W, NR_BP, NR_SP));
-                    list.concat(Taicpu.op_reg(A_POP, S_W, NR_BP));
-                  end
-                else
-                  list.concat(Taicpu.op_none(A_LEAVE,S_NO));
-              end;
+              generate_leave(list);
             list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
           end;
 

+ 38 - 0
compiler/x86/cgx86.pas

@@ -128,6 +128,8 @@ unit cgx86;
         procedure g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string); override;
 
         procedure make_simple_ref(list:TAsmList;var ref: treference);
+
+        procedure generate_leave(list : TAsmList);
       protected
         procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
         procedure check_register_size(size:tcgsize;reg:tregister);
@@ -175,6 +177,9 @@ unit cgx86;
 
     function UseIncDec: boolean;
 
+    { returns true, if the compiler should use leave instead of mov/pop }
+    function UseLeave: boolean;
+
   implementation
 
     uses
@@ -203,6 +208,18 @@ unit cgx86;
       end;
 
 
+    function UseLeave: boolean;
+      begin
+{$if defined(x86_64)}
+        { Modern processors should be happy with mov;pop, maybe except older AMDs }
+        Result:=cs_opt_size in current_settings.optimizerswitches;
+{$elseif defined(i386)}
+        Result:=(cs_opt_size in current_settings.optimizerswitches) or (current_settings.optimizecputype<cpu_Pentium2);
+{$elseif defined(i8086)}
+        Result:=current_settings.cputype>=cpu_186;
+{$endif}
+      end;
+
     const
       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,
@@ -2999,6 +3016,26 @@ unit cgx86;
       end;
 
 
+    procedure tcgx86.generate_leave(list: TAsmList);
+      begin
+        if UseLeave then
+          list.concat(taicpu.op_none(A_LEAVE,S_NO))
+        else
+          begin
+{$if defined(x86_64)}
+            list.Concat(taicpu.op_reg_reg(A_MOV,S_Q,NR_RBP,NR_RSP));
+            list.Concat(taicpu.op_reg(A_POP,S_Q,NR_RBP));
+{$elseif defined(i386)}
+            list.Concat(taicpu.op_reg_reg(A_MOV,S_L,NR_EBP,NR_ESP));
+            list.Concat(taicpu.op_reg(A_POP,S_L,NR_EBP));
+{$elseif defined(i8086)}
+            list.Concat(taicpu.op_reg_reg(A_MOV,S_W,NR_BP,NR_SP));
+            list.Concat(taicpu.op_reg(A_POP,S_W,NR_BP));
+{$endif}
+          end;
+      end;
+
+
     { produces if necessary overflowcode }
     procedure tcgx86.g_overflowcheck(list: TAsmList; const l:tlocation;def:tdef);
       var
@@ -3025,6 +3062,7 @@ unit cgx86;
          a_label(list,hl);
       end;
 
+
     procedure tcgx86.g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string);
       var
         ref : treference;

+ 1 - 1
compiler/x86_64/cgcpu.pas

@@ -398,7 +398,7 @@ unit cgcpu;
                 list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_ADDR],current_procinfo.framepointer));
               end
             else
-              list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+              generate_leave(list);
             list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
           end;