Explorar o código

* optimized spilling writing when the reg operand can be
replaced by reference

peter %!s(int64=21) %!d(string=hai) anos
pai
achega
c853d10cc2
Modificáronse 1 ficheiros con 77 adicións e 383 borrados
  1. 77 383
      compiler/x86/rgx86.pas

+ 77 - 383
compiler/x86/rgx86.pas

@@ -105,388 +105,6 @@ implementation
                                     Trgcpu
 ******************************************************************************}
 
-{$ifdef OLDRGX86}
-    function trgx86.instr_spill_register(list:Taasmoutput;
-                                         instr:taicpu;
-                                         const r:Tsuperregisterset;
-                                         const spilltemplist:Tspill_temp_list): boolean;
-    {
-      Spill the registers in r in this instruction. Returns true if any help
-      registers are used. This procedure has become one big hack party, because
-      of the huge amount of situations you can have. The irregularity of the i386
-      instruction set doesn't help either. (DM)
-    }
-    var i:byte;
-        supreg:Tsuperregister;
-        subreg:Tsubregister;
-        helpreg:Tregister;
-        helpins:Taicpu;
-        op:Tasmop;
-        hopsize:Topsize;
-        pos:Tai;
-
-    begin
-      {Situation examples are in intel notation, so operand order:
-       mov    eax       ,    ebx
-              ^^^            ^^^
-              oper[1]        oper[0]
-      (DM)}
-      result:=false;
-      with taicpu(instr) do
-       begin
-         case ops of
-           0:
-             ;
-           1:
-             begin
-               if (oper[0]^.typ=top_reg) and
-                  (getregtype(oper[0]^.reg)=regtype) then
-                 begin
-                   supreg:=getsupreg(oper[0]^.reg);
-                   if supregset_in(r,supreg) then
-                     begin
-                       {Situation example:
-                        push r20d              ; r20d must be spilled into [ebp-12]
-
-                       Change into:
-                        push [ebp-12]          ; Replace register by reference }
-   {                    hopsize:=reg2opsize(oper[0].reg);}
-                       oper[0]^.typ:=top_ref;
-                       new(oper[0]^.ref);
-                       oper[0]^.ref^:=spilltemplist[supreg];
-   {                    oper[0]^.ref^.size:=hopsize;}
-                     end;
-                 end;
-               if oper[0]^.typ=top_ref then
-                 begin
-                   supreg:=getsupreg(oper[0]^.ref^.base);
-                   if supregset_in(r,supreg) then
-                     begin
-                       {Situation example:
-                        push [r21d+4*r22d]        ; r21d must be spilled into [ebp-12]
-
-                        Change into:
-
-                        mov r23d,[ebp-12]         ; Use a help register
-                        push [r23d+4*r22d]        ; Replace register by helpregister }
-                       subreg:=getsubreg(oper[0]^.ref^.base);
-                       if oper[0]^.ref^.index=NR_NO then
-                         pos:=Tai(previous)
-                       else
-                         pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID);
-                       getregisterinline(list,pos,subreg,helpreg);
-                       result:=true;
-                       helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
-                       if pos=nil then
-                         list.insertafter(helpins,list.first)
-                       else
-                         list.insertafter(helpins,pos.next);
-                       ungetregisterinline(list,helpins,helpreg);
-                       forward_allocation(Tai(helpins.next),instr);
-                       oper[0]^.ref^.base:=helpreg;
-                     end;
-                   supreg:=getsupreg(oper[0]^.ref^.index);
-                   if supregset_in(r,supreg) then
-                     begin
-                       {Situation example:
-                        push [r21d+4*r22d]        ; r22d must be spilled into [ebp-12]
-
-                        Change into:
-
-                        mov r23d,[ebp-12]         ; Use a help register
-                        push [r21d+4*r23d]        ; Replace register by helpregister }
-                       subreg:=getsubreg(oper[0]^.ref^.index);
-                       if oper[0]^.ref^.base=NR_NO then
-                         pos:=Tai(instr.previous)
-                       else
-                         pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID);
-                       getregisterinline(list,pos,subreg,helpreg);
-                       result:=true;
-                       helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
-                       if pos=nil then
-                         list.insertafter(helpins,list.first)
-                       else
-                         list.insertafter(helpins,pos.next);
-                       ungetregisterinline(list,helpins,helpreg);
-                       forward_allocation(Tai(helpins.next),instr);
-                       oper[0]^.ref^.index:=helpreg;
-                     end;
-                   end;
-             end;
-           2,
-           3 :
-             begin
-               { Opcodes with 3 registers are shrd/shld, where the 3rd operand is const or CL,
-                 that doesn't need spilling }
-
-               { First spill the registers from the references. This is
-                 required because the reference can be moved from this instruction
-                 to a MOV instruction when spilling of the register operand is done }
-               for i:=0 to 1 do
-                 if oper[i]^.typ=top_ref then
-                   begin
-                     supreg:=getsupreg(oper[i]^.ref^.base);
-                     if supregset_in(r,supreg) then
-                       begin
-                         {Situation example:
-                          add r20d,[r21d+4*r22d]    ; r21d must be spilled into [ebp-12]
-
-                          Change into:
-
-                          mov r23d,[ebp-12]         ; Use a help register
-                          add r20d,[r23d+4*r22d]    ; Replace register by helpregister }
-                         subreg:=getsubreg(oper[i]^.ref^.base);
-                         if i=1 then
-                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),RS_INVALID)
-                         else
-                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID);
-                         getregisterinline(list,pos,subreg,helpreg);
-                         result:=true;
-                         helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
-                         if pos=nil then
-                           list.insertafter(helpins,list.first)
-                         else
-                           list.insertafter(helpins,pos.next);
-                         oper[i]^.ref^.base:=helpreg;
-                         ungetregisterinline(list,helpins,helpreg);
-                         forward_allocation(Tai(helpins.next),instr);
-                     end;
-                     supreg:=getsupreg(oper[i]^.ref^.index);
-                     if supregset_in(r,supreg) then
-                       begin
-                         {Situation example:
-                          add r20d,[r21d+4*r22d]    ; r22d must be spilled into [ebp-12]
-
-                          Change into:
-
-                          mov r23d,[ebp-12]         ; Use a help register
-                          add r20d,[r21d+4*r23d]    ; Replace register by helpregister }
-                         subreg:=getsubreg(oper[i]^.ref^.index);
-                         if i=1 then
-                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),
-                                               getsupreg(oper[0]^.reg),RS_INVALID)
-                         else
-                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID);
-                         getregisterinline(list,pos,subreg,helpreg);
-                         result:=true;
-                         helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
-                         if pos=nil then
-                           list.insertafter(helpins,list.first)
-                         else
-                           list.insertafter(helpins,pos.next);
-                         oper[i]^.ref^.index:=helpreg;
-                         ungetregisterinline(list,helpins,helpreg);
-                         forward_allocation(Tai(helpins.next),instr);
-                       end;
-                   end;
-               if (oper[0]^.typ=top_reg) and
-                  (getregtype(oper[0]^.reg)=regtype) then
-                 begin
-                   supreg:=getsupreg(oper[0]^.reg);
-                   subreg:=getsubreg(oper[0]^.reg);
-                   if supregset_in(r,supreg) then
-                     if oper[1]^.typ=top_ref then
-                       begin
-                         {Situation example:
-                          add [r20d],r21d      ; r21d must be spilled into [ebp-12]
-
-                          Change into:
-
-                          mov r22d,[ebp-12]    ; Use a help register
-                          add [r20d],r22d      ; Replace register by helpregister }
-                         pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),
-                                             getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index));
-                         getregisterinline(list,pos,subreg,helpreg);
-                         result:=true;
-                         helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
-                         if pos=nil then
-                           list.insertafter(helpins,list.first)
-                         else
-                           list.insertafter(helpins,pos.next);
-                         oper[0]^.reg:=helpreg;
-                         ungetregisterinline(list,helpins,helpreg);
-                         forward_allocation(Tai(helpins.next),instr);
-                       end
-                     else
-                       begin
-                         {Situation example:
-                          add r20d,r21d        ; r21d must be spilled into [ebp-12]
-
-                          Change into:
-
-                          add r20d,[ebp-12]    ; Replace register by reference }
-                         oper[0]^.typ:=top_ref;
-                         new(oper[0]^.ref);
-                         oper[0]^.ref^:=spilltemplist[supreg];
-                       end;
-                 end;
-               if (oper[1]^.typ=top_reg) and
-                  (getregtype(oper[1]^.reg)=regtype) then
-                 begin
-                   supreg:=getsupreg(oper[1]^.reg);
-                   subreg:=getsubreg(oper[1]^.reg);
-                   if supregset_in(r,supreg) then
-                     begin
-                       if oper[0]^.typ=top_ref then
-                         begin
-                           {Situation example:
-                            add r20d,[r21d]      ; r20d must be spilled into [ebp-12]
-
-                            Change into:
-
-                            mov r22d,[r21d]      ; Use a help register
-                            add [ebp-12],r22d    ; Replace register by helpregister }
-                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),
-                                               getsupreg(oper[0]^.ref^.index),RS_INVALID);
-                           getregisterinline(list,pos,subreg,helpreg);
-                           result:=true;
-                           op:=A_MOV;
-                           hopsize:=opsize;  {Save old value...}
-                           if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
-                             begin
-                               {Because 'movzx memory,register' does not exist...}
-                               op:=opcode;
-                               opcode:=A_MOV;
-                               opsize:=reg2opsize(oper[1]^.reg);
-                             end;
-                           helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
-                           if pos=nil then
-                             list.insertafter(helpins,list.first)
-                           else
-                             list.insertafter(helpins,pos.next);
-                           dispose(oper[0]^.ref);
-                           oper[0]^.typ:=top_reg;
-                           oper[0]^.reg:=helpreg;
-                           oper[1]^.typ:=top_ref;
-                           new(oper[1]^.ref);
-                           oper[1]^.ref^:=spilltemplist[supreg];
-                           ungetregisterinline(list,helpins,helpreg);
-                           forward_allocation(Tai(helpins.next),instr);
-                         end
-                       else
-                         begin
-                           {Situation example:
-                            add r20d,r21d        ; r20d must be spilled into [ebp-12]
-
-                            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...}
-                               result:=true;
-                               op:=opcode;
-                               hopsize:=opsize;
-                               opcode:=A_MOV;
-                               opsize:=reg2opsize(oper[1]^.reg);
-                               pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID);
-                               getregisterinline(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);
-                               oper[0]^.reg:=helpreg;
-                               ungetregisterinline(list,helpins,helpreg);
-                               forward_allocation(Tai(helpins.next),instr);
-                             end;
-                           oper[1]^.typ:=top_ref;
-                           new(oper[1]^.ref);
-                           oper[1]^.ref^:=spilltemplist[supreg];
-                         end;
-                     end;
-                 end;
-
-               { The i386 instruction set never gets boring...
-                 some opcodes do not support a memory location as destination }
-               if (oper[1]^.typ=top_ref) and
-                  (
-                   (oper[0]^.typ=top_const) or
-                   ((oper[0]^.typ=top_reg) and
-                    (getregtype(oper[0]^.reg)=regtype))
-                  ) then
-                 begin
-                   case opcode of
-                     A_SHLD,A_SHRD,
-                     A_IMUL :
-                       begin
-                         {Yikes! We just changed the destination register into
-                          a memory location above here.
-
-                          Situation examples:
-
-                          imul [ebp-12],r21d    ; We need a help register
-                          imul [ebp-12],<const> ; We need a help register
-
-                          Change into:
-
-                          mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
-                          imul r22d,r21d       ; Replace reference by helpregister
-                          mov [ebp-12],r22d    ; Use another help instruction}
-                         getregisterinline(list,Tai(previous),subreg,helpreg);
-                         result:=true;
-                         {First help instruction.}
-                         helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
-                         if previous=nil then
-                           list.insert(helpins)
-                         else
-                           list.insertafter(helpins,previous);
-                         {Second help instruction.}
-                         helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
-                         dispose(oper[1]^.ref);
-                         oper[1]^.typ:=top_reg;
-                         oper[1]^.reg:=helpreg;
-                         list.insertafter(helpins,instr);
-                         ungetregisterinline(list,instr,helpreg);
-                       end;
-                   end;
-                 end;
-
-               { The i386 instruction set never gets boring...
-                 some opcodes do not support a memory location as source }
-               if (oper[0]^.typ=top_ref) and
-                  (oper[1]^.typ=top_reg) and
-                  (getregtype(oper[1]^.reg)=regtype) then
-                 begin
-                   case opcode of
-                     A_BT,A_BTS,
-                     A_BTC,A_BTR :
-                       begin
-                         {Yikes! We just changed the source register into
-                          a memory location above here.
-
-                          Situation example:
-
-                          bt  r21d,[ebp-12]   ; We need a help register
-
-                          Change into:
-
-                          mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
-                          bt  r21d,r22d        ; Replace reference by helpregister}
-                         getregisterinline(list,Tai(previous),subreg,helpreg);
-                         result:=true;
-                         {First help instruction.}
-                         helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
-                         if previous=nil then
-                           list.insert(helpins)
-                         else
-                           list.insertafter(helpins,previous);
-                         dispose(oper[0]^.ref);
-                         oper[0]^.typ:=top_reg;
-                         oper[0]^.reg:=helpreg;
-                         ungetregisterinline(list,helpins,helpreg);
-                       end;
-                   end;
-                 end;
-             end;
-           else
-             internalerror(200409202);
-         end;
-       end;
-    end;
-{$endif OLDRGX86}
-
-
     function trgx86.get_spill_subreg(r : tregister) : tsubregister;
       begin
         result:=getsubreg(r);
@@ -494,8 +112,80 @@ implementation
 
 
     function trgx86.do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+      var
+        replaceoper : longint;
       begin
         result:=false;
+        with instr do
+          begin
+            replaceoper:=-1;
+            case ops of
+              1 :
+                begin
+                  if (oper[0]^.typ=top_reg) then
+                    begin
+                      if getsupreg(oper[0]^.reg)<>orgreg then
+                        internalerror(200410101);
+                      replaceoper:=0;
+                    end;
+                end;
+              2,3 :
+                begin
+                  { We can handle opcodes with 2 and 3 operands the same way. The opcodes
+                    with 3 registers are shrd/shld, where the 3rd operand is const or CL,
+                    that doesn't need spilling }
+                  if (oper[0]^.typ=top_reg) and
+                     (oper[1]^.typ=top_reg) and
+                     (getsupreg(oper[0]^.reg)<>getsupreg(oper[1]^.reg)) then
+                    begin
+                      { One of the arguments shall be able to be replaced }
+                      if (getregtype(oper[0]^.reg)=regtype) and
+                         (getsupreg(oper[0]^.reg)=orgreg) then
+                        replaceoper:=0
+                      else
+                        if (getregtype(oper[0]^.reg)=regtype) and
+                           (getsupreg(oper[1]^.reg)=orgreg) then
+                          replaceoper:=1
+                      else
+                        internalerror(200410101);
+                      case replaceoper of
+                        0 :
+                          begin
+                            { Some instructions don't allow memory references
+                              for source }
+                            case instr.opcode of
+                              A_BT,
+                              A_BTS,
+                              A_BTC,
+                              A_BTR :
+                                replaceoper:=-1;
+                            end;
+                          end;
+                        1 :
+                          begin
+                            { Some instructions don't allow memory references
+                              for destination }
+                            case instr.opcode of
+                              A_SHLD,
+                              A_SHRD,
+                              A_IMUL :
+                                replaceoper:=-1;
+                            end;
+                          end;
+                      end;
+                    end;
+                end;
+            end;
+
+            { Replace register with spill reference }
+            if replaceoper<>-1 then
+              begin
+                oper[replaceoper]^.typ:=top_ref;
+                new(oper[replaceoper]^.ref);
+                oper[replaceoper]^.ref^:=spilltemp;
+                result:=true;
+              end;
+          end;
       end;
 
 
@@ -625,7 +315,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.8  2004-10-05 20:41:02  peter
+  Revision 1.9  2004-10-10 16:30:26  peter
+    * optimized spilling writing when the reg operand can be
+      replaced by reference
+
+  Revision 1.8  2004/10/05 20:41:02  peter
     * more spilling rewrites
 
   Revision 1.7  2004/10/04 20:46:22  peter