Browse Source

* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors

peter 21 years ago
parent
commit
1367e342db

+ 19 - 2
compiler/aasmtai.pas

@@ -447,6 +447,7 @@ interface
 
 
       Taasmoutput=class;
       Taasmoutput=class;
 
 
+      tadd_reg_instruction_proc=procedure(instr:Tai;r:tregister) of object;
       Trggetproc=procedure(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister) of object;
       Trggetproc=procedure(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister) of object;
       Trgungetproc=procedure(list:Taasmoutput;position:Tai;r:Tregister) of object;
       Trgungetproc=procedure(list:Taasmoutput;position:Tai;r:Tregister) of object;
 
 
@@ -491,7 +492,7 @@ interface
           procedure loadoper(opidx:longint;o:toper);
           procedure loadoper(opidx:longint;o:toper);
           procedure clearop(opidx:longint);
           procedure clearop(opidx:longint);
           function is_nop:boolean;virtual;abstract;
           function is_nop:boolean;virtual;abstract;
-          function is_move:boolean;virtual;abstract;
+          function is_reg_move:boolean;virtual;abstract;
           { register allocator }
           { register allocator }
           function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister;var live_registers_int:Tsuperregisterworklist):Tai;
           function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister;var live_registers_int:Tsuperregisterworklist):Tai;
           procedure forward_allocation(p:Tai;var {unusedregsint:tsuperregisterset}live_registers_int:Tsuperregisterworklist);
           procedure forward_allocation(p:Tai;var {unusedregsint:tsuperregisterset}live_registers_int:Tsuperregisterworklist);
@@ -542,6 +543,9 @@ interface
       { label when the result is true or false }
       { label when the result is true or false }
       truelabel,falselabel : tasmlabel;
       truelabel,falselabel : tasmlabel;
 
 
+      { hook to notify uses of registers }
+      add_reg_instruction_hook : tadd_reg_instruction_proc;
+
       { default lists }
       { default lists }
       datasegment,codesegment,bsssegment,
       datasegment,codesegment,bsssegment,
       debuglist,withdebuglist,consts,
       debuglist,withdebuglist,consts,
@@ -1677,6 +1681,8 @@ implementation
               segprefix:=ref^.segment;
               segprefix:=ref^.segment;
 {$endif}
 {$endif}
             typ:=top_ref;
             typ:=top_ref;
+            add_reg_instruction_hook(self,ref^.base);
+            add_reg_instruction_hook(self,ref^.index);
             { mark symbol as used }
             { mark symbol as used }
             if assigned(ref^.symbol) then
             if assigned(ref^.symbol) then
               ref^.symbol.increfs;
               ref^.symbol.increfs;
@@ -1694,6 +1700,7 @@ implementation
            reg:=r;
            reg:=r;
            typ:=top_reg;
            typ:=top_reg;
          end;
          end;
+        add_reg_instruction_hook(self,r);
 {$ifdef ARM}
 {$ifdef ARM}
         { R15 is the PC on the ARM thus moves to R15 are jumps.
         { R15 is the PC on the ARM thus moves to R15 are jumps.
           Due to speed considerations we don't use a virtual overridden method here.
           Due to speed considerations we don't use a virtual overridden method here.
@@ -1714,10 +1721,14 @@ implementation
         with oper[opidx]^ do
         with oper[opidx]^ do
           begin
           begin
             case typ of
             case typ of
+              top_reg:
+                add_reg_instruction_hook(self,reg);
               top_ref:
               top_ref:
                 begin
                 begin
                   new(ref);
                   new(ref);
                   ref^:=o.ref^;
                   ref^:=o.ref^;
+                  add_reg_instruction_hook(self,ref^.base);
+                  add_reg_instruction_hook(self,ref^.index);
                 end;
                 end;
 {$ifdef ARM}
 {$ifdef ARM}
               top_shifterop:
               top_shifterop:
@@ -2202,7 +2213,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.60  2003-12-14 20:24:28  daniel
+  Revision 1.61  2003-12-15 21:25:48  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.60  2003/12/14 20:24:28  daniel
     * Register allocator speed optimizations
     * Register allocator speed optimizations
       - Worklist no longer a ringbuffer
       - Worklist no longer a ringbuffer
       - No find operations are left
       - No find operations are left

+ 22 - 11
compiler/cgbase.pas

@@ -133,12 +133,17 @@ interface
       {
       {
         The new register coding:
         The new register coding:
 
 
-        SuperRegister   (bits 0..7)
-        Unused          (bits 8..15)
+        SuperRegister   (bits 0..15)
         Subregister     (bits 16..23)
         Subregister     (bits 16..23)
         Register type   (bits 24..31)
         Register type   (bits 24..31)
+
+        TRegister is defined as an enum to make it incompatible
+        with TSuperRegister to avoid mixing them
       }
       }
-      TRegister = type cardinal;
+      TRegister = (
+        TRegisterLowEnum := $80000000,
+        TRegisterHighEnum := $7fffffff
+      );
       TRegisterRec=packed record
       TRegisterRec=packed record
 {$ifdef FPC_BIG_ENDIAN}
 {$ifdef FPC_BIG_ENDIAN}
          regtype : Tregistertype;
          regtype : Tregistertype;
@@ -316,7 +321,7 @@ implementation
     end;
     end;
 
 
     destructor tsuperregisterworklist.done;
     destructor tsuperregisterworklist.done;
-    
+
     begin
     begin
       if assigned(buf) then
       if assigned(buf) then
         freemem(buf);
         freemem(buf);
@@ -324,7 +329,7 @@ implementation
 
 
 
 
     procedure tsuperregisterworklist.add(s:tsuperregister);
     procedure tsuperregisterworklist.add(s:tsuperregister);
-    
+
     begin
     begin
       inc(length);
       inc(length);
       { Need to increase buffer length? }
       { Need to increase buffer length? }
@@ -341,14 +346,14 @@ implementation
 
 
 
 
     procedure tsuperregisterworklist.clear;
     procedure tsuperregisterworklist.clear;
-    
+
     begin
     begin
       length:=0;
       length:=0;
     end;
     end;
 
 
 
 
     procedure tsuperregisterworklist.deleteidx(i:word);
     procedure tsuperregisterworklist.deleteidx(i:word);
-    
+
     begin
     begin
       if length=0 then
       if length=0 then
         internalerror(200310144);
         internalerror(200310144);
@@ -358,7 +363,7 @@ implementation
 
 
 
 
     function tsuperregisterworklist.get:tsuperregister;
     function tsuperregisterworklist.get:tsuperregister;
-    
+
     begin
     begin
       if length=0 then
       if length=0 then
         internalerror(200310142);
         internalerror(200310142);
@@ -369,9 +374,9 @@ implementation
 
 
 
 
     function tsuperregisterworklist.delete(s:tsuperregister):boolean;
     function tsuperregisterworklist.delete(s:tsuperregister):boolean;
-    
+
     var i:word;
     var i:word;
-    
+
     begin
     begin
       delete:=false;
       delete:=false;
       for i:=1 to length do
       for i:=1 to length do
@@ -569,7 +574,13 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.78  2003-12-14 20:24:28  daniel
+  Revision 1.79  2003-12-15 21:25:48  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.78  2003/12/14 20:24:28  daniel
     * Register allocator speed optimizations
     * Register allocator speed optimizations
       - Worklist no longer a ringbuffer
       - Worklist no longer a ringbuffer
       - No find operations are left
       - No find operations are left

+ 25 - 6
compiler/cgobj.pas

@@ -84,6 +84,7 @@ unit cgobj;
           procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
           procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
           procedure ungetreference(list:Taasmoutput;const r:Treference);virtual;
           procedure ungetreference(list:Taasmoutput;const r:Treference);virtual;
 
 
+          procedure add_reg_instruction(instr:Tai;r:tregister);virtual;
           procedure add_move_instruction(instr:Taicpu);virtual;
           procedure add_move_instruction(instr:Taicpu);virtual;
 
 
           function  uses_registers(rt:Tregistertype):boolean;virtual;
           function  uses_registers(rt:Tregistertype):boolean;virtual;
@@ -553,6 +554,7 @@ implementation
 
 
     constructor tcg.create;
     constructor tcg.create;
       begin
       begin
+        add_reg_instruction_hook:={$ifdef FPCPROCVAR}@{$endif}add_reg_instruction;
       end;
       end;
 
 
 
 
@@ -627,6 +629,8 @@ implementation
       begin
       begin
         if r.base<>NR_NO then
         if r.base<>NR_NO then
           ungetregister(list,r.base);
           ungetregister(list,r.base);
+        if r.index<>NR_NO then
+          ungetregister(list,r.index);
       end;
       end;
 
 
 
 
@@ -657,6 +661,19 @@ implementation
       end;
       end;
 
 
 
 
+    procedure tcg.add_reg_instruction(instr:Tai;r:tregister);
+      var
+        rt : tregistertype;
+      begin
+        rt:=getregtype(r);
+        { Only add it when a register allocator is configured.
+          No IE can be generated, because the VMT is written
+          without a valid rg[] }
+        if assigned(rg[rt]) then
+          rg[rt].add_reg_instruction(instr,r);
+      end;
+
+
     procedure tcg.add_move_instruction(instr:Taicpu);
     procedure tcg.add_move_instruction(instr:Taicpu);
       var
       var
         rt : tregistertype;
         rt : tregistertype;
@@ -676,11 +693,7 @@ implementation
         for rt:=low(tregistertype) to high(tregistertype) do
         for rt:=low(tregistertype) to high(tregistertype) do
           begin
           begin
             if assigned(rg[rt]) then
             if assigned(rg[rt]) then
-              begin
-                rg[rt].check_unreleasedregs;
-                rg[rt].do_register_allocation(list,headertai);
-                rg[rt].translate_registers(list);
-              end;
+              rg[rt].do_register_allocation(list,headertai);
           end;
           end;
       end;
       end;
 
 
@@ -1941,7 +1954,13 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.138  2003-12-12 17:16:17  peter
+  Revision 1.139  2003-12-15 21:25:48  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.138  2003/12/12 17:16:17  peter
     * rg[tregistertype] added in tcg
     * rg[tregistertype] added in tcg
 
 
   Revision 1.137  2003/12/06 22:11:47  jonas
   Revision 1.137  2003/12/06 22:11:47  jonas

+ 9 - 3
compiler/i386/csopt386.pas

@@ -178,7 +178,7 @@ begin
               tmpRef.base := NR_EDI;
               tmpRef.base := NR_EDI;
               tmpRef.index := NR_EDI;
               tmpRef.index := NR_EDI;
               for regCounter := RS_EAX to RS_EDI do
               for regCounter := RS_EAX to RS_EDI do
-                if writeToMemDestroysContents(NR_NO,tmpRef,regCounter,c[regCounter],dummy) then
+                if writeToMemDestroysContents(RS_INVALID,tmpRef,regCounter,c[regCounter],dummy) then
                   begin
                   begin
                     exclude(regsStillValid,regCounter);
                     exclude(regsStillValid,regCounter);
                     modifiesConflictingMemLocation := not(supreg in regsStillValid);
                     modifiesConflictingMemLocation := not(supreg in regsStillValid);
@@ -1954,7 +1954,7 @@ begin
                               if (memreg <> NR_NO) and
                               if (memreg <> NR_NO) and
                                  (not getNextInstruction(p,hp1) or
                                  (not getNextInstruction(p,hp1) or
                                   (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
                                   (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
-                                   FindRegDealloc(getsupreg(regcounter),hp1))) then
+                                   FindRegDealloc(regcounter,hp1))) then
                                 begin
                                 begin
                                   hp1 := Tai_Marker.Create(NoPropInfoEnd);
                                   hp1 := Tai_Marker.Create(NoPropInfoEnd);
                                   insertllitem(asml,p,p.next,hp1);
                                   insertllitem(asml,p,p.next,hp1);
@@ -2074,7 +2074,13 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.57  2003-12-15 16:08:15  jonas
+  Revision 1.58  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.57  2003/12/15 16:08:15  jonas
     - disable removal of dead loads before a call, because register
     - disable removal of dead loads before a call, because register
       parameters are released before a call
       parameters are released before a call
     * fix storeback of registers in case of different sizes (e.g., first
     * fix storeback of registers in case of different sizes (e.g., first

+ 10 - 4
compiler/i386/daopt386.pas

@@ -1785,7 +1785,7 @@ begin
           (typ in [con_ref,con_noRemoveRef]) and
           (typ in [con_ref,con_noRemoveRef]) and
           (not(cs_UncertainOpts in aktglobalswitches) or
           (not(cs_UncertainOpts in aktglobalswitches) or
          { for movsl }
          { for movsl }
-           ((ref.base = RS_EDI) and (ref.index = RS_EDI)) or
+           ((ref.base = NR_EDI) and (ref.index = NR_EDI)) or
          { don't destroy if reg contains a parameter, local or global variable }
          { don't destroy if reg contains a parameter, local or global variable }
            containsPointerLoad(c)
            containsPointerLoad(c)
           );
           );
@@ -1963,7 +1963,7 @@ var
   p, prev: tai;
   p, prev: tai;
   hp1, hp2: tai;
   hp1, hp2: tai;
 {$ifdef i386}
 {$ifdef i386}
-  regcounter: tregister;
+  regcounter,
   supreg : tsuperregister;
   supreg : tsuperregister;
 {$endif i386}
 {$endif i386}
   usedregs, nodeallocregs: tregset;
   usedregs, nodeallocregs: tregset;
@@ -2052,7 +2052,7 @@ begin
   usedRegs := usedRegs - noDeallocRegs;
   usedRegs := usedRegs - noDeallocRegs;
   for regCounter := RS_EAX to RS_EDI do
   for regCounter := RS_EAX to RS_EDI do
     if regCounter in usedRegs then
     if regCounter in usedRegs then
-      addRegDeallocFor(list,regCounter,prev);
+      addRegDeallocFor(list,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prev);
 {$endif i386}
 {$endif i386}
 end;
 end;
 
 
@@ -2714,7 +2714,13 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.60  2003-12-15 15:58:58  peter
+  Revision 1.61  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.60  2003/12/15 15:58:58  peter
     * fix statedebug compile
     * fix statedebug compile
 
 
   Revision 1.59  2003/12/14 22:42:14  peter
   Revision 1.59  2003/12/14 22:42:14  peter

+ 8 - 2
compiler/i386/popt386.pas

@@ -1808,7 +1808,7 @@ begin
                       TmpUsedRegs := UsedRegs;
                       TmpUsedRegs := UsedRegs;
                       UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
                       UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
                       if (RefsEqual(taicpu(hp2).oper[1]^.ref^, taicpu(p).oper[0]^.ref^) and
                       if (RefsEqual(taicpu(hp2).oper[1]^.ref^, taicpu(p).oper[0]^.ref^) and
-                         not(RegUsedAfterInstruction(getsupreg(taicpu(p).oper[1]^.reg),
+                         not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,
                               hp2, TmpUsedRegs))) then
                               hp2, TmpUsedRegs))) then
   { change   mov            (ref), reg            }
   { change   mov            (ref), reg            }
   {          add/sub/or/... reg2/$const, reg      }
   {          add/sub/or/... reg2/$const, reg      }
@@ -1996,7 +1996,13 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.52  2003-12-14 22:42:14  peter
+  Revision 1.53  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.52  2003/12/14 22:42:14  peter
     * fixed csdebug
     * fixed csdebug
 
 
   Revision 1.51  2003/12/13 15:48:47  jonas
   Revision 1.51  2003/12/13 15:48:47  jonas

+ 71 - 71
compiler/i386/r386con.inc

@@ -1,72 +1,72 @@
 { don't edit, this file is generated from x86reg.dat }
 { don't edit, this file is generated from x86reg.dat }
-NR_NO = $00000000;
-NR_AL = $01010000;
-NR_AH = $01020000;
-NR_AX = $01030000;
-NR_EAX = $01040000;
-NR_CL = $01010001;
-NR_CH = $01020001;
-NR_CX = $01030001;
-NR_ECX = $01040001;
-NR_DL = $01010002;
-NR_DH = $01020002;
-NR_DX = $01030002;
-NR_EDX = $01040002;
-NR_BL = $01010003;
-NR_BH = $01020003;
-NR_BX = $01030003;
-NR_EBX = $01040003;
-NR_SI = $01030004;
-NR_ESI = $01040004;
-NR_DI = $01030005;
-NR_EDI = $01040005;
-NR_BP = $01030006;
-NR_EBP = $01040006;
-NR_SP = $01030007;
-NR_ESP = $01040007;
-NR_CS = $05000001;
-NR_DS = $05000002;
-NR_ES = $05000003;
-NR_SS = $05000004;
-NR_FS = $05000005;
-NR_GS = $05000006;
-NR_DR0 = $05000007;
-NR_DR1 = $05000008;
-NR_DR2 = $05000009;
-NR_DR3 = $0500000a;
-NR_DR6 = $0500000b;
-NR_DR7 = $0500000c;
-NR_CR0 = $0500000d;
-NR_CR2 = $0500000e;
-NR_CR3 = $0500000f;
-NR_CR4 = $05000010;
-NR_TR3 = $05000011;
-NR_TR4 = $05000012;
-NR_TR5 = $05000013;
-NR_TR6 = $05000014;
-NR_TR7 = $05000015;
-NR_ST0 = $02000000;
-NR_ST1 = $02000001;
-NR_ST2 = $02000002;
-NR_ST3 = $02000003;
-NR_ST4 = $02000004;
-NR_ST5 = $02000005;
-NR_ST6 = $02000006;
-NR_ST7 = $02000007;
-NR_ST = $02000008;
-NR_MM0 = $03000000;
-NR_MM1 = $03000001;
-NR_MM2 = $03000002;
-NR_MM3 = $03000003;
-NR_MM4 = $03000004;
-NR_MM5 = $03000005;
-NR_MM6 = $03000006;
-NR_MM7 = $03000007;
-NR_XMM0 = $04000000;
-NR_XMM1 = $04000001;
-NR_XMM2 = $04000002;
-NR_XMM3 = $04000003;
-NR_XMM4 = $04000004;
-NR_XMM5 = $04000005;
-NR_XMM6 = $04000006;
-NR_XMM7 = $04000007;
+NR_NO = tregister($00000000);
+NR_AL = tregister($01010000);
+NR_AH = tregister($01020000);
+NR_AX = tregister($01030000);
+NR_EAX = tregister($01040000);
+NR_CL = tregister($01010001);
+NR_CH = tregister($01020001);
+NR_CX = tregister($01030001);
+NR_ECX = tregister($01040001);
+NR_DL = tregister($01010002);
+NR_DH = tregister($01020002);
+NR_DX = tregister($01030002);
+NR_EDX = tregister($01040002);
+NR_BL = tregister($01010003);
+NR_BH = tregister($01020003);
+NR_BX = tregister($01030003);
+NR_EBX = tregister($01040003);
+NR_SI = tregister($01030004);
+NR_ESI = tregister($01040004);
+NR_DI = tregister($01030005);
+NR_EDI = tregister($01040005);
+NR_BP = tregister($01030006);
+NR_EBP = tregister($01040006);
+NR_SP = tregister($01030007);
+NR_ESP = tregister($01040007);
+NR_CS = tregister($05000001);
+NR_DS = tregister($05000002);
+NR_ES = tregister($05000003);
+NR_SS = tregister($05000004);
+NR_FS = tregister($05000005);
+NR_GS = tregister($05000006);
+NR_DR0 = tregister($05000007);
+NR_DR1 = tregister($05000008);
+NR_DR2 = tregister($05000009);
+NR_DR3 = tregister($0500000a);
+NR_DR6 = tregister($0500000b);
+NR_DR7 = tregister($0500000c);
+NR_CR0 = tregister($0500000d);
+NR_CR2 = tregister($0500000e);
+NR_CR3 = tregister($0500000f);
+NR_CR4 = tregister($05000010);
+NR_TR3 = tregister($05000011);
+NR_TR4 = tregister($05000012);
+NR_TR5 = tregister($05000013);
+NR_TR6 = tregister($05000014);
+NR_TR7 = tregister($05000015);
+NR_ST0 = tregister($02000000);
+NR_ST1 = tregister($02000001);
+NR_ST2 = tregister($02000002);
+NR_ST3 = tregister($02000003);
+NR_ST4 = tregister($02000004);
+NR_ST5 = tregister($02000005);
+NR_ST6 = tregister($02000006);
+NR_ST7 = tregister($02000007);
+NR_ST = tregister($02000008);
+NR_MM0 = tregister($03000000);
+NR_MM1 = tregister($03000001);
+NR_MM2 = tregister($03000002);
+NR_MM3 = tregister($03000003);
+NR_MM4 = tregister($03000004);
+NR_MM5 = tregister($03000005);
+NR_MM6 = tregister($03000006);
+NR_MM7 = tregister($03000007);
+NR_XMM0 = tregister($04000000);
+NR_XMM1 = tregister($04000001);
+NR_XMM2 = tregister($04000002);
+NR_XMM3 = tregister($04000003);
+NR_XMM4 = tregister($04000004);
+NR_XMM5 = tregister($04000005);
+NR_XMM6 = tregister($04000006);
+NR_XMM7 = tregister($04000007);

+ 71 - 71
compiler/i386/r386num.inc

@@ -1,72 +1,72 @@
 { don't edit, this file is generated from x86reg.dat }
 { don't edit, this file is generated from x86reg.dat }
-$00000000,
-$01010000,
-$01020000,
-$01030000,
-$01040000,
-$01010001,
-$01020001,
-$01030001,
-$01040001,
-$01010002,
-$01020002,
-$01030002,
-$01040002,
-$01010003,
-$01020003,
-$01030003,
-$01040003,
-$01030004,
-$01040004,
-$01030005,
-$01040005,
-$01030006,
-$01040006,
-$01030007,
-$01040007,
-$05000001,
-$05000002,
-$05000003,
-$05000004,
-$05000005,
-$05000006,
-$05000007,
-$05000008,
-$05000009,
-$0500000a,
-$0500000b,
-$0500000c,
-$0500000d,
-$0500000e,
-$0500000f,
-$05000010,
-$05000011,
-$05000012,
-$05000013,
-$05000014,
-$05000015,
-$02000000,
-$02000001,
-$02000002,
-$02000003,
-$02000004,
-$02000005,
-$02000006,
-$02000007,
-$02000008,
-$03000000,
-$03000001,
-$03000002,
-$03000003,
-$03000004,
-$03000005,
-$03000006,
-$03000007,
-$04000000,
-$04000001,
-$04000002,
-$04000003,
-$04000004,
-$04000005,
-$04000006,
-$04000007
+tregister($00000000),
+tregister($01010000),
+tregister($01020000),
+tregister($01030000),
+tregister($01040000),
+tregister($01010001),
+tregister($01020001),
+tregister($01030001),
+tregister($01040001),
+tregister($01010002),
+tregister($01020002),
+tregister($01030002),
+tregister($01040002),
+tregister($01010003),
+tregister($01020003),
+tregister($01030003),
+tregister($01040003),
+tregister($01030004),
+tregister($01040004),
+tregister($01030005),
+tregister($01040005),
+tregister($01030006),
+tregister($01040006),
+tregister($01030007),
+tregister($01040007),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c),
+tregister($0500000d),
+tregister($0500000e),
+tregister($0500000f),
+tregister($05000010),
+tregister($05000011),
+tregister($05000012),
+tregister($05000013),
+tregister($05000014),
+tregister($05000015),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($04000000),
+tregister($04000001),
+tregister($04000002),
+tregister($04000003),
+tregister($04000004),
+tregister($04000005),
+tregister($04000006),
+tregister($04000007)

+ 15 - 8
compiler/ncgcal.pas

@@ -113,7 +113,7 @@ implementation
         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
           internalerror(200304235);
           internalerror(200304235);
         location_release(exprasmlist,left.location);
         location_release(exprasmlist,left.location);
-        allocate_tempparaloc;
+//        allocate_tempparaloc;
         cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
         cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
         inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
         inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
       end;
       end;
@@ -137,7 +137,7 @@ implementation
         if left.resulttype.def.deftype=floatdef then
         if left.resulttype.def.deftype=floatdef then
          begin
          begin
            location_release(exprasmlist,left.location);
            location_release(exprasmlist,left.location);
-           allocate_tempparaloc;
+//           allocate_tempparaloc;
 {$ifdef i386}
 {$ifdef i386}
            if tempparaloc.loc<>LOC_REFERENCE then
            if tempparaloc.loc<>LOC_REFERENCE then
              internalerror(200309291);
              internalerror(200309291);
@@ -215,7 +215,6 @@ implementation
                   aktcallnode.procdefinition.proccalloption) then
                   aktcallnode.procdefinition.proccalloption) then
             begin
             begin
               location_release(exprasmlist,left.location);
               location_release(exprasmlist,left.location);
-              allocate_tempparaloc;
 {$ifdef i386}
 {$ifdef i386}
               if tempparaloc.loc<>LOC_REFERENCE then
               if tempparaloc.loc<>LOC_REFERENCE then
                 internalerror(200309292);
                 internalerror(200309292);
@@ -249,14 +248,14 @@ implementation
                     if cgsize in [OS_64,OS_S64] then
                     if cgsize in [OS_64,OS_S64] then
                      begin
                      begin
                        inc(tcgcallnode(aktcallnode).pushedparasize,8);
                        inc(tcgcallnode(aktcallnode).pushedparasize,8);
-                       allocate_tempparaloc;
+//                       allocate_tempparaloc;
                        cg64.a_param64_loc(exprasmlist,left.location,tempparaloc);
                        cg64.a_param64_loc(exprasmlist,left.location,tempparaloc);
                        location_release(exprasmlist,left.location);
                        location_release(exprasmlist,left.location);
                      end
                      end
                     else
                     else
                      begin
                      begin
                        location_release(exprasmlist,left.location);
                        location_release(exprasmlist,left.location);
-                       allocate_tempparaloc;
+//                       allocate_tempparaloc;
                        inc(tcgcallnode(aktcallnode).pushedparasize,align(tcgsize2size[tempparaloc.size],tempparaloc.alignment));
                        inc(tcgcallnode(aktcallnode).pushedparasize,align(tcgsize2size[tempparaloc.size],tempparaloc.alignment));
                        cg.a_param_loc(exprasmlist,left.location,tempparaloc);
                        cg.a_param_loc(exprasmlist,left.location,tempparaloc);
                      end;
                      end;
@@ -266,7 +265,7 @@ implementation
                 LOC_CMMXREGISTER:
                 LOC_CMMXREGISTER:
                   begin
                   begin
                      location_release(exprasmlist,left.location);
                      location_release(exprasmlist,left.location);
-                     allocate_tempparaloc;
+//                     allocate_tempparaloc;
                      inc(tcgcallnode(aktcallnode).pushedparasize,8);
                      inc(tcgcallnode(aktcallnode).pushedparasize,8);
                      cg.a_parammm_reg(exprasmlist,left.location.register);
                      cg.a_parammm_reg(exprasmlist,left.location.register);
                   end;
                   end;
@@ -301,6 +300,8 @@ implementation
              objectlibrary.getlabel(falselabel);
              objectlibrary.getlabel(falselabel);
              secondpass(left);
              secondpass(left);
 
 
+             allocate_tempparaloc;
+
              { handle varargs first, because paraitem.parasym is not valid }
              { handle varargs first, because paraitem.parasym is not valid }
              if (nf_varargs_para in flags) then
              if (nf_varargs_para in flags) then
                begin
                begin
@@ -337,7 +338,7 @@ implementation
                     begin
                     begin
                       inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
                       inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
                       location_release(exprasmlist,left.location);
                       location_release(exprasmlist,left.location);
-                      allocate_tempparaloc;
+//                      allocate_tempparaloc;
                       cg.a_param_loc(exprasmlist,left.location,tempparaloc);
                       cg.a_param_loc(exprasmlist,left.location,tempparaloc);
                     end
                     end
                   else
                   else
@@ -1129,7 +1130,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.145  2003-12-07 12:41:32  jonas
+  Revision 1.146  2003-12-15 21:25:48  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.145  2003/12/07 12:41:32  jonas
     * fixed ansistring/widestring results: deallocate result reg only after
     * fixed ansistring/widestring results: deallocate result reg only after
       it has been stored to memory, as the storing itself may require extra
       it has been stored to memory, as the storing itself may require extra
       results (e.g. on ppc)
       results (e.g. on ppc)

+ 28 - 16
compiler/pdecl.pas

@@ -526,26 +526,32 @@ implementation
                   tt.def.needs_inittable) then
                   tt.def.needs_inittable) then
                 generate_inittable(newtype);
                 generate_inittable(newtype);
 
 
-              { Always generate RTTI info for all types. This is to have typeinfo() return
-                the same pointer }
-              generate_rtti(newtype);
-
               { for objects we should write the vmt and interfaces.
               { for objects we should write the vmt and interfaces.
                 This need to be done after the rtti has been written, because
                 This need to be done after the rtti has been written, because
                 it can contain a reference to that data (PFV)
                 it can contain a reference to that data (PFV)
                 This is not for forward classes }
                 This is not for forward classes }
-              if (tt.def.deftype=objectdef) and
-                 not(oo_is_forward in tobjectdef(tt.def).objectoptions) then
+              if (tt.def.deftype=objectdef) then
+               begin
+                 if not(oo_is_forward in tobjectdef(tt.def).objectoptions) then
+                   begin
+                     ch:=cclassheader.create(tobjectdef(tt.def));
+                     { generate and check virtual methods, must be done
+                       before RTTI is written }
+                     ch.genvmt;
+                     { Generate RTTI for class }
+                     generate_rtti(newtype);
+                     if is_interface(tobjectdef(tt.def)) then
+                       ch.writeinterfaceids;
+                     if (oo_has_vmt in tobjectdef(tt.def).objectoptions) then
+                       ch.writevmt;
+                     ch.free;
+                   end;
+               end
+              else
                begin
                begin
-                 ch:=cclassheader.create(tobjectdef(tt.def));
-                 { generate and check virtual methods, must be done
-                   before RTTI is written }
-                 ch.genvmt;
-                 if is_interface(tobjectdef(tt.def)) then
-                   ch.writeinterfaceids;
-                 if (oo_has_vmt in tobjectdef(tt.def).objectoptions) then
-                   ch.writevmt;
-                 ch.free;
+                 { Always generate RTTI info for all types. This is to have typeinfo() return
+                   the same pointer }
+                 generate_rtti(newtype);
                end;
                end;
 
 
               aktfilepos:=oldfilepos;
               aktfilepos:=oldfilepos;
@@ -656,7 +662,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.74  2003-12-12 12:09:40  marco
+  Revision 1.75  2003-12-15 21:25:48  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.74  2003/12/12 12:09:40  marco
    * always generate RTTI patch from peter
    * always generate RTTI patch from peter
 
 
   Revision 1.73  2003/12/10 16:37:01  peter
   Revision 1.73  2003/12/10 16:37:01  peter

+ 8 - 5
compiler/psub.pas

@@ -749,10 +749,7 @@ implementation
 
 
             { The procedure body is finished, we can now
             { The procedure body is finished, we can now
               allocate the registers }
               allocate the registers }
-            if not(cs_no_regalloc in aktglobalswitches) then
-              begin
-                cg.do_register_allocation(aktproccode,headertai);
-              end;
+            cg.do_register_allocation(aktproccode,headertai);
 
 
             { Add save and restore of used registers }
             { Add save and restore of used registers }
             aktfilepos:=entrypos;
             aktfilepos:=entrypos;
@@ -1333,7 +1330,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.176  2003-12-10 16:37:01  peter
+  Revision 1.177  2003-12-15 21:25:48  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.176  2003/12/10 16:37:01  peter
     * global property support for fpc modes
     * global property support for fpc modes
 
 
   Revision 1.175  2003/12/03 23:13:20  peter
   Revision 1.175  2003/12/03 23:13:20  peter

+ 179 - 88
compiler/rgobj.pas

@@ -146,6 +146,9 @@ unit rgobj;
       Treginfoflagset=set of Treginfoflag;
       Treginfoflagset=set of Treginfoflag;
 
 
       Treginfo=record
       Treginfo=record
+        live_start,
+        live_end   : Tai;
+        subreg   : tsubregister;
         alias    : Tsuperregister;
         alias    : Tsuperregister;
         { The register allocator assigns each register a colour }
         { The register allocator assigns each register a colour }
         colour   : Tsuperregister;
         colour   : Tsuperregister;
@@ -156,21 +159,6 @@ unit rgobj;
       end;
       end;
       Preginfo=^TReginfo;
       Preginfo=^TReginfo;
 
 
-      { This is the base class used for a register allocator. }
-      trgbase=class
-        function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;abstract;
-        {# Get the register specified.}
-        procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;abstract;
-        {# Get multiple registers specified.}
-        procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;abstract;
-        {# Free multiple registers specified.}
-        procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;abstract;
-        function uses_registers:boolean;virtual;abstract;
-        {# Deallocate any kind of register }
-        procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;abstract;
-      end;
-
-
       {#------------------------------------------------------------------
       {#------------------------------------------------------------------
 
 
       This class implements the default register allocator. It is used by the
       This class implements the default register allocator. It is used by the
@@ -181,7 +169,7 @@ unit rgobj;
       by cpu-specific implementations.
       by cpu-specific implementations.
 
 
       --------------------------------------------------------------------}
       --------------------------------------------------------------------}
-      trgobj=class(trgbase)
+      trgobj=class
         preserved_by_proc : tcpuregisterset;
         preserved_by_proc : tcpuregisterset;
         used_in_proc : tcpuregisterset;
         used_in_proc : tcpuregisterset;
 //        is_reg_var : Tsuperregisterset; {old regvars}
 //        is_reg_var : Tsuperregisterset; {old regvars}
@@ -206,37 +194,18 @@ unit rgobj;
         function uses_registers:boolean;virtual;
         function uses_registers:boolean;virtual;
         {# Deallocate any kind of register }
         {# Deallocate any kind of register }
         procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
         procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
-        procedure add_constraints(reg:Tregister);virtual;
-
+        procedure add_reg_instruction(instr:Tai;r:tregister);
+        procedure add_move_instruction(instr:Taicpu);
         {# Do the register allocation.}
         {# Do the register allocation.}
         procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
         procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
-
-{        procedure resetusableregisters;virtual;}
-
-{        procedure makeregvar(reg:Tsuperregister);}
-
-{$ifdef EXTDEBUG}
-        procedure writegraph(loopidx:longint);
-{$endif EXTDEBUG}
-        procedure add_move_instruction(instr:Taicpu);
-        {# Prepare the register colouring.}
-        procedure prepare_colouring;
-        {# Clean up after register colouring.}
-        procedure epilogue_colouring;
-        {# Colour the registers; that is do the register allocation.}
-        procedure colour_registers;
-        {# Spills certain registers in the specified assembler list.}
-        function  spill_registers(list:Taasmoutput;headertai:tai):boolean;
-        procedure translate_registers(list:Taasmoutput);
-        {# Adds an interference edge.}
-        procedure add_edge(u,v:Tsuperregister);
-        procedure check_unreleasedregs;
-
-
       protected
       protected
         regtype           : Tregistertype;
         regtype           : Tregistertype;
         { default subregister used }
         { default subregister used }
         defaultsub        : tsubregister;
         defaultsub        : tsubregister;
+        {# Adds an interference edge.}
+        procedure add_edge(u,v:Tsuperregister);
+        procedure add_constraints(reg:Tregister);virtual;
+      private
         {# First imaginary register.}
         {# First imaginary register.}
         first_imaginary   : Tsuperregister;
         first_imaginary   : Tsuperregister;
         {# Highest register allocated until now.}
         {# Highest register allocated until now.}
@@ -259,7 +228,21 @@ unit rgobj;
         coalesced_moves,
         coalesced_moves,
         constrained_moves : Tlinkedlist;
         constrained_moves : Tlinkedlist;
         live_registers:Tsuperregisterworklist;
         live_registers:Tsuperregisterworklist;
-        function  getnewreg:tsuperregister;
+{$ifdef EXTDEBUG}
+        procedure writegraph(loopidx:longint);
+{$endif EXTDEBUG}
+        {# Prepare the register colouring.}
+        procedure prepare_colouring;
+        {# Clean up after register colouring.}
+        procedure epilogue_colouring;
+        {# Colour the registers; that is do the register allocation.}
+        procedure colour_registers;
+        {# Spills certain registers in the specified assembler list.}
+        procedure insert_regalloc_info(list:Taasmoutput;headertai:tai);
+        procedure generate_interference_graph(list:Taasmoutput;headertai:tai);
+        procedure translate_registers(list:Taasmoutput);
+        function  spill_registers(list:Taasmoutput;headertai:tai):boolean;
+        function  getnewreg(subreg:tsubregister):tsuperregister;
         procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
         procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
         procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
         procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
         procedure add_edges_used(u:Tsuperregister);
         procedure add_edges_used(u:Tsuperregister);
@@ -429,7 +412,7 @@ implementation
     end;
     end;
 
 
 
 
-    function trgobj.getnewreg:tsuperregister;
+    function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
       var
       var
         oldmaxreginfo : tsuperregister;
         oldmaxreginfo : tsuperregister;
       begin
       begin
@@ -447,24 +430,16 @@ implementation
             { Do we really need it to clear it ? At least for 1.0.x (PFV) }
             { Do we really need it to clear it ? At least for 1.0.x (PFV) }
             fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
             fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
           end;
           end;
+        reginfo[result].subreg:=subreg;
       end;
       end;
 
 
 
 
     function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
     function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
-      var
-        p : Tsuperregister;
-        r : Tregister;
       begin
       begin
-         p:=getnewreg;
-         live_registers.add(p);
          if defaultsub=R_SUBNONE then
          if defaultsub=R_SUBNONE then
-           r:=newreg(regtype,p,R_SUBNONE)
+           result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
          else
          else
-           r:=newreg(regtype,p,subreg);
-         list.concat(Tai_regalloc.alloc(r));
-         add_edges_used(p);
-         add_constraints(r);
-         result:=r;
+           result:=newreg(regtype,getnewreg(subreg),subreg);
       end;
       end;
 
 
 
 
@@ -475,29 +450,23 @@ implementation
 
 
 
 
     procedure trgobj.ungetregister(list:Taasmoutput;r:Tregister);
     procedure trgobj.ungetregister(list:Taasmoutput;r:Tregister);
-
-    var supreg:Tsuperregister;
-
-    begin
-      supreg:=getsupreg(r);
-      if live_registers.delete(supreg) then
-        list.concat(Tai_regalloc.dealloc(r));
-    end;
+      begin
+        { Only explicit allocs insert regalloc info }
+        if getsupreg(r)<first_imaginary then
+          list.concat(Tai_regalloc.dealloc(r));
+      end;
 
 
 
 
     procedure trgobj.getexplicitregister(list:Taasmoutput;r:Tregister);
     procedure trgobj.getexplicitregister(list:Taasmoutput;r:Tregister);
-
-    var supreg:Tsuperregister;
-
-    begin
-      supreg:=getsupreg(r);
-      live_registers.add(supreg);
-      if supreg<first_imaginary then
+      var
+        supreg:Tsuperregister;
+      begin
+        supreg:=getsupreg(r);
+        if supreg>=first_imaginary then
+          internalerror(2003121503);
         include(used_in_proc,supreg);
         include(used_in_proc,supreg);
-      list.concat(Tai_regalloc.alloc(r));
-      add_edges_used(supreg);
-      add_constraints(r);
-    end;
+        list.concat(Tai_regalloc.alloc(r));
+      end;
 
 
 
 
     procedure trgobj.allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
     procedure trgobj.allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
@@ -507,7 +476,7 @@ implementation
     begin
     begin
       for i:=0 to first_imaginary-1 do
       for i:=0 to first_imaginary-1 do
         if i in r then
         if i in r then
-          getexplicitregister(list,i);
+          getexplicitregister(list,newreg(regtype,i,defaultsub));
     end;
     end;
 
 
 
 
@@ -518,7 +487,7 @@ implementation
     begin
     begin
       for i:=0 to first_imaginary-1 do
       for i:=0 to first_imaginary-1 do
         if i in r then
         if i in r then
-          ungetregister(list,i);
+          ungetregister(list,newreg(regtype,i,defaultsub));
     end;
     end;
 
 
 
 
@@ -527,6 +496,12 @@ implementation
         spillingcounter:byte;
         spillingcounter:byte;
         endspill:boolean;
         endspill:boolean;
       begin
       begin
+        { Insert regalloc info for imaginary registers }
+        insert_regalloc_info(list,headertai);
+        generate_interference_graph(list,headertai);
+        { Don't do the real allocation when -sr is passed }
+        if (cs_no_regalloc in aktglobalswitches) then
+          exit;
         {Do register allocation.}
         {Do register allocation.}
         spillingcounter:=0;
         spillingcounter:=0;
         repeat
         repeat
@@ -542,6 +517,7 @@ implementation
               endspill:=not spill_registers(list,headertai);
               endspill:=not spill_registers(list,headertai);
             end;
             end;
         until endspill;
         until endspill;
+        translate_registers(list);
       end;
       end;
 
 
 
 
@@ -588,8 +564,9 @@ implementation
     var i:word;
     var i:word;
 
 
     begin
     begin
-      for i:=0 to live_registers.length-1 do
-        add_edge(u,live_registers.buf[i]);
+      if live_registers.length>0 then
+        for i:=0 to live_registers.length-1 do
+          add_edge(u,live_registers.buf[i]);
     end;
     end;
 
 
 {$ifdef EXTDEBUG}
 {$ifdef EXTDEBUG}
@@ -644,6 +621,21 @@ implementation
       inc(reginfo[u].movelist^.count);
       inc(reginfo[u].movelist^.count);
     end;
     end;
 
 
+
+    procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
+      var
+        supreg : tsuperregister;
+      begin
+        supreg:=getsupreg(r);
+        if supreg>=first_imaginary then
+          begin
+            if not assigned(reginfo[supreg].live_start) then
+              reginfo[supreg].live_start:=instr;
+            reginfo[supreg].live_end:=instr;
+          end;
+      end;
+
+
     procedure trgobj.add_move_instruction(instr:Taicpu);
     procedure trgobj.add_move_instruction(instr:Taicpu);
 
 
     {This procedure notifies a certain as a move instruction so the
     {This procedure notifies a certain as a move instruction so the
@@ -827,8 +819,8 @@ implementation
     procedure trgobj.simplify;
     procedure trgobj.simplify;
 
 
     var adj : Psuperregisterworklist;
     var adj : Psuperregisterworklist;
-        p,n : Tsuperregister;
-        min,i:word;
+        n : Tsuperregister;
+        i : word;
     begin
     begin
       {We take the element with the least interferences out of the
       {We take the element with the least interferences out of the
        simplifyworklist. Since the simplifyworklist is now sorted, we
        simplifyworklist. Since the simplifyworklist is now sorted, we
@@ -1367,7 +1359,7 @@ implementation
     var p:Tsuperregister;
     var p:Tsuperregister;
         r:Tregister;
         r:Tregister;
     begin
     begin
-       p:=getnewreg;
+       p:=getnewreg(subreg);
        live_registers.add(p);
        live_registers.add(p);
        r:=newreg(regtype,p,subreg);
        r:=newreg(regtype,p,subreg);
        if position=nil then
        if position=nil then
@@ -1395,6 +1387,105 @@ implementation
     end;
     end;
 
 
 
 
+    procedure trgobj.insert_regalloc_info(list:Taasmoutput;headertai:tai);
+      var
+        supreg : tsuperregister;
+        p : tai;
+        r : tregister;
+      begin
+        { Insert regallocs for all imaginary registers }
+        for supreg:=first_imaginary to maxreg-1 do
+          begin
+            r:=newreg(regtype,supreg,reginfo[supreg].subreg);
+            if assigned(reginfo[supreg].live_start) then
+              begin
+{$ifdef EXTDEBUG}
+                if reginfo[supreg].live_start=reginfo[supreg].live_end then
+                  Comment(V_Warning,'Register '+std_regname(r)+' is only used once');
+{$endif EXTDEBUG}
+                list.insertbefore(Tai_regalloc.alloc(r),reginfo[supreg].live_start);
+                { Insert live end deallocation before reg allocations
+                  to reduce conflicts }
+                p:=reginfo[supreg].live_end;
+                while assigned(p) and
+                      assigned(p.previous) and
+                      (tai(p.previous).typ=ait_regalloc) and
+                      tai_regalloc(p.previous).allocation do
+                  p:=tai(p.previous);
+                list.insertbefore(Tai_regalloc.dealloc(r),p);
+              end
+{$ifdef EXTDEBUG}
+            else
+              Comment(V_Warning,'Register '+std_regname(r)+' not used');
+{$endif EXTDEBUG}
+          end;
+      end;
+
+
+    procedure trgobj.generate_interference_graph(list:Taasmoutput;headertai:tai);
+      var
+        p : tai;
+        i : integer;
+        supreg : tsuperregister;
+      begin
+        { All allocations are available. Now we can generate the
+          interference graph. Walk through all instructions, we can
+          start with the headertai, because before the header tai is
+          only symbols. }
+        live_registers.clear;
+        p:=headertai;
+        while assigned(p) do
+          begin
+            case p.typ of
+              ait_regalloc:
+                begin
+                  if (getregtype(Tai_regalloc(p).reg)=regtype) then
+                    begin
+                      supreg:=getsupreg(Tai_regalloc(p).reg);
+                      if Tai_regalloc(p).allocation then
+                        live_registers.add(supreg)
+                      else
+                        live_registers.delete(supreg);
+                      add_edges_used(supreg);
+                      add_constraints(Tai_regalloc(p).reg);
+                    end;
+                end;
+{              ait_instruction:
+                begin
+                  aktfilepos:=Taicpu_abstract(p).fileinfo;
+                  for i:=0 to Taicpu_abstract(p).ops-1 do
+                    with Taicpu_abstract(p).oper[i]^ do
+                      begin
+                        case typ of
+                          top_reg :
+                            begin
+                              add_edges_used(getsupreg(reg));
+                              add_constraints(reg);
+                            end;
+                          top_ref :
+                            begin
+                              add_edges_used(getsupreg(ref^.base));
+                              add_constraints(ref^.base);
+                              add_edges_used(getsupreg(ref^.index));
+                              add_constraints(ref^.index);
+                            end;
+                        end;
+                      end;
+                end; }
+            end;
+            p:=Tai(p.next);
+          end;
+
+{$ifdef EXTDEBUG}
+        if live_registers.length>0 then
+          begin
+            for i:=0 to live_registers.length-1 do
+              Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf[i],defaultsub))+' not released');
+          end;
+{$endif}
+      end;
+
+
     function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
     function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
 
 
     {Returns true if any help registers have been used.}
     {Returns true if any help registers have been used.}
@@ -1473,8 +1564,7 @@ implementation
                                                       live_registers,
                                                       live_registers,
                                                       spill_temps^) then
                                                       spill_temps^) then
                   spill_registers:=true;
                   spill_registers:=true;
-
-                if Taicpu_abstract(p).is_move then
+                if Taicpu_abstract(p).is_reg_move then
                   add_move_instruction(Taicpu(p));
                   add_move_instruction(Taicpu(p));
               end;
               end;
           end;
           end;
@@ -1579,15 +1669,16 @@ implementation
     end;
     end;
 
 
 
 
-    procedure Trgobj.check_unreleasedregs;
-      begin
-      end;
-
-
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.102  2003-12-15 16:37:47  daniel
+  Revision 1.103  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.102  2003/12/15 16:37:47  daniel
     * More microoptimizations
     * More microoptimizations
 
 
   Revision 1.101  2003/12/15 15:58:58  peter
   Revision 1.101  2003/12/15 15:58:58  peter

+ 10 - 3
compiler/utils/mkx86reg.pp

@@ -13,6 +13,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 
  **********************************************************************}
  **********************************************************************}
+{$mode objfpc}
 {$i+}
 {$i+}
 program mkx86reg;
 program mkx86reg;
 
 
@@ -383,8 +384,8 @@ begin
         end
         end
       else
       else
         first:=false;
         first:=false;
-      writeln(confile,names[i],' = ',numbers[i],';');
-      write(numfile,numbers[i]);
+      writeln(confile,names[i],' = ','tregister(',numbers[i],')',';');
+      write(numfile,'tregister(',numbers[i],')');
       write(stdfile,'''',stdnames[i],'''');
       write(stdfile,'''',stdnames[i],'''');
       write(attfile,'''',attnames[i],'''');
       write(attfile,'''',attnames[i],'''');
       if not(x86_64) then
       if not(x86_64) then
@@ -457,7 +458,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.3  2003-09-24 17:11:33  florian
+  Revision 1.4  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.3  2003/09/24 17:11:33  florian
     * x86_64 support; turn on by passing x86_64
     * x86_64 support; turn on by passing x86_64
 
 
   Revision 1.2  2003/09/03 15:55:02  peter
   Revision 1.2  2003/09/03 15:55:02  peter

+ 10 - 4
compiler/x86/aasmcpu.pas

@@ -201,7 +201,7 @@ interface
          procedure Pass2(sec:TAsmObjectdata);virtual;
          procedure Pass2(sec:TAsmObjectdata);virtual;
          procedure SetOperandOrder(order:TOperandOrder);
          procedure SetOperandOrder(order:TOperandOrder);
          function is_nop:boolean;override;
          function is_nop:boolean;override;
-         function is_move:boolean;override;
+         function is_reg_move:boolean;override;
          function spill_registers(list:Taasmoutput;
          function spill_registers(list:Taasmoutput;
                                   rgget:Trggetproc;
                                   rgget:Trggetproc;
                                   rgunget:Trgungetproc;
                                   rgunget:Trgungetproc;
@@ -1904,7 +1904,7 @@ implementation
               (opcode=A_XCHG) and (oper[0]^.typ=top_reg) and (oper[1]^.typ=top_reg) and (oper[0]^.reg=oper[1]^.reg);
               (opcode=A_XCHG) and (oper[0]^.typ=top_reg) and (oper[1]^.typ=top_reg) and (oper[0]^.reg=oper[1]^.reg);
     end;
     end;
 
 
-    function Taicpu.is_move:boolean;
+    function Taicpu.is_reg_move:boolean;
 
 
     begin
     begin
       {We do not check the number of operands; we assume that nobody constructs
       {We do not check the number of operands; we assume that nobody constructs
@@ -1912,7 +1912,7 @@ implementation
        a move between a reference and a register is not a move that is of
        a move between a reference and a register is not a move that is of
        interrest to the register allocation, therefore we only return true
        interrest to the register allocation, therefore we only return true
        for a move between two registers. (DM)}
        for a move between two registers. (DM)}
-      is_move:=((opcode=A_MOV) or (opcode=A_MOVZX) or (opcode=A_MOVSX)) and
+      result:=((opcode=A_MOV) or (opcode=A_MOVZX) or (opcode=A_MOVSX)) and
         ((oper[0]^.typ=top_reg) and (oper[1]^.typ=top_reg));
         ((oper[0]^.typ=top_reg) and (oper[1]^.typ=top_reg));
     end;
     end;
 
 
@@ -2344,7 +2344,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.39  2003-12-14 20:24:28  daniel
+  Revision 1.40  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.39  2003/12/14 20:24:28  daniel
     * Register allocator speed optimizations
     * Register allocator speed optimizations
       - Worklist no longer a ringbuffer
       - Worklist no longer a ringbuffer
       - No find operations are left
       - No find operations are left

+ 24 - 20
compiler/x86/cgx86.pas

@@ -43,10 +43,10 @@ unit cgx86;
         function  getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
         function  getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
         procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
         procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
         procedure ungetregister(list:Taasmoutput;r:Tregister);override;
         procedure ungetregister(list:Taasmoutput;r:Tregister);override;
-        procedure ungetreference(list:Taasmoutput;const r:Treference);override;
         procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
         procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
         procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
         procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
         function  uses_registers(rt:Tregistertype):boolean;override;
         function  uses_registers(rt:Tregistertype):boolean;override;
+        procedure add_reg_instruction(instr:Tai;r:tregister);override;
         procedure dec_fpu_stack;
         procedure dec_fpu_stack;
         procedure inc_fpu_stack;
         procedure inc_fpu_stack;
 
 
@@ -211,15 +211,6 @@ unit cgx86;
       end;
       end;
 
 
 
 
-    procedure tcgx86.ungetreference(list:Taasmoutput;const r:Treference);
-      begin
-        if r.base<>NR_NO then
-          ungetregister(list,r.base);
-        if r.index<>NR_NO then
-          ungetregister(list,r.index);
-      end;
-
-
     procedure Tcgx86.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
     procedure Tcgx86.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
       begin
       begin
         if rt<>R_FPUREGISTER then
         if rt<>R_FPUREGISTER then
@@ -243,6 +234,13 @@ unit cgx86;
       end;
       end;
 
 
 
 
+    procedure tcgx86.add_reg_instruction(instr:Tai;r:tregister);
+      begin
+        if getregtype(r)<>R_FPUREGISTER then
+          inherited add_reg_instruction(instr,r);
+      end;
+
+
     procedure tcgx86.dec_fpu_stack;
     procedure tcgx86.dec_fpu_stack;
       begin
       begin
         dec(rgfpu.fpuvaroffset);
         dec(rgfpu.fpuvaroffset);
@@ -1426,18 +1424,18 @@ unit cgx86;
            system_i386_win32,
            system_i386_win32,
         {$endif}
         {$endif}
            system_i386_freebsd,
            system_i386_freebsd,
-	   system_i386_netbsd,
-//	   system_i386_openbsd,
+           system_i386_netbsd,
+//         system_i386_openbsd,
            system_i386_wdosx,
            system_i386_wdosx,
            system_i386_linux:
            system_i386_linux:
              begin
              begin
-		Case target_info.system Of
-		 system_i386_freebsd : mcountprefix:='.';
-		 system_i386_netbsd : mcountprefix:='__';
-//		 system_i386_openbsd : mcountprefix:='.';
-		else
-  		 mcountPrefix:='';
-		end;
+                Case target_info.system Of
+                 system_i386_freebsd : mcountprefix:='.';
+                 system_i386_netbsd : mcountprefix:='__';
+//               system_i386_openbsd : mcountprefix:='.';
+                else
+                 mcountPrefix:='';
+                end;
                 objectlibrary.getaddrlabel(pl);
                 objectlibrary.getaddrlabel(pl);
                 list.concat(Tai_section.Create(sec_data));
                 list.concat(Tai_section.Create(sec_data));
                 list.concat(Tai_align.Create(4));
                 list.concat(Tai_align.Create(4));
@@ -1684,7 +1682,13 @@ unit cgx86;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.90  2003-12-12 17:16:18  peter
+  Revision 1.91  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.90  2003/12/12 17:16:18  peter
     * rg[tregistertype] added in tcg
     * rg[tregistertype] added in tcg
 
 
   Revision 1.89  2003/12/06 01:15:23  florian
   Revision 1.89  2003/12/06 01:15:23  florian

+ 8 - 2
compiler/x86/cpubase.pas

@@ -176,7 +176,7 @@ uses
 {$endif x86_64}
 {$endif x86_64}
       );
       );
 
 
-      regstabs_table : array[tregisterindex] of tregister = (
+      regstabs_table : array[tregisterindex] of shortint = (
 {$ifdef x86_64}
 {$ifdef x86_64}
         {$i r8664stab.inc}
         {$i r8664stab.inc}
 {$else x86_64}
 {$else x86_64}
@@ -526,7 +526,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.30  2003-10-31 09:22:55  mazen
+  Revision 1.31  2003-12-15 21:25:49  peter
+    * reg allocations for imaginary register are now inserted just
+      before reg allocation
+    * tregister changed to enum to allow compile time check
+    * fixed several tregister-tsuperregister errors
+
+  Revision 1.30  2003/10/31 09:22:55  mazen
   * using findreg_by_<name|number>_table directly to decrease heap overheading
   * using findreg_by_<name|number>_table directly to decrease heap overheading
 
 
   Revision 1.29  2003/10/30 17:13:18  peter
   Revision 1.29  2003/10/30 17:13:18  peter