Просмотр исходного кода

* Fixed label optimizer to work with MIPS, and enabled level 1 optimization for MIPS targets.
The difference in branch instruction formats is isolated in function JumpTargetOp, it is a plain function rather than a virtual method, so it can be easily inlined and, after inlining, produces the same code for non-MIPS targets as it was before change.

git-svn-id: trunk@25033 -

sergei 12 лет назад
Родитель
Сommit
1c84c3edbf
3 измененных файлов с 64 добавлено и 29 удалено
  1. 2 2
      compiler/aoptbase.pas
  2. 61 26
      compiler/aoptobj.pas
  3. 1 1
      compiler/mips/cpuinfo.pas

+ 2 - 2
compiler/aoptbase.pas

@@ -171,11 +171,11 @@ unit aoptbase;
       Current := tai(Current.Next);
       Current := tai(Current.Next);
       While Assigned(Current) And
       While Assigned(Current) And
             ((Current.typ In SkipInstr) or
             ((Current.typ In SkipInstr) or
-{$ifdef SPARC}
+{$if defined(SPARC) or defined(MIPS)}
              ((Current.typ=ait_instruction) and
              ((Current.typ=ait_instruction) and
               (taicpu(Current).opcode=A_NOP)
               (taicpu(Current).opcode=A_NOP)
              ) or
              ) or
-{$endif SPARC}
+{$endif SPARC or MIPS}
              ((Current.typ = ait_label) And
              ((Current.typ = ait_label) And
               labelCanBeSkipped(Tai_Label(Current)))) Do
               labelCanBeSkipped(Tai_Label(Current)))) Do
         Current := tai(Current.Next);
         Current := tai(Current.Next);

+ 61 - 26
compiler/aoptobj.pas

@@ -344,6 +344,18 @@ Unit AoptObj;
       verbose,
       verbose,
       procinfo;
       procinfo;
 
 
+
+    function JumpTargetOp(ai: taicpu): poper; inline;
+      begin
+{$ifdef MIPS}
+        { MIPS branches can have 1,2 or 3 operands, target label is the last one. }
+        result:=ai.oper[ai.ops-1];
+{$else MIPS}
+        result:=ai.oper[0];
+{$endif MIPS}
+      end;
+
+
       { ************************************************************************* }
       { ************************************************************************* }
       { ******************************** TUsedRegs ****************************** }
       { ******************************** TUsedRegs ****************************** }
       { ************************************************************************* }
       { ************************************************************************* }
@@ -1126,8 +1138,8 @@ Unit AoptObj;
 {$ifdef arm}
 {$ifdef arm}
           (hp.condition=c_None) and
           (hp.condition=c_None) and
 {$endif arm}
 {$endif arm}
-          (hp.oper[0]^.typ = top_ref) and
-          (hp.oper[0]^.ref^.symbol is TAsmLabel);
+          (JumpTargetOp(hp)^.typ = top_ref) and
+          (JumpTargetOp(hp)^.ref^.symbol is TAsmLabel);
       end;
       end;
 
 
 
 
@@ -1151,7 +1163,7 @@ Unit AoptObj;
         GetfinalDestination := false;
         GetfinalDestination := false;
         if level > 20 then
         if level > 20 then
           exit;
           exit;
-        p1 := getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
+        p1 := getlabelwithsym(tasmlabel(JumpTargetOp(hp)^.ref^.symbol));
         if assigned(p1) then
         if assigned(p1) then
           begin
           begin
             SkipLabels(p1,p1);
             SkipLabels(p1,p1);
@@ -1159,8 +1171,12 @@ Unit AoptObj;
                (taicpu(p1).is_jmp) then
                (taicpu(p1).is_jmp) then
               if { the next instruction after the label where the jump hp arrives}
               if { the next instruction after the label where the jump hp arrives}
                  { is unconditional or of the same type as hp, so continue       }
                  { is unconditional or of the same type as hp, so continue       }
-                 (IsJumpToLabel(taicpu(p1)) or
-                  conditions_equal(taicpu(p1).condition,hp.condition)) or
+                 IsJumpToLabel(taicpu(p1))
+{$ifndef MIPS}
+{ for MIPS, it isn't enough to check the condition; first operands must be same, too. }
+                 or
+                 conditions_equal(taicpu(p1).condition,hp.condition) or
+
                  { the next instruction after the label where the jump hp arrives
                  { the next instruction after the label where the jump hp arrives
                    is the opposite of hp (so this one is never taken), but after
                    is the opposite of hp (so this one is never taken), but after
                    that one there is a branch that will be taken, so perform a
                    that one there is a branch that will be taken, so perform a
@@ -1172,18 +1188,21 @@ Unit AoptObj;
                   (taicpu(p2).is_jmp) and
                   (taicpu(p2).is_jmp) and
                    (IsJumpToLabel(taicpu(p2)) or
                    (IsJumpToLabel(taicpu(p2)) or
                    (conditions_equal(taicpu(p2).condition,hp.condition))) and
                    (conditions_equal(taicpu(p2).condition,hp.condition))) and
-                  SkipLabels(p1,p1)) then
+                  SkipLabels(p1,p1))
+{$endif MIPS}
+                 then
                 begin
                 begin
                   { quick check for loops of the form "l5: ; jmp l5 }
                   { quick check for loops of the form "l5: ; jmp l5 }
-                  if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
-                       tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
+                  if (tasmlabel(JumpTargetOp(taicpu(p1))^.ref^.symbol).labelnr =
+                       tasmlabel(JumpTargetOp(hp)^.ref^.symbol).labelnr) then
                     exit;
                     exit;
                   if not GetFinalDestination(taicpu(p1),succ(level)) then
                   if not GetFinalDestination(taicpu(p1),succ(level)) then
                     exit;
                     exit;
-                  tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
-                  hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
-                  tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
+                  tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
+                  JumpTargetOp(hp)^.ref^.symbol:=JumpTargetOp(taicpu(p1))^.ref^.symbol;
+                  tasmlabel(JumpTargetOp(hp)^.ref^.symbol).increfs;
                 end
                 end
+{$ifndef MIPS}
               else
               else
                 if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
                 if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
                   if not FindAnyLabel(p1,l) then
                   if not FindAnyLabel(p1,l) then
@@ -1194,8 +1213,8 @@ Unit AoptObj;
       {$endif finaldestdebug}
       {$endif finaldestdebug}
                       current_asmdata.getjumplabel(l);
                       current_asmdata.getjumplabel(l);
                       insertllitem(p1,p1.next,tai_label.Create(l));
                       insertllitem(p1,p1.next,tai_label.Create(l));
-                      tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
-                      hp.oper[0]^.ref^.symbol := l;
+                      tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
+                      JumpTargetOp(hp)^.ref^.symbol := l;
                       l.increfs;
                       l.increfs;
       {               this won't work, since the new label isn't in the labeltable }
       {               this won't work, since the new label isn't in the labeltable }
       {               so it will fail the rangecheck. Labeltable should become a   }
       {               so it will fail the rangecheck. Labeltable should become a   }
@@ -1209,11 +1228,12 @@ Unit AoptObj;
                         strpnew('next label reused'))));
                         strpnew('next label reused'))));
       {$endif finaldestdebug}
       {$endif finaldestdebug}
                       l.increfs;
                       l.increfs;
-                      tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
-                      hp.oper[0]^.ref^.symbol := l;
+                      tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
+                      JumpTargetOp(hp)^.ref^.symbol := l;
                       if not GetFinalDestination(hp,succ(level)) then
                       if not GetFinalDestination(hp,succ(level)) then
                         exit;
                         exit;
                     end;
                     end;
+{$endif not MIPS}
           end;
           end;
         GetFinalDestination := true;
         GetFinalDestination := true;
       end;
       end;
@@ -1263,9 +1283,9 @@ Unit AoptObj;
                               begin
                               begin
                                 if (hp1.typ = ait_instruction) and
                                 if (hp1.typ = ait_instruction) and
                                    taicpu(hp1).is_jmp and
                                    taicpu(hp1).is_jmp and
-                                   (taicpu(hp1).oper[0]^.typ = top_ref) and
-                                   (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) then
-                                   TAsmLabel(taicpu(hp1).oper[0]^.ref^.symbol).decrefs;
+                                   (JumpTargetOp(taicpu(hp1))^.typ = top_ref) and
+                                   (JumpTargetOp(taicpu(hp1))^.ref^.symbol is TAsmLabel) then
+                                   TAsmLabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).decrefs;
                                 { don't kill start/end of assembler block,
                                 { don't kill start/end of assembler block,
                                   no-line-info-start/end etc }
                                   no-line-info-start/end etc }
                                 if hp1.typ<>ait_marker then
                                 if hp1.typ<>ait_marker then
@@ -1281,13 +1301,18 @@ Unit AoptObj;
                       { remove jumps to a label coming right after them }
                       { remove jumps to a label coming right after them }
                       if GetNextInstruction(p, hp1) then
                       if GetNextInstruction(p, hp1) then
                         begin
                         begin
-                          if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
+                          if FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp1) and
         { TODO: FIXME removing the first instruction fails}
         { TODO: FIXME removing the first instruction fails}
                               (p<>blockstart) then
                               (p<>blockstart) then
                             begin
                             begin
+                              tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol).decrefs;
+{$if defined(SPARC) or defined(MIPS)}
+                              hp2:=tai(p.next);
+                              asml.remove(hp2);
+                              hp2.free;
+{$endif SPARC or MIPS}
                               hp2:=tai(hp1.next);
                               hp2:=tai(hp1.next);
                               asml.remove(p);
                               asml.remove(p);
-                              tasmlabel(taicpu(p).oper[0]^.ref^.symbol).decrefs;
                               p.free;
                               p.free;
                               p:=hp2;
                               p:=hp2;
                               continue;
                               continue;
@@ -1299,7 +1324,7 @@ Unit AoptObj;
                               if (tai(hp1).typ=ait_instruction) and
                               if (tai(hp1).typ=ait_instruction) and
                                   IsJumpToLabel(taicpu(hp1)) and
                                   IsJumpToLabel(taicpu(hp1)) and
                                   GetNextInstruction(hp1, hp2) and
                                   GetNextInstruction(hp1, hp2) and
-                                  FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
+                                  FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp2) then
                                 begin
                                 begin
                                   if (taicpu(p).opcode=aopt_condjmp)
                                   if (taicpu(p).opcode=aopt_condjmp)
 {$ifdef arm}
 {$ifdef arm}
@@ -1309,17 +1334,27 @@ Unit AoptObj;
                                     begin
                                     begin
                                       taicpu(p).condition:=inverse_cond(taicpu(p).condition);
                                       taicpu(p).condition:=inverse_cond(taicpu(p).condition);
                                       tai_label(hp2).labsym.decrefs;
                                       tai_label(hp2).labsym.decrefs;
-                                      taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
+                                      JumpTargetOp(taicpu(p))^.ref^.symbol:=JumpTargetOp(taicpu(hp1))^.ref^.symbol;
                                       { when freeing hp1, the reference count
                                       { when freeing hp1, the reference count
                                         isn't decreased, so don't increase
                                         isn't decreased, so don't increase
 
 
                                        taicpu(p).oper[0]^.ref^.symbol.increfs;
                                        taicpu(p).oper[0]^.ref^.symbol.increfs;
                                       }
                                       }
-{$ifdef SPARC}
+{$if defined(SPARC) or defined(MIPS)}
+                                      { Remove delay slot. Initially is is placed immediately after
+                                        branch, but RA can insert regallocs in between. }
                                       hp2:=tai(hp1.next);
                                       hp2:=tai(hp1.next);
-                                      asml.remove(hp2);
-                                      hp2.free;
-{$endif SPARC}
+                                      while assigned(hp2) and (hp2.typ in SkipInstr) do
+                                        hp2:=tai(hp2.next);
+                                      if assigned(hp2) and (hp2.typ=ait_instruction) and
+                                         (taicpu(hp2).opcode=A_NOP) then
+                                        begin
+                                          asml.remove(hp2);
+                                          hp2.free;
+                                        end
+                                      else
+                                        InternalError(2013070301);
+{$endif SPARC or MIPS}
                                       asml.remove(hp1);
                                       asml.remove(hp1);
                                       hp1.free;
                                       hp1.free;
                                       GetFinalDestination(taicpu(p),0);
                                       GetFinalDestination(taicpu(p),0);

+ 1 - 1
compiler/mips/cpuinfo.pas

@@ -111,7 +111,7 @@ Const
    supported_optimizerswitches = [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,
    supported_optimizerswitches = [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,
                                   cs_opt_reorder_fields,cs_opt_fastmath];
                                   cs_opt_reorder_fields,cs_opt_fastmath];
 
 
-   level1optimizerswitches = [];
+   level1optimizerswitches = [cs_opt_level1];
    level2optimizerswitches = level1optimizerswitches + [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse];
    level2optimizerswitches = level1optimizerswitches + [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse];
    level3optimizerswitches = level2optimizerswitches + [cs_opt_loopunroll];
    level3optimizerswitches = level2optimizerswitches + [cs_opt_loopunroll];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [];