# HG changeset patch # User Stefan Anzinger # Date 1436192876 -7200 # Node ID 5ac2e4dab379f14ec5b3d3e9b0548eabb6417bca # Parent bcb742860dd77b486398e517ada6d25f84b74e77 [SPARC] Optimize StrategySwitchOp diff -r bcb742860dd7 -r 5ac2e4dab379 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jul 06 16:27:01 2015 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jul 06 16:27:56 2015 +0200 @@ -31,6 +31,7 @@ import static com.oracle.graal.lir.sparc.SPARCMove.*; import static jdk.internal.jvmci.code.ValueUtil.*; import static jdk.internal.jvmci.sparc.SPARC.*; +import static jdk.internal.jvmci.sparc.SPARC.CPUFeature.*; import java.util.*; @@ -54,6 +55,9 @@ import com.oracle.graal.lir.asm.*; public class SPARCControlFlow { + // This describes the maximum offset between the first emitted (load constant in to scratch, + // if does not fit into simm5 of cbcond) instruction and the final branch instruction + private static final int maximumSelfOffsetInstructions = 2; public static final class ReturnOp extends SPARCLIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ReturnOp.class); @@ -96,9 +100,6 @@ private boolean emitted = false; private int delaySlotPosition = -1; private double trueDestinationProbability; - // This describes the maximum offset between the first emitted (load constant in to scratch, - // if does not fit into simm5 of cbcond) instruction and the final branch instruction - private static int maximumSelfOffsetInstructions = 2; public CompareBranchOp(SPARCCompare opcode, Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind, boolean unorderedIsTrue, double trueDestinationProbability) { @@ -295,26 +296,6 @@ return hasShortJumpTarget; } - private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) { - int disp = 0; - if (label.isBound()) { - disp = label.position() - position; - } else if (hint != null && hint.isValid()) { - disp = hint.getTarget() - hint.getPosition(); - } - if (disp != 0) { - if (disp < 0) { - disp -= maximumSelfOffsetInstructions * asm.target.wordSize; - } else { - disp += maximumSelfOffsetInstructions * asm.target.wordSize; - } - return isSimm10(disp >> 2); - } else if (hint == null) { - asm.requestLabelHint(label); - } - return false; - } - public void resetState() { emitted = false; delaySlotPosition = -1; @@ -328,6 +309,26 @@ } } + private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) { + int disp = 0; + if (label.isBound()) { + disp = label.position() - position; + } else if (hint != null && hint.isValid()) { + disp = hint.getTarget() - hint.getPosition(); + } + if (disp != 0) { + if (disp < 0) { + disp -= maximumSelfOffsetInstructions * asm.target.wordSize; + } else { + disp += maximumSelfOffsetInstructions * asm.target.wordSize; + } + return isSimm10(disp >> 2); + } else if (hint == null) { + asm.requestLabelHint(label); + } + return false; + } + public static final class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BranchOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(2); @@ -402,6 +403,7 @@ @Alive({REG, ILLEGAL}) protected Value constantTableBase; @Temp({REG}) protected Value scratch; private final SwitchStrategy strategy; + private final LabelHint[] labelHints; public StrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { super(TYPE); @@ -412,6 +414,7 @@ this.constantTableBase = constantTableBase; this.key = key; this.scratch = scratch; + this.labelHints = new LabelHint[keyTargets.length]; assert keyConstants.length == keyTargets.length; assert keyConstants.length == strategy.keyProbabilities.length; } @@ -423,39 +426,70 @@ BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) { @Override protected void conditionalJump(int index, Condition condition, Label target) { - const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY); + requestHint(masm, index); + JavaConstant constant = keyConstants[index]; CC conditionCode; - Register scratchRegister; + Long bits; switch (key.getKind()) { case Char: case Byte: case Short: case Int: conditionCode = CC.Icc; - scratchRegister = asIntReg(scratch); + bits = constant.asLong(); break; case Long: { conditionCode = CC.Xcc; - scratchRegister = asLongReg(scratch); + bits = constant.asLong(); break; } case Object: { conditionCode = crb.codeCache.getTarget().wordKind == Kind.Long ? CC.Xcc : CC.Icc; - scratchRegister = asObjectReg(scratch); + bits = constant.isDefaultForKind() ? 0L : null; break; } default: throw new JVMCIError("switch only supported for int, long and object"); } ConditionFlag conditionFlag = fromCondition(conditionCode, condition, false); - masm.cmp(keyRegister, scratchRegister); - masm.bpcc(conditionFlag, NOT_ANNUL, target, conditionCode, PREDICT_TAKEN); - masm.nop(); // delay slot + LabelHint hint = labelHints[index]; + boolean canUseShortBranch = masm.hasFeature(CBCOND) && hint.isValid() && isShortBranch(masm, masm.position(), hint, target); + if (bits != null && canUseShortBranch) { + if (isSimm5(constant)) { + if (conditionCode == Icc) { + masm.cbcondw(conditionFlag, keyRegister, (int) (long) bits, target); + } else { + masm.cbcondx(conditionFlag, keyRegister, (int) (long) bits, target); + } + } else { + Register scratchRegister = asRegister(scratch); + const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY); + if (conditionCode == Icc) { + masm.cbcondw(conditionFlag, keyRegister, scratchRegister, target); + } else { + masm.cbcondx(conditionFlag, keyRegister, scratchRegister, target); + } + } + } else { + if (bits != null && isSimm13(constant)) { + masm.cmp(keyRegister, (int) (long) bits); // Cast is safe + } else { + Register scratchRegister = asRegister(scratch); + const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY); + masm.cmp(keyRegister, scratchRegister); + } + masm.bpcc(conditionFlag, ANNUL, target, conditionCode, PREDICT_TAKEN); + masm.nop(); // delay slot + } } }; strategy.run(closure); } + private void requestHint(SPARCMacroAssembler masm, int index) { + labelHints[index] = masm.requestLabelHint(keyTargets[index].label()); + } + @Override public SizeEstimate estimateSize() { int constantBytes = 0;