Browse Source

+ Teach peephole optimizer the cmc/adc trick I used in int_str.

git-svn-id: trunk@9799 -
daniel 17 years ago
parent
commit
459382faa8
1 changed files with 175 additions and 120 deletions
  1. 175 120
      compiler/i386/popt386.pas

+ 175 - 120
compiler/i386/popt386.pas

@@ -1745,6 +1745,7 @@ var
   hp3: tai;
 {$endif USECMOV}
   UsedRegs, TmpUsedRegs: TRegSet;
+  carryadd_opcode: Tasmop;
 
 begin
   p := BlockStart;
@@ -1756,131 +1757,185 @@ begin
         Ait_Instruction:
           begin
             case taicpu(p).opcode Of
-{$ifdef USECMOV}
               A_Jcc:
-                if (current_settings.cputype>=cpu_Pentium2) then
-                  begin
-                     { check for
-                            jCC   xxx
-                            <several movs>
-                         xxx:
-                     }
-                     l:=0;
-                     GetNextInstruction(p, hp1);
-                     while assigned(hp1) and
-                       CanBeCMOV(hp1) and
-                       { stop on labels }
-                       not(hp1.typ=ait_label) do
-                       begin
-                          inc(l);
-                          GetNextInstruction(hp1,hp1);
-                       end;
-                     if assigned(hp1) then
-                       begin
-                          if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+                begin
+                  { jb @@1                            cmc
+                    inc/dec operand           -->     adc/sbb operand,0
+		  @@1:
+		  
+		  ... and ...
+		  
+                    jnb @@1                            
+                    inc/dec operand           -->     adc/sbb operand,0
+		  @@1: }
+                  if GetNextInstruction(p,hp1) and (hp1.typ=ait_instruction) and
+                     GetNextInstruction(hp1,hp2) and (hp2.typ=ait_label) and
+                     (Tasmlabel(Taicpu(p).oper[0]^.ref^.symbol)=Tai_label(hp2).labsym) then
+                    begin
+                      carryadd_opcode:=A_NONE;
+                      if Taicpu(p).condition in [C_NAE,C_B] then
+                        begin
+                          if Taicpu(hp1).opcode=A_INC then
+                            carryadd_opcode:=A_ADC;
+                          if Taicpu(hp1).opcode=A_DEC then
+                            carryadd_opcode:=A_SBB;
+                          if carryadd_opcode<>A_NONE then
                             begin
-                              if (l<=4) and (l>0) then
-                                begin
-                                  condition:=inverse_cond(taicpu(p).condition);
-                                  hp2:=p;
-                                  GetNextInstruction(p,hp1);
-                                  p:=hp1;
-                                  repeat
-                                    taicpu(hp1).opcode:=A_CMOVcc;
-                                    taicpu(hp1).condition:=condition;
-                                    GetNextInstruction(hp1,hp1);
-                                  until not(assigned(hp1)) or
-                                    not(CanBeCMOV(hp1));
-                                  { wait with removing else GetNextInstruction could
-                                    ignore the label if it was the only usage in the
-                                    jump moved away }
-                                  tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
-                                  asml.remove(hp2);
-                                  hp2.free;
-                                  continue;
-                                end;
-                            end
-                          else
+                              Taicpu(p).clearop(0);
+                              Taicpu(p).ops:=0;
+                              Taicpu(p).is_jmp:=false;
+			      Taicpu(p).opcode:=A_CMC;
+			      Taicpu(p).condition:=C_NONE;
+			      Taicpu(hp1).ops:=2;
+                              Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
+                              Taicpu(hp1).loadconst(0,0);
+			      Taicpu(hp1).opcode:=carryadd_opcode;
+			      continue;
+                            end;
+                        end;
+                      if Taicpu(p).condition in [C_AE,C_NB] then
+                        begin
+                          if Taicpu(hp1).opcode=A_INC then
+                            carryadd_opcode:=A_ADC;
+                          if Taicpu(hp1).opcode=A_DEC then
+                            carryadd_opcode:=A_SBB;
+                          if carryadd_opcode<>A_NONE then
                             begin
-                               { check further for
-                                      jCC   xxx
-                                      <several movs 1>
-                                      jmp   yyy
-                              xxx:
-                                      <several movs 2>
-                              yyy:
-                               }
-                              { hp2 points to jmp yyy }
-                              hp2:=hp1;
-                              { skip hp1 to xxx }
-                              GetNextInstruction(hp1, hp1);
-                              if assigned(hp2) and
-                                assigned(hp1) and
-                                (l<=3) and
-                                (hp2.typ=ait_instruction) and
-                                (taicpu(hp2).is_jmp) and
-                                (taicpu(hp2).condition=C_None) and
-                                { real label and jump, no further references to the
-                                  label are allowed }
-                                (tasmlabel(taicpu(p).oper[0]^.ref^.symbol).getrefs=2) and
-                                FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
-                                 begin
-                                   l:=0;
-                                   { skip hp1 to <several moves 2> }
-                                   GetNextInstruction(hp1, hp1);
-                                   while assigned(hp1) and
-                                     CanBeCMOV(hp1) do
-                                     begin
-                                       inc(l);
-                                       GetNextInstruction(hp1, hp1);
-                                     end;
-                                   { hp1 points to yyy: }
-                                   if assigned(hp1) and
-                                     FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
-                                     begin
-                                        condition:=inverse_cond(taicpu(p).condition);
-                                        GetNextInstruction(p,hp1);
-                                        hp3:=p;
-                                        p:=hp1;
-                                        repeat
-                                          taicpu(hp1).opcode:=A_CMOVcc;
-                                          taicpu(hp1).condition:=condition;
-                                          GetNextInstruction(hp1,hp1);
-                                        until not(assigned(hp1)) or
-                                          not(CanBeCMOV(hp1));
-                                        { hp2 is still at jmp yyy }
-                                        GetNextInstruction(hp2,hp1);
-                                        { hp2 is now at xxx: }
-                                        condition:=inverse_cond(condition);
-                                        GetNextInstruction(hp1,hp1);
-                                        { hp1 is now at <several movs 2> }
-                                        repeat
-                                          taicpu(hp1).opcode:=A_CMOVcc;
-                                          taicpu(hp1).condition:=condition;
-                                          GetNextInstruction(hp1,hp1);
-                                        until not(assigned(hp1)) or
-                                          not(CanBeCMOV(hp1));
-                                        {
-                                        asml.remove(hp1.next)
-                                        hp1.next.free;
-                                        asml.remove(hp1);
-                                        hp1.free;
-                                        }
-                                        { remove jCC }
-                                        tasmlabel(taicpu(hp3).oper[0]^.ref^.symbol).decrefs;
-                                        asml.remove(hp3);
-                                        hp3.free;
-                                        { remove jmp }
-                                        tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
-                                        asml.remove(hp2);
-                                        hp2.free;
-                                        continue;
-                                     end;
-                                 end;
+                              asml.remove(p);
+                              p.free;
+			      Taicpu(hp1).ops:=2;
+                              Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
+                              Taicpu(hp1).loadconst(0,0);
+			      Taicpu(hp1).opcode:=carryadd_opcode;
+			      continue;
                             end;
-                       end;
-                  end;
+                        end;
+                    end;
+{$ifdef USECMOV}
+                  if (current_settings.cputype>=cpu_Pentium2) then
+                    begin
+                       { check for
+                              jCC   xxx
+                              <several movs>
+                           xxx:
+                       }
+                       l:=0;
+                       GetNextInstruction(p, hp1);
+                       while assigned(hp1) and
+                         CanBeCMOV(hp1) and
+                         { stop on labels }
+                         not(hp1.typ=ait_label) do
+                         begin
+                            inc(l);
+                            GetNextInstruction(hp1,hp1);
+                         end;
+                       if assigned(hp1) then
+                         begin
+                            if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+                              begin
+                                if (l<=4) and (l>0) then
+                                  begin
+                                    condition:=inverse_cond(taicpu(p).condition);
+                                    hp2:=p;
+                                    GetNextInstruction(p,hp1);
+                                    p:=hp1;
+                                    repeat
+                                      taicpu(hp1).opcode:=A_CMOVcc;
+                                      taicpu(hp1).condition:=condition;
+                                      GetNextInstruction(hp1,hp1);
+                                    until not(assigned(hp1)) or
+                                      not(CanBeCMOV(hp1));
+                                    { wait with removing else GetNextInstruction could
+                                      ignore the label if it was the only usage in the
+                                      jump moved away }
+                                    tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+                                    asml.remove(hp2);
+                                    hp2.free;
+                                    continue;
+                                  end;
+                              end
+                            else
+                              begin
+                                 { check further for
+                                        jCC   xxx
+                                        <several movs 1>
+                                        jmp   yyy
+                                xxx:
+                                        <several movs 2>
+                                yyy:
+                                 }
+                                { hp2 points to jmp yyy }
+                                hp2:=hp1;
+                                { skip hp1 to xxx }
+                                GetNextInstruction(hp1, hp1);
+                                if assigned(hp2) and
+                                  assigned(hp1) and
+                                  (l<=3) and
+                                  (hp2.typ=ait_instruction) and
+                                  (taicpu(hp2).is_jmp) and
+                                  (taicpu(hp2).condition=C_None) and
+                                  { real label and jump, no further references to the
+                                    label are allowed }
+                                  (tasmlabel(taicpu(p).oper[0]^.ref^.symbol).getrefs=2) and
+                                  FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+                                   begin
+                                     l:=0;
+                                     { skip hp1 to <several moves 2> }
+                                     GetNextInstruction(hp1, hp1);
+                                     while assigned(hp1) and
+                                       CanBeCMOV(hp1) do
+                                       begin
+                                         inc(l);
+                                         GetNextInstruction(hp1, hp1);
+                                       end;
+                                     { hp1 points to yyy: }
+                                     if assigned(hp1) and
+                                       FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
+                                       begin
+                                          condition:=inverse_cond(taicpu(p).condition);
+                                          GetNextInstruction(p,hp1);
+                                          hp3:=p;
+                                          p:=hp1;
+                                          repeat
+                                            taicpu(hp1).opcode:=A_CMOVcc;
+                                            taicpu(hp1).condition:=condition;
+                                            GetNextInstruction(hp1,hp1);
+                                          until not(assigned(hp1)) or
+                                            not(CanBeCMOV(hp1));
+                                          { hp2 is still at jmp yyy }
+                                          GetNextInstruction(hp2,hp1);
+                                          { hp2 is now at xxx: }
+                                          condition:=inverse_cond(condition);
+                                          GetNextInstruction(hp1,hp1);
+                                          { hp1 is now at <several movs 2> }
+                                          repeat
+                                            taicpu(hp1).opcode:=A_CMOVcc;
+                                            taicpu(hp1).condition:=condition;
+                                            GetNextInstruction(hp1,hp1);
+                                          until not(assigned(hp1)) or
+                                            not(CanBeCMOV(hp1));
+                                          {
+                                          asml.remove(hp1.next)
+                                          hp1.next.free;
+                                          asml.remove(hp1);
+                                          hp1.free;
+                                          }
+                                          { remove jCC }
+                                          tasmlabel(taicpu(hp3).oper[0]^.ref^.symbol).decrefs;
+                                          asml.remove(hp3);
+                                          hp3.free;
+                                          { remove jmp }
+                                          tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+                                          asml.remove(hp2);
+                                          hp2.free;
+                                          continue;
+                                       end;
+                                   end;
+                              end;
+                         end;
+                    end;
 {$endif USECMOV}
+                end;
               A_FSTP,A_FISTP:
                 if doFpuLoadStoreOpt(asmL,p) then
                   continue;