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 */
23 package com.oracle.graal.lir.ptx;
24
25 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
26
27 import com.oracle.graal.api.meta.*;
28 import com.oracle.graal.asm.*;
29 import com.oracle.graal.asm.ptx.*;
30 import com.oracle.graal.lir.*;
31 import com.oracle.graal.lir.asm.*;
32 import com.oracle.graal.nodes.calc.*;
33
34 public class PTXControlFlow {
35
36 public static class ReturnOp extends PTXLIRInstruction {
37
38 @Use({REG, ILLEGAL}) protected Value x;
39
40 public ReturnOp(Value x) {
41 this.x = x;
42 }
43
44 @Override
45 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
46 if (tasm.frameContext != null) {
47 tasm.frameContext.leave(tasm);
48 }
49 masm.exit();
50 }
51 }
52
63 @Override
64 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
65 masm.at();
66 Label l = destination.label();
67 l.addPatchAt(tasm.asm.codeBuffer.position());
68 String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
69 masm.bra(target);
70 }
71
72 @Override
73 public LabelRef destination() {
74 return destination;
75 }
76
77 @Override
78 public void negate(LabelRef newDestination) {
79 destination = newDestination;
80 condition = condition.negate();
81 }
82 }
83 }
|
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 */
23 package com.oracle.graal.lir.ptx;
24
25 import static com.oracle.graal.api.code.ValueUtil.asIntReg;
26 import static com.oracle.graal.api.code.ValueUtil.asLongReg;
27 import static com.oracle.graal.api.code.ValueUtil.asObjectReg;
28 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
29
30 import com.oracle.graal.api.code.Register;
31 import com.oracle.graal.api.code.CompilationResult.JumpTable;
32 import com.oracle.graal.api.meta.Constant;
33 import com.oracle.graal.api.meta.Kind;
34 import com.oracle.graal.api.meta.Value;
35 import com.oracle.graal.asm.Buffer;
36 import com.oracle.graal.asm.Label;
37 import com.oracle.graal.asm.NumUtil;
38 import com.oracle.graal.asm.ptx.AbstractPTXAssembler;
39 import com.oracle.graal.asm.ptx.PTXAssembler;
40 import com.oracle.graal.graph.GraalInternalError;
41 import com.oracle.graal.lir.LabelRef;
42 import com.oracle.graal.lir.StandardOp;
43 import com.oracle.graal.lir.StandardOp.FallThroughOp;
44 import com.oracle.graal.lir.Variable;
45 import com.oracle.graal.lir.asm.TargetMethodAssembler;
46 import com.oracle.graal.nodes.calc.Condition;
47
48 public class PTXControlFlow {
49
50 public static class ReturnOp extends PTXLIRInstruction {
51
52 @Use({REG, ILLEGAL}) protected Value x;
53
54 public ReturnOp(Value x) {
55 this.x = x;
56 }
57
58 @Override
59 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
60 if (tasm.frameContext != null) {
61 tasm.frameContext.leave(tasm);
62 }
63 masm.exit();
64 }
65 }
66
77 @Override
78 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
79 masm.at();
80 Label l = destination.label();
81 l.addPatchAt(tasm.asm.codeBuffer.position());
82 String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
83 masm.bra(target);
84 }
85
86 @Override
87 public LabelRef destination() {
88 return destination;
89 }
90
91 @Override
92 public void negate(LabelRef newDestination) {
93 destination = newDestination;
94 condition = condition.negate();
95 }
96 }
97
98 public static class CondMoveOp extends PTXLIRInstruction {
99 @Def({REG, HINT}) protected Value result;
100 @Alive({REG}) protected Value trueValue;
101 @Use({REG, STACK, CONST}) protected Value falseValue;
102 private final Condition condition;
103
104 public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
105 this.result = result;
106 this.condition = condition;
107 this.trueValue = trueValue;
108 this.falseValue = falseValue;
109 }
110
111 @Override
112 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
113 // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
114 // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
115 throw new InternalError("NYI");
116 }
117 }
118
119
120 public static class FloatCondMoveOp extends PTXLIRInstruction {
121 @Def({REG}) protected Value result;
122 @Alive({REG}) protected Value trueValue;
123 @Alive({REG}) protected Value falseValue;
124 private final Condition condition;
125 private final boolean unorderedIsTrue;
126
127 public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
128 this.result = result;
129 this.condition = condition;
130 this.unorderedIsTrue = unorderedIsTrue;
131 this.trueValue = trueValue;
132 this.falseValue = falseValue;
133 }
134
135 @Override
136 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
137 // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
138 // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
139 throw new InternalError("NYI");
140 }
141 }
142
143 public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp {
144 @Use({CONST}) protected Constant[] keyConstants;
145 private final LabelRef[] keyTargets;
146 private LabelRef defaultTarget;
147 @Alive({REG}) protected Value key;
148 @Temp({REG, ILLEGAL}) protected Value scratch;
149
150 public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
151 assert keyConstants.length == keyTargets.length;
152 this.keyConstants = keyConstants;
153 this.keyTargets = keyTargets;
154 this.defaultTarget = defaultTarget;
155 this.key = key;
156 this.scratch = scratch;
157 }
158
159 @Override
160 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
161 if (key.getKind() == Kind.Int) {
162 Register intKey = asIntReg(key);
163 for (int i = 0; i < keyConstants.length; i++) {
164 if (tasm.runtime.needsDataPatch(keyConstants[i])) {
165 tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
166 }
167 long lc = keyConstants[i].asLong();
168 assert NumUtil.isInt(lc);
169 masm.setp_eq_s32((int)lc, intKey);
170 masm.at();
171 Label l = keyTargets[i].label();
172 l.addPatchAt(tasm.asm.codeBuffer.position());
173 String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
174 masm.bra(target);
175 }
176 } else if (key.getKind() == Kind.Long) {
177 Register longKey = asLongReg(key);
178 for (int i = 0; i < keyConstants.length; i++) {
179 masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey);
180 masm.at();
181 Label l = keyTargets[i].label();
182 l.addPatchAt(tasm.asm.codeBuffer.position());
183 String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
184 masm.bra(target);
185 }
186 } else if (key.getKind() == Kind.Object) {
187 Register intKey = asObjectReg(key);
188 Register temp = asObjectReg(scratch);
189 for (int i = 0; i < keyConstants.length; i++) {
190 PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
191 masm.setp_eq_u32(intKey, temp);
192 masm.at();
193 masm.bra(keyTargets[i].label().toString());
194 }
195 } else {
196 throw new GraalInternalError("sequential switch only supported for int, long and object");
197 }
198 if (defaultTarget != null) {
199 masm.jmp(defaultTarget.label());
200 } else {
201 // masm.hlt();
202 }
203 }
204
205 @Override
206 public LabelRef fallThroughTarget() {
207 return defaultTarget;
208 }
209
210 @Override
211 public void setFallThroughTarget(LabelRef target) {
212 defaultTarget = target;
213 }
214 }
215
216 public static class TableSwitchOp extends PTXLIRInstruction {
217 private final int lowKey;
218 private final LabelRef defaultTarget;
219 private final LabelRef[] targets;
220 @Alive protected Value index;
221 @Temp protected Value scratch;
222
223 public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets,
224 Variable index, Variable scratch) {
225 this.lowKey = lowKey;
226 this.defaultTarget = defaultTarget;
227 this.targets = targets;
228 this.index = index;
229 this.scratch = scratch;
230 }
231
232 @Override
233 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
234 tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
235 }
236 }
237
238 private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey,
239 LabelRef defaultTarget, LabelRef[] targets,
240 Register value, Register scratch) {
241 Buffer buf = masm.codeBuffer;
242 // Compare index against jump table bounds
243 int highKey = lowKey + targets.length - 1;
244 if (lowKey != 0) {
245 // subtract the low value from the switch value
246 masm.sub_s32(value, value, lowKey);
247 masm.setp_gt_s32(value, highKey - lowKey);
248 } else {
249 masm.setp_gt_s32(value, highKey);
250 }
251
252 // Jump to default target if index is not within the jump table
253 if (defaultTarget != null) {
254 masm.at();
255 masm.bra(defaultTarget.label().toString());
256 }
257
258 // address of jump table
259 int tablePos = buf.position();
260
261 JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
262 tasm.compilationResult.addAnnotation(jt);
263
264 System.err.println("PTX: unimp: tableswitch");
265 }
266 }
|