ソースを参照

* Fixed register allocator. *Lots* of fixes.

daniel 22 年 前
コミット
268bfcf784

+ 12 - 10
compiler/i386/ag386nsm.pas

@@ -297,17 +297,16 @@ interface
             end;
           top_symbol :
             begin
-              AsmWrite('dword ');
+              asmwrite('dword ');
               if assigned(o.sym) then
-               AsmWrite(o.sym.name);
+               begin
+                asmwrite(o.sym.name);
+                if o.symofs=0 then
+                  exit;
+               end;
               if o.symofs>0 then
-               AsmWrite('+'+tostr(o.symofs))
-              else
-               if o.symofs<0 then
-                AsmWrite(tostr(o.symofs))
-               else
-                if not(assigned(o.sym)) then
-                 AsmWrite('0');
+               asmwrite('+');
+              asmwrite(tostr(o.symofs))
             end;
           top_ref :
             begin
@@ -926,7 +925,10 @@ initialization
 end.
 {
   $Log$
-  Revision 1.35  2003-06-03 13:01:59  daniel
+  Revision 1.36  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.35  2003/06/03 13:01:59  daniel
     * Register allocator finished
 
   Revision 1.34  2003/05/26 19:37:57  peter

+ 7 - 15
compiler/i386/n386add.pas

@@ -378,26 +378,15 @@ interface
                        location_release(exprasmlist,right.location);
                        cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(exprasmlist,1));
                       {$ifdef newra}
-                        r.enum:=R_INTREGISTER;
-                        for i:=first_supreg to last_supreg do
-                          if i<>RS_FRAME_POINTER_REG then
-                            begin
-                              r.number:=i shl 8 or R_SUBWHOLE;
-                              rg.getexplicitregisterint(exprasmlist,r.number);
-                            end;
+                       rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                       {$else}
-                        rg.saveintregvars(exprasmlist,regstopush);
+                       rg.saveintregvars(exprasmlist,regstopush);
                       {$endif}
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
                        paramanager.freeintparaloc(exprasmlist,2);
                        paramanager.freeintparaloc(exprasmlist,1);
                       {$ifdef newra}
-                        for i:=first_supreg to last_supreg do
-                          if i<>RS_FRAME_POINTER_REG then
-                            begin
-                              r.number:=i shl 8 or R_SUBWHOLE;
-                              rg.ungetregisterint(exprasmlist,r);
-                            end;
+                       rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                       {$else}
                         rg.restoreusedintregisters(exprasmlist,pushed);
                       {$endif}
@@ -1644,7 +1633,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.72  2003-06-17 16:51:30  peter
+  Revision 1.73  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.72  2003/06/17 16:51:30  peter
     * cycle fixes
 
   Revision 1.71  2003/06/07 18:57:04  jonas

+ 19 - 36
compiler/ncgcal.pas

@@ -756,14 +756,15 @@ implementation
                  (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                begin
 {$ifndef cpu64bit}
-                 if resulttype.def.size>sizeof(aword) then
-                   begin
-                     include(regs_to_push_int,RS_FUNCTION_RESULT64_LOW_REG);
-                     include(regs_to_push_int,RS_FUNCTION_RESULT64_HIGH_REG);
-                   end
-                 else
+                 if resulttype.def.deftype<>floatdef then
+                   if resulttype.def.size>sizeof(aword) then
+                     begin
+                       include(regs_to_push_int,RS_FUNCTION_RESULT64_LOW_REG);
+                       include(regs_to_push_int,RS_FUNCTION_RESULT64_HIGH_REG);
+                     end
+                   else
 {$endif cpu64bit}
-                   include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
+                    include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
                end;
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
 {$endif}
@@ -787,7 +788,7 @@ implementation
            begin
               {No procedure is allowed to destroy ebp.}
 {$ifdef newra}
-              regs_to_alloc:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
+              regs_to_alloc:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
               if (not is_void(resulttype.def)) and
                  not(paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                 begin
@@ -939,12 +940,7 @@ implementation
                      end;
 
 {$ifdef newra}
-                   for i:=first_supreg to last_supreg do
-                    if i in regs_to_alloc then
-                      begin
-                        r.number:=i shl 8 or R_SUBWHOLE;
-                        rg.getexplicitregisterint(exprasmlist,r.number);
-                      end;
+                   rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
 {$endif}
                    { call method }
                    reference_reset_base(href,{$ifdef newra}vmtreg2{$else}vmtreg{$endif},
@@ -966,12 +962,7 @@ implementation
                     end;
 
 {$ifdef newra}
-                  for i:=first_supreg to last_supreg do
-                    if i in regs_to_alloc then
-                      begin
-                        r.number:=i shl 8 or R_SUBWHOLE;
-                        rg.getexplicitregisterint(exprasmlist,r.number);
-                      end;
+                  rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
 {$endif}
                   { Calling interrupt from the same code requires some
                     extra code }
@@ -990,14 +981,14 @@ implementation
               if right.location.loc in  [LOC_REFERENCE,LOC_CREFERENCE] then
                 begin
                   helpref:=right.location.reference;
-                  if helpref.index.number<>NR_NO then
+                  if (helpref.index.number<>NR_NO) and (helpref.index.number<>NR_FRAME_POINTER_REG) then
                     begin
                       rg.ungetregisterint(exprasmlist,helpref.index);
                       helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
                       cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
                                         right.location.reference.index,helpref.index);
                     end;
-                  if helpref.base.number<>NR_NO then
+                  if (helpref.base.number<>NR_NO) and (helpref.base.number<>NR_FRAME_POINTER_REG) then
                     begin
                       rg.ungetregisterint(exprasmlist,helpref.base);
                       helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
@@ -1021,12 +1012,7 @@ implementation
                 end;
 
 {$ifdef newra}
-              for i:=first_supreg to last_supreg do
-                if i in regs_to_alloc then
-                  begin
-                    r.number:=i shl 8 or R_SUBWHOLE;
-                    rg.getexplicitregisterint(exprasmlist,r.number);
-                  end;
+              rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
 {$endif}
               { Calling interrupt from the same code requires some
                 extra code }
@@ -1097,13 +1083,7 @@ implementation
                  end;
              end;
            end;
-         r.enum:=R_INTREGISTER;
-         for i:=first_supreg to last_supreg do
-           if i in regs_to_free then
-             begin
-               r.number:=i shl 8 or R_SUBWHOLE;
-               rg.ungetregisterint(exprasmlist,r);
-             end;
+         rg.deallocexplicitregistersint(exprasmlist,regs_to_free);
 {$endif}
          { handle function results }
          if (not is_void(resulttype.def)) then
@@ -1561,7 +1541,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.97  2003-07-05 20:21:26  jonas
+  Revision 1.98  2003-07-06 15:31:20  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.97  2003/07/05 20:21:26  jonas
      * create_paraloc_info() is now called separately for the caller and
        callee info
      * fixed ppc cycle

+ 13 - 53
compiler/ncgmem.pas

@@ -521,13 +521,8 @@ implementation
                cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(exprasmlist,2));
                cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(exprasmlist,1));
             {$ifdef newra}
-               hreg.enum:=R_INTREGISTER;
-               for i:=first_supreg to last_supreg do
-                 if i<>RS_FRAME_POINTER_REG then
-                   begin
-                     hreg.number:=i shl 8 or R_SUBWHOLE;
-                     rg.getexplicitregisterint(exprasmlist,hreg.number);
-                   end;
+               rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
+
             {$else}
                rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
             {$endif}
@@ -535,12 +530,7 @@ implementation
                paramanager.freeintparaloc(exprasmlist,2);
                paramanager.freeintparaloc(exprasmlist,1);
             {$ifdef newra}
-               for i:=first_supreg to last_supreg do
-                 if i<>RS_FRAME_POINTER_REG then
-                   begin
-                     hreg.number:=i shl 8 or R_SUBWHOLE;
-                     rg.ungetregisterint(exprasmlist,hreg);
-                   end;
+               rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
             {$else}
                rg.restoreusedintregisters(exprasmlist,pushed);
             {$endif}
@@ -608,25 +598,14 @@ implementation
                 {$endif}
                    cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(exprasmlist,1));
                 {$ifdef newra}
-                   hreg.enum:=R_INTREGISTER;
-                   for i:=first_supreg to last_supreg do
-                     if i<>RS_FRAME_POINTER_REG then
-                       begin
-                         hreg.number:=i shl 8 or R_SUBWHOLE;
-                         rg.getexplicitregisterint(exprasmlist,hreg.number);
-                       end;
+                   rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                 {$else}
                    rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                 {$endif}
                    cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
                    paramanager.freeintparaloc(exprasmlist,1);
                 {$ifdef newra}
-                   for i:=first_supreg to last_supreg do
-                     if i<>RS_FRAME_POINTER_REG then
-                       begin
-                         hreg.number:=i shl 8 or R_SUBWHOLE;
-                         rg.ungetregisterint(exprasmlist,hreg);
-                       end;
+                   rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                 {$else}
                    rg.restoreusedintregisters(exprasmlist,pushed);
                 {$endif}
@@ -710,13 +689,7 @@ implementation
                               dec(href.offset,7);
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
                             {$ifdef newra}
-                              hreg.enum:=R_INTREGISTER;
-                              for i:=first_supreg to last_supreg do
-                               if i<>RS_FRAME_POINTER_REG then
-                                  begin
-                                    hreg.number:=i shl 8 or R_SUBWHOLE;
-                                    rg.getexplicitregisterint(exprasmlist,hreg.number);
-                                  end;
+                              rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                             {$else}
                               rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                             {$endif}
@@ -724,12 +697,7 @@ implementation
                               paramanager.freeintparaloc(exprasmlist,2);
                               paramanager.freeintparaloc(exprasmlist,1);
                             {$ifdef newra}
-                              for i:=first_supreg to last_supreg do
-                               if i<>RS_FRAME_POINTER_REG then
-                                  begin
-                                    hreg.number:=i shl 8 or R_SUBWHOLE;
-                                    rg.ungetregisterint(exprasmlist,hreg);
-                                  end;
+                              rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                             {$else}
                               rg.restoreusedintregisters(exprasmlist,pushed);
                             {$endif}
@@ -868,13 +836,7 @@ implementation
                               dec(href.offset,7);
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
                             {$ifdef newra}
-                              hreg.enum:=R_INTREGISTER;
-                              for i:=first_supreg to last_supreg do
-                               if i<>RS_FRAME_POINTER_REG then
-                                  begin
-                                    hreg.number:=i shl 8 or R_SUBWHOLE;
-                                    rg.getexplicitregisterint(exprasmlist,hreg.number);
-                                  end;
+                              rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                             {$else}
                               rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                             {$endif}
@@ -882,12 +844,7 @@ implementation
                               paramanager.freeintparaloc(exprasmlist,2);
                               paramanager.freeintparaloc(exprasmlist,1);
                             {$ifdef newra}
-                              for i:=first_supreg to last_supreg do
-                               if i<>RS_FRAME_POINTER_REG then
-                                  begin
-                                    hreg.number:=i shl 8 or R_SUBWHOLE;
-                                    rg.ungetregisterint(exprasmlist,hreg);
-                                  end;
+                              rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
                             {$else}
                               rg.restoreusedintregisters(exprasmlist,pushed);
                             {$endif}
@@ -924,7 +881,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.64  2003-06-17 19:24:08  jonas
+  Revision 1.65  2003-07-06 15:31:20  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.64  2003/06/17 19:24:08  jonas
     * fixed conversion of fpc_*str_unique to compilerproc
 
   Revision 1.63  2003/06/17 16:34:44  jonas

+ 18 - 3
compiler/ncgutil.pas

@@ -401,6 +401,20 @@ implementation
          end
         else
          begin
+         {$ifdef newra}
+           { transformations to 32bit or smaller }
+           if (l.loc=LOC_REGISTER) and (l.size in [OS_64,OS_S64]) then
+             { if the previous was 64bit release the high register }
+             begin
+               rg.ungetregisterint(list,l.registerhigh);
+               l.registerhigh.enum:=R_NO;
+             end;
+           {Do not bother to recycle the existing register. The register
+            allocator eliminates unnecessary moves, so it's not needed
+            and trying to recycle registers can cause problems because
+            the registers changes size and may need aditional constraints.}
+           hregister:=rg.getregisterint(list,dst_size);
+         {$else}
            { transformations to 32bit or smaller }
            if l.loc=LOC_REGISTER then
             begin
@@ -441,8 +455,6 @@ implementation
                  hregister:=rg.getregisterint(list,dst_size);
              end;
            hregister:=rg.makeregsize(hregister,dst_size);
-        {$ifdef newra}
-           rg.add_constraints(hregister.number);
         {$endif}
            { load value in new register }
            case l.loc of
@@ -1976,7 +1988,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.128  2003-07-02 22:18:04  peter
+  Revision 1.129  2003-07-06 15:31:20  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.128  2003/07/02 22:18:04  peter
     * paraloc splitted in callerparaloc,calleeparaloc
     * sparc calling convention updates
 

+ 6 - 3
compiler/nflw.pas

@@ -119,9 +119,9 @@ interface
           labsym : tlabelsym;
           labsymderef : tderef;
           exceptionblock : integer;
-//          internlab : tinterngotolabel;
+{          internlab : tinterngotolabel;}
           constructor create(p : tlabelsym);virtual;
-//          constructor createintern(g:tinterngotolabel);
+{          constructor createintern(g:tinterngotolabel);}
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure derefimpl;override;
@@ -1429,7 +1429,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.78  2003-06-13 21:19:30  peter
+  Revision 1.79  2003-07-06 15:31:20  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.78  2003/06/13 21:19:30  peter
     * current_procdef removed, use current_procinfo.procdef instead
 
   Revision 1.77  2003/06/07 20:26:32  peter

+ 11 - 2
compiler/pass_2.pas

@@ -205,7 +205,11 @@ implementation
                  Comment(V_Warning,'Location is different in secondpass: '+nodetype2str[p.nodetype]);
              end;
 
-{$ifndef newra}
+{$ifdef newra}
+            if rg.unusedregsint*([first_supreg..last_supreg] - [RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG])<>
+                                ([first_supreg..last_supreg] - [RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]) then
+              internalerror(200306171);
+{$else}
             { check if all scratch registers are freed }
             for i:=1 to max_scratch_regs do
               if not(scratch_regs[i] in cg.unusedscratchregisters) then
@@ -255,7 +259,9 @@ implementation
 
     procedure generatecode(var p : tnode);
       begin
+       {$ifndef newra}
          rg.cleartempgen;
+       {$endif}
          flowcontrol:=[];
          { when size optimization only count occurrence }
          if cs_littlesize in aktglobalswitches then
@@ -310,7 +316,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.59  2003-07-06 10:18:47  jonas
+  Revision 1.60  2003-07-06 15:31:20  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.59  2003/07/06 10:18:47  jonas
     * also generate the caller paraloc info of a procedure if it doesn't exist
       yet at the start of pass_2
 

+ 5 - 2
compiler/pp.pas

@@ -186,11 +186,14 @@ begin
   exitproc:=@myexit;
 
 { Call the compiler with empty command, so it will take the parameters }
-  Halt(compiler.Compile(''));
+  {Halt(}compiler.Compile(''){)};
 end.
 {
   $Log$
-  Revision 1.22  2003-04-22 14:33:38  peter
+  Revision 1.23  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.22  2003/04/22 14:33:38  peter
     * removed some notes/hints
 
   Revision 1.21  2003/02/15 22:25:50  carl

+ 6 - 2
compiler/psub.pas

@@ -595,7 +595,8 @@ implementation
 
         { reset the temporary memory }
         rg.cleartempgen;
-        rg.used_in_proc_int:=[];
+{        exclude(rg.unusedregsint,RS_STACK_POINTER_REG);}
+        rg.used_in_proc_int:=[{RS_STACK_POINTER_REG}];
         rg.used_in_proc_other:=[];
 
         { set the start offset to the start of the temp area in the stack }
@@ -1253,7 +1254,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.130  2003-07-05 20:15:24  jonas
+  Revision 1.131  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.130  2003/07/05 20:15:24  jonas
     * set pi_do_call if range/overflow checking is on
 
   Revision 1.129  2003/06/17 16:34:44  jonas

+ 93 - 14
compiler/rgobj.pas

@@ -34,14 +34,21 @@
 
 Register allocator introduction.
 
-Free Pascal uses a Chaitin style register allocator similair to the one
-described in the book "Modern compiler implementation in C" by Andrew W. Appel.,
-published by Cambridge University Press.
+Free Pascal uses a Chaitin style register allocator. We use a variant similair
+to the one described in the book "Modern compiler implementation in C" by
+Andrew W. Appel., published by Cambridge University Press.
+
+The register allocator that is described by Appel uses a much improved way
+of register coalescing, called "iterated register coalescing". Instead
+of doing coalescing as a prepass to the register allocation, the coalescing
+is done inside the register allocator. This has the advantage that the
+register allocator can coalesce very aggresively without introducing spills.
 
 Reading this book is recommended for a complete understanding. Here is a small
 introduction.
 
-The code generator thinks it has an infinite amount of registers. Our processorhas a limited amount of registers. Therefore we must reduce the amount of
+The code generator thinks it has an infinite amount of registers. Our processor
+has a limited amount of registers. Therefore we must reduce the amount of
 registers until there are less enough to fit into the processors registers.
 
 Registers can interfere or not interfere. If two imaginary registers interfere
@@ -68,6 +75,9 @@ Graph colouring is an NP complete problem. Therefore we use an approximation
 that pushes registers to colour on to a stack. This is done in the "simplify"
 procedure.
 
+The register allocator first checks which registers are a candidate for
+coalescing.
+
 *******************************************************************************}
 
 
@@ -275,6 +285,11 @@ unit rgobj;
           }
           function getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;virtual;
 
+{$ifdef newra}
+          procedure allocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
+          procedure deallocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
+{$endif}
+
           {# Deallocate any kind of register }
           procedure ungetregister(list: taasmoutput; r : tregister); virtual;
 
@@ -493,7 +508,9 @@ unit rgobj;
 
       punusedstate = ^tunusedstate;
       tunusedstate = record
+{$ifndef newra}
         unusedregsint : Tsupregset;
+{$endif}
         unusedregsaddr : Tsupregset;
         unusedregsfpu : tregisterset;
         unusedregsmm : tregisterset;
@@ -521,7 +538,12 @@ unit rgobj;
        resetusableregisters;
        lastintreg:=0;
        maxintreg:=first_imreg;
-       cpu_registers:={Acpu_registers}last_supreg-first_supreg+1;
+       {What madman decided to change the code like this: (??)
+       cpu_registers:=last_supreg-first_supreg+1;
+       The amount of registers available for register allocation is
+       allmost allways smaller than the amount of registers that exists!
+       Therefore: }
+       cpu_registers:=Acpu_registers;
 {$ifdef TEMPREGDEBUG}
        fillchar(reg_user,sizeof(reg_user),0);
        fillchar(reg_releaser,sizeof(reg_releaser),0);
@@ -763,6 +785,52 @@ unit rgobj;
        getexplicitregisterint:=r2;
     end;
 
+{$ifdef newra}
+    procedure Trgobj.allocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
+
+    var reg:Tregister;
+        i:Tsuperregister;
+
+    begin
+      if unusedregsint*r=r then
+        begin
+          unusedregsint:=unusedregsint-r;
+          used_in_proc_int:=used_in_proc_int+r;
+          for i:=first_supreg to last_supreg do
+            if i in r then
+              begin
+                add_edges_used(i);
+                reg.enum:=R_INTREGISTER;
+                reg.number:=i shl 8 or R_SUBWHOLE;
+                list.concat(Tai_regalloc.alloc(reg));
+              end;
+         end
+       else
+         internalerror(200305061);
+    end;
+
+    procedure Trgobj.deallocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
+
+    var reg:Tregister;
+        i:Tsuperregister;
+
+    begin
+      if unusedregsint*r=[] then
+        begin
+          unusedregsint:=unusedregsint+r;
+          for i:=last_supreg downto first_supreg do
+            if i in r then
+              begin
+                reg.enum:=R_INTREGISTER;
+                reg.number:=i shl 8 or R_SUBWHOLE;
+                list.concat(Tai_regalloc.dealloc(reg));
+              end;
+         end
+       else
+         internalerror(200305062);
+    end;
+{$endif}
+
 
     { tries to allocate the passed register, if possible }
     function trgobj.getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
@@ -853,9 +921,7 @@ unit rgobj;
            exit;
          if r.enum>lastreg then
           internalerror(200301081);
-         if r.enum in intregs then
-           ungetregisterint(list,r)
-         else if r.enum in fpuregs then
+         if r.enum in fpuregs then
            ungetregisterfpu(list,r,OS_NO)
          else if r.enum in mmregs then
            ungetregistermm(list,r)
@@ -1357,7 +1423,9 @@ unit rgobj;
     procedure trgobj.saveUnusedState(var state: pointer);
       begin
         new(punusedstate(state));
+      {$ifndef newra}
         punusedstate(state)^.unusedregsint := unusedregsint;
+      {$endif}
         punusedstate(state)^.unusedregsfpu := unusedregsfpu;
         punusedstate(state)^.unusedregsmm := unusedregsmm;
       {$ifndef newra}
@@ -1370,7 +1438,9 @@ unit rgobj;
 
     procedure trgobj.restoreUnusedState(var state: pointer);
       begin
+      {$ifndef newra}
         unusedregsint := punusedstate(state)^.unusedregsint;
+      {$endif}
         unusedregsfpu := punusedstate(state)^.unusedregsfpu;
         unusedregsmm := punusedstate(state)^.unusedregsmm;
       {$ifndef newra}
@@ -1643,7 +1713,9 @@ unit rgobj;
               end;
         end;
       n:=Tsuperregister(simplifyworklist[p]);
-      delete(simplifyworklist,p,1);
+      if length(simplifyworklist)>1 then
+        simplifyworklist[p]:=simplifyworklist[length(simplifyworklist)];
+      dec(simplifyworklist[0]);
 
       {Push it on the selectstack.}
       selectstack:=selectstack+char(n);
@@ -1671,7 +1743,10 @@ unit rgobj;
       if not(u in [first_supreg..last_supreg]) and not move_related(u) and
          (degree[u]<cpu_registers) then
         begin
-          delete(freezeworklist,pos(char(u),freezeworklist),1);
+          if length(freezeworklist)>1 then
+            freezeworklist[pos(char(u),freezeworklist)]:=freezeworklist[length(freezeworklist)];
+          dec(freezeworklist[0]);
+{          delete(freezeworklist,pos(char(u),freezeworklist),1);}
           simplifyworklist:=simplifyworklist+char(u);
         end;
     end;
@@ -1940,6 +2015,7 @@ unit rgobj;
                 if a in colourednodes then
                   include(adj_colours,colour[a]);
               end;
+          include(adj_colours,RS_STACK_POINTER_REG);
           {Assume a spill by default...}
           spillednodes:=spillednodes+char(n);
           {Search for a colour not in this list.}
@@ -2246,9 +2322,8 @@ unit rgobj;
 
     begin
       if r.enum<=lastreg then
-        internalerror(2003010803);
+        internalerror(200301083);
       supreg:=r.number shr 8;
-      { takes much time }
       include(unusedregsint,supreg);
       if position=nil then
         list.insert(Tai_regalloc.dealloc(r))
@@ -2271,9 +2346,10 @@ unit rgobj;
       spill_registers:=false;
       unusedregsint:=[0..255];
       fillchar(degree,sizeof(degree),0);
+{      exclude(unusedregsint,RS_STACK_POINTER_REG);}
       if current_procinfo.framepointer.number=NR_FRAME_POINTER_REG then
         {Make sure the register allocator won't allocate registers into ebp.}
-        exclude(rg.unusedregsint,RS_FRAME_POINTER_REG);
+        exclude(unusedregsint,RS_FRAME_POINTER_REG);
       new(spill_temps);
       fillchar(spill_temps^,sizeof(spill_temps^),0);
       regs_to_spill_set:=[];
@@ -2459,7 +2535,10 @@ end.
 
 {
   $Log$
-  Revision 1.59  2003-07-06 15:00:47  jonas
+  Revision 1.60  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.59  2003/07/06 15:00:47  jonas
     * fixed my previous completely broken commit. It's not perfect though,
       registers > last_supreg and < max_intreg may still be "translated"
 

+ 6 - 3
compiler/symdef.pas

@@ -3415,7 +3415,7 @@ implementation
           end;
          lastref:=defref;
        { first, we assume that all registers are used }
-         usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
+         usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
          usedotherregisters:=ALL_REGISTERS;
          forwarddef:=true;
          interfacedef:=false;
@@ -3557,7 +3557,7 @@ implementation
          { set all registers to used for simplified compilation PM }
          if simplify_ppu then
            begin
-             usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
+             usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
              usedotherregisters:=ALL_REGISTERS;
            end;
 
@@ -5838,7 +5838,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.154  2003-07-02 22:18:04  peter
+  Revision 1.155  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.154  2003/07/02 22:18:04  peter
     * paraloc splitted in callerparaloc,calleeparaloc
     * sparc calling convention updates
 

+ 25 - 5
compiler/x86/aasmcpu.pas

@@ -2081,7 +2081,7 @@ implementation
       case ops of
         1:
           begin
-            if oper[0].typ=top_reg then
+            if (oper[0].typ=top_reg) and (oper[0].reg.enum=R_INTREGISTER) then
               begin
                 supreg:=oper[0].reg.number shr 8;
                 if supreg in r then
@@ -2109,7 +2109,7 @@ implementation
                      Change into:
 
                      mov r23d,[ebp-12]         ; Use a help register
-                     push [r23d+4*r22d]       ; Replace register by helpregister }
+                     push [r23d+4*r22d]        ; Replace register by helpregister }
                     subreg:=oper[0].ref^.base.number and $ff;
                     if oper[0].ref^.index.number=NR_NO then
                       pos:=Tai(previous)
@@ -2156,7 +2156,7 @@ implementation
           end;
         2:
           begin
-            if oper[0].typ=top_reg then
+            if (oper[0].typ=top_reg) and (oper[0].reg.enum=R_INTREGISTER) then
               begin
                 supreg:=oper[0].reg.number shr 8;
                 subreg:=oper[0].reg.number and $ff;
@@ -2196,7 +2196,7 @@ implementation
                       oper[0].ref^:=spilltemplist[supreg];
                     end;
               end;
-            if oper[1].typ=top_reg then
+            if (oper[1].typ=top_reg) and (oper[1].reg.enum=R_INTREGISTER) then
               begin
                 supreg:=oper[1].reg.number shr 8;
                 subreg:=oper[1].reg.number and $ff;
@@ -2246,6 +2246,23 @@ implementation
                          Change into:
   
                          add [ebp-12],r21d    ; Replace register by reference }
+                        if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
+                          begin
+                            {Because 'movzx memory,register' does not exist...}
+                            spill_registers:=true;
+                            op:=opcode;
+                            opcode:=A_MOV;
+                            opsize:=reg2opsize(oper[1].reg);
+                            pos:=get_insert_pos(Tai(previous),oper[0].reg.number,0,0);
+                            rgget(list,pos,subreg,helpreg);
+                            helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0].reg,helpreg);
+                            if pos=nil then
+                              list.insertafter(helpins,list.first)
+                            else
+                              list.insertafter(helpins,pos.next);
+                            rgunget(list,helpins,helpreg);
+                            forward_allocation(Tai(helpins.next));
+                          end;
                         oper[1].typ:=top_ref;
                         new(oper[1].ref);
                         oper[1].ref^:=spilltemplist[supreg];
@@ -2396,7 +2413,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.6  2003-06-14 14:53:50  jonas
+  Revision 1.7  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.6  2003/06/14 14:53:50  jonas
     * fixed newra cycle for x86
     * added constants for indicating source and destination operands of the
       "move reg,reg" instruction to aasmcpu (and use those in rgobj)

+ 6 - 5
compiler/x86/itx86att.pas

@@ -146,11 +146,9 @@ interface
      function gas_regnum_search(const s:string):Tnewregister;
 
 
-  implementation
+implementation
 
-    uses
-      cutils,systems,
-      verbose;
+     uses cutils;
 
      function gas_regnum_search(const s:string):Tnewregister;
 
@@ -178,7 +176,10 @@ interface
 end.
 {
   $Log$
-  Revision 1.1  2003-05-22 21:33:08  peter
+  Revision 1.2  2003-07-06 15:31:21  daniel
+    * Fixed register allocator. *Lots* of fixes.
+
+  Revision 1.1  2003/05/22 21:33:08  peter
     * i386 att instruction table moved to separate unit
 
 }