Browse Source

+ basic register renaming (not yet working completely, between
-dreplacereg/-dreplaceregdebug)

Jonas Maebe 26 years ago
parent
commit
404ca4568d
1 changed files with 335 additions and 5 deletions
  1. 335 5
      compiler/csopt386.pas

+ 335 - 5
compiler/csopt386.pas

@@ -405,6 +405,315 @@ begin
 End;
 End;
 {$endif alignreg}
 {$endif alignreg}
 
 
+{$ifdef replacereg}
+function FindRegDealloc(reg: tregister; p: pai): boolean;
+begin
+  findregdealloc := false;
+  while assigned(p^.previous) and
+        ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
+         ((Pai(p^.previous)^.typ = ait_label) and
+          not(Pai_Label(p^.previous)^.l^.is_used))) do
+    begin
+      p := pai(p^.previous);
+      if (p^.typ = ait_regalloc) and
+         (pairegalloc(p)^.reg = reg) then
+        begin
+          findregdealloc := not(pairegalloc(p)^.allocation);
+          break;
+        end;
+    end
+end;
+
+function regLoadedWithNewValue(reg: tregister; hp: pai): boolean;
+var p: paicpu;
+begin
+  p := paicpu(hp);
+  regLoadedWithNewValue :=
+    assigned(hp) and
+    ((hp^.typ = ait_instruction) and
+     (((p^.opcode = A_MOV) or
+       (p^.opcode = A_MOVZX) or
+       (p^.opcode = A_MOVSX) or
+       (p^.opcode = A_LEA)) and
+      (p^.oper[1].typ = top_reg) and
+      (p^.oper[1].reg = reg) {and
+      (not(p^.oper[0].typ = top_ref) or
+       not RegInRef(p^.oper[1].reg,p^.oper[0].ref^))}) or
+     ((p^.opcode = A_POP) and
+      (p^.oper[0].reg = reg))) {or
+    findRegDealloc(reg,hp)};
+end;
+
+Procedure RestoreRegContentsTo(reg: TRegister; const c: TContent; p: pai);
+var hp: pai;
+    tmpState: byte;
+begin
+  tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
+  PPaiProp(p^.optInfo)^.Regs[reg] := c;
+  while getNextInstruction(p,p) and
+        (PPaiProp(p^.optInfo)^.Regs[reg].wState = tmpState) do
+    PPaiProp(p^.optInfo)^.Regs[reg] := c;
+{$ifdef replaceregdebug}
+  if assigned(p) then
+    begin
+      hp := new(pai_asm_comment,init(strpnew(
+        'restored '+att_reg2str[reg]+' till here...')));
+      hp^.next := p;
+      hp^.previous := p^.previous;
+      p^.previous := hp;
+      if assigned(hp^.previous) then
+        hp^.previous^.next := hp;
+    end;
+{$endif replaceregdebug}
+end;
+
+Procedure ClearRegContentsFrom(reg: TRegister; p: pai);
+var hp: pai;
+    tmpState: byte;
+begin
+  tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
+  PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
+  while getNextInstruction(p,p) and
+        (PPaiProp(p^.optInfo)^.Regs[reg].wState = tmpState) do
+    PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
+{$ifdef replaceregdebug}
+  if assigned(p) then
+    begin
+      hp := new(pai_asm_comment,init(strpnew(
+        'cleared '+att_reg2str[reg]+' till here...')));
+      hp^.next := p;
+      hp^.previous := p^.previous;
+      p^.previous := hp;
+      if assigned(hp^.previous) then
+        hp^.previous^.next := hp;
+    end;
+{$endif replaceregdebug}
+end;
+
+function NoHardCodedRegs(p: paicpu): boolean;
+var chCount: byte;
+begin
+  NoHardCodedRegs := true;
+  with InsProp[p^.opcode] do
+    for chCount := 1 to MaxCh do
+      if Ch[chCount] in ([Ch_REAX..Ch_MEDI]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
+        begin
+          NoHardCodedRegs := false;
+          break
+        end;
+end;
+
+Procedure ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister);
+begin
+  if reg = newReg then
+    reg := orgReg
+  else if reg = regtoreg8(newReg) then
+         reg := regtoreg8(orgReg)
+  else if reg = regtoreg16(newReg) then
+         reg := regtoreg16(orgReg);
+end;
+
+Procedure DoReplaceReg(orgReg,newReg: tregister; hp: paicpu);
+var opCount: byte;
+begin
+  for opCount := 0 to 2 do
+    with hp^.oper[opCount] Do
+      case typ of
+        top_reg: ChangeReg(reg,orgReg,newReg);
+        top_ref:
+          begin
+            ChangeReg(ref^.base,orgReg,newReg);
+            ChangeReg(ref^.index,orgReg,newReg);
+          end;
+      end;
+end;
+
+function RegSizesOK(oldReg,newReg: TRegister; p: paicpu): boolean;
+{ oldreg and newreg must be 32bit components }
+var opCount: byte;
+begin
+  RegSizesOK := true;
+  if not(IsGP32reg(oldReg) and IsGP32Reg(newReg)) then
+    begin
+      for opCount := 0 to 2 do
+        if (p^.oper[opCount].typ = top_reg) and
+           (p^.oper[opCount].reg in [R_AL..R_DH]) then
+          begin
+            RegSizesOK := false;
+            break
+          end
+    end;
+end;
+
+function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
+{ assumes p doesn't modify registers implicitely (like div) }
+var p: paicpu;
+    opCount: byte;
+begin
+  RegReadByInstruction := false;
+  p := paicpu(hp);
+  if hp^.typ <> ait_instruction then
+    exit;
+  for opCount := 0 to 2 do
+    if (p^.oper[opCount].typ = top_ref) and
+       RegInRef(reg,p^.oper[opCount].ref^) then
+      begin
+        RegReadByInstruction := true;
+        exit
+      end;
+  for opCount := 1 to MaxCh do
+    case InsProp[p^.opcode].Ch[opCount] of
+      Ch_RWOp1,Ch_ROp1{$ifdef arithopt},Ch_MOp1{$endif}:
+        if (p^.oper[0].typ = top_reg) and
+           (p^.oper[0].reg = reg) then
+          begin
+            RegReadByInstruction := true;
+            exit
+          end;
+      Ch_RWOp2,Ch_ROp2{$ifdef arithopt},Ch_MOp2{$endif}:
+        if (p^.oper[1].typ = top_reg) and
+           (p^.oper[1].reg = reg) then
+          begin
+            RegReadByInstruction := true;
+            exit
+          end;
+      Ch_RWOp3,Ch_ROp3{$ifdef arithopt},Ch_MOp3{$endif}:
+        if (p^.oper[2].typ = top_reg) and
+           (p^.oper[2].reg = reg) then
+          begin
+            RegReadByInstruction := true;
+            exit
+          end;
+    end;
+end;
+
+procedure DoReplaceReadReg(orgReg,newReg: tregister; p: paicpu);
+var opCount: byte;
+begin
+  for opCount := 0 to 2 do
+    if p^.oper[opCount].typ = top_ref then
+      begin
+        ChangeReg(p^.oper[opCount].ref^.base,orgReg,newReg);
+        ChangeReg(p^.oper[opCount].ref^.index,orgReg,newReg);
+      end;
+  for opCount := 1 to MaxCh do
+    case InsProp[p^.opcode].Ch[opCount] of
+      Ch_RWOp1,Ch_ROp1{$ifdef arithopt},Ch_MOp1{$endif}:
+        if p^.oper[0].typ = top_reg then
+          ChangeReg(p^.oper[0].reg,orgReg,newReg);
+      Ch_RWOp2,Ch_ROp2{$ifdef arithopt},Ch_MOp2{$endif}:
+        if p^.oper[1].typ = top_reg then
+          ChangeReg(p^.oper[1].reg,orgReg,newReg);
+      Ch_RWOp3,Ch_ROp3{$ifdef arithopt},Ch_MOp3{$endif}:
+        if p^.oper[2].typ = top_reg then
+          ChangeReg(p^.oper[2].reg,orgReg,newReg);
+    end;
+end;
+
+function ReplaceReg(orgReg, newReg: TRegister; p: pai;
+           const c: TContent): Boolean;
+{ Tries to replace orgreg with newreg in all instructions coming after p }
+{ until orgreg gets loaded with a new value. Returns true if successful, }
+{ false otherwise. If successful, the contents of newReg are set to c,   }
+{ which should hold the contents of newReg before the current sequence   }
+{ started                                                                }
+var endP, hp: Pai;
+    sequenceEnd, tmpResult, newRegModified, orgRegRead, orgRegModified: Boolean;
+begin
+  ReplaceReg := False;
+  tmpResult := true;
+  sequenceEnd := false;
+  newRegModified := false;
+  orgRegRead := false;
+  endP := pai(p^.previous);
+  while tmpResult and not sequenceEnd Do
+    begin
+      tmpResult :=
+        getNextInstruction(endP,endP);
+      If tmpResult then
+        begin
+          sequenceEnd :=
+            RegLoadedWithNewValue(newReg,paicpu(endP)) or
+{             FindRegDealloc(newReg,endP) or}
+            (GetNextInstruction(endp,hp) and
+             FindRegDealloc(newReg,hp));
+          newRegModified :=
+            newRegModified or
+            (not(sequenceEnd) and
+             RegModifiedByInstruction(newReg,endP));
+          orgRegRead := newRegModified and RegReadByInstruction(orgReg,endP);
+          sequenceEnd := SequenceEnd and not(newRegModified and orgRegRead);
+          tmpResult :=
+            not(newRegModified and orgRegRead) and
+            (endP^.typ = ait_instruction) and
+            not(paicpu(endP)^.is_jmp) and
+            NoHardCodedRegs(paicpu(endP)) and
+            RegSizesOk(orgReg,newReg,paicpu(endP)) and
+            not RegModifiedByInstruction(orgReg,endP);
+        end;
+    end;
+  if SequenceEnd then
+    begin
+{$ifdef replaceregdebug}
+      hp := new(pai_asm_comment,init(strpnew(
+        'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
+        ' from here...')));
+      hp^.next := p;
+      hp^.previous := p^.previous;
+      p^.previous := hp;
+      if assigned(hp^.previous) then
+        hp^.previous^.next := hp;
+
+      hp := new(pai_asm_comment,init(strpnew(
+        'replaced '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
+        ' till here')));
+      hp^.next := endp^.next;
+      hp^.previous := endp;
+      endp^.next := hp;
+      if assigned(hp^.next) then
+        hp^.next^.previous := hp;
+{$endif replaceregdebug}
+      ReplaceReg := true;
+      hp := p;
+      while hp <> endP do
+        begin
+          if hp^.typ = ait_instruction then
+            DoReplaceReg(orgReg,newReg,paicpu(hp));
+          GetNextInstruction(hp,hp)
+        end;
+      if assigned(endp) and (endp^.typ = ait_instruction) then
+        DoReplaceReadReg(orgReg,newReg,paicpu(endP));
+      if (p <> endp) then
+        if not RegModifiedByInstruction(newReg,endP) then
+          RestoreRegContentsTo(newReg, c ,p)
+        else
+          ClearRegContentsFrom(orgReg,p);
+    end
+{$ifdef replaceregdebug}
+     else
+       begin
+         hp := new(pai_asm_comment,init(strpnew(
+           'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
+           ' from here...')));
+         hp^.previous := p^.previous;
+         hp^.next := p;
+         p^.previous := hp;
+        if assigned(hp^.previous) then
+          hp^.previous^.next := hp;
+
+      hp := new(pai_asm_comment,init(strpnew(
+        'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
+        ' failed here')));
+      hp^.next := endp^.next;
+      hp^.previous := endp;
+      endp^.next := hp;
+      if assigned(hp^.next) then
+        hp^.next^.previous := hp;
+       end;
+{$endif replaceregdebug}
+End;
+{$endif replacereg}
+
 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
@@ -510,10 +819,27 @@ Begin
                                                         {old reg                new reg}
                                                         {old reg                new reg}
                                             (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
                                             (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
                                            Begin
                                            Begin
-                                             hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
-                                                                  {old reg          new reg}
-                                                    RegInfo.New2OldReg[RegCounter], RegCounter));
-                                             InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
+{$ifdef replacereg}
+                                             If not ReplaceReg(RegInfo.New2OldReg[RegCounter],
+                                                      regCounter,p,
+                                                      PPaiProp(hp4^.optInfo)^.Regs[regCounter]) then
+                                               begin
+{$endif replacereg}
+                                                 hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
+                                                                         {old reg          new reg}
+                                                       RegInfo.New2OldReg[RegCounter], RegCounter));
+                                                 InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
+{$ifdef replacereg}
+                                               end
+{$ifdef replaceregdebug}
+                                                else
+                                                  begin
+                                                    hp3 := new(pai_asm_comment,init(strpnew(
+                                                               'restored '+att_reg2str[regCounter]+' with data from here...')));
+                                                    insertllitem(asml,hp4,hp4^.next,hp3);
+                                                  end;
+{$endif replaceregdebug}
+{$endif replacereg}
                                            End
                                            End
                                          Else
                                          Else
 {   imagine the following code:                                            }
 {   imagine the following code:                                            }
@@ -701,7 +1027,11 @@ End.
 
 
 {
 {
  $Log$
  $Log$
- Revision 1.31  1999-11-06 16:21:57  jonas
+ Revision 1.32  1999-11-14 11:26:53  jonas
+   + basic register renaming (not yet working completely, between
+     -dreplacereg/-dreplaceregdebug)
+
+ Revision 1.31  1999/11/06 16:21:57  jonas
    + search optimial register to use in alignment code (compile with
    + search optimial register to use in alignment code (compile with
      -dalignreg, -dalignregdebug to see chosen register in
      -dalignreg, -dalignregdebug to see chosen register in
      assembler code). Still needs support in ag386bin.
      assembler code). Still needs support in ag386bin.