< 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
*** 29,38 ****
--- 29,39 ----
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import java.util.function.Function;
+ import jdk.vm.ci.meta.AllocatableValue;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType;
*** 57,134 ****
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.Value;
public class AArch64ControlFlow {
! /**
! * Compares integer register to 0 and branches if condition is true. Condition may only be equal
! * or non-equal.
! */
! // TODO (das) where do we need this?
! // public static class CompareAndBranchOp extends AArch64LIRInstruction implements
! // StandardOp.BranchOp {
! // private final ConditionFlag condition;
! // private final LabelRef destination;
! // @Use({REG}) private Value x;
! //
! // public CompareAndBranchOp(Condition condition, LabelRef destination, Value x) {
! // assert condition == Condition.EQ || condition == Condition.NE;
! // assert ARMv8.isGpKind(x.getKind());
! // this.condition = condition == Condition.EQ ? ConditionFlag.EQ : ConditionFlag.NE;
! // this.destination = destination;
! // this.x = x;
! // }
! //
! // @Override
! // public void emitCode(CompilationResultBuilder crb, ARMv8MacroAssembler masm) {
! // int size = ARMv8.bitsize(x.getKind());
! // if (condition == ConditionFlag.EQ) {
! // masm.cbz(size, asRegister(x), destination.label());
! // } else {
! // masm.cbnz(size, asRegister(x), destination.label());
! // }
! // }
! // }
!
! public static class BranchOp extends AArch64BlockEndOp implements StandardOp.BranchOp {
! public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class);
!
! private final AArch64Assembler.ConditionFlag condition;
private final LabelRef trueDestination;
private final LabelRef falseDestination;
private final double trueDestinationProbability;
! public BranchOp(AArch64Assembler.ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
! super(TYPE);
! this.condition = condition;
this.trueDestination = trueDestination;
this.falseDestination = falseDestination;
this.trueDestinationProbability = trueDestinationProbability;
}
@Override
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
/*
* Explanation: Depending on what the successor edge is, we can use the fall-through to
* optimize the generated code. If neither is a successor edge, use the branch
* probability to try to take the conditional jump as often as possible to avoid
* executing two instructions instead of one.
*/
if (crb.isSuccessorEdge(trueDestination)) {
! masm.branchConditionally(condition.negate(), falseDestination.label());
} else if (crb.isSuccessorEdge(falseDestination)) {
! masm.branchConditionally(condition, trueDestination.label());
} else if (trueDestinationProbability < 0.5) {
! masm.branchConditionally(condition.negate(), falseDestination.label());
masm.jmp(trueDestination.label());
} else {
! masm.branchConditionally(condition, trueDestination.label());
masm.jmp(falseDestination.label());
}
}
}
@Opcode("CMOVE")
public static class CondMoveOp extends AArch64LIRInstruction {
public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
--- 58,189 ----
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.Value;
public class AArch64ControlFlow {
! public abstract static class AbstractBranchOp extends AArch64BlockEndOp implements StandardOp.BranchOp {
private final LabelRef trueDestination;
private final LabelRef falseDestination;
private final double trueDestinationProbability;
! private AbstractBranchOp(LIRInstructionClass<? extends AbstractBranchOp> c, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
! super(c);
this.trueDestination = trueDestination;
this.falseDestination = falseDestination;
this.trueDestinationProbability = trueDestinationProbability;
}
+ protected abstract void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate);
+
@Override
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
/*
* Explanation: Depending on what the successor edge is, we can use the fall-through to
* optimize the generated code. If neither is a successor edge, use the branch
* probability to try to take the conditional jump as often as possible to avoid
* executing two instructions instead of one.
*/
if (crb.isSuccessorEdge(trueDestination)) {
! emitBranch(crb, masm, falseDestination, true);
} else if (crb.isSuccessorEdge(falseDestination)) {
! emitBranch(crb, masm, trueDestination, false);
} else if (trueDestinationProbability < 0.5) {
! emitBranch(crb, masm, falseDestination, true);
masm.jmp(trueDestination.label());
} else {
! emitBranch(crb, masm, trueDestination, false);
masm.jmp(falseDestination.label());
}
}
+ }
+
+ public static class BranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
+ public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class);
+
+ private final AArch64Assembler.ConditionFlag condition;
+
+ public BranchOp(AArch64Assembler.ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
+ super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
+ this.condition = condition;
+ }
+
+ @Override
+ protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
+ AArch64Assembler.ConditionFlag finalCond = negate ? condition.negate() : condition;
+ masm.branchConditionally(finalCond, target.label());
+ }
+ }
+
+ public static class CompareBranchZeroOp extends AbstractBranchOp implements StandardOp.BranchOp {
+ public static final LIRInstructionClass<CompareBranchZeroOp> TYPE = LIRInstructionClass.create(CompareBranchZeroOp.class);
+
+ @Use(REG) private AllocatableValue value;
+
+ public CompareBranchZeroOp(AllocatableValue value, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
+ super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
+ this.value = value;
+ }
+ @Override
+ 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());
+ } else {
+ masm.cbz(size, asRegister(this.value), target.label());
+ }
+ }
+ }
+
+ public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
+ public static final LIRInstructionClass<BitTestAndBranchOp> TYPE = LIRInstructionClass.create(BitTestAndBranchOp.class);
+
+ @Use protected AllocatableValue value;
+ private final int index;
+
+ public BitTestAndBranchOp(LabelRef trueDestination, LabelRef falseDestination, AllocatableValue value, double trueDestinationProbability, int index) {
+ super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
+ this.value = value;
+ this.index = index;
+ }
+
+ @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()) {
+ isFarBranch = NumUtil.isSignedNbit(18, 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);
+ }
+
+ if (isFarBranch) {
+ cond = cond.negate();
+ label = new Label();
+ }
+
+ if (cond == ConditionFlag.EQ) {
+ masm.tbz(asRegister(value), index, label);
+ } else {
+ masm.tbnz(asRegister(value), index, label);
+ }
+
+ if (isFarBranch) {
+ masm.jmp(target.label());
+ masm.bind(label);
+ }
+ }
}
@Opcode("CMOVE")
public static class CondMoveOp extends AArch64LIRInstruction {
public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
< prev index next >