< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java

Print this page
rev 56282 : [mq]: graal

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -43,10 +43,11 @@
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.ConstantValue;
+import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.LabelRef;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.StandardOp;
 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;

@@ -146,14 +147,29 @@
         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
             AArch64Kind kind = (AArch64Kind) this.value.getPlatformKind();
             assert kind.isInteger();
             int size = kind.getSizeInBytes() * Byte.SIZE;
 
-            if (negate) {
-                masm.cbnz(size, asRegister(this.value), target.label());
+            Label label = target.label();
+            boolean isFarBranch = isFarBranch(this, 21, crb, masm, label);
+            boolean useCbnz;
+            if (isFarBranch) {
+                useCbnz = !negate;
+                label = new Label();
+            } else {
+                useCbnz = negate;
+            }
+
+            if (useCbnz) {
+                masm.cbnz(size, asRegister(this.value), label);
             } else {
-                masm.cbz(size, asRegister(this.value), target.label());
+                masm.cbz(size, asRegister(this.value), label);
+            }
+
+            if (isFarBranch) {
+                masm.jmp(target.label());
+                masm.bind(label);
             }
         }
     }
 
     public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {

@@ -170,24 +186,11 @@
 
         @Override
         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
             ConditionFlag cond = negate ? ConditionFlag.NE : ConditionFlag.EQ;
             Label label = target.label();
-            boolean isFarBranch;
-
-            if (label.isBound()) {
-                // The label.position() is a byte based index. The TBZ instruction has 14 bits for
-                // the offset and AArch64 instruction is 4 bytes aligned. So TBZ can encode 16 bits
-                // signed offset.
-                isFarBranch = !NumUtil.isSignedNbit(16, masm.position() - label.position());
-            } else {
-                // Max range of tbz is +-2^13 instructions. We estimate that each LIR instruction
-                // emits 2 AArch64 instructions on average. Thus we test for maximum 2^12 LIR
-                // instruction offset.
-                int maxLIRDistance = (1 << 12);
-                isFarBranch = !crb.labelWithinRange(this, label, maxLIRDistance);
-            }
+            boolean isFarBranch = isFarBranch(this, 14, crb, masm, label);
 
             if (isFarBranch) {
                 cond = cond.negate();
                 label = new Label();
             }

@@ -390,6 +393,22 @@
             AArch64Move.move(crb, masm, asAllocatableValue(scratchValue), c);
             masm.cmp(size, asRegister(key), asRegister(scratchValue));
         }
     }
 
+    private static boolean isFarBranch(LIRInstruction instruction, int offsetBits, CompilationResultBuilder crb, AArch64MacroAssembler masm, Label label) {
+        boolean isFarBranch;
+        if (label.isBound()) {
+            // The label.position() is a byte based index. The instruction instruction has
+            // offsetBits bits for the offset and AArch64 instruction is 4 bytes aligned. So
+            // instruction can encode offsetBits+2 bits signed offset.
+            isFarBranch = !NumUtil.isSignedNbit(offsetBits + 2, masm.position() - label.position());
+        } else {
+            // Max range of instruction is 2^offsetBits instructions. We estimate that each LIR
+            // instruction emits 2 AArch64 instructions on average. Thus we test for maximum
+            // 2^(offsetBits-2) LIR instruction offset.
+            int maxLIRDistance = (1 << (offsetBits - 2));
+            isFarBranch = !crb.labelWithinRange(instruction, label, maxLIRDistance);
+        }
+        return isFarBranch;
+    }
 }
< prev index next >