瀏覽代碼

* Fixed register allocator. *Lots* of fixes.

daniel 22 年之前
父節點
當前提交
268bfcf784

+ 12 - 10
compiler/i386/ag386nsm.pas

@@ -297,17 +297,16 @@ interface
             end;
             end;
           top_symbol :
           top_symbol :
             begin
             begin
-              AsmWrite('dword ');
+              asmwrite('dword ');
               if assigned(o.sym) then
               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
               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;
             end;
           top_ref :
           top_ref :
             begin
             begin
@@ -926,7 +925,10 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $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
     * Register allocator finished
 
 
   Revision 1.34  2003/05/26 19:37:57  peter
   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);
                        location_release(exprasmlist,right.location);
                        cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(exprasmlist,1));
                        cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(exprasmlist,1));
                       {$ifdef newra}
                       {$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}
                       {$else}
-                        rg.saveintregvars(exprasmlist,regstopush);
+                       rg.saveintregvars(exprasmlist,regstopush);
                       {$endif}
                       {$endif}
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
                        paramanager.freeintparaloc(exprasmlist,2);
                        paramanager.freeintparaloc(exprasmlist,2);
                        paramanager.freeintparaloc(exprasmlist,1);
                        paramanager.freeintparaloc(exprasmlist,1);
                       {$ifdef newra}
                       {$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}
                       {$else}
                         rg.restoreusedintregisters(exprasmlist,pushed);
                         rg.restoreusedintregisters(exprasmlist,pushed);
                       {$endif}
                       {$endif}
@@ -1644,7 +1633,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * cycle fixes
 
 
   Revision 1.71  2003/06/07 18:57:04  jonas
   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
                  (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                begin
                begin
 {$ifndef cpu64bit}
 {$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}
 {$endif cpu64bit}
-                   include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
+                    include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
                end;
                end;
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
 {$endif}
 {$endif}
@@ -787,7 +788,7 @@ implementation
            begin
            begin
               {No procedure is allowed to destroy ebp.}
               {No procedure is allowed to destroy ebp.}
 {$ifdef newra}
 {$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
               if (not is_void(resulttype.def)) and
                  not(paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                  not(paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                 begin
                 begin
@@ -939,12 +940,7 @@ implementation
                      end;
                      end;
 
 
 {$ifdef newra}
 {$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}
 {$endif}
                    { call method }
                    { call method }
                    reference_reset_base(href,{$ifdef newra}vmtreg2{$else}vmtreg{$endif},
                    reference_reset_base(href,{$ifdef newra}vmtreg2{$else}vmtreg{$endif},
@@ -966,12 +962,7 @@ implementation
                     end;
                     end;
 
 
 {$ifdef newra}
 {$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}
 {$endif}
                   { Calling interrupt from the same code requires some
                   { Calling interrupt from the same code requires some
                     extra code }
                     extra code }
@@ -990,14 +981,14 @@ implementation
               if right.location.loc in  [LOC_REFERENCE,LOC_CREFERENCE] then
               if right.location.loc in  [LOC_REFERENCE,LOC_CREFERENCE] then
                 begin
                 begin
                   helpref:=right.location.reference;
                   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
                     begin
                       rg.ungetregisterint(exprasmlist,helpref.index);
                       rg.ungetregisterint(exprasmlist,helpref.index);
                       helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
                       helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
                       cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
                       cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
                                         right.location.reference.index,helpref.index);
                                         right.location.reference.index,helpref.index);
                     end;
                     end;
-                  if helpref.base.number<>NR_NO then
+                  if (helpref.base.number<>NR_NO) and (helpref.base.number<>NR_FRAME_POINTER_REG) then
                     begin
                     begin
                       rg.ungetregisterint(exprasmlist,helpref.base);
                       rg.ungetregisterint(exprasmlist,helpref.base);
                       helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
                       helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
@@ -1021,12 +1012,7 @@ implementation
                 end;
                 end;
 
 
 {$ifdef newra}
 {$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}
 {$endif}
               { Calling interrupt from the same code requires some
               { Calling interrupt from the same code requires some
                 extra code }
                 extra code }
@@ -1097,13 +1083,7 @@ implementation
                  end;
                  end;
              end;
              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}
 {$endif}
          { handle function results }
          { handle function results }
          if (not is_void(resulttype.def)) then
          if (not is_void(resulttype.def)) then
@@ -1561,7 +1541,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
      * create_paraloc_info() is now called separately for the caller and
        callee info
        callee info
      * fixed ppc cycle
      * 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,right.location,paramanager.getintparaloc(exprasmlist,2));
                cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(exprasmlist,1));
                cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(exprasmlist,1));
             {$ifdef newra}
             {$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}
             {$else}
                rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
             {$endif}
             {$endif}
@@ -535,12 +530,7 @@ implementation
                paramanager.freeintparaloc(exprasmlist,2);
                paramanager.freeintparaloc(exprasmlist,2);
                paramanager.freeintparaloc(exprasmlist,1);
                paramanager.freeintparaloc(exprasmlist,1);
             {$ifdef newra}
             {$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}
             {$else}
                rg.restoreusedintregisters(exprasmlist,pushed);
                rg.restoreusedintregisters(exprasmlist,pushed);
             {$endif}
             {$endif}
@@ -608,25 +598,14 @@ implementation
                 {$endif}
                 {$endif}
                    cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(exprasmlist,1));
                    cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(exprasmlist,1));
                 {$ifdef newra}
                 {$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}
                 {$else}
                    rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                    rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                 {$endif}
                 {$endif}
                    cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
                    cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
                    paramanager.freeintparaloc(exprasmlist,1);
                    paramanager.freeintparaloc(exprasmlist,1);
                 {$ifdef newra}
                 {$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}
                 {$else}
                    rg.restoreusedintregisters(exprasmlist,pushed);
                    rg.restoreusedintregisters(exprasmlist,pushed);
                 {$endif}
                 {$endif}
@@ -710,13 +689,7 @@ implementation
                               dec(href.offset,7);
                               dec(href.offset,7);
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
                             {$ifdef newra}
                             {$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}
                             {$else}
                               rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                               rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                             {$endif}
                             {$endif}
@@ -724,12 +697,7 @@ implementation
                               paramanager.freeintparaloc(exprasmlist,2);
                               paramanager.freeintparaloc(exprasmlist,2);
                               paramanager.freeintparaloc(exprasmlist,1);
                               paramanager.freeintparaloc(exprasmlist,1);
                             {$ifdef newra}
                             {$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}
                             {$else}
                               rg.restoreusedintregisters(exprasmlist,pushed);
                               rg.restoreusedintregisters(exprasmlist,pushed);
                             {$endif}
                             {$endif}
@@ -868,13 +836,7 @@ implementation
                               dec(href.offset,7);
                               dec(href.offset,7);
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
                             {$ifdef newra}
                             {$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}
                             {$else}
                               rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                               rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
                             {$endif}
                             {$endif}
@@ -882,12 +844,7 @@ implementation
                               paramanager.freeintparaloc(exprasmlist,2);
                               paramanager.freeintparaloc(exprasmlist,2);
                               paramanager.freeintparaloc(exprasmlist,1);
                               paramanager.freeintparaloc(exprasmlist,1);
                             {$ifdef newra}
                             {$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}
                             {$else}
                               rg.restoreusedintregisters(exprasmlist,pushed);
                               rg.restoreusedintregisters(exprasmlist,pushed);
                             {$endif}
                             {$endif}
@@ -924,7 +881,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * fixed conversion of fpc_*str_unique to compilerproc
 
 
   Revision 1.63  2003/06/17 16:34:44  jonas
   Revision 1.63  2003/06/17 16:34:44  jonas

+ 18 - 3
compiler/ncgutil.pas

@@ -401,6 +401,20 @@ implementation
          end
          end
         else
         else
          begin
          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 }
            { transformations to 32bit or smaller }
            if l.loc=LOC_REGISTER then
            if l.loc=LOC_REGISTER then
             begin
             begin
@@ -441,8 +455,6 @@ implementation
                  hregister:=rg.getregisterint(list,dst_size);
                  hregister:=rg.getregisterint(list,dst_size);
              end;
              end;
            hregister:=rg.makeregsize(hregister,dst_size);
            hregister:=rg.makeregsize(hregister,dst_size);
-        {$ifdef newra}
-           rg.add_constraints(hregister.number);
         {$endif}
         {$endif}
            { load value in new register }
            { load value in new register }
            case l.loc of
            case l.loc of
@@ -1976,7 +1988,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
     * paraloc splitted in callerparaloc,calleeparaloc
     * sparc calling convention updates
     * sparc calling convention updates
 
 

+ 6 - 3
compiler/nflw.pas

@@ -119,9 +119,9 @@ interface
           labsym : tlabelsym;
           labsym : tlabelsym;
           labsymderef : tderef;
           labsymderef : tderef;
           exceptionblock : integer;
           exceptionblock : integer;
-//          internlab : tinterngotolabel;
+{          internlab : tinterngotolabel;}
           constructor create(p : tlabelsym);virtual;
           constructor create(p : tlabelsym);virtual;
-//          constructor createintern(g:tinterngotolabel);
+{          constructor createintern(g:tinterngotolabel);}
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure derefimpl;override;
           procedure derefimpl;override;
@@ -1429,7 +1429,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * current_procdef removed, use current_procinfo.procdef instead
 
 
   Revision 1.77  2003/06/07 20:26:32  peter
   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]);
                  Comment(V_Warning,'Location is different in secondpass: '+nodetype2str[p.nodetype]);
              end;
              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 }
             { check if all scratch registers are freed }
             for i:=1 to max_scratch_regs do
             for i:=1 to max_scratch_regs do
               if not(scratch_regs[i] in cg.unusedscratchregisters) then
               if not(scratch_regs[i] in cg.unusedscratchregisters) then
@@ -255,7 +259,9 @@ implementation
 
 
     procedure generatecode(var p : tnode);
     procedure generatecode(var p : tnode);
       begin
       begin
+       {$ifndef newra}
          rg.cleartempgen;
          rg.cleartempgen;
+       {$endif}
          flowcontrol:=[];
          flowcontrol:=[];
          { when size optimization only count occurrence }
          { when size optimization only count occurrence }
          if cs_littlesize in aktglobalswitches then
          if cs_littlesize in aktglobalswitches then
@@ -310,7 +316,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
     * also generate the caller paraloc info of a procedure if it doesn't exist
       yet at the start of pass_2
       yet at the start of pass_2
 
 

+ 5 - 2
compiler/pp.pas

@@ -186,11 +186,14 @@ begin
   exitproc:=@myexit;
   exitproc:=@myexit;
 
 
 { Call the compiler with empty command, so it will take the parameters }
 { Call the compiler with empty command, so it will take the parameters }
-  Halt(compiler.Compile(''));
+  {Halt(}compiler.Compile(''){)};
 end.
 end.
 {
 {
   $Log$
   $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
     * removed some notes/hints
 
 
   Revision 1.21  2003/02/15 22:25:50  carl
   Revision 1.21  2003/02/15 22:25:50  carl

+ 6 - 2
compiler/psub.pas

@@ -595,7 +595,8 @@ implementation
 
 
         { reset the temporary memory }
         { reset the temporary memory }
         rg.cleartempgen;
         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:=[];
         rg.used_in_proc_other:=[];
 
 
         { set the start offset to the start of the temp area in the stack }
         { set the start offset to the start of the temp area in the stack }
@@ -1253,7 +1254,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * set pi_do_call if range/overflow checking is on
 
 
   Revision 1.129  2003/06/17 16:34:44  jonas
   Revision 1.129  2003/06/17 16:34:44  jonas

+ 93 - 14
compiler/rgobj.pas

@@ -34,14 +34,21 @@
 
 
 Register allocator introduction.
 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
 Reading this book is recommended for a complete understanding. Here is a small
 introduction.
 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 until there are less enough to fit into the processors registers.
 
 
 Registers can interfere or not interfere. If two imaginary registers interfere
 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"
 that pushes registers to colour on to a stack. This is done in the "simplify"
 procedure.
 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;
           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 }
           {# Deallocate any kind of register }
           procedure ungetregister(list: taasmoutput; r : tregister); virtual;
           procedure ungetregister(list: taasmoutput; r : tregister); virtual;
 
 
@@ -493,7 +508,9 @@ unit rgobj;
 
 
       punusedstate = ^tunusedstate;
       punusedstate = ^tunusedstate;
       tunusedstate = record
       tunusedstate = record
+{$ifndef newra}
         unusedregsint : Tsupregset;
         unusedregsint : Tsupregset;
+{$endif}
         unusedregsaddr : Tsupregset;
         unusedregsaddr : Tsupregset;
         unusedregsfpu : tregisterset;
         unusedregsfpu : tregisterset;
         unusedregsmm : tregisterset;
         unusedregsmm : tregisterset;
@@ -521,7 +538,12 @@ unit rgobj;
        resetusableregisters;
        resetusableregisters;
        lastintreg:=0;
        lastintreg:=0;
        maxintreg:=first_imreg;
        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}
 {$ifdef TEMPREGDEBUG}
        fillchar(reg_user,sizeof(reg_user),0);
        fillchar(reg_user,sizeof(reg_user),0);
        fillchar(reg_releaser,sizeof(reg_releaser),0);
        fillchar(reg_releaser,sizeof(reg_releaser),0);
@@ -763,6 +785,52 @@ unit rgobj;
        getexplicitregisterint:=r2;
        getexplicitregisterint:=r2;
     end;
     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 }
     { tries to allocate the passed register, if possible }
     function trgobj.getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
     function trgobj.getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
@@ -853,9 +921,7 @@ unit rgobj;
            exit;
            exit;
          if r.enum>lastreg then
          if r.enum>lastreg then
           internalerror(200301081);
           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)
            ungetregisterfpu(list,r,OS_NO)
          else if r.enum in mmregs then
          else if r.enum in mmregs then
            ungetregistermm(list,r)
            ungetregistermm(list,r)
@@ -1357,7 +1423,9 @@ unit rgobj;
     procedure trgobj.saveUnusedState(var state: pointer);
     procedure trgobj.saveUnusedState(var state: pointer);
       begin
       begin
         new(punusedstate(state));
         new(punusedstate(state));
+      {$ifndef newra}
         punusedstate(state)^.unusedregsint := unusedregsint;
         punusedstate(state)^.unusedregsint := unusedregsint;
+      {$endif}
         punusedstate(state)^.unusedregsfpu := unusedregsfpu;
         punusedstate(state)^.unusedregsfpu := unusedregsfpu;
         punusedstate(state)^.unusedregsmm := unusedregsmm;
         punusedstate(state)^.unusedregsmm := unusedregsmm;
       {$ifndef newra}
       {$ifndef newra}
@@ -1370,7 +1438,9 @@ unit rgobj;
 
 
     procedure trgobj.restoreUnusedState(var state: pointer);
     procedure trgobj.restoreUnusedState(var state: pointer);
       begin
       begin
+      {$ifndef newra}
         unusedregsint := punusedstate(state)^.unusedregsint;
         unusedregsint := punusedstate(state)^.unusedregsint;
+      {$endif}
         unusedregsfpu := punusedstate(state)^.unusedregsfpu;
         unusedregsfpu := punusedstate(state)^.unusedregsfpu;
         unusedregsmm := punusedstate(state)^.unusedregsmm;
         unusedregsmm := punusedstate(state)^.unusedregsmm;
       {$ifndef newra}
       {$ifndef newra}
@@ -1643,7 +1713,9 @@ unit rgobj;
               end;
               end;
         end;
         end;
       n:=Tsuperregister(simplifyworklist[p]);
       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.}
       {Push it on the selectstack.}
       selectstack:=selectstack+char(n);
       selectstack:=selectstack+char(n);
@@ -1671,7 +1743,10 @@ unit rgobj;
       if not(u in [first_supreg..last_supreg]) and not move_related(u) and
       if not(u in [first_supreg..last_supreg]) and not move_related(u) and
          (degree[u]<cpu_registers) then
          (degree[u]<cpu_registers) then
         begin
         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);
           simplifyworklist:=simplifyworklist+char(u);
         end;
         end;
     end;
     end;
@@ -1940,6 +2015,7 @@ unit rgobj;
                 if a in colourednodes then
                 if a in colourednodes then
                   include(adj_colours,colour[a]);
                   include(adj_colours,colour[a]);
               end;
               end;
+          include(adj_colours,RS_STACK_POINTER_REG);
           {Assume a spill by default...}
           {Assume a spill by default...}
           spillednodes:=spillednodes+char(n);
           spillednodes:=spillednodes+char(n);
           {Search for a colour not in this list.}
           {Search for a colour not in this list.}
@@ -2246,9 +2322,8 @@ unit rgobj;
 
 
     begin
     begin
       if r.enum<=lastreg then
       if r.enum<=lastreg then
-        internalerror(2003010803);
+        internalerror(200301083);
       supreg:=r.number shr 8;
       supreg:=r.number shr 8;
-      { takes much time }
       include(unusedregsint,supreg);
       include(unusedregsint,supreg);
       if position=nil then
       if position=nil then
         list.insert(Tai_regalloc.dealloc(r))
         list.insert(Tai_regalloc.dealloc(r))
@@ -2271,9 +2346,10 @@ unit rgobj;
       spill_registers:=false;
       spill_registers:=false;
       unusedregsint:=[0..255];
       unusedregsint:=[0..255];
       fillchar(degree,sizeof(degree),0);
       fillchar(degree,sizeof(degree),0);
+{      exclude(unusedregsint,RS_STACK_POINTER_REG);}
       if current_procinfo.framepointer.number=NR_FRAME_POINTER_REG then
       if current_procinfo.framepointer.number=NR_FRAME_POINTER_REG then
         {Make sure the register allocator won't allocate registers into ebp.}
         {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);
       new(spill_temps);
       fillchar(spill_temps^,sizeof(spill_temps^),0);
       fillchar(spill_temps^,sizeof(spill_temps^),0);
       regs_to_spill_set:=[];
       regs_to_spill_set:=[];
@@ -2459,7 +2535,10 @@ end.
 
 
 {
 {
   $Log$
   $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,
     * fixed my previous completely broken commit. It's not perfect though,
       registers > last_supreg and < max_intreg may still be "translated"
       registers > last_supreg and < max_intreg may still be "translated"
 
 

+ 6 - 3
compiler/symdef.pas

@@ -3415,7 +3415,7 @@ implementation
           end;
           end;
          lastref:=defref;
          lastref:=defref;
        { first, we assume that all registers are used }
        { 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;
          usedotherregisters:=ALL_REGISTERS;
          forwarddef:=true;
          forwarddef:=true;
          interfacedef:=false;
          interfacedef:=false;
@@ -3557,7 +3557,7 @@ implementation
          { set all registers to used for simplified compilation PM }
          { set all registers to used for simplified compilation PM }
          if simplify_ppu then
          if simplify_ppu then
            begin
            begin
-             usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
+             usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
              usedotherregisters:=ALL_REGISTERS;
              usedotherregisters:=ALL_REGISTERS;
            end;
            end;
 
 
@@ -5838,7 +5838,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
     * paraloc splitted in callerparaloc,calleeparaloc
     * sparc calling convention updates
     * sparc calling convention updates
 
 

+ 25 - 5
compiler/x86/aasmcpu.pas

@@ -2081,7 +2081,7 @@ implementation
       case ops of
       case ops of
         1:
         1:
           begin
           begin
-            if oper[0].typ=top_reg then
+            if (oper[0].typ=top_reg) and (oper[0].reg.enum=R_INTREGISTER) then
               begin
               begin
                 supreg:=oper[0].reg.number shr 8;
                 supreg:=oper[0].reg.number shr 8;
                 if supreg in r then
                 if supreg in r then
@@ -2109,7 +2109,7 @@ implementation
                      Change into:
                      Change into:
 
 
                      mov r23d,[ebp-12]         ; Use a help register
                      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;
                     subreg:=oper[0].ref^.base.number and $ff;
                     if oper[0].ref^.index.number=NR_NO then
                     if oper[0].ref^.index.number=NR_NO then
                       pos:=Tai(previous)
                       pos:=Tai(previous)
@@ -2156,7 +2156,7 @@ implementation
           end;
           end;
         2:
         2:
           begin
           begin
-            if oper[0].typ=top_reg then
+            if (oper[0].typ=top_reg) and (oper[0].reg.enum=R_INTREGISTER) then
               begin
               begin
                 supreg:=oper[0].reg.number shr 8;
                 supreg:=oper[0].reg.number shr 8;
                 subreg:=oper[0].reg.number and $ff;
                 subreg:=oper[0].reg.number and $ff;
@@ -2196,7 +2196,7 @@ implementation
                       oper[0].ref^:=spilltemplist[supreg];
                       oper[0].ref^:=spilltemplist[supreg];
                     end;
                     end;
               end;
               end;
-            if oper[1].typ=top_reg then
+            if (oper[1].typ=top_reg) and (oper[1].reg.enum=R_INTREGISTER) then
               begin
               begin
                 supreg:=oper[1].reg.number shr 8;
                 supreg:=oper[1].reg.number shr 8;
                 subreg:=oper[1].reg.number and $ff;
                 subreg:=oper[1].reg.number and $ff;
@@ -2246,6 +2246,23 @@ implementation
                          Change into:
                          Change into:
   
   
                          add [ebp-12],r21d    ; Replace register by reference }
                          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;
                         oper[1].typ:=top_ref;
                         new(oper[1].ref);
                         new(oper[1].ref);
                         oper[1].ref^:=spilltemplist[supreg];
                         oper[1].ref^:=spilltemplist[supreg];
@@ -2396,7 +2413,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
     * fixed newra cycle for x86
     * added constants for indicating source and destination operands of the
     * added constants for indicating source and destination operands of the
       "move reg,reg" instruction to aasmcpu (and use those in rgobj)
       "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;
      function gas_regnum_search(const s:string):Tnewregister;
 
 
 
 
-  implementation
+implementation
 
 
-    uses
-      cutils,systems,
-      verbose;
+     uses cutils;
 
 
      function gas_regnum_search(const s:string):Tnewregister;
      function gas_regnum_search(const s:string):Tnewregister;
 
 
@@ -178,7 +176,10 @@ interface
 end.
 end.
 {
 {
   $Log$
   $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
     * i386 att instruction table moved to separate unit
 
 
 }
 }