Browse Source

Optimize FoldShiftLdrStr in ARM Peephole optimizer

The optimizer now juggles around the base and index register if that opens
up the possibility of folding the shift into the instruction.

This can only be done in the case of addressmode=AM_OFFSET, in case of
[AM_POSTINDEXED, AM_PREINDEXED] we can not move the base register, as this
would cause havoc and destruction.

git-svn-id: trunk@24645 -
masta 12 years ago
parent
commit
073cab8d86
1 changed files with 20 additions and 3 deletions
  1. 20 3
      compiler/arm/aoptcpu.pas

+ 20 - 3
compiler/arm/aoptcpu.pas

@@ -1150,18 +1150,35 @@ Implementation
                        {Only LDR, LDRB, STR, STRB can handle scaled register indexing}
                        {Only LDR, LDRB, STR, STRB can handle scaled register indexing}
                        MatchInstruction(hp1, [A_LDR, A_STR], [taicpu(p).condition],
                        MatchInstruction(hp1, [A_LDR, A_STR], [taicpu(p).condition],
                                              [PF_None, PF_B]) and
                                              [PF_None, PF_B]) and
-                       (taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) and
-                       (taicpu(hp1).oper[1]^.ref^.base <> taicpu(p).oper[0]^.reg) and
+                       (
+                         {If this is address by offset, one of the two registers can be used}
+                         ((taicpu(hp1).oper[1]^.ref^.addressmode=AM_OFFSET) and
+                           (
+                             (taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) xor
+                             (taicpu(hp1).oper[1]^.ref^.base = taicpu(p).oper[0]^.reg)
+                           )
+                         ) or
+                         {For post and preindexed only the index register can be used}
+                         ((taicpu(hp1).oper[1]^.ref^.addressmode in [AM_POSTINDEXED, AM_PREINDEXED]) and
+                           (
+                             (taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) and
+                             (taicpu(hp1).oper[1]^.ref^.base <> taicpu(p).oper[0]^.reg)
+                           )
+                         )
+                       ) and
                        { Only fold if there isn't another shifterop already. }
                        { Only fold if there isn't another shifterop already. }
                        (taicpu(hp1).oper[1]^.ref^.shiftmode = SM_None) and
                        (taicpu(hp1).oper[1]^.ref^.shiftmode = SM_None) and
                        not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
                        not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
                        (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
                        (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
                          regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) then
                          regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) then
                        begin
                        begin
-                         DebugMsg('Peephole FoldShiftLdrStr done', hp1);
+                         { If the register we want to do the shift for resides in base, we need to swap that}
+                         if (taicpu(hp1).oper[1]^.ref^.base = taicpu(p).oper[0]^.reg) then
+                           taicpu(hp1).oper[1]^.ref^.base := taicpu(hp1).oper[1]^.ref^.index;
                          taicpu(hp1).oper[1]^.ref^.index := taicpu(p).oper[1]^.reg;
                          taicpu(hp1).oper[1]^.ref^.index := taicpu(p).oper[1]^.reg;
                          taicpu(hp1).oper[1]^.ref^.shiftmode := taicpu(p).oper[2]^.shifterop^.shiftmode;
                          taicpu(hp1).oper[1]^.ref^.shiftmode := taicpu(p).oper[2]^.shifterop^.shiftmode;
                          taicpu(hp1).oper[1]^.ref^.shiftimm := taicpu(p).oper[2]^.shifterop^.shiftimm;
                          taicpu(hp1).oper[1]^.ref^.shiftimm := taicpu(p).oper[2]^.shifterop^.shiftimm;
+                         DebugMsg('Peephole FoldShiftLdrStr done', hp1);
                          asml.remove(p);
                          asml.remove(p);
                          p.free;
                          p.free;
                          p:=hp1;
                          p:=hp1;