Browse Source

* i386: Bug fix where EBP was marked as preserved when it wasn't, causing faulty optimisations

J. Gareth "Curious Kit" Moreton 2 years ago
parent
commit
4e8ef448ed
2 changed files with 15 additions and 3 deletions
  1. 10 2
      compiler/i386/cgcpu.pas
  2. 5 1
      compiler/x86/aoptx86.pas

+ 10 - 2
compiler/i386/cgcpu.pas

@@ -82,10 +82,18 @@ unit cgcpu;
     procedure tcg386.init_register_allocators;
       begin
         inherited init_register_allocators;
-        if (cs_useebp in current_settings.optimizerswitches) and assigned(current_procinfo) and (current_procinfo.framepointer<>NR_EBP) then
-          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI,RS_EBP],first_int_imreg,[])
+
+        if assigned(current_procinfo) and (current_procinfo.framepointer<>NR_EBP) then
+          begin
+            { Sometimes, whole program optimization will forego a frame pointer on leaf functions }
+            if (cs_useebp in current_settings.optimizerswitches) then
+              rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI,RS_EBP],first_int_imreg,[])
+            else
+              rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[]);
+          end
         else
           rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
+
         rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
         rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBWHOLE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
         rgfpu:=Trgx86fpu.create;

+ 5 - 1
compiler/x86/aoptx86.pas

@@ -1362,7 +1362,11 @@ unit aoptx86;
         RegSet :=
           paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption) +
           current_procinfo.saved_regs_int;
-
+(*
+        { Don't use the frame register unless explicitly allowed (fixes i40111) }
+        if ([cs_useebp, cs_userbp] * current_settings.optimizerswitches) = [] then
+          Exclude(RegSet, RS_FRAME_POINTER_REG);
+*)
         for CurrentSuperReg in RegSet do
           begin
             CurrentReg := newreg(R_INTREGISTER, TSuperRegister(CurrentSuperReg), RegSize);