changeset 22155:5ac2e4dab379

[SPARC] Optimize StrategySwitchOp
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Mon, 06 Jul 2015 16:27:56 +0200
parents bcb742860dd7
children 627188a01c4a
files graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java
diffstat 1 files changed, 65 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- 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<ReturnOp> 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<BranchOp> 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;