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 }
|