Browse Source

* several fixes to allocregbetween()

Jonas Maebe 21 years ago
parent
commit
cf085fb9d0
4 changed files with 119 additions and 79 deletions
  1. 30 14
      compiler/i386/csopt386.pas
  2. 68 47
      compiler/i386/daopt386.pas
  3. 13 15
      compiler/i386/popt386.pas
  4. 8 3
      compiler/i386/rropt386.pas

+ 30 - 14
compiler/i386/csopt386.pas

@@ -1352,7 +1352,7 @@ begin
         ClearRegContentsFrom(orgsupreg,p,hp);
       if removeLast then
         ptaiprop(endp.optinfo)^.canBeRemoved := true;
-      allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP);
+      allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP,ptaiprop(p.optinfo)^.usedregs);
 
     end
 {$ifdef replaceregdebug}
@@ -1560,8 +1560,14 @@ begin
     if (reginfo.new2oldreg[regcounter] <> RS_INVALID) Then
       begin
         include(regsloaded,regcounter);
-        AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
-          ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart);
+        if assigned(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod) then
+          AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
+            ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart,
+            ptaiprop(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod.optinfo)^.usedregs)
+        else
+          AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
+            prevseqstart,curseqstart,ptaiprop(prevseqstart.optinfo)^.usedregs);
+ 
         if curprev <> prevseqstart then
           begin
             if assigned(reginfo.lastReload[regCounter]) then
@@ -1572,7 +1578,8 @@ begin
               hp := curprev;
             clearRegContentsFrom(regCounter,prevSeq_next,hp);
             getnextInstruction(hp,hp);
-            allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp);
+            allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp,
+              ptaiprop(prevseqstart.optinfo)^.usedregs);
           end;
         if not(regcounter in reginfo.RegsLoadedforRef) and
                       {old reg                new reg}
@@ -1815,8 +1822,12 @@ begin
                               ptaiprop(hp4.optinfo)^.regs[getsupreg(taicpu(p).oper[1]^.reg)],false,hp1) then
                           begin
                             ptaiprop(p.optinfo)^.canBeRemoved := true;
+                            { this is just a regular move that was here, so the source register should be }
+                            { allocated already at this point -> only allocate from here onwards          }
+                            if not(getsupreg(taicpu(p).oper[0]^.reg) in pTaiProp(p.optinfo)^.usedregs) then
+                              internalerror(2004101011);
                             allocRegBetween(asml,taicpu(p).oper[0]^.reg,
-                              pTaiProp(p.optinfo)^.regs[getsupreg(taicpu(p).oper[0]^.reg)].startMod,hp1);
+                              p,hp1,pTaiProp(p.optinfo)^.usedregs)
                           end
                         else
                           begin
@@ -1836,12 +1847,12 @@ begin
                                      (taicpu(p).oper[1]^.reg = memreg) then
                                     begin
                                       pTaiProp(p.optinfo)^.canberemoved := true;
-                                      allocregbetween(asml,memreg,hp5,p);
+                                      allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
                                     end
                                   else
                                     begin
                                       replaceoperandwithreg(asml,p,0,memreg);
-                                      allocregbetween(asml,memreg,hp5,p);
+                                      allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
                                       regcounter := getsupreg(memreg);
                                       incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
                                       updatestate(regcounter,p);
@@ -1871,7 +1882,8 @@ begin
                                      opsequal(taicpu(StartMod).oper[0]^,taicpu(p).oper[0]^) then
                                     begin
                                       ptaiprop(p.optinfo)^.CanBeRemoved := True;
-                                      allocRegBetween(asml,taicpu(p).oper[1]^.reg,startMod,p);
+                                      allocRegBetween(asml,taicpu(p).oper[1]^.reg,startmod,p,
+                                        ptaiprop(startmod.optinfo)^.usedregs);
                                     end
                                   else
                                     removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
@@ -1884,7 +1896,8 @@ begin
                               begin
                                 taicpu(p).loadreg(0,memreg);
                                 allocRegBetween(asml,memreg,
-                                  ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p);
+                                  ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p,
+                                  ptaiprop(ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod.optinfo)^.usedregs);
                               end;
                         end;
                       end;
@@ -1919,7 +1932,7 @@ begin
                               if memreg <> NR_NO then
                                 begin
                                   replaceoperandwithreg(asml,p,0,memreg);
-                                  allocregbetween(asml,memreg,hp5,p);
+                                  allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
                                   regcounter := getsupreg(memreg);
                                   incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
                                   updatestate(regcounter,p);
@@ -1951,7 +1964,7 @@ begin
                                   insertllitem(asml,p,p.next,hp1);
                                   replaceoperandwithreg(asml,p,0,memreg);
                                   allocregbetween(asml,memreg,hp5,
-                                    tai(p.next.next));
+                                    tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
                                   ClearRegContentsFrom(regcounter,hp5,p);
                                 end;
                             end;
@@ -1966,7 +1979,7 @@ begin
                               if memreg <> NR_NO then
                                 begin
                                   replaceoperandwithreg(asml,p,1,memreg);
-                                  allocregbetween(asml,memreg,hp5,p);
+                                  allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
                                   regcounter := getsupreg(memreg);
                                   incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
                                   updatestate(regcounter,p);
@@ -2004,7 +2017,7 @@ begin
                                   insertllitem(asml,p,p.next,hp1);
                                   replaceoperandwithreg(asml,p,1,memreg);
                                   allocregbetween(asml,memreg,hp5,
-                                    tai(p.next.next));
+                                    tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
                                   ClearRegContentsFrom(regcounter,hp5,p);
                                 end;
                             end;
@@ -2109,7 +2122,10 @@ end.
 
 {
   $Log$
-  Revision 1.67  2004-10-06 19:24:38  jonas
+  Revision 1.68  2004-10-10 15:01:19  jonas
+    * several fixes to allocregbetween()
+
+  Revision 1.67  2004/10/06 19:24:38  jonas
     * take into account the size of a write to determine whether a write to
       one reference influences the contents of another reference
 

+ 68 - 47
compiler/i386/daopt386.pas

@@ -197,7 +197,7 @@ procedure RemoveLastDeallocForFuncRes(asmL: TAAsmOutput; p: tai);
 function regLoadedWithNewValue(supreg: tsuperregister; canDependOnPrevValue: boolean;
            hp: tai): boolean;
 procedure UpdateUsedRegs(var UsedRegs: TRegSet; p: tai);
-procedure AllocRegBetween(asml: taasmoutput; reg: tregister; p1, p2: tai);
+procedure AllocRegBetween(asml: taasmoutput; reg: tregister; p1, p2: tai; const initialusedregs: tregset);
 function FindRegDealloc(supreg: tsuperregister; p: tai): boolean;
 
 //function RegsEquivalent(OldReg, NewReg: tregister; var RegInfo: toptreginfo; OpAct: TopAction): Boolean;
@@ -736,6 +736,8 @@ begin
     exit;
   p := taicpu(hp);
   case p.opcode of
+    A_CALL:
+      regreadbyinstruction := true;
     A_IMUL:
       case p.ops of
         1:
@@ -808,6 +810,8 @@ begin
     exit;
   p := taicpu(p1);
   case p.opcode of
+    A_CALL:
+      regininstruction := true;
     A_IMUL:
       case p.ops of
         1:
@@ -1141,14 +1145,21 @@ begin
 end;
 
 
-procedure AllocRegBetween(asml: taasmoutput; reg: tregister; p1, p2: tai);
+procedure AllocRegBetween(asml: taasmoutput; reg: tregister; p1, p2: tai; const initialusedregs: tregset);
 { allocates register reg between (and including) instructions p1 and p2 }
 { the type of p1 and p2 must not be in SkipInstr                        }
+{ note that this routine is both called from the peephole optimizer     }
+{ where optinfo is not yet initialised) and from the cse (where it is)  }
 var
-  hp, start: tai;
-  lastRemovedWasDealloc, firstRemovedWasAlloc, first: boolean;
+  hp: tai;
+  lastRemovedWasDealloc: boolean;
   supreg: tsuperregister;
 begin
+{$ifdef EXTDEBUG}
+  if assigned(p1.optinfo) and
+     (ptaiprop(p1.optinfo)^.usedregs <> initialusedregs) then
+   internalerror(2004101010);
+{$endif EXTDEBUG}
   supreg := getsupreg(reg);
 { if not(supreg in rg.usableregsint+[RS_EDI,RS_ESI]) or
      not(assigned(p1)) then}
@@ -1158,11 +1169,8 @@ begin
     { current block (e.g. esi with self)                                    }
     exit;
   { make sure we allocate it for this instruction }
-  if p1 = p2 then
-    getnextinstruction(p2,p2);
+  getnextinstruction(p2,p2);
   lastRemovedWasDealloc := false;
-  firstRemovedWasAlloc := false;
-  first := true;
 {$ifdef allocregdebug}
   hp := tai_comment.Create(strpnew('allocating '+std_reg2str[supreg]+
     ' from here...')));
@@ -1171,51 +1179,44 @@ begin
     ' till here...')));
   insertllitem(asml,p2,p1.next,hp);
 {$endif allocregdebug}
-  start := p1;
-  repeat
-    if assigned(p1.OptInfo) then
-      include(ptaiprop(p1.OptInfo)^.UsedRegs,supreg);
-    p1 := tai(p1.next);
-    repeat
-      while assigned(p1) and
-            (p1.typ in (SkipInstr-[ait_regalloc])) Do
-        p1 := tai(p1.next);
+  if not(supreg in initialusedregs) then
+    begin
+      hp := tai_regalloc.alloc(reg,nil);
+      insertllItem(asmL,p1.previous,p1,hp);
+    end;
+  while assigned(p1) and
+        (p1 <> p2) do
+    begin
+      if assigned(p1.optinfo) then
+        include(ptaiprop(p1.optinfo)^.usedregs,supreg);
+      p1 := tai(p1.next);
+      repeat
+        while assigned(p1) and
+              (p1.typ in (SkipInstr-[ait_regalloc])) Do
+          p1 := tai(p1.next);
 { remove all allocation/deallocation info about the register in between }
-      if assigned(p1) and
-         (p1.typ = ait_regalloc) then
-        if (getsupreg(tai_regalloc(p1).reg) = supreg) then
-          begin
-            if first then
-              begin
-                firstRemovedWasAlloc := (tai_regalloc(p1).ratype=ra_alloc);
-                first := false;
-              end;
-            lastRemovedWasDealloc := (tai_regalloc(p1).ratype=ra_dealloc);
-            hp := tai(p1.Next);
-            asml.Remove(p1);
-            p1.free;
-            p1 := hp;
-          end
-        else p1 := tai(p1.next);
-    until not(assigned(p1)) or
-          not(p1.typ in SkipInstr);
-  until not(assigned(p1)) or
-        (p1 = p2);
+        if assigned(p1) and
+           (p1.typ = ait_regalloc) then
+          if (getsupreg(tai_regalloc(p1).reg) = supreg) then
+            begin
+              lastRemovedWasDealloc := (tai_regalloc(p1).ratype=ra_dealloc);
+              hp := tai(p1.Next);
+              asml.Remove(p1);
+              p1.free;
+              p1 := hp;
+            end
+          else p1 := tai(p1.next);
+      until not(assigned(p1)) or
+            not(p1.typ in SkipInstr);
+    end;
   if assigned(p1) then
     begin
-      if assigned(p1.optinfo) then
-        include(ptaiprop(p1.OptInfo)^.UsedRegs,supreg);
       if lastRemovedWasDealloc then
         begin
           hp := tai_regalloc.DeAlloc(reg,nil);
-          insertLLItem(asmL,p1,p1.next,hp);
+          insertLLItem(asmL,p1.previous,p1,hp);
         end;
     end;
-  if firstRemovedWasAlloc then
-    begin
-      hp := tai_regalloc.Alloc(reg,nil);
-      insertLLItem(asmL,start.previous,start,hp);
-    end;
 end;
 
 
@@ -2068,7 +2069,13 @@ begin
                   if not(supreg in usedregs) then
                     include(usedregs, supreg)
                   else
-                    addregdeallocfor(list, tai_regalloc(p).reg, p);
+                    begin
+                      //addregdeallocfor(list, tai_regalloc(p).reg, p);
+                      hp1 := tai(p.previous);
+                      list.remove(p);
+                      p.free;
+                      p := hp1;
+                    end;
                 end;
               ra_dealloc :
                 begin
@@ -2085,6 +2092,17 @@ begin
                       list.remove(p);
                       insertllitem(list, hp2, tai(hp2.next), p);
                       p := hp1;
+                    end
+                  else if findregalloc(tai_regalloc(p).reg, tai(p.next),ra_alloc)
+                          and getnextinstruction(p,hp1) and
+                      (hp1.typ = ait_instruction) and
+                      (taicpu(hp1).opcode = A_CALL) then
+                    begin
+                      hp1 := tai(p.previous);
+                      list.remove(p);
+                      p.free;
+                      p := hp1;
+                      include(usedregs,supreg);
                     end;
                 end;
              end;
@@ -2765,7 +2783,10 @@ end.
 
 {
   $Log$
-  Revision 1.72  2004-10-06 19:24:38  jonas
+  Revision 1.73  2004-10-10 15:01:19  jonas
+    * several fixes to allocregbetween()
+
+  Revision 1.72  2004/10/06 19:24:38  jonas
     * take into account the size of a write to determine whether a write to
       one reference influences the contents of another reference
 

+ 13 - 15
compiler/i386/popt386.pas

@@ -939,7 +939,7 @@ begin
                                 TmpUsedRegs := UsedRegs;
                                 { reg1 will be used after the first instruction, }
                                 { so update the allocation info                  }
-                                allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1);
+                                allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
                                 if GetNextInstruction(hp1, hp2) and
                                    (hp2.typ = ait_instruction) and
                                    taicpu(hp2).is_jmp and
@@ -999,7 +999,7 @@ begin
           {change "mov reg1, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
                                 begin
                                   taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
-                                  allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1);
+                                  allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
                                 end;
                     { Next instruction is also a MOV ? }
                       if GetNextInstruction(p, hp1) and
@@ -1022,7 +1022,7 @@ begin
                             mov mem1/reg2, reg1 }
                                     begin
                                       if (taicpu(p).oper[0]^.typ = top_reg) then
-                                        AllocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1);
+                                        AllocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
                                       asml.remove(hp1);
                                       hp1.free;
                                     end
@@ -1080,7 +1080,7 @@ begin
                                 mov mem1, reg2
                                 mov reg2, mem2}
                                       begin
-                                        AllocRegBetween(asmL,taicpu(hp2).oper[1]^.reg,p,hp2);
+                                        AllocRegBetween(asmL,taicpu(hp2).oper[1]^.reg,p,hp2,usedregs);
                                         taicpu(p).Loadoper(1,taicpu(hp2).oper[1]^);
                                         taicpu(hp1).loadoper(0,taicpu(hp2).oper[1]^);
                                         asml.remove(hp2);
@@ -1110,19 +1110,19 @@ begin
                                           taicpu(hp1).LoadReg(1,taicpu(hp2).oper[1]^.reg);
                                           taicpu(hp2).LoadRef(1,taicpu(hp2).oper[0]^.ref^);
                                           taicpu(hp2).LoadReg(0,taicpu(p).oper[1]^.reg);
-                                          allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2);
+                                          allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
                                           if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
                                              (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
-                                            allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.base,p,hp2);
+                                            allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.base,p,hp2,usedregs);
                                           if (taicpu(p).oper[0]^.ref^.index <> NR_NO) and
                                              (getsupreg(taicpu(p).oper[0]^.ref^.index) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
-                                            allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.index,p,hp2);
+                                            allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.index,p,hp2,usedregs);
                                         end
                                       else
                                         if (taicpu(hp1).Oper[0]^.reg <> taicpu(hp2).Oper[1]^.reg) then
                                           begin
                                             taicpu(hp2).LoadReg(0,taicpu(hp1).Oper[0]^.reg);
-                                            allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2);
+                                            allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
                                           end
                                         else
                                           begin
@@ -1159,12 +1159,7 @@ begin
                                  (taicpu(p).opsize = taicpu(hp1).opsize) and
                                  RefsEqual(taicpu(hp1).oper[0]^.ref^,taicpu(p).oper[1]^.ref^) then
                                 begin
-                                  allocregbetween(asml,taicpu(hp1).oper[1]^.reg,p,hp1);
-                                  { allocregbetween doesn't insert this because at }
-                                  { this time, no regalloc info is available in    }
-                                  { the optinfo field, so do it manually (JM)      }
-                                  hp2 := tai_regalloc.Alloc(taicpu(hp1).oper[1]^.reg,nil);
-                                  insertllitem(asml,p.previous,p,hp2);
+                                  allocregbetween(asml,taicpu(hp1).oper[1]^.reg,p,hp1,usedregs);
                                   taicpu(hp1).LoadReg(0,taicpu(hp1).oper[1]^.reg);
                                   taicpu(hp1).LoadRef(1,taicpu(p).oper[1]^.ref^);
                                   taicpu(p).LoadReg(1,taicpu(hp1).oper[0]^.reg);
@@ -2004,7 +1999,10 @@ end.
 
 {
   $Log$
-  Revision 1.63  2004-10-05 20:41:02  peter
+  Revision 1.64  2004-10-10 15:01:19  jonas
+    * several fixes to allocregbetween()
+
+  Revision 1.63  2004/10/05 20:41:02  peter
     * more spilling rewrites
 
   Revision 1.62  2004/10/05 17:31:41  peter

+ 8 - 3
compiler/i386/rropt386.pas

@@ -320,8 +320,10 @@ begin
         end
       else
         getLastInstruction(hp,hp);
-      allocRegBetween(asmL,newreg(R_INTREGISTER,reg1,R_SUBWHOLE),start,lastreg1);
-      allocRegBetween(asmL,newreg(R_INTREGISTER,reg2,R_SUBWHOLE),start,lastreg2);
+      allocRegBetween(asmL,newreg(R_INTREGISTER,reg1,R_SUBWHOLE),start,lastreg1,
+        ptaiprop(start.optinfo)^.usedregs);
+      allocRegBetween(asmL,newreg(R_INTREGISTER,reg2,R_SUBWHOLE),start,lastreg2,
+        ptaiprop(start.optinfo)^.usedregs);
     end;
 end;
 
@@ -364,7 +366,10 @@ End.
 
 {
   $Log$
-  Revision 1.28  2004-08-17 16:34:58  jonas
+  Revision 1.29  2004-10-10 15:01:19  jonas
+    * several fixes to allocregbetween()
+
+  Revision 1.28  2004/08/17 16:34:58  jonas
     * do not rename registers across conditional jumps
 
   Revision 1.27  2004/06/20 08:55:31  florian