< 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 /*
   2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */


  28 import static jdk.vm.ci.code.ValueUtil.asAllocatableValue;
  29 import static jdk.vm.ci.code.ValueUtil.asRegister;
  30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
  31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
  32 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  33 
  34 import java.util.function.Function;
  35 
  36 import jdk.vm.ci.meta.AllocatableValue;
  37 import org.graalvm.compiler.asm.Label;
  38 import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
  39 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
  40 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType;
  41 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
  42 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  43 import org.graalvm.compiler.core.common.LIRKind;
  44 import org.graalvm.compiler.core.common.NumUtil;
  45 import org.graalvm.compiler.core.common.calc.Condition;
  46 import org.graalvm.compiler.debug.GraalError;
  47 import org.graalvm.compiler.lir.ConstantValue;

  48 import org.graalvm.compiler.lir.LIRInstructionClass;
  49 import org.graalvm.compiler.lir.LabelRef;
  50 import org.graalvm.compiler.lir.Opcode;
  51 import org.graalvm.compiler.lir.StandardOp;
  52 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
  53 import org.graalvm.compiler.lir.SwitchStrategy;
  54 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
  55 import org.graalvm.compiler.lir.Variable;
  56 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  57 
  58 import jdk.vm.ci.aarch64.AArch64Kind;
  59 import jdk.vm.ci.code.Register;
  60 import jdk.vm.ci.meta.Constant;
  61 import jdk.vm.ci.meta.JavaConstant;
  62 import jdk.vm.ci.meta.Value;
  63 
  64 public class AArch64ControlFlow {
  65     public static final class ReturnOp extends AArch64BlockEndOp implements BlockEndOp {
  66         public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
  67         @Use({REG, ILLEGAL}) protected Value x;


 131             masm.branchConditionally(finalCond, target.label());
 132         }
 133     }
 134 
 135     public static class CompareBranchZeroOp extends AbstractBranchOp implements StandardOp.BranchOp {
 136         public static final LIRInstructionClass<CompareBranchZeroOp> TYPE = LIRInstructionClass.create(CompareBranchZeroOp.class);
 137 
 138         @Use(REG) private AllocatableValue value;
 139 
 140         public CompareBranchZeroOp(AllocatableValue value, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
 141             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 142             this.value = value;
 143         }
 144 
 145         @Override
 146         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 147             AArch64Kind kind = (AArch64Kind) this.value.getPlatformKind();
 148             assert kind.isInteger();
 149             int size = kind.getSizeInBytes() * Byte.SIZE;
 150 
 151             if (negate) {
 152                 masm.cbnz(size, asRegister(this.value), target.label());










 153             } else {
 154                 masm.cbz(size, asRegister(this.value), target.label());





 155             }
 156         }
 157     }
 158 
 159     public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
 160         public static final LIRInstructionClass<BitTestAndBranchOp> TYPE = LIRInstructionClass.create(BitTestAndBranchOp.class);
 161 
 162         @Use protected AllocatableValue value;
 163         private final int index;
 164 
 165         public BitTestAndBranchOp(LabelRef trueDestination, LabelRef falseDestination, AllocatableValue value, double trueDestinationProbability, int index) {
 166             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 167             this.value = value;
 168             this.index = index;
 169         }
 170 
 171         @Override
 172         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 173             ConditionFlag cond = negate ? ConditionFlag.NE : ConditionFlag.EQ;
 174             Label label = target.label();
 175             boolean isFarBranch;
 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 
 190             if (isFarBranch) {
 191                 cond = cond.negate();
 192                 label = new Label();
 193             }
 194 
 195             if (cond == ConditionFlag.EQ) {
 196                 masm.tbz(asRegister(value), index, label);
 197             } else {
 198                 masm.tbnz(asRegister(value), index, label);
 199             }
 200 
 201             if (isFarBranch) {
 202                 masm.jmp(target.label());
 203                 masm.bind(label);
 204             }
 205         }
 206     }
 207 
 208     @Opcode("CMOVE")


 375             // emit jump table entries
 376             for (LabelRef target : targets) {
 377                 masm.jmp(target.label());
 378             }
 379             JumpTable jt = new JumpTable(jumpTable.position(), lowKey, highKey - 1, 4);
 380             crb.compilationResult.addAnnotation(jt);
 381         }
 382     }
 383 
 384     private static void emitCompare(CompilationResultBuilder crb, AArch64MacroAssembler masm, Value key, Value scratchValue, ConstantValue c) {
 385         long imm = c.getJavaConstant().asLong();
 386         final int size = key.getPlatformKind().getSizeInBytes() * Byte.SIZE;
 387         if (AArch64MacroAssembler.isComparisonImmediate(imm)) {
 388             masm.cmp(size, asRegister(key), (int) imm);
 389         } else {
 390             AArch64Move.move(crb, masm, asAllocatableValue(scratchValue), c);
 391             masm.cmp(size, asRegister(key), asRegister(scratchValue));
 392         }
 393     }
 394 
















 395 }
   1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */


  28 import static jdk.vm.ci.code.ValueUtil.asAllocatableValue;
  29 import static jdk.vm.ci.code.ValueUtil.asRegister;
  30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
  31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
  32 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  33 
  34 import java.util.function.Function;
  35 
  36 import jdk.vm.ci.meta.AllocatableValue;
  37 import org.graalvm.compiler.asm.Label;
  38 import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
  39 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
  40 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType;
  41 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
  42 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  43 import org.graalvm.compiler.core.common.LIRKind;
  44 import org.graalvm.compiler.core.common.NumUtil;
  45 import org.graalvm.compiler.core.common.calc.Condition;
  46 import org.graalvm.compiler.debug.GraalError;
  47 import org.graalvm.compiler.lir.ConstantValue;
  48 import org.graalvm.compiler.lir.LIRInstruction;
  49 import org.graalvm.compiler.lir.LIRInstructionClass;
  50 import org.graalvm.compiler.lir.LabelRef;
  51 import org.graalvm.compiler.lir.Opcode;
  52 import org.graalvm.compiler.lir.StandardOp;
  53 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
  54 import org.graalvm.compiler.lir.SwitchStrategy;
  55 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
  56 import org.graalvm.compiler.lir.Variable;
  57 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  58 
  59 import jdk.vm.ci.aarch64.AArch64Kind;
  60 import jdk.vm.ci.code.Register;
  61 import jdk.vm.ci.meta.Constant;
  62 import jdk.vm.ci.meta.JavaConstant;
  63 import jdk.vm.ci.meta.Value;
  64 
  65 public class AArch64ControlFlow {
  66     public static final class ReturnOp extends AArch64BlockEndOp implements BlockEndOp {
  67         public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
  68         @Use({REG, ILLEGAL}) protected Value x;


 132             masm.branchConditionally(finalCond, target.label());
 133         }
 134     }
 135 
 136     public static class CompareBranchZeroOp extends AbstractBranchOp implements StandardOp.BranchOp {
 137         public static final LIRInstructionClass<CompareBranchZeroOp> TYPE = LIRInstructionClass.create(CompareBranchZeroOp.class);
 138 
 139         @Use(REG) private AllocatableValue value;
 140 
 141         public CompareBranchZeroOp(AllocatableValue value, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
 142             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 143             this.value = value;
 144         }
 145 
 146         @Override
 147         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 148             AArch64Kind kind = (AArch64Kind) this.value.getPlatformKind();
 149             assert kind.isInteger();
 150             int size = kind.getSizeInBytes() * Byte.SIZE;
 151 
 152             Label label = target.label();
 153             boolean isFarBranch = isFarBranch(this, 21, crb, masm, label);
 154             boolean useCbnz;
 155             if (isFarBranch) {
 156                 useCbnz = !negate;
 157                 label = new Label();
 158             } else {
 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);
 171             }
 172         }
 173     }
 174 
 175     public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
 176         public static final LIRInstructionClass<BitTestAndBranchOp> TYPE = LIRInstructionClass.create(BitTestAndBranchOp.class);
 177 
 178         @Use protected AllocatableValue value;
 179         private final int index;
 180 
 181         public BitTestAndBranchOp(LabelRef trueDestination, LabelRef falseDestination, AllocatableValue value, double trueDestinationProbability, int index) {
 182             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 183             this.value = value;
 184             this.index = index;
 185         }
 186 
 187         @Override
 188         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 189             ConditionFlag cond = negate ? ConditionFlag.NE : ConditionFlag.EQ;
 190             Label label = target.label();
 191             boolean isFarBranch = isFarBranch(this, 14, crb, masm, label);













 192 
 193             if (isFarBranch) {
 194                 cond = cond.negate();
 195                 label = new Label();
 196             }
 197 
 198             if (cond == ConditionFlag.EQ) {
 199                 masm.tbz(asRegister(value), index, label);
 200             } else {
 201                 masm.tbnz(asRegister(value), index, label);
 202             }
 203 
 204             if (isFarBranch) {
 205                 masm.jmp(target.label());
 206                 masm.bind(label);
 207             }
 208         }
 209     }
 210 
 211     @Opcode("CMOVE")


 378             // emit jump table entries
 379             for (LabelRef target : targets) {
 380                 masm.jmp(target.label());
 381             }
 382             JumpTable jt = new JumpTable(jumpTable.position(), lowKey, highKey - 1, 4);
 383             crb.compilationResult.addAnnotation(jt);
 384         }
 385     }
 386 
 387     private static void emitCompare(CompilationResultBuilder crb, AArch64MacroAssembler masm, Value key, Value scratchValue, ConstantValue c) {
 388         long imm = c.getJavaConstant().asLong();
 389         final int size = key.getPlatformKind().getSizeInBytes() * Byte.SIZE;
 390         if (AArch64MacroAssembler.isComparisonImmediate(imm)) {
 391             masm.cmp(size, asRegister(key), (int) imm);
 392         } else {
 393             AArch64Move.move(crb, masm, asAllocatableValue(scratchValue), c);
 394             masm.cmp(size, asRegister(key), asRegister(scratchValue));
 395         }
 396     }
 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     }
 414 }
< prev index next >