Browse Source

* search much further back for CSE sequences (non-conflicting stores are
now passed)
* remove more unnecessary loads of registers (especially the self pointer)

Jonas Maebe 25 years ago
parent
commit
9e77e31a28
1 changed files with 172 additions and 72 deletions
  1. 172 72
      compiler/csopt386.pas

+ 172 - 72
compiler/csopt386.pas

@@ -58,61 +58,100 @@ Begin
 End;
 End;
 }
 }
 
 
-function modifiesMemLocation(p1: pai): boolean;
-var p: paicpu;
-    opCount: byte;
+function modifiesConflictingMemLocation(p1: pai; reg: tregister; c: tregContent;
+   var regsStillValid: tregset): boolean;
+var
+  p: paicpu;
+  tmpRef: treference;
+  regCounter: tregister;
+  opCount: byte;
 begin
 begin
-  modifiesMemLocation := false;
+  modifiesConflictingMemLocation := false;
   if p1^.typ <> ait_instruction then
   if p1^.typ <> ait_instruction then
     exit;
     exit;
   p := paicpu(p1);
   p := paicpu(p1);
-  for opCount := 1 to MaxCh do
-    case InsProp[p^.opcode].Ch[opCount] of
-      Ch_MOp1,CH_WOp1,CH_RWOp1:
-        if (p^.oper[0].typ = top_ref) or
-           ((p^.oper[0].typ = top_reg) and
-            not(reg32(p^.oper[0].reg) in (usableregs+[R_EDI]))) then
-          begin
-            modifiesMemLocation := true;
-            exit
-          end;
-      Ch_MOp2,CH_WOp2,CH_RWOp2:
-        if (p^.oper[1].typ = top_ref) or
-           ((p^.oper[1].typ = top_reg) and
-            not(reg32(p^.oper[1].reg) in (usableregs+[R_EDI]))) then
+  case p^.opcode of
+    A_MOV,A_MOVSX,A_MOVZX:
+      if p^.oper[1].typ = top_ref then
+        for regCounter := R_EAX to R_EDI do
           begin
           begin
-            modifiesMemLocation := true;
-            exit
-          end;
-      Ch_MOp3,CH_WOp3,CH_RWOp3:
-        if (p^.oper[2].typ = top_ref) or
-           ((p^.oper[2].typ = top_reg) and
-            not(reg32(p^.oper[2].reg) in (usableregs+[R_EDI]))) then
+            if writeToMemDestroysContents(reg32(p^.oper[0].reg),p^.oper[1].ref^,
+                 regCounter,c[regCounter]) then
+              begin
+                exclude(regsStillValid,regCounter);
+                modifiesConflictingMemLocation := not(reg in regsStillValid);
+              end;
+          end
+ {      else
+        for regCounter := R_EAX to R_EDI do
           begin
           begin
-            modifiesMemLocation := true;
-            exit
-          end;
-      Ch_WMemEDI:
-        begin
-          modifiesMemLocation := true;
-          exit;
+            if writeDestroysContents(p^.oper[1],regCounter,c[regCounter]) then
+              begin
+                exclude(regsStillValid,regCounter);
+                modifiesConflictingMemLocation := not(reg in regsStillValid);
+              end
+          end};
+    A_IMUL,A_DIV, A_IDIV, A_MUL:; { they never write to memory }
+    else
+	    for opCount := 1 to MaxCh do
+        case InsProp[p^.opcode].Ch[opCount] of
+          Ch_MOp1,CH_WOp1,CH_RWOp1:
+            if paicpu(p)^.oper[0].typ = top_ref then
+              for regCounter := R_EAX to R_EDI do
+                if writeDestroysContents(p^.oper[0],regCounter,c[regCounter]) then
+                  begin
+                    exclude(regsStillValid,regCounter);
+                    modifiesConflictingMemLocation := not(reg in regsStillValid);
+                  end;
+          Ch_MOp2,CH_WOp2,CH_RWOp2:
+            if paicpu(p)^.oper[1].typ = top_ref then
+              for regCounter := R_EAX to R_EDI do
+                if writeDestroysContents(p^.oper[1],regCounter,c[regCounter]) then
+                  begin
+                    exclude(regsStillValid,regCounter);
+                    modifiesConflictingMemLocation := not(reg in regsStillValid);
+                  end;
+          Ch_MOp3,CH_WOp3,CH_RWOp3:
+            if paicpu(p)^.oper[2].typ = top_ref then
+              for regCounter := R_EAX to R_EDI do
+                if writeDestroysContents(p^.oper[2],regCounter,c[regCounter]) then
+                  begin
+                    exclude(regsStillValid,regCounter);
+                    modifiesConflictingMemLocation := not(reg in regsStillValid);
+                  end;
+          Ch_WMemEDI:
+            begin
+              fillchar(tmpref,sizeof(tmpref),0);
+              tmpRef.base := R_EDI;
+              tmpRef.index := R_EDI;
+              for regCounter := R_EAX to R_EDI do
+                if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter]) then
+                  begin
+                    exclude(regsStillValid,regCounter);
+                    modifiesConflictingMemLocation := not(reg in regsStillValid);
+                 end;
+            end;
         end;
         end;
-    end;
+  end;
 end;
 end;
 
 
-function getPrevSequence(reg: tregister; current: pai; var prev: pai; var passedJump: boolean):
-  tregister;
+function getPrevSequence(p: pai; reg: tregister; currentPrev: pai; var newPrev: pai;
+  var passedJump: boolean; var regsNotRead, regsStillValid: tregset): tregister;
+
+const
+  current_reg: tregister = R_NO;
 
 
   function stillValid(p: pai): boolean;
   function stillValid(p: pai): boolean;
   begin
   begin
     stillValid :=
     stillValid :=
       (p^.typ = ait_instruction) and
       (p^.typ = ait_instruction) and
       (paicpu(p)^.opcode <> a_jmp) and
       (paicpu(p)^.opcode <> a_jmp) and
-      (ppaiprop(p^.optinfo)^.regs[reg].state =
-         ppaiprop(current^.optinfo)^.regs[reg].state) and
-      { in case destroyreg is called with doIncState = false }
+      (ppaiprop(p^.optinfo)^.regs[reg].wstate =
+         ppaiprop(currentPrev^.optinfo)^.regs[reg].wstate) and
+     { in case destroyreg is called with doIncState = false }
       (ppaiprop(p^.optinfo)^.regs[reg].typ =
       (ppaiprop(p^.optinfo)^.regs[reg].typ =
-        ppaiprop(current^.optinfo)^.regs[reg].typ);
+         ppaiprop(currentPrev^.optinfo)^.regs[reg].typ) and
+      (reg in (regsNotRead * regsStillValid));
     passedJump :=
     passedJump :=
       (p^.typ = ait_instruction) and
       (p^.typ = ait_instruction) and
       (paicpu(p)^.is_jmp);
       (paicpu(p)^.is_jmp);
@@ -122,54 +161,86 @@ function getPrevSequence(reg: tregister; current: pai; var prev: pai; var passed
   var
   var
     regCounter: tregister;
     regCounter: tregister;
   begin
   begin
-    for regCounter := R_EAX to R_EDI do
+    for regCounter := succ(current_reg) to R_EDI do
       with ppaiprop(p^.optinfo)^.regs[regCounter] do
       with ppaiprop(p^.optinfo)^.regs[regCounter] do
       if ((startmod <>
       if ((startmod <>
-            ppaiprop(current^.optinfo)^.regs[regCounter].startmod)  or
+            ppaiprop(currentPrev^.optinfo)^.regs[regCounter].startmod)  or
           (nrOfMods <>
           (nrOfMods <>
-            ppaiprop(current^.optinfo)^.regs[regCounter].nrOfMods)) and
-           (not ppaiprop(p^.optinfo)^.canBeRemoved) and
+            ppaiprop(currentPrev^.optinfo)^.regs[regCounter].nrOfMods)) and
          (ppaiprop(p^.optinfo)^.regs[regCounter].typ in
          (ppaiprop(p^.optinfo)^.regs[regCounter].typ in
            [con_ref,con_noRemoveRef]) then
            [con_ref,con_noRemoveRef]) then
         begin
         begin
           findChangedRegister := regCounter;
           findChangedRegister := regCounter;
+          current_reg := regCounter;
           exit;
           exit;
         end;
         end;
+    current_reg := R_NO;
     findChangedRegister := R_NO;
     findChangedRegister := R_NO;
   end;
   end;
 
 
 var
 var
   hp, prevFound: pai;
   hp, prevFound: pai;
-  tmpResult: tregister;
+  tmpResult, regCounter: tregister;
 begin
 begin
+  if not(current_reg in [R_NO,R_EDI]) then
+    begin
+      tmpResult := findChangedRegister(currentPrev);
+      if tmpResult <> R_NO then
+        begin
+          getPrevSequence := tmpResult;
+          exit;
+        end;
+    end;
+
   getPrevSequence := R_NO;
   getPrevSequence := R_NO;
-  { no memory writes (could be refined further) }
-    passedJump := passedJump or
-      ((current^.typ = ait_instruction) and
-       (paicpu(current)^.is_jmp));
-  if modifiesMemLocation(current) or
-     (passedJump and not(reg in (usableregs+[R_EDI]))) or
-     not getLastInstruction(current,hp) then
+  passedJump := passedJump or
+    ((currentPrev^.typ = ait_instruction) and
+     (paicpu(currentPrev)^.is_jmp));
+
+  if (passedJump and not(reg in (usableregs+[R_EDI]))) or
+     not getLastInstruction(currentPrev,hp) then
     exit;
     exit;
+
+  prevFound := currentPrev;
   tmpResult := R_NO;
   tmpResult := R_NO;
+
   while (tmpResult = R_NO) and
   while (tmpResult = R_NO) and
-        stillValid(hp) do
+        stillValid(hp) and
+        not(modifiesConflictingMemLocation(prevFound,reg,
+           ppaiprop(p^.optinfo)^.regs,regsStillValid)) do
     begin
     begin
+      { only update the regsread for the instructions we already passed }
+      if not(ppaiprop(prevFound^.optinfo)^.canBeRemoved) then
+        for regCounter := R_EAX to R_EDI do
+          if regReadByInstruction(regCounter,prevFound) then
+            exclude(regsNotRead,regCounter);
+
       { in case getPreviousInstruction fails and sets hp to nil in the }
       { in case getPreviousInstruction fails and sets hp to nil in the }
       { next iteration                                                 }
       { next iteration                                                 }
       prevFound := hp;
       prevFound := hp;
-      tmpResult := findChangedRegister(hp);
-      if modifiesMemLocation(hp) or
-        { do not load the self pointer or a regvar before a (conditional)  }
-        { jump with a new value, since if the jump is taken, the old value }
-        { is (probably) still necessary                                    }
-        (passedJump and not(reg in (usableregs+[R_EDI]))) or
+      if not(ppaiprop(hp^.optinfo)^.canBeRemoved) then
+        tmpResult := findChangedRegister(hp);
+      if { do not load the self pointer or a regvar before a (conditional)  }
+         { jump with a new value, since if the jump is taken, the old value }
+         { is (probably) still necessary                                    }
+         (passedJump and not(reg in (usableregs+[R_EDI]))) or
          not getLastInstruction(hp,hp) then
          not getLastInstruction(hp,hp) then
         break;
         break;
     end;
     end;
   getPrevSequence := tmpResult;
   getPrevSequence := tmpResult;
   if tmpResult <> R_NO then
   if tmpResult <> R_NO then
-    prev := prevFound;
+    newPrev := prevFound;
+end;
+
+
+function isSimpleMemLoc(const ref: treference): boolean;
+begin
+  isSimpleMemLoc :=
+    (ref.index = R_NO) and
+    (not(ref.base in (usableregs+[R_EDI])) or
+     (assigned(ref.symbol) and
+      (ref.base = R_NO) and
+      (ref.index = R_NO)));
 end;
 end;
 
 
 
 
@@ -181,26 +252,25 @@ end;
 Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint;
 Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint;
            Var RegInfo: TRegInfo): Boolean;
            Var RegInfo: TRegInfo): Boolean;
 
 
+const
+  checkingPrevSequences: boolean = false;
+var
+  regsNotRead, regsStillValid: tregset;
 
 
-  function getNextRegToTest(var orgP: pai; currentReg: tregister): tregister;
+  function getNextRegToTest(var prev: pai; currentReg: tregister): tregister;
   const
   const
-    checkingPrevSequences: boolean = false;
     passedJump: boolean = false;
     passedJump: boolean = false;
   begin
   begin
-    if currentReg = R_NO then
-      checkingPrevSequences := false;
     if not checkingPrevSequences then
     if not checkingPrevSequences then
       begin
       begin
         Repeat
         Repeat
           Inc(currentReg);
           Inc(currentReg);
         Until (currentReg > R_EDI) or
         Until (currentReg > R_EDI) or
-              (ppaiprop(orgP^.optInfo)^.regs[currentReg].typ
+              (ppaiprop(prev^.optInfo)^.regs[currentReg].typ
                  in [con_ref,con_noRemoveRef]);
                  in [con_ref,con_noRemoveRef]);
         if currentReg > R_EDI then
         if currentReg > R_EDI then
           begin
           begin
-            if not modifiesMemLocation(orgP) and
-               (ppaiprop(orgP^.optinfo)^.regs[reg].rstate =
-                  ppaiprop(p^.optinfo)^.regs[reg].rstate) then
+            if isSimpleMemLoc(paicpu(p)^.oper[0].ref^) then
               begin
               begin
                 checkingPrevSequences := true;
                 checkingPrevSequences := true;
                 passedJump := false;
                 passedJump := false;
@@ -211,7 +281,8 @@ Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint
         else getNextRegToTest := currentReg;
         else getNextRegToTest := currentReg;
       end;
       end;
     if checkingPrevSequences then
     if checkingPrevSequences then
-      getNextRegToTest := getPrevSequence(reg,orgP,orgP, passedJump);
+      getNextRegToTest :=
+        getPrevSequence(p,reg,prev,prev,passedJump,regsNotRead,RegsStillValid);
   end;
   end;
 
 
 Var hp2, hp3{, EndMod},highPrev, orgPrev: Pai;
 Var hp2, hp3{, EndMod},highPrev, orgPrev: Pai;
@@ -238,6 +309,9 @@ Begin {CheckSequence}
       oldRegsEncountered := newRegsEncountered;
       oldRegsEncountered := newRegsEncountered;
     end;
     end;
 
 
+  checkingPrevSequences := false;
+  regsNotRead := [R_EAX,R_EBX,R_ECX,R_EDX,R_ESP,R_EBP,R_EDI,R_ESI];
+  regsStillValid := regsNotRead;
   GetLastInstruction(p, prev);
   GetLastInstruction(p, prev);
   regCounter := getNextRegToTest(prev,R_NO);
   regCounter := getNextRegToTest(prev,R_NO);
   While (RegCounter <> R_NO) Do
   While (RegCounter <> R_NO) Do
@@ -268,11 +342,23 @@ Begin {CheckSequence}
           GetNextInstruction(hp3, hp3);
           GetNextInstruction(hp3, hp3);
           Inc(Found)
           Inc(Found)
         End;
         End;
-      for regCounter2 := R_EAX to R_EDX do
+
+      for regCounter2 := R_EAX to R_EDI do
         if (regInfo.new2OldReg[regCounter2] <> R_NO) and
         if (regInfo.new2OldReg[regCounter2] <> R_NO) and
            (regCounter2 in PPaiProp(hp3^.optInfo)^.usedRegs) and
            (regCounter2 in PPaiProp(hp3^.optInfo)^.usedRegs) and
            not regLoadedWithNewValue(regCounter2,false,hp3) then
            not regLoadedWithNewValue(regCounter2,false,hp3) then
           include(regInfo.regsStillUsedAfterSeq,regCounter2);
           include(regInfo.regsStillUsedAfterSeq,regCounter2);
+
+      if checkingPrevSequences then
+        for regCounter2 := R_EAX to R_EDI do
+          if not(regInfo.new2OldReg[regCounter2] in [R_NO,regCounter2]) and
+             (not(regCounter2 in (regsNotRead * regsStillValid)) or
+              not(regInfo.new2OldReg[regCounter2] in regsStillValid)) then
+            begin
+              found := 0;
+              break;
+            end;
+
       If (Found <> OldNrOfMods) or
       If (Found <> OldNrOfMods) or
  { the following is to avoid problems with rangecheck code (see testcse2) }
  { the following is to avoid problems with rangecheck code (see testcse2) }
          (assigned(hp3) and
          (assigned(hp3) and
@@ -1144,6 +1230,7 @@ begin
         ppaiprop(startMod^.optInfo)^.canBeRemoved := true;
         ppaiprop(startMod^.optInfo)^.canBeRemoved := true;
 end;
 end;
 
 
+
 Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
 Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
 {marks the instructions that can be removed by RemoveInstructs. They're not
 {marks the instructions that can be removed by RemoveInstructs. They're not
  removed immediately because sometimes an instruction needs to be checked in
  removed immediately because sometimes an instruction needs to be checked in
@@ -1407,7 +1494,11 @@ Begin
                                     allocRegBetween(asmL,paicpu(p)^.oper[0].reg,
                                     allocRegBetween(asmL,paicpu(p)^.oper[0].reg,
                                     PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod,
                                     PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod,
                                     hp1);
                                     hp1);
-                                end;
+                                end
+                              else
+                                if reg32(paicpu(p)^.oper[0].reg) <> reg32(paicpu(p)^.oper[1].reg) then
+                                  removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
+
                           end
                           end
                         end;
                         end;
                     top_symbol,Top_Const:
                     top_symbol,Top_Const:
@@ -1424,7 +1515,10 @@ Begin
                                     begin
                                     begin
                                       PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
                                       PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
                                       allocRegBetween(asmL,regCounter,startMod,p);
                                       allocRegBetween(asmL,regCounter,startMod,p);
-                                    end;
+                                    end
+                                  else
+                                    removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
+
                             End;
                             End;
                           Top_Ref:
                           Top_Ref:
                             if (paicpu(p)^.oper[0].typ = top_const) and
                             if (paicpu(p)^.oper[0].typ = top_const) and
@@ -1438,6 +1532,7 @@ Begin
                         End;
                         End;
                       End;
                       End;
                   End;
                   End;
+                  
                 End;
                 End;
               A_STD: If GetLastInstruction(p, hp1) And
               A_STD: If GetLastInstruction(p, hp1) And
                         (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
                         (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
@@ -1495,7 +1590,12 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.12  2000-09-26 11:49:41  jonas
+  Revision 1.13  2000-09-29 23:14:45  jonas
+    * search much further back for CSE sequences (non-conflicting stores are
+      now passed)
+    * remove more unnecessary loads of registers (especially the self pointer)
+
+  Revision 1.12  2000/09/26 11:49:41  jonas
     * writes to register variables and to the self pointer now also count as
     * writes to register variables and to the self pointer now also count as
       memore writes
       memore writes