src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java
equal
deleted
inserted
replaced
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 } |