mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 11:39:40 +01:00 
			
		
		
		
	was not being initialised -> getfinaldestination always failed, which
    caused wrong optimizations in some cases)
  * changed the inverse_cond into a function, because tasmcond is a record
    on ppc
  + added a compare_conditions() function for the same reason
		
	
			
		
			
				
	
	
		
			286 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						||
    $Id$
 | 
						||
    Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
 | 
						||
    Development Team
 | 
						||
 | 
						||
    This unit contains the interface routines between the code generator
 | 
						||
    and the optimizer.
 | 
						||
 | 
						||
    This program is free software; you can redistribute it and/or modify
 | 
						||
    it under the terms of the GNU General Public License as published by
 | 
						||
    the Free Software Foundation; either version 2 of the License, or
 | 
						||
    (at your option) any later version.
 | 
						||
 | 
						||
    This program is distributed in the hope that it will be useful,
 | 
						||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						||
    GNU General Public License for more details.
 | 
						||
 | 
						||
    You should have received a copy of the GNU General Public License
 | 
						||
    along with this program; if not, write to the Free Software
 | 
						||
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						||
 | 
						||
 ****************************************************************************
 | 
						||
}
 | 
						||
Unit aopt;
 | 
						||
 | 
						||
{$i fpcdefs.inc}
 | 
						||
 | 
						||
  Interface
 | 
						||
 | 
						||
    Uses
 | 
						||
      aasmbase,aasmtai,aasmcpu,
 | 
						||
      aoptobj;
 | 
						||
 | 
						||
    Type
 | 
						||
      TAsmOptimizer = class(TAoptObj)
 | 
						||
 | 
						||
        { _AsmL is the PAasmOutpout list that has to be optimized }
 | 
						||
        Constructor create(_AsmL: taasmoutput);
 | 
						||
 | 
						||
        { call the necessary optimizer procedures }
 | 
						||
        Procedure Optimize;
 | 
						||
        Destructor destroy;override;
 | 
						||
 | 
						||
      private
 | 
						||
        procedure FindLoHiLabels;
 | 
						||
        Procedure BuildLabelTableAndFixRegAlloc;
 | 
						||
        procedure clear;
 | 
						||
        procedure pass_1;
 | 
						||
      End;
 | 
						||
 | 
						||
    var
 | 
						||
      casmoptimizer : class of tasmoptimizer;
 | 
						||
 | 
						||
    procedure Optimize(AsmL:taasmoutput);
 | 
						||
 | 
						||
  Implementation
 | 
						||
 | 
						||
    uses
 | 
						||
      globtype, globals,
 | 
						||
      aoptda,aoptcpu,aoptcpud;
 | 
						||
 | 
						||
    Constructor TAsmOptimizer.create(_AsmL: taasmoutput);
 | 
						||
      Begin
 | 
						||
        inherited create(_asml,nil,nil,nil);
 | 
						||
      {setup labeltable, always necessary}
 | 
						||
        New(LabelInfo);
 | 
						||
      End;
 | 
						||
 | 
						||
    procedure TAsmOptimizer.FindLoHiLabels;
 | 
						||
      { Walks through the paasmlist to find the lowest and highest label number.  }
 | 
						||
      { Returns the last Pai object of the current block                          }
 | 
						||
      Var LabelFound: Boolean;
 | 
						||
          p, prev: tai;
 | 
						||
      Begin
 | 
						||
        LabelInfo^.LowLabel := High(AWord);
 | 
						||
        LabelInfo^.HighLabel := 0;
 | 
						||
        LabelInfo^.LabelDif := 0;
 | 
						||
        LabelInfo^.LabelTable:=nil;
 | 
						||
        LabelFound := False;
 | 
						||
        P := BlockStart;
 | 
						||
        prev := p;
 | 
						||
        With LabelInfo^ Do
 | 
						||
          Begin
 | 
						||
            While Assigned(P) And
 | 
						||
                  ((P.typ <> Ait_Marker) Or
 | 
						||
                   (tai_Marker(P).Kind <> AsmBlockStart)) Do
 | 
						||
              Begin
 | 
						||
                If (p.typ = ait_label) Then
 | 
						||
                  If (tai_Label(p).l.is_used) Then
 | 
						||
                    Begin
 | 
						||
                      LabelFound := True;
 | 
						||
                      If (tai_Label(p).l.labelnr < LowLabel) Then
 | 
						||
                        LowLabel := tai_Label(p).l.labelnr;
 | 
						||
                      If (tai_Label(p).l.labelnr > HighLabel) Then
 | 
						||
                        HighLabel := tai_Label(p).l.labelnr
 | 
						||
                    End;
 | 
						||
                prev := p;
 | 
						||
                GetNextInstruction(p, p)
 | 
						||
              End;
 | 
						||
            if (prev.typ = ait_marker) and
 | 
						||
               (tai_marker(prev).kind = asmblockstart) then
 | 
						||
              blockend := prev
 | 
						||
            else blockend := nil;
 | 
						||
            If LabelFound
 | 
						||
              Then LabelDif := HighLabel-LowLabel+1
 | 
						||
              Else LabelDif := 0
 | 
						||
          End
 | 
						||
      End;
 | 
						||
 | 
						||
    Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
 | 
						||
    { Builds a table with the locations of the labels in the taasmoutput.       }
 | 
						||
    { Also fixes some RegDeallocs like "# %eax released; push (%eax)"           }
 | 
						||
    Var p, hp1, hp2: tai;
 | 
						||
        UsedRegs: TRegSet;
 | 
						||
    Begin
 | 
						||
      UsedRegs := [];
 | 
						||
      With LabelInfo^ Do
 | 
						||
        If (LabelDif <> 0) Then
 | 
						||
          Begin
 | 
						||
            GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
 | 
						||
            FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
 | 
						||
            p := BlockStart;
 | 
						||
            While (P <> BlockEnd) Do
 | 
						||
              Begin
 | 
						||
                Case p.typ Of
 | 
						||
                  ait_Label:
 | 
						||
                    If tai_label(p).l.is_used Then
 | 
						||
                      LabelTable^[tai_label(p).l.labelnr-LowLabel].PaiObj := p;
 | 
						||
                  ait_regAlloc:
 | 
						||
                    begin
 | 
						||
                    {!!!!!!!!!
 | 
						||
                      if tai_regalloc(p).ratype=ra_alloc then
 | 
						||
                        Begin
 | 
						||
                          If Not(tai_regalloc(p).Reg in UsedRegs) Then
 | 
						||
                            UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
 | 
						||
                          Else
 | 
						||
                            Begin
 | 
						||
                              hp1 := p;
 | 
						||
                              hp2 := nil;
 | 
						||
                              While GetLastInstruction(hp1, hp1) And
 | 
						||
                                    Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
 | 
						||
                                hp2:=hp1;
 | 
						||
                              If hp2<>nil Then
 | 
						||
                                Begin
 | 
						||
                                  hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
 | 
						||
                                  InsertLLItem(tai(hp2.previous), hp2, hp1);
 | 
						||
                                End;
 | 
						||
                            End;
 | 
						||
                        End
 | 
						||
                      else
 | 
						||
                        Begin
 | 
						||
                          UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
 | 
						||
                          hp1 := p;
 | 
						||
                          hp2 := nil;
 | 
						||
                          While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
 | 
						||
                                GetNextInstruction(hp1, hp1) And
 | 
						||
                                RegInInstruction(tai_regalloc(p).Reg, hp1) Do
 | 
						||
                            hp2 := hp1;
 | 
						||
                          If hp2 <> nil Then
 | 
						||
                            Begin
 | 
						||
                              hp1 := tai(p.previous);
 | 
						||
                              AsmL.Remove(p);
 | 
						||
                              InsertLLItem(hp2, tai(hp2.Next), p);
 | 
						||
                              p := hp1;
 | 
						||
                            End
 | 
						||
                        End
 | 
						||
                    };
 | 
						||
                    End
 | 
						||
                End;
 | 
						||
                P := tai(p.Next);
 | 
						||
                While Assigned(p) and
 | 
						||
                      (p <> blockend) and
 | 
						||
                      (p.typ in (SkipInstr - [ait_regalloc])) Do
 | 
						||
                  P := tai(P.Next)
 | 
						||
              End;
 | 
						||
          End
 | 
						||
    End;
 | 
						||
 | 
						||
    procedure tasmoptimizer.clear;
 | 
						||
      begin
 | 
						||
        if LabelInfo^.labeldif <> 0 then
 | 
						||
          begin
 | 
						||
            freemem(LabelInfo^.labeltable);
 | 
						||
            LabelInfo^.labeltable := nil;
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure tasmoptimizer.pass_1;
 | 
						||
      begin
 | 
						||
        findlohilabels;
 | 
						||
        BuildLabelTableAndFixRegAlloc;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    Procedure TAsmOptimizer.Optimize;
 | 
						||
      Var
 | 
						||
        HP: tai;
 | 
						||
        pass: longint;
 | 
						||
      Begin
 | 
						||
        pass:=0;
 | 
						||
        BlockStart := tai(AsmL.First);
 | 
						||
        pass_1;
 | 
						||
        While Assigned(BlockStart) Do
 | 
						||
          Begin
 | 
						||
             if pass = 0 then
 | 
						||
               PrePeepHoleOpts;
 | 
						||
            { Peephole optimizations }
 | 
						||
             PeepHoleOptPass1;
 | 
						||
            { Only perform them twice in the first pass }
 | 
						||
             if pass = 0 then
 | 
						||
               PeepHoleOptPass1;
 | 
						||
            If (cs_slowoptimize in aktglobalswitches) Then
 | 
						||
              Begin
 | 
						||
//                DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
 | 
						||
                { data flow analyzer }
 | 
						||
//                DFA.DoDFA;
 | 
						||
                { common subexpression elimination }
 | 
						||
      {          CSE;}
 | 
						||
              End;
 | 
						||
            { more peephole optimizations }
 | 
						||
      {      PeepHoleOptPass2;}
 | 
						||
            { free memory<72>}
 | 
						||
            clear;
 | 
						||
            { continue where we left off, BlockEnd is either the start of an }
 | 
						||
            { assembler block or nil}
 | 
						||
            BlockStart := BlockEnd;
 | 
						||
            While Assigned(BlockStart) And
 | 
						||
                  (BlockStart.typ = ait_Marker) And
 | 
						||
                  (tai_Marker(BlockStart).Kind = AsmBlockStart) Do
 | 
						||
              Begin
 | 
						||
               { we stopped at an assembler block, so skip it    }
 | 
						||
               While GetNextInstruction(BlockStart, BlockStart) And
 | 
						||
                     ((BlockStart.Typ <> Ait_Marker) Or
 | 
						||
                      (tai_Marker(Blockstart).Kind <> AsmBlockEnd)) Do;
 | 
						||
               { blockstart now contains a tai_marker(asmblockend) }
 | 
						||
               If GetNextInstruction(BlockStart, HP) And
 | 
						||
                  ((HP.typ <> ait_Marker) Or
 | 
						||
                   (Tai_Marker(HP).Kind <> AsmBlockStart)) Then
 | 
						||
               { There is no assembler block anymore after the current one, so }
 | 
						||
               { optimize the next block of "normal" instructions              }
 | 
						||
                 pass_1
 | 
						||
               { Otherwise, skip the next assembler block }
 | 
						||
               else
 | 
						||
                 blockStart := hp;
 | 
						||
              End
 | 
						||
          End;
 | 
						||
      End;
 | 
						||
 | 
						||
    Destructor TAsmOptimizer.Destroy;
 | 
						||
      Begin
 | 
						||
        Dispose(LabelInfo)
 | 
						||
      End;
 | 
						||
 | 
						||
 | 
						||
    procedure Optimize(AsmL:taasmoutput);
 | 
						||
      var
 | 
						||
        p : TAsmOptimizer;
 | 
						||
      begin
 | 
						||
        p:=casmoptimizer.Create(AsmL);
 | 
						||
        p.Optimize;
 | 
						||
        p.free
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
begin
 | 
						||
  casmoptimizer:=TAsmOptimizer;
 | 
						||
end.
 | 
						||
 | 
						||
{Virtual methods, most have to be overridden by processor dependent methods}
 | 
						||
 | 
						||
{
 | 
						||
 $Log$
 | 
						||
 Revision 1.10  2005-02-26 01:26:59  jonas
 | 
						||
   * fixed generic jumps optimizer and enabled it for ppc (the label table
 | 
						||
     was not being initialised -> getfinaldestination always failed, which
 | 
						||
     caused wrong optimizations in some cases)
 | 
						||
   * changed the inverse_cond into a function, because tasmcond is a record
 | 
						||
     on ppc
 | 
						||
   + added a compare_conditions() function for the same reason
 | 
						||
 | 
						||
 Revision 1.9  2005/02/14 17:13:06  peter
 | 
						||
   * truncate log
 | 
						||
 | 
						||
}
 |