浏览代码

* fixed optimiser so it compiles again
* fixed several bugs which were in there already for a long time, but
which only popped up now :) -O2/-O3 will now optimise less than in
the past (and correctly so), but -O2u/-O3u will optimise a bit more
* some more small improvements for -O3 are still possible

Jonas Maebe 22 年之前
父节点
当前提交
aad37ce53c
共有 5 个文件被更改,包括 2185 次插入2290 次删除
  1. 369 324
      compiler/i386/csopt386.pas
  2. 368 465
      compiler/i386/daopt386.pas
  3. 1331 1388
      compiler/i386/popt386.pas
  4. 98 103
      compiler/i386/rropt386.pas
  5. 19 10
      compiler/psub.pas

文件差异内容过多而无法显示
+ 369 - 324
compiler/i386/csopt386.pas


文件差异内容过多而无法显示
+ 368 - 465
compiler/i386/daopt386.pas


文件差异内容过多而无法显示
+ 1331 - 1388
compiler/i386/popt386.pas


+ 98 - 103
compiler/i386/rropt386.pas

@@ -21,23 +21,23 @@
 
  ****************************************************************************
 }
-Unit rrOpt386;
+unit rropt386;
 
 {$i fpcdefs.inc}
 
-Interface
+interface
 
-Uses aasmbase,aasmtai,aasmcpu;
+uses aasmbase,aasmtai,aasmcpu;
 
-procedure doRenaming(asml: TAAsmoutput; first, last: Tai);
+procedure doRenaming(asml: taasmoutput; first, last: tai);
 
-Implementation
+implementation
 
-Uses
+uses
   {$ifdef replaceregdebug}cutils,{$endif}
-  verbose,globals,cpubase,daopt386,csopt386,cginfo,rgobj;
+  verbose,globals,cpubase,daopt386,csopt386,rgobj, cgbase, cgobj;
 
-function canBeFirstSwitch(p: Taicpu; reg: tregister): boolean;
+function canBeFirstSwitch(p: taicpu; supreg: tsuperregister): boolean;
 { checks whether an operation on reg can be switched to another reg without an }
 { additional mov, e.g. "addl $4,%reg1" can be changed to "leal 4(%reg1),%reg2" }
 begin
@@ -45,64 +45,56 @@ begin
   case p.opcode of
     A_MOV,A_MOVZX,A_MOVSX,A_LEA:
       canBeFirstSwitch :=
-        (p.oper[1].typ = top_reg) and
-        (reg32(p.oper[1].reg).enum = reg.enum);
+        (p.oper[1]^.typ = top_reg) and
+        (getsupreg(p.oper[1]^.reg) = supreg);
     A_IMUL:
       canBeFirstSwitch :=
         (p.ops >= 2) and
-        (reg32(p.oper[p.ops-1].reg).enum = reg.enum) and
-        (p.oper[0].typ <> top_ref) and
+        (getsupreg(p.oper[p.ops-1]^.reg) = supreg) and
+        (p.oper[0]^.typ <> top_ref) and
         (not pTaiprop(p.optinfo)^.FlagsUsed);
-    A_INC,A_DEC,A_SUB,A_ADD:
+    A_INC,A_DEC:
+      canBeFirstSwitch := 
+        (p.oper[0]^.typ = top_reg) and
+        (p.opsize = S_L) and
+        (not pTaiprop(p.optinfo)^.FlagsUsed);
+    A_SUB,A_ADD:
       canBeFirstSwitch :=
-        (p.oper[1].typ = top_reg) and
+        (p.oper[1]^.typ = top_reg) and
         (p.opsize = S_L) and
-        (reg32(p.oper[1].reg).enum = reg.enum) and
-        (p.oper[0].typ <> top_ref) and
+        (getsupreg(p.oper[1]^.reg) = supreg) and
+        (p.oper[0]^.typ <> top_ref) and
         ((p.opcode <> A_SUB) or
-         (p.oper[0].typ = top_const)) and
+         (p.oper[0]^.typ = top_const)) and
         (not pTaiprop(p.optinfo)^.FlagsUsed);
     A_SHL:
       canBeFirstSwitch :=
         (p.opsize = S_L) and
-        (p.oper[1].typ = top_reg) and
-        (p.oper[1].reg.enum = reg.enum) and
-        (p.oper[0].typ = top_const) and
-        (p.oper[0].val in [1,2,3]) and
+        (p.oper[1]^.typ = top_reg) and
+        (getsupreg(p.oper[1]^.reg) = supreg) and
+        (p.oper[0]^.typ = top_const) and
+        (p.oper[0]^.val in [1,2,3]) and
         (not pTaiprop(p.optinfo)^.FlagsUsed);
   end;
 end;
 
-procedure switchReg(var reg: tregister; reg1, reg2: tregister);
+
+procedure switchReg(var reg: tregister; reg1, reg2: tsuperregister);
+var
+  supreg: tsuperregister;
 begin
-  if reg1.enum>lastreg then
-    internalerror(2003010801);
-  if reg2.enum>lastreg then
-    internalerror(2003010801);
-  if reg.enum>lastreg then
-    internalerror(2003010801);
-  if reg.enum = reg1.enum then
-    reg := reg2
-  else if reg.enum = reg2.enum then
-    reg := reg1
-  else if (reg.enum in regset8bit) then
-    begin
-      if (reg.enum = changeregsize(reg1,S_B).enum) then
-        reg := changeregsize(reg2,S_B)
-      else if reg.enum = changeregsize(reg2,S_B).enum then
-        reg := changeregsize(reg1,S_B);
-    end
-  else if (reg.enum in regset16bit) then
-    begin
-      if reg.enum = changeregsize(reg1,S_W).enum then
-        reg := changeregsize(reg2,S_W)
-      else if reg.enum = changeregsize(reg2,S_W).enum then
-        reg := changeregsize(reg1,S_W);
-    end;
+  if (reg = NR_NO) or
+     (getregtype(reg) <> R_INTREGISTER) then
+    exit;
+  supreg := getsupreg(reg);
+  if (supreg = reg1) then
+    setsupreg(reg,reg2)
+  else if (supreg = reg2) then
+    setsupreg(reg,reg1);
 end;
 
 
-procedure switchOp(var op: toper; reg1, reg2: tregister);
+procedure switchOp(var op: toper; reg1, reg2: tsuperregister);
 begin
   case op.typ of
     top_reg:
@@ -115,35 +107,36 @@ begin
   end;
 end;
 
-procedure doSwitchReg(hp: Taicpu; reg1,reg2: tregister);
+
+procedure doSwitchReg(hp: taicpu; reg1,reg2: tsuperregister);
 var
   opCount: longint;
 begin
   for opCount := 0 to hp.ops-1 do
-    switchOp(hp.oper[opCount],reg1,reg2);
+    switchOp(hp.oper[opCount]^,reg1,reg2);
 end;
 
 
-procedure doFirstSwitch(p: Taicpu; reg1, reg2: tregister);
+procedure doFirstSwitch(p: taicpu; reg1, reg2: tsuperregister);
 var
   tmpRef: treference;
 begin
   case p.opcode of
     A_MOV,A_MOVZX,A_MOVSX,A_LEA:
        begin
-         changeOp(p.oper[1],reg1,reg2);
-         changeOp(p.oper[0],reg2,reg1);
+         changeOp(p.oper[1]^,reg1,reg2);
+         changeOp(p.oper[0]^,reg2,reg1);
        end;
     A_IMUL:
       begin
         p.ops := 3;
-        p.loadreg(2,p.oper[1].reg);
-        changeOp(p.oper[2],reg1,reg2);
+        p.loadreg(2,p.oper[1]^.reg);
+        changeOp(p.oper[2]^,reg1,reg2);
       end;
     A_INC,A_DEC:
       begin
         reference_reset(tmpref);
-        tmpref.base := reg1;
+        tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
         case p.opcode of
           A_INC:
             tmpref.offset := 1;
@@ -152,51 +145,51 @@ begin
         end;
         p.ops := 2;
         p.opcode := A_LEA;
-        p.loadreg(1,reg2);
+        p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
         p.loadref(0,tmpref);
       end;
     A_SUB,A_ADD:
       begin
         reference_reset(tmpref);
-        tmpref.base := reg1;
-        case p.oper[0].typ of
+        tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+        case p.oper[0]^.typ of
           top_const:
             begin
-              tmpref.offset := p.oper[0].val;
+              tmpref.offset := longint(p.oper[0]^.val);
               if p.opcode = A_SUB then
                 tmpref.offset := - tmpRef.offset;
             end;
           top_symbol:
-            tmpref.symbol := p.oper[0].sym;
+            tmpref.symbol := p.oper[0]^.sym;
           top_reg:
             begin
-              tmpref.index := p.oper[0].reg;
+              tmpref.index := p.oper[0]^.reg;
               tmpref.scalefactor := 1;
             end;
           else internalerror(200010031);
         end;
         p.opcode := A_LEA;
         p.loadref(0,tmpref);
-        p.loadreg(1,reg2);
+        p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
       end;
     A_SHL:
       begin
         reference_reset(tmpref);
-        tmpref.index := reg1;
-        tmpref.scalefactor := 1 shl p.oper[0].val;
+        tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+        tmpref.scalefactor := 1 shl p.oper[0]^.val;
         p.opcode := A_LEA;
         p.loadref(0,tmpref);
-        p.loadreg(1,reg2);
+        p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
       end;
     else internalerror(200010032);
   end;
 end;
 
 
-function switchRegs(asml: TAAsmoutput; reg1, reg2: tregister; start: Tai): Boolean;
+function switchRegs(asml: taasmoutput; reg1, reg2: tsuperregister; start: tai): Boolean;
 { change movl  %reg1,%reg2 ... bla ... to ... bla with reg1 and reg2 switched }
 var
-  endP, hp, lastreg1,lastreg2: Tai;
+  endP, hp, lastreg1,lastreg2: tai;
   switchDone, switchLast, tmpResult, sequenceEnd, reg1Modified, reg2Modified: boolean;
   reg1StillUsed, reg2StillUsed, isInstruction: boolean;
 begin
@@ -217,8 +210,8 @@ begin
           { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
           { %oldReg" to "<operations on %oldReg>"                       }
           switchLast := storeBack(endP,reg1,reg2);
-          reg1StillUsed := reg1.enum in pTaiprop(endp.optinfo)^.usedregs;
-          reg2StillUsed := reg2.enum in pTaiprop(endp.optinfo)^.usedregs;
+          reg1StillUsed := reg1 in pTaiprop(endp.optinfo)^.usedregs;
+          reg2StillUsed := reg2 in pTaiprop(endp.optinfo)^.usedregs;
           isInstruction := endp.typ = ait_instruction;
           sequenceEnd :=
             switchLast or
@@ -227,13 +220,13 @@ begin
             (not reg1StillUsed and not reg2StillUsed) or
             { no support for (i)div, mul and imul with hardcoded operands }
             (((not isInstruction) or
-              noHardCodedRegs(Taicpu(endP),reg1,reg2)) and
+              noHardCodedRegs(taicpu(endP),reg1,reg2)) and
              (not reg1StillUsed or
               (isInstruction and findRegDealloc(reg1,endP) and
-               regLoadedWithNewValue(reg1,false,Taicpu(endP)))) and
+               regLoadedWithNewValue(reg1,false,taicpu(endP)))) and
              (not reg2StillUsed or
               (isInstruction and findRegDealloc(reg2,endP) and
-               regLoadedWithNewValue(reg2,false,Taicpu(endP)))));
+               regLoadedWithNewValue(reg2,false,taicpu(endP)))));
 
           { we can't switch reg1 and reg2 in something like }
           {   movl  %reg1,%reg2                             }
@@ -249,7 +242,7 @@ begin
           if not reg1Modified then
             begin
               reg1Modified := regModifiedByInstruction(reg1,endP);
-              if reg1Modified and not canBeFirstSwitch(Taicpu(endP),reg1) then
+              if reg1Modified and not canBeFirstSwitch(taicpu(endP),reg1) then
                 begin
                   tmpResult := false;
                   break;
@@ -264,9 +257,9 @@ begin
           tmpResult :=
             (endp.typ <> ait_label) and
             ((not isInstruction) or
-             (NoHardCodedRegs(Taicpu(endP),reg1,reg2) and
-              RegSizesOk(reg1,reg2,Taicpu(endP)) and
-              (Taicpu(endp).opcode <> A_JMP)));
+             (NoHardCodedRegs(taicpu(endP),reg1,reg2) and
+              RegSizesOk(reg1,reg2,taicpu(endP)) and
+              (taicpu(endp).opcode <> A_JMP)));
         end;
     end;
 
@@ -289,33 +282,35 @@ begin
                   reg1Modified := regModifiedByInstruction(reg1,hp);
                   if reg1Modified then
                     begin
-                      doFirstSwitch(Taicpu(hp),reg1,reg2);
+                      doFirstSwitch(taicpu(hp),reg1,reg2);
                       switchDone := true;
                     end;
                 end;
               if not switchDone then
                 if reg1Modified then
-                  doSwitchReg(Taicpu(hp),reg1,reg2)
+                  doSwitchReg(taicpu(hp),reg1,reg2)
                 else
-                  doReplaceReg(Taicpu(hp),reg2,reg1);
+                  doReplaceReg(taicpu(hp),reg2,reg1);
             end;
-          if regininstruction(reg1.enum,hp) then
+          if regininstruction(reg1,hp) then
              lastreg1 := hp;
-          if regininstruction(reg2.enum,hp) then
+          if regininstruction(reg2,hp) then
              lastreg2 := hp;
           getNextInstruction(hp,hp);
         end;
       if switchLast then
-        doSwitchReg(Taicpu(hp),reg1,reg2)
-      else getLastInstruction(hp,hp);
-      allocRegBetween(asmL,reg1,start,lastreg1);
-      allocRegBetween(asmL,reg2,start,lastreg2);
+        doSwitchReg(taicpu(hp),reg1,reg2)
+      else
+        getLastInstruction(hp,hp);
+      allocRegBetween(asmL,newreg(R_INTREGISTER,reg1,R_SUBWHOLE),start,lastreg1);
+      allocRegBetween(asmL,newreg(R_INTREGISTER,reg2,R_SUBWHOLE),start,lastreg2);
     end;
 end;
 
-procedure doRenaming(asml: TAAsmoutput; first, last: Tai);
+
+procedure doRenaming(asml: taasmoutput; first, last: tai);
 var
-  p: Tai;
+  p: tai;
 begin
   p := First;
   SkipHead(p);
@@ -324,25 +319,18 @@ begin
       case p.typ of
         ait_instruction:
           begin
-            case Taicpu(p).opcode of
+            case taicpu(p).opcode of
               A_MOV:
                 begin
                   if not(pTaiprop(p.optinfo)^.canBeRemoved) and
-                     (Taicpu(p).oper[0].typ = top_reg) and
-                     (Taicpu(p).oper[1].typ = top_reg) and
-                     (Taicpu(p).opsize = S_L) and
-{                     (Taicpu(p).oper[0].reg.enum in (rg.usableregsint+[R_EDI])) and
-                     (Taicpu(p).oper[1].reg.enum in (rg.usableregsint+[R_EDI])) then}
-                     (Taicpu(p).oper[0].reg.enum in ([R_EDI])) and
-                     (Taicpu(p).oper[1].reg.enum in ([R_EDI])) then
-                    if switchRegs(asml,Taicpu(p).oper[0].reg,
-                         Taicpu(p).oper[1].reg,p) then
+                     (taicpu(p).oper[0]^.typ = top_reg) and
+                     (taicpu(p).oper[1]^.typ = top_reg) and
+                     (taicpu(p).opsize = S_L) and
+                     (getsupreg(taicpu(p).oper[0]^.reg) in ([RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI])) and
+                     (getsupreg(taicpu(p).oper[1]^.reg) in ([RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI])) then
+                    if switchRegs(asml,getsupreg(taicpu(p).oper[0]^.reg),
+                         getsupreg(taicpu(p).oper[1]^.reg),p) then
                       begin
-{                        getnextinstruction(p,hp);
-                        asmL^.remove(p);
-                        dispose(p,done);
-                        p := hp;
-                        continue }
                         pTaiprop(p.optinfo)^.canBeRemoved := true;
                       end;
                 end;
@@ -358,7 +346,14 @@ End.
 
 {
   $Log$
-  Revision 1.22  2003-06-03 21:09:05  peter
+  Revision 1.23  2003-11-22 00:40:19  jonas
+    * fixed optimiser so it compiles again
+    * fixed several bugs which were in there already for a long time, but
+      which only popped up now :) -O2/-O3 will now optimise less than in
+      the past (and correctly so), but -O2u/-O3u will optimise a bit more
+    * some more small improvements for -O3 are still possible
+
+  Revision 1.22  2003/06/03 21:09:05  peter
     * internal changeregsize for optimizer
     * fix with a hack to not remove the first instruction of a block
       which will leave blockstart pointing to invalid memory

+ 19 - 10
compiler/psub.pas

@@ -24,7 +24,6 @@ unit psub;
 
 {$i fpcdefs.inc}
 
-{$define NOOPT}
 
 interface
 
@@ -752,14 +751,6 @@ implementation
             if not(cs_no_regalloc in aktglobalswitches) then
               begin
                 cg.do_register_allocation(aktproccode,headertai);
-(*
-{$ifndef NoOpt}
-                if (cs_optimize in aktglobalswitches) and
-                { do not optimize pure assembler procedures }
-                   not(pi_is_assembler in current_procinfo.flags)  then
-                  optimize(aktproccode);
-{$endif NoOpt}
-*)
               end;
 
             { Add save and restore of used registers }
@@ -776,6 +767,17 @@ implementation
             aktfilepos:=exitpos;
             gen_stackfree_code(templist,usesacc,usesacchi);
             aktproccode.concatlist(templist);
+
+{$ifndef NoOpt}
+            if not(cs_no_regalloc in aktglobalswitches) then
+              begin
+                if (cs_optimize in aktglobalswitches) and
+                { do not optimize pure assembler procedures }
+                    not(pi_is_assembler in current_procinfo.flags)  then
+                    optimize(aktproccode);
+              end;
+{$endif NoOpt}
+
             { Add end symbol and debug info }
             aktfilepos:=exitpos;
             gen_proc_symbol_end(templist);
@@ -1312,7 +1314,14 @@ implementation
 end.
 {
   $Log$
-  Revision 1.171  2003-11-10 22:02:52  peter
+  Revision 1.172  2003-11-22 00:40:19  jonas
+    * fixed optimiser so it compiles again
+    * fixed several bugs which were in there already for a long time, but
+      which only popped up now :) -O2/-O3 will now optimise less than in
+      the past (and correctly so), but -O2u/-O3u will optimise a bit more
+    * some more small improvements for -O3 are still possible
+
+  Revision 1.171  2003/11/10 22:02:52  peter
     * cross unit inlining fixed
 
   Revision 1.170  2003/11/07 15:58:32  florian

部分文件因为文件数量过多而无法显示