< 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




  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  */
  23 
  24 
  25 package org.graalvm.compiler.lir.aarch64;
  26 
  27 import static jdk.vm.ci.code.ValueUtil.asAllocatableValue;
  28 import static jdk.vm.ci.code.ValueUtil.asRegister;
  29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
  30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  31 
  32 import java.util.function.Function;
  33 

  34 import org.graalvm.compiler.asm.Label;
  35 import org.graalvm.compiler.core.common.NumUtil;
  36 import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
  37 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
  38 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType;
  39 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
  40 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  41 import org.graalvm.compiler.core.common.LIRKind;
  42 import org.graalvm.compiler.core.common.calc.Condition;
  43 import org.graalvm.compiler.debug.GraalError;
  44 import org.graalvm.compiler.lir.ConstantValue;
  45 import org.graalvm.compiler.lir.LIRInstructionClass;
  46 import org.graalvm.compiler.lir.LabelRef;
  47 import org.graalvm.compiler.lir.Opcode;
  48 import org.graalvm.compiler.lir.StandardOp;
  49 import org.graalvm.compiler.lir.SwitchStrategy;
  50 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
  51 import org.graalvm.compiler.lir.Variable;
  52 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  53 
  54 import jdk.vm.ci.aarch64.AArch64Kind;
  55 import jdk.vm.ci.code.Register;
  56 import jdk.vm.ci.meta.Constant;
  57 import jdk.vm.ci.meta.JavaConstant;
  58 import jdk.vm.ci.meta.Value;
  59 
  60 public class AArch64ControlFlow {
  61 
  62     /**
  63      * Compares integer register to 0 and branches if condition is true. Condition may only be equal
  64      * or non-equal.
  65      */
  66     // TODO (das) where do we need this?
  67     // public static class CompareAndBranchOp extends AArch64LIRInstruction implements
  68     // StandardOp.BranchOp {
  69     // private final ConditionFlag condition;
  70     // private final LabelRef destination;
  71     // @Use({REG}) private Value x;
  72     //
  73     // public CompareAndBranchOp(Condition condition, LabelRef destination, Value x) {
  74     // assert condition == Condition.EQ || condition == Condition.NE;
  75     // assert ARMv8.isGpKind(x.getKind());
  76     // this.condition = condition == Condition.EQ ? ConditionFlag.EQ : ConditionFlag.NE;
  77     // this.destination = destination;
  78     // this.x = x;
  79     // }
  80     //
  81     // @Override
  82     // public void emitCode(CompilationResultBuilder crb, ARMv8MacroAssembler masm) {
  83     // int size = ARMv8.bitsize(x.getKind());
  84     // if (condition == ConditionFlag.EQ) {
  85     // masm.cbz(size, asRegister(x), destination.label());
  86     // } else {
  87     // masm.cbnz(size, asRegister(x), destination.label());
  88     // }
  89     // }
  90     // }
  91 
  92     public static class BranchOp extends AArch64BlockEndOp implements StandardOp.BranchOp {
  93         public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class);
  94 
  95         private final AArch64Assembler.ConditionFlag condition;
  96         private final LabelRef trueDestination;
  97         private final LabelRef falseDestination;
  98 
  99         private final double trueDestinationProbability;
 100 
 101         public BranchOp(AArch64Assembler.ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
 102             super(TYPE);
 103             this.condition = condition;
 104             this.trueDestination = trueDestination;
 105             this.falseDestination = falseDestination;
 106             this.trueDestinationProbability = trueDestinationProbability;
 107         }
 108 


 109         @Override
 110         public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
 111             /*
 112              * Explanation: Depending on what the successor edge is, we can use the fall-through to
 113              * optimize the generated code. If neither is a successor edge, use the branch
 114              * probability to try to take the conditional jump as often as possible to avoid
 115              * executing two instructions instead of one.
 116              */
 117             if (crb.isSuccessorEdge(trueDestination)) {
 118                 masm.branchConditionally(condition.negate(), falseDestination.label());
 119             } else if (crb.isSuccessorEdge(falseDestination)) {
 120                 masm.branchConditionally(condition, trueDestination.label());
 121             } else if (trueDestinationProbability < 0.5) {
 122                 masm.branchConditionally(condition.negate(), falseDestination.label());
 123                 masm.jmp(trueDestination.label());
 124             } else {
 125                 masm.branchConditionally(condition, trueDestination.label());
 126                 masm.jmp(falseDestination.label());
 127             }
 128         }











































































 129 











 130     }
 131 
 132     @Opcode("CMOVE")
 133     public static class CondMoveOp extends AArch64LIRInstruction {
 134         public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
 135 
 136         @Def protected Value result;
 137         @Use protected Value trueValue;
 138         @Use protected Value falseValue;
 139         private final AArch64Assembler.ConditionFlag condition;
 140 
 141         public CondMoveOp(Variable result, AArch64Assembler.ConditionFlag condition, Value trueValue, Value falseValue) {
 142             super(TYPE);
 143             assert trueValue.getPlatformKind() == falseValue.getPlatformKind() && trueValue.getPlatformKind() == result.getPlatformKind();
 144             this.result = result;
 145             this.condition = condition;
 146             this.trueValue = trueValue;
 147             this.falseValue = falseValue;
 148         }
 149 




  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  */
  23 
  24 
  25 package org.graalvm.compiler.lir.aarch64;
  26 
  27 import static jdk.vm.ci.code.ValueUtil.asAllocatableValue;
  28 import static jdk.vm.ci.code.ValueUtil.asRegister;
  29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
  30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  31 
  32 import java.util.function.Function;
  33 
  34 import jdk.vm.ci.meta.AllocatableValue;
  35 import org.graalvm.compiler.asm.Label;
  36 import org.graalvm.compiler.core.common.NumUtil;
  37 import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
  38 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
  39 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType;
  40 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
  41 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  42 import org.graalvm.compiler.core.common.LIRKind;
  43 import org.graalvm.compiler.core.common.calc.Condition;
  44 import org.graalvm.compiler.debug.GraalError;
  45 import org.graalvm.compiler.lir.ConstantValue;
  46 import org.graalvm.compiler.lir.LIRInstructionClass;
  47 import org.graalvm.compiler.lir.LabelRef;
  48 import org.graalvm.compiler.lir.Opcode;
  49 import org.graalvm.compiler.lir.StandardOp;
  50 import org.graalvm.compiler.lir.SwitchStrategy;
  51 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
  52 import org.graalvm.compiler.lir.Variable;
  53 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  54 
  55 import jdk.vm.ci.aarch64.AArch64Kind;
  56 import jdk.vm.ci.code.Register;
  57 import jdk.vm.ci.meta.Constant;
  58 import jdk.vm.ci.meta.JavaConstant;
  59 import jdk.vm.ci.meta.Value;
  60 
  61 public class AArch64ControlFlow {
  62 
  63     public abstract static class AbstractBranchOp extends AArch64BlockEndOp implements StandardOp.BranchOp {

































  64         private final LabelRef trueDestination;
  65         private final LabelRef falseDestination;
  66 
  67         private final double trueDestinationProbability;
  68 
  69         private AbstractBranchOp(LIRInstructionClass<? extends AbstractBranchOp> c, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
  70             super(c);

  71             this.trueDestination = trueDestination;
  72             this.falseDestination = falseDestination;
  73             this.trueDestinationProbability = trueDestinationProbability;
  74         }
  75 
  76         protected abstract void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate);
  77 
  78         @Override
  79         public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
  80             /*
  81              * Explanation: Depending on what the successor edge is, we can use the fall-through to
  82              * optimize the generated code. If neither is a successor edge, use the branch
  83              * probability to try to take the conditional jump as often as possible to avoid
  84              * executing two instructions instead of one.
  85              */
  86             if (crb.isSuccessorEdge(trueDestination)) {
  87                 emitBranch(crb, masm, falseDestination, true);
  88             } else if (crb.isSuccessorEdge(falseDestination)) {
  89                 emitBranch(crb, masm, trueDestination, false);
  90             } else if (trueDestinationProbability < 0.5) {
  91                 emitBranch(crb, masm, falseDestination, true);
  92                 masm.jmp(trueDestination.label());
  93             } else {
  94                 emitBranch(crb, masm, trueDestination, false);
  95                 masm.jmp(falseDestination.label());
  96             }
  97         }
  98     }
  99 
 100     public static class BranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
 101         public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class);
 102 
 103         private final AArch64Assembler.ConditionFlag condition;
 104 
 105         public BranchOp(AArch64Assembler.ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
 106             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 107             this.condition = condition;
 108         }
 109 
 110         @Override
 111         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 112             AArch64Assembler.ConditionFlag finalCond = negate ? condition.negate() : condition;
 113             masm.branchConditionally(finalCond, target.label());
 114         }
 115     }
 116 
 117     public static class CompareBranchZeroOp extends AbstractBranchOp implements StandardOp.BranchOp {
 118         public static final LIRInstructionClass<CompareBranchZeroOp> TYPE = LIRInstructionClass.create(CompareBranchZeroOp.class);
 119 
 120         @Use(REG) private AllocatableValue value;
 121 
 122         public CompareBranchZeroOp(AllocatableValue value, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
 123             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 124             this.value = value;
 125         }
 126 
 127         @Override
 128         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 129             AArch64Kind kind = (AArch64Kind) this.value.getPlatformKind();
 130             assert kind.isInteger();
 131             int size = kind.getSizeInBytes() * Byte.SIZE;
 132 
 133             if (negate) {
 134                 masm.cbnz(size, asRegister(this.value), target.label());
 135             } else {
 136                 masm.cbz(size, asRegister(this.value), target.label());
 137             }
 138         }
 139     }
 140 
 141     public static class BitTestAndBranchOp extends AbstractBranchOp implements StandardOp.BranchOp {
 142         public static final LIRInstructionClass<BitTestAndBranchOp> TYPE = LIRInstructionClass.create(BitTestAndBranchOp.class);
 143 
 144         @Use protected AllocatableValue value;
 145         private final int index;
 146 
 147         public BitTestAndBranchOp(LabelRef trueDestination, LabelRef falseDestination, AllocatableValue value, double trueDestinationProbability, int index) {
 148             super(TYPE, trueDestination, falseDestination, trueDestinationProbability);
 149             this.value = value;
 150             this.index = index;
 151         }
 152 
 153         @Override
 154         protected void emitBranch(CompilationResultBuilder crb, AArch64MacroAssembler masm, LabelRef target, boolean negate) {
 155             ConditionFlag cond = negate ? ConditionFlag.NE : ConditionFlag.EQ;
 156             Label label = target.label();
 157             boolean isFarBranch;
 158 
 159             if (label.isBound()) {
 160                 isFarBranch = NumUtil.isSignedNbit(18, masm.position() - label.position());
 161             } else {
 162                 // Max range of tbz is +-2^13 instructions. We estimate that each LIR instruction
 163                 // emits 2 AArch64 instructions on average. Thus we test for maximum 2^12 LIR
 164                 // instruction offset.
 165                 int maxLIRDistance = (1 << 12);
 166                 isFarBranch = !crb.labelWithinRange(this, label, maxLIRDistance);
 167             }
 168 
 169             if (isFarBranch) {
 170                 cond = cond.negate();
 171                 label = new Label();
 172             }
 173 
 174             if (cond == ConditionFlag.EQ) {
 175                 masm.tbz(asRegister(value), index, label);
 176             } else {
 177                 masm.tbnz(asRegister(value), index, label);
 178             }
 179 
 180             if (isFarBranch) {
 181                 masm.jmp(target.label());
 182                 masm.bind(label);
 183             }
 184         }
 185     }
 186 
 187     @Opcode("CMOVE")
 188     public static class CondMoveOp extends AArch64LIRInstruction {
 189         public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
 190 
 191         @Def protected Value result;
 192         @Use protected Value trueValue;
 193         @Use protected Value falseValue;
 194         private final AArch64Assembler.ConditionFlag condition;
 195 
 196         public CondMoveOp(Variable result, AArch64Assembler.ConditionFlag condition, Value trueValue, Value falseValue) {
 197             super(TYPE);
 198             assert trueValue.getPlatformKind() == falseValue.getPlatformKind() && trueValue.getPlatformKind() == result.getPlatformKind();
 199             this.result = result;
 200             this.condition = condition;
 201             this.trueValue = trueValue;
 202             this.falseValue = falseValue;
 203         }
 204 


< prev index next >