src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java
changeset 58299 6df94ce3ab2f
parent 54601 c40b2a190173
equal deleted inserted replaced
58298:0152ad7b38b8 58299:6df94ce3ab2f
     1 /*
     1 /*
     2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    43 import org.graalvm.compiler.core.common.LIRKind;
    43 import org.graalvm.compiler.core.common.LIRKind;
    44 import org.graalvm.compiler.core.common.NumUtil;
    44 import org.graalvm.compiler.core.common.NumUtil;
    45 import org.graalvm.compiler.core.common.calc.Condition;
    45 import org.graalvm.compiler.core.common.calc.Condition;
    46 import org.graalvm.compiler.debug.GraalError;
    46 import org.graalvm.compiler.debug.GraalError;
    47 import org.graalvm.compiler.lir.ConstantValue;
    47 import org.graalvm.compiler.lir.ConstantValue;
       
    48 import org.graalvm.compiler.lir.LIRInstruction;
    48 import org.graalvm.compiler.lir.LIRInstructionClass;
    49 import org.graalvm.compiler.lir.LIRInstructionClass;
    49 import org.graalvm.compiler.lir.LabelRef;
    50 import org.graalvm.compiler.lir.LabelRef;
    50 import org.graalvm.compiler.lir.Opcode;
    51 import org.graalvm.compiler.lir.Opcode;
    51 import org.graalvm.compiler.lir.StandardOp;
    52 import org.graalvm.compiler.lir.StandardOp;
    52 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
    53 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
   146         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
   147         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
   147             AArch64Kind kind = (AArch64Kind) this.value.getPlatformKind();
   148             AArch64Kind kind = (AArch64Kind) this.value.getPlatformKind();
   148             assert kind.isInteger();
   149             assert kind.isInteger();
   149             int size = kind.getSizeInBytes() * Byte.SIZE;
   150             int size = kind.getSizeInBytes() * Byte.SIZE;
   150 
   151 
   151             if (negate) {
   152             Label label = target.label();
   152                 masm.cbnz(size, asRegister(this.value), target.label());
   153             boolean isFarBranch = isFarBranch(this, 21, crb, masm, label);
       
   154             boolean useCbnz;
       
   155             if (isFarBranch) {
       
   156                 useCbnz = !negate;
       
   157                 label = new Label();
   153             } else {
   158             } else {
   154                 masm.cbz(size, asRegister(this.value), target.label());
   159                 useCbnz = negate;
       
   160             }
       
   161 
       
   162             if (useCbnz) {
       
   163                 masm.cbnz(size, asRegister(this.value), label);
       
   164             } else {
       
   165                 masm.cbz(size, asRegister(this.value), label);
       
   166             }
       
   167 
       
   168             if (isFarBranch) {
       
   169                 masm.jmp(target.label());
       
   170                 masm.bind(label);
   155             }
   171             }
   156         }
   172         }
   157     }
   173     }
   158 
   174 
   159     public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
   175     public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
   170 
   186 
   171         @Override
   187         @Override
   172         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
   188         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
   173             ConditionFlag cond = negate ? ConditionFlag.NE : ConditionFlag.EQ;
   189             ConditionFlag cond = negate ? ConditionFlag.NE : ConditionFlag.EQ;
   174             Label label = target.label();
   190             Label label = target.label();
   175             boolean isFarBranch;
   191             boolean isFarBranch = isFarBranch(this, 14, crb, masm, label);
   176 
       
   177             if (label.isBound()) {
       
   178                 // The label.position() is a byte based index. The TBZ instruction has 14 bits for
       
   179                 // the offset and AArch64 instruction is 4 bytes aligned. So TBZ can encode 16 bits
       
   180                 // signed offset.
       
   181                 isFarBranch = !NumUtil.isSignedNbit(16, masm.position() - label.position());
       
   182             } else {
       
   183                 // Max range of tbz is +-2^13 instructions. We estimate that each LIR instruction
       
   184                 // emits 2 AArch64 instructions on average. Thus we test for maximum 2^12 LIR
       
   185                 // instruction offset.
       
   186                 int maxLIRDistance = (1 << 12);
       
   187                 isFarBranch = !crb.labelWithinRange(this, label, maxLIRDistance);
       
   188             }
       
   189 
   192 
   190             if (isFarBranch) {
   193             if (isFarBranch) {
   191                 cond = cond.negate();
   194                 cond = cond.negate();
   192                 label = new Label();
   195                 label = new Label();
   193             }
   196             }
   390             AArch64Move.move(crb, masm, asAllocatableValue(scratchValue), c);
   393             AArch64Move.move(crb, masm, asAllocatableValue(scratchValue), c);
   391             masm.cmp(size, asRegister(key), asRegister(scratchValue));
   394             masm.cmp(size, asRegister(key), asRegister(scratchValue));
   392         }
   395         }
   393     }
   396     }
   394 
   397 
       
   398     private static boolean isFarBranch(LIRInstruction instruction, int offsetBits, CompilationResultBuilder crb, AArch64MacroAssembler masm, Label label) {
       
   399         boolean isFarBranch;
       
   400         if (label.isBound()) {
       
   401             // The label.position() is a byte based index. The instruction instruction has
       
   402             // offsetBits bits for the offset and AArch64 instruction is 4 bytes aligned. So
       
   403             // instruction can encode offsetBits+2 bits signed offset.
       
   404             isFarBranch = !NumUtil.isSignedNbit(offsetBits + 2, masm.position() - label.position());
       
   405         } else {
       
   406             // Max range of instruction is 2^offsetBits instructions. We estimate that each LIR
       
   407             // instruction emits 2 AArch64 instructions on average. Thus we test for maximum
       
   408             // 2^(offsetBits-2) LIR instruction offset.
       
   409             int maxLIRDistance = (1 << (offsetBits - 2));
       
   410             isFarBranch = !crb.labelWithinRange(instruction, label, maxLIRDistance);
       
   411         }
       
   412         return isFarBranch;
       
   413     }
   395 }
   414 }