Browse Source

+ Add/SubLdr2Ldr optimization

git-svn-id: trunk@22217 -
florian 13 years ago
parent
commit
8a20ccc5f9
1 changed files with 65 additions and 0 deletions
  1. 65 0
      compiler/arm/aoptcpu.pas

+ 65 - 0
compiler/arm/aoptcpu.pas

@@ -950,6 +950,71 @@ Implementation
                         asml.remove(hp1);
                         hp1.free;
                       end;
+                   {
+                      change
+                      add/sub reg2,reg1,const1
+                      str/ldr reg3,[reg2,const2]
+                      dealloc reg2
+                      to
+                      str/ldr reg3,[reg1,const2+/-const1]
+                    }
+                    if (taicpu(p).opcode in [A_ADD,A_SUB]) and
+                       (taicpu(p).oper[1]^.typ = top_reg) and
+                       (taicpu(p).oper[2]^.typ = top_const) then
+                      begin
+                        hp1:=p;
+                        while GetNextInstructionUsingReg(hp1, hp1, taicpu(p).oper[0]^.reg) and
+                          (MatchInstruction(hp1, A_LDR, [taicpu(p).condition], [PF_None]) or
+                           MatchInstruction(hp1, A_STR, [taicpu(p).condition], [PF_None])) and
+                          (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
+                          (taicpu(hp1).oper[1]^.ref^.index=NR_NO) and
+                          (taicpu(hp1).oper[1]^.ref^.addressmode=AM_OFFSET) and
+                          { new offset must be valid: either in the range of 8 or 12 bit, depend on the
+                            ldr postfix }
+                          (((taicpu(p).opcode=A_ADD) and
+                            (((taicpu(hp1).oppostfix=PF_None) and
+                              (abs(taicpu(hp1).oper[1]^.ref^.offset+taicpu(p).oper[2]^.val)<4096)) or
+                             (abs(taicpu(hp1).oper[1]^.ref^.offset+taicpu(p).oper[2]^.val)<256)
+                            )
+                           ) or
+                           ((taicpu(p).opcode=A_SUB) and
+                             (((taicpu(hp1).oppostfix=PF_None) and
+                               (abs(taicpu(hp1).oper[1]^.ref^.offset-taicpu(p).oper[2]^.val)<4096)) or
+                              (abs(taicpu(hp1).oper[1]^.ref^.offset-taicpu(p).oper[2]^.val)<256)
+                             )
+                           )
+                          ) do
+                          begin
+                            { reg2 might not be changed inbetween }
+                            if RegModifiedBetween(taicpu(p).oper[0]^.reg,p,hp1) then
+                              break;
+                            { reg2 must be either overwritten by the ldr or it is deallocated afterwards }
+                            if ((taicpu(hp1).opcode=A_LDR) and (taicpu(p).oper[0]^.reg=taicpu(hp1).oper[0]^.reg)) or
+                              assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+                              begin
+                                { remember last instruction }
+                                hp2:=hp1;
+                                asml.insertbefore(tai_comment.Create(strpnew('Peephole Add/SubLdr2Ldr done')), p);
+                                hp1:=p;
+                                { fix all ldr/str }
+                                while GetNextInstructionUsingReg(hp1, hp1, taicpu(p).oper[0]^.reg) do
+                                  begin
+                                    taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg;
+                                    if taicpu(p).opcode=A_ADD then
+                                      inc(taicpu(hp1).oper[1]^.ref^.offset,taicpu(p).oper[2]^.val)
+                                    else
+                                      dec(taicpu(hp1).oper[1]^.ref^.offset,taicpu(p).oper[2]^.val);
+                                    if hp1=hp2 then
+                                      break;
+                                  end;
+                                GetNextInstruction(p,hp1);
+                                asml.remove(p);
+                                p.free;
+                                p:=hp1;
+                                break;
+                              end;
+                          end;
+                      end;
                     {
                       change
                       add reg1, ...