1 /* 2 * Copyright (c) 2013, 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 */ 23 package com.oracle.graal.lir.hsail; 24 25 import static com.oracle.graal.api.code.ValueUtil.*; 26 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 27 28 import com.oracle.graal.api.meta.*; 29 import com.oracle.graal.asm.hsail.*; 30 import com.oracle.graal.graph.*; 31 import com.oracle.graal.lir.*; 32 import com.oracle.graal.lir.asm.CompilationResultBuilder; 33 34 /** 35 * Defines arithmetic instruction nodes. 36 */ 37 public enum HSAILArithmetic { 38 ABS, 39 CALL, 40 CEIL, 41 FDIV, 42 FLOOR, 43 FREM, 44 DADD, 45 DDIV, 46 DMUL, 47 DNEG, 48 DREM, 49 DSUB, 50 FADD, 51 FMUL, 52 FNEG, 53 FSUB, 54 IADD, 55 IAND, 56 ICARRY, 57 IDIV, 58 IMAX, 59 IMIN, 60 IMUL, 61 INEG, 62 INOT, 63 IOR, 64 IREM, 65 ISHL, 66 ISHR, 67 ISUB, 68 IUADD, 69 IUCARRY, 70 IUDIV, 71 IUMAX, 72 IUMIN, 73 IUMUL, 74 IUREM, 75 IUSHR, 76 IUSUB, 77 IXOR, 78 LADD, 79 LAND, 80 LCARRY, 81 LDIV, 82 LMAX, 83 LMIN, 84 LMUL, 85 LNEG, 86 LNOT, 87 LOR, 88 LREM, 89 LSHL, 90 LSHR, 91 LSUB, 92 LUADD, 93 LUCARRY, 94 LUDIV, 95 LUMAX, 96 LUMIN, 97 LUMUL, 98 LUREM, 99 LUSHR, 100 LUSUB, 101 LXOR, 102 OADD, 103 RINT, 104 SQRT, 105 UNDEF; 106 107 public static class ConvertOp extends HSAILLIRInstruction { 108 private final Kind from; 109 private final Kind to; 110 @Def({REG}) protected AllocatableValue result; 111 @Use({REG, STACK}) protected AllocatableValue x; 112 113 public ConvertOp(AllocatableValue result, AllocatableValue x, Kind to, Kind from) { 114 this.from = from; 115 this.to = to; 116 this.result = result; 117 this.x = x; 118 } 119 120 @Override 121 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 122 masm.emitConvert(result, x, to, from); 123 } 124 } 125 126 public static class Op1Stack extends HSAILLIRInstruction { 127 @Opcode private final HSAILArithmetic opcode; 128 @Def({REG, HINT}) protected Value result; 129 @Use({REG, STACK, CONST}) protected Value x; 130 131 public Op1Stack(HSAILArithmetic opcode, Value result, Value x) { 132 this.opcode = opcode; 133 this.result = result; 134 this.x = x; 135 } 136 137 @Override 138 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 139 emit(crb, masm, opcode, result, x, null); 140 } 141 } 142 143 public static class Op2Stack extends HSAILLIRInstruction { 144 @Opcode private final HSAILArithmetic opcode; 145 @Def({REG, HINT}) protected Value result; 146 @Use({REG, CONST}) protected Value x; 147 @Alive({REG, CONST}) protected Value y; 148 149 public Op2Stack(HSAILArithmetic opcode, Value result, Value x, Value y) { 150 this.opcode = opcode; 151 this.result = result; 152 this.x = x; 153 this.y = y; 154 } 155 156 @Override 157 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 158 emit(crb, masm, opcode, result, x, y, null); 159 } 160 161 @Override 162 public void verify() { 163 super.verify(); 164 verifyKind(opcode, result, x, y); 165 } 166 } 167 168 public static class Op1Reg extends HSAILLIRInstruction { 169 @Opcode private final HSAILArithmetic opcode; 170 @Def({REG, HINT}) protected Value result; 171 @Use({REG}) protected Value x; 172 173 public Op1Reg(HSAILArithmetic opcode, Value result, Value x) { 174 this.opcode = opcode; 175 this.result = result; 176 this.x = x; 177 } 178 179 @Override 180 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 181 emit(crb, masm, opcode, result, x, null); 182 } 183 } 184 185 public static class Op2Reg extends HSAILLIRInstruction { 186 @Opcode private final HSAILArithmetic opcode; 187 @Def({REG, HINT}) protected Value result; 188 @Use({REG, STACK, CONST}) protected Value x; 189 @Alive({REG, CONST}) protected Value y; 190 191 public Op2Reg(HSAILArithmetic opcode, Value result, Value x, Value y) { 192 this.opcode = opcode; 193 this.result = result; 194 this.x = x; 195 this.y = y; 196 } 197 198 @Override 199 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 200 emit(crb, masm, opcode, result, x, y, null); 201 } 202 203 @Override 204 public void verify() { 205 super.verify(); 206 verifyKind(opcode, result, x, y); 207 } 208 } 209 210 public static class Op2RegCommutative extends HSAILLIRInstruction { 211 @Opcode private final HSAILArithmetic opcode; 212 @Def({REG, HINT}) protected Value result; 213 @Use({REG, STACK, CONST}) protected Value x; 214 @Use({REG, CONST}) protected Value y; 215 216 public Op2RegCommutative(HSAILArithmetic opcode, Value result, Value x, Value y) { 217 this.opcode = opcode; 218 this.result = result; 219 this.x = x; 220 this.y = y; 221 } 222 223 @Override 224 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 225 throw GraalInternalError.shouldNotReachHere(); 226 } 227 228 @Override 229 protected void verify() { 230 super.verify(); 231 verifyKind(opcode, result, x, y); 232 } 233 } 234 235 public static class ShiftOp extends HSAILLIRInstruction { 236 @Opcode private final HSAILArithmetic opcode; 237 @Def({REG, HINT}) protected Value result; 238 @Use({REG, STACK, CONST}) protected Value x; 239 @Alive({REG, CONST}) protected Value y; 240 241 public ShiftOp(HSAILArithmetic opcode, Value result, Value x, Value y) { 242 this.opcode = opcode; 243 this.result = result; 244 this.x = x; 245 this.y = y; 246 } 247 248 @Override 249 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 250 emit(crb, masm, opcode, result, x, y, null); 251 } 252 253 @Override 254 public void verify() { 255 super.verify(); 256 verifyKind(opcode, result, x, x); 257 assert y.getKind().getStackKind() == Kind.Int; 258 } 259 } 260 261 public static class DivOp extends HSAILLIRInstruction { 262 @Opcode private final HSAILArithmetic opcode; 263 @Def protected Value result; 264 @Use protected Value x; 265 @Alive protected Value y; 266 @State protected LIRFrameState state; 267 268 public DivOp(HSAILArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { 269 this.opcode = opcode; 270 this.result = result; 271 this.x = x; 272 this.y = y; 273 this.state = state; 274 } 275 276 @Override 277 public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { 278 emit(crb, masm, opcode, result, y, state); 279 } 280 281 @Override 282 protected void verify() { 283 super.verify(); 284 verifyKind(opcode, result, x, y); 285 } 286 } 287 288 @SuppressWarnings("unused") 289 protected static void emit(CompilationResultBuilder crb, HSAILAssembler masm, HSAILArithmetic opcode, Value result) { 290 switch (opcode) { 291 default: 292 throw GraalInternalError.shouldNotReachHere(); 293 } 294 } 295 296 /** 297 * Emit the HSAIL code for an arithmetic operation taking one input parameter. 298 * 299 * @param crb the CompilationResultBuilder 300 * @param masm the HSAIL assembler 301 * @param opcode the opcode of the arithmetic operation 302 * @param dst the destination 303 * @param src the source parameter 304 * @param info structure that stores the LIRFrameState. Used for exception handling. 305 */ 306 307 public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src, LIRFrameState info) { 308 int exceptionOffset = -1; 309 if (isRegister(src)) { 310 switch (opcode) { 311 case ABS: 312 masm.emit("abs", dst, src); 313 break; 314 case CEIL: 315 masm.emit("ceil", dst, src); 316 break; 317 case FLOOR: 318 masm.emit("floor", dst, src); 319 break; 320 case RINT: 321 masm.emit("rint", dst, src); 322 break; 323 case SQRT: 324 masm.emit("sqrt", dst, src); 325 break; 326 case UNDEF: 327 masm.undefined("undefined node"); 328 break; 329 case CALL: 330 masm.undefined("undefined node CALL"); 331 break; 332 case INOT: 333 case LNOT: 334 masm.emitForceBitwise("not", dst, src); 335 break; 336 case INEG: 337 case LNEG: 338 case FNEG: 339 case DNEG: 340 masm.emit("neg", dst, src); 341 break; 342 default: 343 throw GraalInternalError.shouldNotReachHere(); 344 } 345 } else { 346 throw GraalInternalError.shouldNotReachHere(); 347 } 348 if (info != null) { 349 assert exceptionOffset != -1; 350 crb.recordImplicitException(exceptionOffset, info); 351 } 352 } 353 354 public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { 355 /** 356 * First check if one of src1 or src2 is an AddressValue. If it is, convert the address to a 357 * register using an lda instruction. We can just reuse the eventual dst register for this. 358 */ 359 if (src1 instanceof HSAILAddressValue) { 360 assert (!(src2 instanceof HSAILAddressValue)); 361 masm.emitLda(dst, ((HSAILAddressValue) src1).toAddress()); 362 emit(crb, masm, opcode, dst, dst, src2, info); 363 return; 364 } else if (src2 instanceof HSAILAddressValue) { 365 assert (!(src1 instanceof HSAILAddressValue)); 366 masm.emitLda(dst, ((HSAILAddressValue) src2).toAddress()); 367 emit(crb, masm, opcode, dst, src1, dst, info); 368 return; 369 } 370 int exceptionOffset = -1; 371 switch (opcode) { 372 case IADD: 373 case LADD: 374 case DADD: 375 case FADD: 376 case OADD: 377 masm.emit("add", dst, src1, src2); 378 break; 379 case ISUB: 380 case LSUB: 381 case DSUB: 382 case FSUB: 383 masm.emit("sub", dst, src1, src2); 384 break; 385 case IMUL: 386 case LMUL: 387 case FMUL: 388 case DMUL: 389 case LUMUL: 390 masm.emit("mul", dst, src1, src2); 391 break; 392 case IDIV: 393 case LDIV: 394 case FDIV: 395 case DDIV: 396 masm.emit("div", dst, src1, src2); 397 break; 398 case IMAX: 399 case LMAX: 400 masm.emit("max", dst, src1, src2); 401 break; 402 case IMIN: 403 case LMIN: 404 masm.emit("min", dst, src1, src2); 405 break; 406 case ISHL: 407 case LSHL: 408 masm.emit("shl", dst, src1, src2); 409 break; 410 case ISHR: 411 case LSHR: 412 masm.emit("shr", dst, src1, src2); 413 break; 414 case IUSHR: 415 case LUSHR: 416 masm.emitForceUnsigned("shr", dst, src1, src2); 417 break; 418 case IAND: 419 case LAND: 420 masm.emitForceBitwise("and", dst, src1, src2); 421 break; 422 case IXOR: 423 case LXOR: 424 masm.emitForceBitwise("xor", dst, src1, src2); 425 break; 426 case IOR: 427 case LOR: 428 masm.emitForceBitwise("or", dst, src1, src2); 429 break; 430 case IREM: 431 case LREM: 432 masm.emit("rem", dst, src1, src2); 433 break; 434 default: 435 throw GraalInternalError.shouldNotReachHere(); 436 } 437 if (info != null) { 438 assert exceptionOffset != -1; 439 crb.recordImplicitException(exceptionOffset, info); 440 } 441 } 442 443 private static void verifyKind(HSAILArithmetic opcode, Value result, Value x, Value y) { 444 assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || 445 (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || 446 (opcode.name().startsWith("LU") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Int) || 447 (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || 448 (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double) || 449 (opcode.name().startsWith("O") && result.getKind() == Kind.Object && x.getKind() == Kind.Object && (y.getKind() == Kind.Int || y.getKind() == Kind.Long)); 450 } 451 }