Ver Fonte

Split OP_ADD, OP_SUB, OP_AND and OP_ORR into multiple instructions if that can avoid constant construction or even loading from a pool.

OP_ADD, OP_SUB, OP_ORR will be split into two intructions if possible when a load/const
construction is required.

OP_AND is a bit different, because we can't just split it up, but we try
to find a two instruction BIC-equivalent to it.

Till now code like

a:= a and $FFFF;

produced code like

mov r0, $FF00
orr r0, r0, $FF
and r1, r1, r0

With this addition we produce code like:

bic r0, r0, $FF00
bic r0, r0, $FF

Saving us at least a cycle and in some cases also a load from the
constant-pool.

This uses the new split_into_shifter_const function.

git-svn-id: trunk@21647 -
masta há 13 anos atrás
pai
commit
0f3441a9c2
1 ficheiros alterados com 28 adições e 0 exclusões
  1. 28 0
      compiler/arm/cgcpu.pas

+ 28 - 0
compiler/arm/cgcpu.pas

@@ -631,6 +631,7 @@ unit cgcpu;
         tmpreg : tregister;
         so : tshifterop;
         l1 : longint;
+        imm1, imm2: DWord;
       begin
         ovloc.loc:=LOC_VOID;
         if {$ifopt R+}(a<>-2147483648) and{$endif} is_shifter_const(-a,shift) then
@@ -784,6 +785,33 @@ unit cgcpu;
               broader range of shifterconstants.}
             else if (op = OP_AND) and is_shifter_const(not(dword(a)),shift) then
               list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,not(dword(a))))
+            else if (op = OP_AND) and split_into_shifter_const(not(dword(a)), imm1, imm2) then
+              begin
+                list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,imm1));
+                list.concat(taicpu.op_reg_reg_const(A_BIC,dst,dst,imm2));
+              end
+            else if (op in [OP_ADD, OP_SUB, OP_OR]) and
+                    not(cgsetflags or setflags) and
+                    split_into_shifter_const(a, imm1, imm2) then
+              begin
+                case (op) of
+                  OP_ADD:
+                    begin
+                      list.concat(taicpu.op_reg_reg_const(A_ADD,dst,src,imm1));
+                      list.concat(taicpu.op_reg_reg_const(A_ADD,dst,dst,imm2));
+                    end;
+                  OP_SUB:
+                    begin
+                      list.concat(taicpu.op_reg_reg_const(A_SUB,dst,src,imm1));
+                      list.concat(taicpu.op_reg_reg_const(A_SUB,dst,dst,imm2));
+                    end;
+                  OP_OR:
+                    begin
+                      list.concat(taicpu.op_reg_reg_const(A_ORR,dst,src,imm1));
+                      list.concat(taicpu.op_reg_reg_const(A_ORR,dst,dst,imm2));
+                    end;
+                end;
+              end
             else
               begin
                 tmpreg:=getintregister(list,size);