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 24 package com.oracle.graal.compiler.ptx; 25 26 import static com.oracle.graal.api.code.ValueUtil.*; 27 import static com.oracle.graal.lir.ptx.PTXArithmetic.*; 28 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*; 29 import static com.oracle.graal.lir.ptx.PTXCompare.*; 30 31 import com.oracle.graal.api.code.*; 32 import com.oracle.graal.api.meta.*; 33 import com.oracle.graal.asm.*; 34 import com.oracle.graal.compiler.gen.*; 35 import com.oracle.graal.compiler.target.*; 36 import com.oracle.graal.graph.*; 37 import com.oracle.graal.lir.*; 38 import com.oracle.graal.lir.StandardOp.JumpOp; 39 import com.oracle.graal.lir.ptx.*; 40 import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; 41 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; 42 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; 43 import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; 44 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; 45 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; 46 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; 47 import com.oracle.graal.lir.ptx.PTXMove.LoadOp; 48 import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp; 49 import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; 50 import com.oracle.graal.lir.ptx.PTXMove.StoreOp; 51 import com.oracle.graal.nodes.*; 52 import com.oracle.graal.nodes.calc.*; 53 import com.oracle.graal.nodes.java.*; 54 55 /** 56 * This class implements the PTX specific portion of the LIR generator. 57 */ 58 public class PTXLIRGenerator extends LIRGenerator { 59 60 public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory { 61 62 @Override 63 public LIRInstruction createMove(Value result, Value input) { 64 throw new InternalError("NYI"); 65 } 66 } 67 68 public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { 69 super(graph, runtime, target, frameMap, method, lir); 70 lir.spillMoveFactory = new PTXSpillMoveFactory(); 71 } 72 73 @Override 74 protected void emitNode(ValueNode node) { 75 if (node instanceof LIRGenLowerable) { 76 ((LIRGenLowerable) node).generate(this); 77 } else { 78 super.emitNode(node); 79 } 80 } 81 82 @Override 83 public boolean canStoreConstant(Constant c) { 84 // Operand b must be in the .reg state space. 85 return false; 86 } 87 88 @Override 89 public boolean canInlineConstant(Constant c) { 90 switch (c.getKind()) { 91 case Long: 92 return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c); 93 case Object: 94 return c.isNull(); 95 default: 96 return true; 97 } 98 } 99 100 @Override 101 public Variable emitMove(Value input) { 102 Variable result = newVariable(input.getKind()); 103 emitMove(result, input); 104 return result; 105 } 106 107 @Override 108 public void emitMove(Value dst, Value src) { 109 if (isRegister(src) || isStackSlot(dst)) { 110 append(new MoveFromRegOp(dst, src)); 111 } else { 112 append(new MoveToRegOp(dst, src)); 113 } 114 } 115 116 private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { 117 AllocatableValue baseRegister; 118 long finalDisp = displacement; 119 if (isConstant(base)) { 120 if (asConstant(base).isNull()) { 121 baseRegister = AllocatableValue.UNUSED; 122 } else if (asConstant(base).getKind() != Kind.Object) { 123 finalDisp += asConstant(base).asLong(); 124 baseRegister = AllocatableValue.UNUSED; 125 } else { 126 baseRegister = load(base); 127 } 128 } else if (base == Value.ILLEGAL) { 129 baseRegister = AllocatableValue.UNUSED; 130 } else { 131 baseRegister = asAllocatable(base); 132 } 133 134 if (index != Value.ILLEGAL) { 135 if (isConstant(index)) { 136 finalDisp += asConstant(index).asLong() * scale; 137 } else { 138 Value indexRegister; 139 if (scale != 1) { 140 indexRegister = emitMul(index, Constant.forInt(scale)); 141 } else { 142 indexRegister = index; 143 } 144 145 if (baseRegister == AllocatableValue.UNUSED) { 146 baseRegister = asAllocatable(indexRegister); 147 } else { 148 baseRegister = emitAdd(baseRegister, indexRegister); 149 } 150 } 151 } 152 153 return new PTXAddressValue(kind, baseRegister, finalDisp); 154 } 155 156 @Override 157 public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { 158 PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); 159 Variable result = newVariable(loadAddress.getKind()); 160 append(new LoadOp(result, loadAddress, canTrap ? state() : null)); 161 return result; 162 } 163 164 @Override 165 public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { 166 PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); 167 Variable input = load(inputVal); 168 append(new StoreOp(storeAddress, input, canTrap ? state() : null)); 169 } 170 171 @Override 172 public Variable emitLea(Value base, int displacement, Value index, int scale) { 173 throw new InternalError("NYI"); 174 } 175 176 @Override 177 public Variable emitLea(StackSlot address) { 178 throw new InternalError("NYI"); 179 } 180 181 @Override 182 public void emitJump(LabelRef label) { 183 append(new JumpOp(label)); 184 } 185 186 @Override 187 public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) { 188 switch (left.getKind().getStackKind()) { 189 case Int: 190 append(new CompareOp(ICMP, cond, left, right)); 191 append(new BranchOp(cond, label)); 192 break; 193 case Object: 194 append(new CompareOp(ACMP, cond, left, right)); 195 append(new BranchOp(cond, label)); 196 break; 197 default: 198 throw GraalInternalError.shouldNotReachHere("" + left.getKind()); 199 } 200 } 201 202 @Override 203 public void emitOverflowCheckBranch(LabelRef label, boolean negated) { 204 throw new InternalError("NYI"); 205 } 206 207 @Override 208 public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) { 209 throw new InternalError("NYI"); 210 } 211 212 @Override 213 public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { 214 throw new InternalError("NYI"); 215 } 216 217 @Override 218 public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { 219 throw new InternalError("NYI"); 220 } 221 222 @Override 223 public Variable emitNegate(Value input) { 224 Variable result = newVariable(input.getKind()); 225 switch (input.getKind()) { 226 case Int: 227 append(new Op1Stack(INEG, result, input)); 228 break; 229 default: 230 throw GraalInternalError.shouldNotReachHere(); 231 } 232 return result; 233 } 234 235 @Override 236 public Variable emitAdd(Value a, Value b) { 237 Variable result = newVariable(a.getKind()); 238 switch (a.getKind()) { 239 case Int: 240 append(new Op2Stack(IADD, result, a, loadNonConst(b))); 241 break; 242 default: 243 throw GraalInternalError.shouldNotReachHere(); 244 } 245 return result; 246 } 247 248 @Override 249 public Variable emitSub(Value a, Value b) { 250 Variable result = newVariable(a.getKind()); 251 switch (a.getKind()) { 252 case Int: 253 append(new Op2Stack(ISUB, result, a, loadNonConst(b))); 254 break; 255 default: 256 throw GraalInternalError.shouldNotReachHere(); 257 } 258 return result; 259 } 260 261 @Override 262 public Variable emitMul(Value a, Value b) { 263 Variable result = newVariable(a.getKind()); 264 switch (a.getKind()) { 265 case Int: 266 append(new Op2Reg(IMUL, result, a, loadNonConst(b))); 267 break; 268 default: 269 throw GraalInternalError.shouldNotReachHere(); 270 } 271 return result; 272 } 273 274 @Override 275 protected boolean peephole(ValueNode valueNode) { 276 // No peephole optimizations for now 277 return false; 278 } 279 280 @Override 281 public Value emitDiv(Value a, Value b) { 282 throw new InternalError("NYI"); 283 } 284 285 @Override 286 public Value emitRem(Value a, Value b) { 287 throw new InternalError("NYI"); 288 } 289 290 @Override 291 public Variable emitUDiv(Value a, Value b) { 292 throw new InternalError("NYI"); 293 } 294 295 @Override 296 public Variable emitURem(Value a, Value b) { 297 throw new InternalError("NYI"); 298 } 299 300 @Override 301 public Variable emitAnd(Value a, Value b) { 302 Variable result = newVariable(a.getKind()); 303 switch (a.getKind()) { 304 case Int: 305 append(new Op2Stack(IAND, result, a, loadNonConst(b))); 306 break; 307 default: 308 throw GraalInternalError.shouldNotReachHere(); 309 } 310 return result; 311 } 312 313 @Override 314 public Variable emitOr(Value a, Value b) { 315 throw new InternalError("NYI"); 316 } 317 318 @Override 319 public Variable emitXor(Value a, Value b) { 320 throw new InternalError("NYI"); 321 } 322 323 @Override 324 public Variable emitShl(Value a, Value b) { 325 throw new InternalError("NYI"); 326 } 327 328 @Override 329 public Variable emitShr(Value a, Value b) { 330 throw new InternalError("NYI"); 331 } 332 333 @Override 334 public Variable emitUShr(Value a, Value b) { 335 Variable result = newVariable(a.getKind()); 336 switch (a.getKind()) { 337 case Int: 338 append(new ShiftOp(IUSHR, result, a, b)); 339 break; 340 default: 341 GraalInternalError.shouldNotReachHere(); 342 } 343 return result; 344 } 345 346 @Override 347 public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { 348 throw new InternalError("NYI"); 349 } 350 351 @Override 352 public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) { 353 append(new ReturnOp(Value.ILLEGAL)); 354 } 355 356 @Override 357 public void emitMembar(int barriers) { 358 throw new InternalError("NYI"); 359 } 360 361 @Override 362 protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 363 throw new InternalError("NYI"); 364 } 365 366 @Override 367 protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 368 throw new InternalError("NYI"); 369 } 370 371 @Override 372 protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { 373 throw new InternalError("NYI"); 374 } 375 376 @Override 377 public void emitBitCount(Variable result, Value value) { 378 if (value.getKind().getStackKind() == Kind.Int) { 379 append(new PTXBitManipulationOp(IPOPCNT, result, value)); 380 } else { 381 append(new PTXBitManipulationOp(LPOPCNT, result, value)); 382 } 383 } 384 385 @Override 386 public void emitBitScanForward(Variable result, Value value) { 387 throw new InternalError("NYI"); 388 } 389 390 @Override 391 public void emitBitScanReverse(Variable result, Value value) { 392 throw new InternalError("NYI"); 393 } 394 395 @Override 396 public void emitMathAbs(Variable result, Variable input) { 397 throw new InternalError("NYI"); 398 } 399 400 @Override 401 public void emitMathSqrt(Variable result, Variable input) { 402 throw new InternalError("NYI"); 403 } 404 405 @Override 406 public void emitMathLog(Variable result, Variable input, boolean base10) { 407 throw new InternalError("NYI"); 408 } 409 410 @Override 411 public void emitMathCos(Variable result, Variable input) { 412 throw new InternalError("NYI"); 413 } 414 415 @Override 416 public void emitMathSin(Variable result, Variable input) { 417 throw new InternalError("NYI"); 418 } 419 420 @Override 421 public void emitMathTan(Variable result, Variable input) { 422 throw new InternalError("NYI"); 423 } 424 425 @Override 426 public void emitByteSwap(Variable result, Value input) { 427 throw new InternalError("NYI"); 428 } 429 430 @Override 431 protected void emitReturn(Value input) { 432 append(new ReturnOp(input)); 433 } 434 435 @Override 436 protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { 437 throw new InternalError("NYI"); 438 } 439 440 @Override 441 protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { 442 throw new InternalError("NYI"); 443 } 444 445 @Override 446 protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { 447 throw new InternalError("NYI"); 448 } 449 450 @Override 451 public void visitCompareAndSwap(CompareAndSwapNode node) { 452 throw new InternalError("NYI"); 453 } 454 455 @Override 456 public void visitBreakpointNode(BreakpointNode node) { 457 throw new InternalError("NYI"); 458 } 459 460 @Override 461 public void visitSafepointNode(SafepointNode i) { 462 throw new InternalError("NYI"); 463 } 464 465 @Override 466 public void emitUnwind(Value operand) { 467 // TODO Auto-generated method stub 468 469 } 470 471 @Override 472 public void emitNullCheck(ValueNode v) { 473 throw new InternalError("NYI"); 474 } 475 }