Browse Source

* support for AArch64 branch forwarding
o don't forward cb(n)z, as we don't check the maxiumum offsets
o don't forward conditional branches to global labels, as they also have a
limited range and at least the OS X toolchain doesn't support this

git-svn-id: trunk@29929 -

Jonas Maebe 10 years ago
parent
commit
620af1732a
1 changed files with 19 additions and 5 deletions
  1. 19 5
      compiler/aoptobj.pas

+ 19 - 5
compiler/aoptobj.pas

@@ -361,7 +361,7 @@ Unit AoptObj;
 
 
     function JumpTargetOp(ai: taicpu): poper; inline;
     function JumpTargetOp(ai: taicpu): poper; inline;
       begin
       begin
-{$ifdef MIPS}
+{$if defined(MIPS)}
         { MIPS branches can have 1,2 or 3 operands, target label is the last one. }
         { MIPS branches can have 1,2 or 3 operands, target label is the last one. }
         result:=ai.oper[ai.ops-1];
         result:=ai.oper[ai.ops-1];
 {$else MIPS}
 {$else MIPS}
@@ -1179,9 +1179,9 @@ Unit AoptObj;
     function IsJumpToLabel(hp: taicpu): boolean;
     function IsJumpToLabel(hp: taicpu): boolean;
       begin
       begin
         result:=(hp.opcode=aopt_uncondjmp) and
         result:=(hp.opcode=aopt_uncondjmp) and
-{$ifdef arm}
+{$if defined(arm) or defined(aarch64)}
           (hp.condition=c_None) and
           (hp.condition=c_None) and
-{$endif arm}
+{$endif arm or aarch64}
           (JumpTargetOp(hp)^.typ = top_ref) and
           (JumpTargetOp(hp)^.typ = top_ref) and
           (JumpTargetOp(hp)^.ref^.symbol is TAsmLabel);
           (JumpTargetOp(hp)^.ref^.symbol is TAsmLabel);
       end;
       end;
@@ -1260,6 +1260,14 @@ Unit AoptObj;
                     exit;
                     exit;
                   if not GetFinalDestination(taicpu(p1),succ(level)) then
                   if not GetFinalDestination(taicpu(p1),succ(level)) then
                     exit;
                     exit;
+{$if defined(aarch64)}
+                  { can't have conditional branches to
+                    global labels on AArch64, because the
+                    offset may become too big }
+                  if not(taicpu(hp).condition in [C_None,C_AL,C_NV]) and
+                     (tasmlabel(JumpTargetOp(taicpu(p1))^.ref^.symbol).bind<>AB_LOCAL) then
+                    exit;
+{$endif aarch64}
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
                   JumpTargetOp(hp)^.ref^.symbol:=JumpTargetOp(taicpu(p1))^.ref^.symbol;
                   JumpTargetOp(hp)^.ref^.symbol:=JumpTargetOp(taicpu(p1))^.ref^.symbol;
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).increfs;
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).increfs;
@@ -1398,9 +1406,15 @@ Unit AoptObj;
                                     FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.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}
+  {$if defined(arm) or defined(aarch64)}
                                       and (taicpu(p).condition<>C_None)
                                       and (taicpu(p).condition<>C_None)
-  {$endif arm}
+  {$endif arm or aarch64}
+  {$if defined(aarch64)}
+                                      { can't have conditional branches to
+                                        global labels on AArch64, because the
+                                        offset may become too big }
+                                      and (tasmlabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).bind=AB_LOCAL)
+  {$endif aarch64}
                                     then
                                     then
                                       begin
                                       begin
                                         taicpu(p).condition:=inverse_cond(taicpu(p).condition);
                                         taicpu(p).condition:=inverse_cond(taicpu(p).condition);