Explorar el Código

Make r12 one of the first registers to be allocated since it's volatile.
Add some extra optimizations for LDREX and STREX opcodes, and fix some of the spilling information.

git-svn-id: branches/laksen/intrinsics@32155 -

Jeppe Johansen hace 10 años
padre
commit
009f40dfe3
Se han modificado 3 ficheros con 65 adiciones y 6 borrados
  1. 1 3
      compiler/arm/aasmcpu.pas
  2. 62 1
      compiler/arm/aoptcpu.pas
  3. 2 2
      compiler/arm/cgcpu.pas

+ 1 - 3
compiler/arm/aasmcpu.pas

@@ -815,13 +815,11 @@ implementation
               result:=operand_readwrite
               result:=operand_readwrite
             else
             else
               result:=operand_read;
               result:=operand_read;
-          A_LDREX:
+          A_LDREX,A_STREX:
             if opnr in [0] then
             if opnr in [0] then
               result:=operand_write
               result:=operand_write
             else
             else
               result:=operand_read;
               result:=operand_read;
-          A_STREX:
-            result:=operand_write;
           else
           else
             internalerror(200403151);
             internalerror(200403151);
         end;
         end;

+ 62 - 1
compiler/arm/aoptcpu.pas

@@ -702,6 +702,18 @@ Implementation
                       end;
                       end;
                     Result:=LookForPostindexedPattern(taicpu(p)) or Result;
                     Result:=LookForPostindexedPattern(taicpu(p)) or Result;
                   end;
                   end;
+                A_LDREX,A_LDREXB,A_LDREXH:
+                  begin
+                    if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                       RemoveSuperfluousMove(p, hp1, 'LdrMov2Ldr') then
+                      Result:=true;
+                  end;
+                A_STREX,A_STREXB,A_STREXH:
+                  begin
+                    if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                       RemoveSuperfluousMove(p, hp1, 'StrMov2Str') then
+                      Result:=true;
+                  end;
                 A_LDR:
                 A_LDR:
                   begin
                   begin
                     { change
                     { change
@@ -1245,7 +1257,7 @@ Implementation
                        (taicpu(p).oper[1]^.typ = top_reg) and
                        (taicpu(p).oper[1]^.typ = top_reg) and
                        (taicpu(p).oppostfix = PF_NONE) and
                        (taicpu(p).oppostfix = PF_NONE) and
                        GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
                        GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
-                       MatchInstruction(hp1, [A_LDR, A_STR], [taicpu(p).condition], []) and
+                       MatchInstruction(hp1, [A_LDR, A_STR, A_LDREX,A_LDREXB,A_LDREXH], [taicpu(p).condition], []) and
                        (taicpu(hp1).oper[1]^.typ = top_ref) and
                        (taicpu(hp1).oper[1]^.typ = top_ref) and
                        { We can change the base register only when the instruction uses AM_OFFSET }
                        { We can change the base register only when the instruction uses AM_OFFSET }
                        ((taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) or
                        ((taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) or
@@ -1282,6 +1294,55 @@ Implementation
                         p:=hp1;
                         p:=hp1;
                         result:=true;
                         result:=true;
                       end;
                       end;
+                    { Fold
+                        mov  regA, regB
+                        strex* regA, regC, [regA]
+                      to
+                        strex* regA, regC, [regB]
+                      CAUTION! If this one is successful p might not be a mov instruction anymore!
+                    }
+                    if (taicpu(p).opcode = A_MOV) and
+                       (taicpu(p).ops = 2) and
+                       (taicpu(p).oper[1]^.typ = top_reg) and
+                       (taicpu(p).oppostfix = PF_NONE) and
+                       GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                       MatchInstruction(hp1, [A_STREX, A_STREXB, A_STREXH], [taicpu(p).condition], []) and
+                       (taicpu(hp1).oper[2]^.typ = top_ref) and
+                       { We can change the base register only when the instruction uses AM_OFFSET }
+                       ((taicpu(hp1).oper[2]^.ref^.index = taicpu(p).oper[0]^.reg) or
+                         ((taicpu(hp1).oper[2]^.ref^.addressmode = AM_OFFSET) and
+                          (taicpu(hp1).oper[2]^.ref^.base = taicpu(p).oper[0]^.reg))
+                       ) and
+                       not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
+
+                       // Make sure that Thumb code doesn't propagate a high register into a reference
+                       ((GenerateThumbCode and
+                         (getsupreg(taicpu(p).oper[1]^.reg) < RS_R8)) or
+                        (not GenerateThumbCode)) and
+
+                       RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
+                      begin
+                        DebugMsg('Peephole MovStrex2Strex done', hp1);
+                        if (taicpu(hp1).oper[2]^.ref^.addressmode = AM_OFFSET) and
+                           (taicpu(hp1).oper[2]^.ref^.base = taicpu(p).oper[0]^.reg) then
+                          taicpu(hp1).oper[2]^.ref^.base := taicpu(p).oper[1]^.reg;
+
+                        if taicpu(hp1).oper[2]^.ref^.index = taicpu(p).oper[0]^.reg then
+                          taicpu(hp1).oper[2]^.ref^.index := taicpu(p).oper[1]^.reg;
+
+                        dealloc:=FindRegDeAlloc(taicpu(p).oper[1]^.reg, taicpu(p.Next));
+                        if Assigned(dealloc) then
+                          begin
+                            asml.remove(dealloc);
+                            asml.InsertAfter(dealloc,hp1);
+                          end;
+
+                        GetNextInstruction(p, hp1);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp1;
+                        result:=true;
+                      end;
 
 
                     { This folds shifterops into following instructions
                     { This folds shifterops into following instructions
                       mov r0, r1, lsl #8
                       mov r0, r1, lsl #8

+ 2 - 2
compiler/arm/cgcpu.pas

@@ -4126,8 +4126,8 @@ unit cgcpu;
         { currently, we save R14 always, so we can use it }
         { currently, we save R14 always, so we can use it }
         if (target_info.system<>system_arm_darwin) then
         if (target_info.system<>system_arm_darwin) then
           rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
           rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
-              [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
-               RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[])
+              [RS_R0,RS_R1,RS_R2,RS_R3,RS_R12,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+               RS_R9,RS_R10,RS_R14],first_int_imreg,[])
         else
         else
           { r9 is not available on Darwin according to the llvm code generator }
           { r9 is not available on Darwin according to the llvm code generator }
           rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
           rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,