1 /*
2 * Copyright (c) 2013, 2016, 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 */
59 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.LessUnsigned;
60 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual;
61 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Subcc;
62 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
63 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
64 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
65 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
66 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
67 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
68 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
69 import static org.graalvm.compiler.lir.sparc.SPARCMove.const2reg;
70 import static org.graalvm.compiler.lir.sparc.SPARCOP3Op.emitOp3;
71 import static jdk.vm.ci.code.ValueUtil.asRegister;
72 import static jdk.vm.ci.sparc.SPARC.CPU;
73 import static jdk.vm.ci.sparc.SPARC.g0;
74 import static jdk.vm.ci.sparc.SPARCKind.WORD;
75 import static jdk.vm.ci.sparc.SPARCKind.XWORD;
76
77 import java.util.ArrayList;
78 import java.util.EnumSet;
79 import java.util.HashMap;
80 import java.util.List;
81 import java.util.Map;
82
83 import org.graalvm.compiler.asm.Assembler;
84 import org.graalvm.compiler.asm.Assembler.LabelHint;
85 import org.graalvm.compiler.asm.Label;
86 import org.graalvm.compiler.asm.NumUtil;
87 import org.graalvm.compiler.asm.sparc.SPARCAssembler;
88 import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict;
89 import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC;
90 import org.graalvm.compiler.asm.sparc.SPARCAssembler.CMOV;
91 import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag;
92 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
93 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
94 import org.graalvm.compiler.core.common.calc.Condition;
95 import org.graalvm.compiler.debug.GraalError;
96 import org.graalvm.compiler.lir.LIRInstructionClass;
97 import org.graalvm.compiler.lir.LabelRef;
98 import org.graalvm.compiler.lir.Opcode;
99 import org.graalvm.compiler.lir.StandardOp;
100 import org.graalvm.compiler.lir.SwitchStrategy;
101 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
102 import org.graalvm.compiler.lir.Variable;
103 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
104
105 import jdk.vm.ci.code.Register;
106 import jdk.vm.ci.meta.AllocatableValue;
107 import jdk.vm.ci.meta.Constant;
108 import jdk.vm.ci.meta.JavaConstant;
109 import jdk.vm.ci.meta.PlatformKind;
110 import jdk.vm.ci.meta.Value;
111 import jdk.vm.ci.sparc.SPARC.CPUFeature;
112 import jdk.vm.ci.sparc.SPARCKind;
113
114 public class SPARCControlFlow {
115 // This describes the maximum offset between the first emitted (load constant in to scratch,
116 // if does not fit into simm5 of cbcond) instruction and the final branch instruction
117 private static final int maximumSelfOffsetInstructions = 2;
118
119 public static final class ReturnOp extends SPARCBlockEndOp {
120 public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
121 public static final SizeEstimate SIZE = SizeEstimate.create(2);
122
123 @Use({REG, ILLEGAL}) protected Value x;
127 this.x = x;
128 }
129
130 @Override
131 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
132 emitCodeHelper(crb, masm);
133 }
134
135 public static void emitCodeHelper(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
136 masm.ret();
137 // On SPARC we always leave the frame (in the delay slot).
138 crb.frameContext.leave(crb);
139 }
140 }
141
142 public static final class CompareBranchOp extends SPARCBlockEndOp implements SPARCDelayedControlTransfer {
143 public static final LIRInstructionClass<CompareBranchOp> TYPE = LIRInstructionClass.create(CompareBranchOp.class);
144 public static final SizeEstimate SIZE = SizeEstimate.create(3);
145 static final EnumSet<SPARCKind> SUPPORTED_KINDS = EnumSet.of(XWORD, WORD);
146
147 @Use({REG}) protected Value x;
148 @Use({REG, CONST}) protected Value y;
149 private ConditionFlag conditionFlag;
150 protected final LabelRef trueDestination;
151 protected LabelHint trueDestinationHint;
152 protected final LabelRef falseDestination;
153 protected LabelHint falseDestinationHint;
154 protected final SPARCKind kind;
155 protected final boolean unorderedIsTrue;
156 private boolean emitted = false;
157 private int delaySlotPosition = -1;
158 private double trueDestinationProbability;
159
160 public CompareBranchOp(Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, double trueDestinationProbability) {
161 super(TYPE, SIZE);
162 this.x = x;
163 this.y = y;
164 this.trueDestination = trueDestination;
165 this.falseDestination = falseDestination;
166 this.kind = kind;
167 this.unorderedIsTrue = unorderedIsTrue;
168 this.trueDestinationProbability = trueDestinationProbability;
169 conditionFlag = fromCondition(kind.isInteger(), condition, unorderedIsTrue);
170 }
171
172 @Override
173 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
174 if (emitted) { // Only if delayed control transfer is used we must check this
175 assert masm.position() - delaySlotPosition == 4 : "Only one instruction can be stuffed into the delay slot";
176 }
177 if (!emitted) {
178 requestHints(masm);
179 int targetPosition = getTargetPosition(masm);
180 if (canUseShortBranch(crb, masm, targetPosition)) {
409 BPCC.emit(masm, cc, actualConditionFlag, NOT_ANNUL, predictTaken, actualTarget);
410 }
411 if (withDelayedNop) {
412 masm.nop(); // delay slot
413 }
414 if (needJump) {
415 masm.jmp(falseDestination.label());
416 }
417 return true;
418 }
419
420 public static class StrategySwitchOp extends SPARCBlockEndOp {
421 public static final LIRInstructionClass<StrategySwitchOp> TYPE = LIRInstructionClass.create(StrategySwitchOp.class);
422 protected Constant[] keyConstants;
423 private final LabelRef[] keyTargets;
424 private LabelRef defaultTarget;
425 @Alive({REG}) protected Value key;
426 @Alive({REG, ILLEGAL}) protected Value constantTableBase;
427 @Temp({REG}) protected Value scratch;
428 protected final SwitchStrategy strategy;
429 private final Map<Label, LabelHint> labelHints;
430 private final List<Label> conditionalLabels = new ArrayList<>();
431
432 public StrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
433 this(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch);
434 }
435
436 protected StrategySwitchOp(LIRInstructionClass<? extends StrategySwitchOp> c, Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key,
437 Value scratch) {
438 super(c);
439 this.strategy = strategy;
440 this.keyConstants = strategy.getKeyConstants();
441 this.keyTargets = keyTargets;
442 this.defaultTarget = defaultTarget;
443 this.constantTableBase = constantTableBase;
444 this.key = key;
445 this.scratch = scratch;
446 this.labelHints = new HashMap<>();
447 assert keyConstants.length == keyTargets.length;
448 assert keyConstants.length == strategy.keyProbabilities.length;
449 }
450
451 @Override
452 public void emitCode(final CompilationResultBuilder crb, final SPARCMacroAssembler masm) {
453 final Register keyRegister = asRegister(key);
454 final Register constantBaseRegister = AllocatableValue.ILLEGAL.equals(constantTableBase) ? g0 : asRegister(constantTableBase);
455 strategy.run(new SwitchClosure(keyRegister, constantBaseRegister, crb, masm));
456 }
457
458 public class SwitchClosure extends BaseSwitchClosure {
459 private int conditionalLabelPointer = 0;
460
461 protected final Register keyRegister;
462 protected final Register constantBaseRegister;
463 protected final CompilationResultBuilder crb;
464 protected final SPARCMacroAssembler masm;
465
466 protected SwitchClosure(Register keyRegister, Register constantBaseRegister, CompilationResultBuilder crb, SPARCMacroAssembler masm) {
|
1 /*
2 * Copyright (c) 2013, 2017, 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 */
59 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.LessUnsigned;
60 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual;
61 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Subcc;
62 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
63 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
64 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
65 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
66 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
67 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
68 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
69 import static org.graalvm.compiler.lir.sparc.SPARCMove.const2reg;
70 import static org.graalvm.compiler.lir.sparc.SPARCOP3Op.emitOp3;
71 import static jdk.vm.ci.code.ValueUtil.asRegister;
72 import static jdk.vm.ci.sparc.SPARC.CPU;
73 import static jdk.vm.ci.sparc.SPARC.g0;
74 import static jdk.vm.ci.sparc.SPARCKind.WORD;
75 import static jdk.vm.ci.sparc.SPARCKind.XWORD;
76
77 import java.util.ArrayList;
78 import java.util.EnumSet;
79 import java.util.List;
80 import org.graalvm.compiler.asm.Assembler;
81 import org.graalvm.compiler.asm.Assembler.LabelHint;
82 import org.graalvm.compiler.asm.Label;
83 import org.graalvm.compiler.core.common.NumUtil;
84 import org.graalvm.compiler.asm.sparc.SPARCAssembler;
85 import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict;
86 import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC;
87 import org.graalvm.compiler.asm.sparc.SPARCAssembler.CMOV;
88 import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag;
89 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
90 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
91 import org.graalvm.compiler.core.common.calc.Condition;
92 import org.graalvm.compiler.debug.GraalError;
93 import org.graalvm.compiler.lir.LIRInstructionClass;
94 import org.graalvm.compiler.lir.LabelRef;
95 import org.graalvm.compiler.lir.Opcode;
96 import org.graalvm.compiler.lir.StandardOp;
97 import org.graalvm.compiler.lir.SwitchStrategy;
98 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
99 import org.graalvm.compiler.lir.Variable;
100 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
101 import org.graalvm.util.Equivalence;
102 import org.graalvm.util.EconomicMap;
103
104 import jdk.vm.ci.code.Register;
105 import jdk.vm.ci.meta.AllocatableValue;
106 import jdk.vm.ci.meta.Constant;
107 import jdk.vm.ci.meta.JavaConstant;
108 import jdk.vm.ci.meta.PlatformKind;
109 import jdk.vm.ci.meta.Value;
110 import jdk.vm.ci.sparc.SPARC.CPUFeature;
111 import jdk.vm.ci.sparc.SPARCKind;
112
113 public class SPARCControlFlow {
114 // This describes the maximum offset between the first emitted (load constant in to scratch,
115 // if does not fit into simm5 of cbcond) instruction and the final branch instruction
116 private static final int maximumSelfOffsetInstructions = 2;
117
118 public static final class ReturnOp extends SPARCBlockEndOp {
119 public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
120 public static final SizeEstimate SIZE = SizeEstimate.create(2);
121
122 @Use({REG, ILLEGAL}) protected Value x;
126 this.x = x;
127 }
128
129 @Override
130 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
131 emitCodeHelper(crb, masm);
132 }
133
134 public static void emitCodeHelper(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
135 masm.ret();
136 // On SPARC we always leave the frame (in the delay slot).
137 crb.frameContext.leave(crb);
138 }
139 }
140
141 public static final class CompareBranchOp extends SPARCBlockEndOp implements SPARCDelayedControlTransfer {
142 public static final LIRInstructionClass<CompareBranchOp> TYPE = LIRInstructionClass.create(CompareBranchOp.class);
143 public static final SizeEstimate SIZE = SizeEstimate.create(3);
144 static final EnumSet<SPARCKind> SUPPORTED_KINDS = EnumSet.of(XWORD, WORD);
145
146 @Use({REG}) protected AllocatableValue x;
147 @Use({REG, CONST}) protected Value y;
148 private ConditionFlag conditionFlag;
149 protected final LabelRef trueDestination;
150 protected LabelHint trueDestinationHint;
151 protected final LabelRef falseDestination;
152 protected LabelHint falseDestinationHint;
153 protected final SPARCKind kind;
154 protected final boolean unorderedIsTrue;
155 private boolean emitted = false;
156 private int delaySlotPosition = -1;
157 private double trueDestinationProbability;
158
159 public CompareBranchOp(AllocatableValue x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue,
160 double trueDestinationProbability) {
161 super(TYPE, SIZE);
162 this.x = x;
163 this.y = y;
164 this.trueDestination = trueDestination;
165 this.falseDestination = falseDestination;
166 this.kind = kind;
167 this.unorderedIsTrue = unorderedIsTrue;
168 this.trueDestinationProbability = trueDestinationProbability;
169 conditionFlag = fromCondition(kind.isInteger(), condition, unorderedIsTrue);
170 }
171
172 @Override
173 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
174 if (emitted) { // Only if delayed control transfer is used we must check this
175 assert masm.position() - delaySlotPosition == 4 : "Only one instruction can be stuffed into the delay slot";
176 }
177 if (!emitted) {
178 requestHints(masm);
179 int targetPosition = getTargetPosition(masm);
180 if (canUseShortBranch(crb, masm, targetPosition)) {
409 BPCC.emit(masm, cc, actualConditionFlag, NOT_ANNUL, predictTaken, actualTarget);
410 }
411 if (withDelayedNop) {
412 masm.nop(); // delay slot
413 }
414 if (needJump) {
415 masm.jmp(falseDestination.label());
416 }
417 return true;
418 }
419
420 public static class StrategySwitchOp extends SPARCBlockEndOp {
421 public static final LIRInstructionClass<StrategySwitchOp> TYPE = LIRInstructionClass.create(StrategySwitchOp.class);
422 protected Constant[] keyConstants;
423 private final LabelRef[] keyTargets;
424 private LabelRef defaultTarget;
425 @Alive({REG}) protected Value key;
426 @Alive({REG, ILLEGAL}) protected Value constantTableBase;
427 @Temp({REG}) protected Value scratch;
428 protected final SwitchStrategy strategy;
429 private final EconomicMap<Label, LabelHint> labelHints;
430 private final List<Label> conditionalLabels = new ArrayList<>();
431
432 public StrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, AllocatableValue key, Variable scratch) {
433 this(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch);
434 }
435
436 protected StrategySwitchOp(LIRInstructionClass<? extends StrategySwitchOp> c, Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget,
437 AllocatableValue key,
438 Variable scratch) {
439 super(c);
440 this.strategy = strategy;
441 this.keyConstants = strategy.getKeyConstants();
442 this.keyTargets = keyTargets;
443 this.defaultTarget = defaultTarget;
444 this.constantTableBase = constantTableBase;
445 this.key = key;
446 this.scratch = scratch;
447 this.labelHints = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE);
448 assert keyConstants.length == keyTargets.length;
449 assert keyConstants.length == strategy.keyProbabilities.length;
450 }
451
452 @Override
453 public void emitCode(final CompilationResultBuilder crb, final SPARCMacroAssembler masm) {
454 final Register keyRegister = asRegister(key);
455 final Register constantBaseRegister = AllocatableValue.ILLEGAL.equals(constantTableBase) ? g0 : asRegister(constantTableBase);
456 strategy.run(new SwitchClosure(keyRegister, constantBaseRegister, crb, masm));
457 }
458
459 public class SwitchClosure extends BaseSwitchClosure {
460 private int conditionalLabelPointer = 0;
461
462 protected final Register keyRegister;
463 protected final Register constantBaseRegister;
464 protected final CompilationResultBuilder crb;
465 protected final SPARCMacroAssembler masm;
466
467 protected SwitchClosure(Register keyRegister, Register constantBaseRegister, CompilationResultBuilder crb, SPARCMacroAssembler masm) {
|